mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-05-26 05:45:48 +08:00
[bsp][rdk s100] Add the RDC S100 BSP (#11406)
ToolsCI / Tools (push) Has been cancelled
RT-Thread BSP Static Build Check / 🔍 Summary of Git Diff Changes (push) Has been cancelled
pkgs_test / change (push) Has been cancelled
utest_auto_run / A9 :components/dfs.cfg (push) Has been cancelled
utest_auto_run / A9 :components/lwip.cfg (push) Has been cancelled
utest_auto_run / A9 :components/netdev.cfg (push) Has been cancelled
utest_auto_run / A9 :components/sal.cfg (push) Has been cancelled
utest_auto_run / A9 :cpp11/cpp11.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :default.cfg (push) Has been cancelled
utest_auto_run / A9-smp :default.cfg (push) Has been cancelled
utest_auto_run / RISCV :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :kernel/mem.cfg (push) Has been cancelled
RT-Thread BSP Static Build Check / ${{ matrix.legs.RTT_BSP }} (push) Has been cancelled
RT-Thread BSP Static Build Check / collect-artifacts (push) Has been cancelled
ToolsCI / Tools (push) Has been cancelled
RT-Thread BSP Static Build Check / 🔍 Summary of Git Diff Changes (push) Has been cancelled
pkgs_test / change (push) Has been cancelled
utest_auto_run / A9 :components/dfs.cfg (push) Has been cancelled
utest_auto_run / A9 :components/lwip.cfg (push) Has been cancelled
utest_auto_run / A9 :components/netdev.cfg (push) Has been cancelled
utest_auto_run / A9 :components/sal.cfg (push) Has been cancelled
utest_auto_run / A9 :cpp11/cpp11.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :default.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :default.cfg (push) Has been cancelled
utest_auto_run / A9-smp :default.cfg (push) Has been cancelled
utest_auto_run / RISCV :default.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :default.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/atomic_c11.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/ipc.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/kernel_basic.cfg (push) Has been cancelled
utest_auto_run / AARCH64-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / XUANTIE-rtsmart :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / AARCH64 :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / AARCH64-smp :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9 :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / A9-smp :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV :kernel/mem.cfg (push) Has been cancelled
utest_auto_run / RISCV-smp :kernel/mem.cfg (push) Has been cancelled
RT-Thread BSP Static Build Check / ${{ matrix.legs.RTT_BSP }} (push) Has been cancelled
RT-Thread BSP Static Build Check / collect-artifacts (push) Has been cancelled
* 添加 rdk_s100 bsp * 添加 CI 看护
This commit is contained in:
@@ -525,6 +525,13 @@
|
||||
"SUB_RTT_BSP": [
|
||||
"novosns/ns800/ns800rt7p65-nssinepad"
|
||||
]
|
||||
},
|
||||
{
|
||||
"RTT_BSP": "RDK",
|
||||
"RTT_TOOL_CHAIN": "sourcery-arm",
|
||||
"SUB_RTT_BSP": [
|
||||
"rdk/s100"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
mainmenu "RT-Thread Configuration"
|
||||
|
||||
BSP_DIR := .
|
||||
|
||||
# you can change the RTT_ROOT default "rt-thread"
|
||||
# example : default "F:/git_repositories/rt-thread"
|
||||
|
||||
PKGS_DIR := packages
|
||||
|
||||
ENV_DIR := /
|
||||
|
||||
config SOC_S100
|
||||
bool
|
||||
select RT_USING_COMPONENTS_INIT
|
||||
select RT_USING_USER_MAIN
|
||||
default y
|
||||
|
||||
menu "S100 BSP Options"
|
||||
|
||||
config RT_USING_FPU
|
||||
bool "Enable Cortex-R52 VFP/FPU support"
|
||||
default y
|
||||
help
|
||||
Enable hardware floating-point support for the S100 BSP.
|
||||
|
||||
When enabled, the BSP builds with hard-float ABI and enables
|
||||
the VFP context save/restore path.
|
||||
|
||||
When disabled, the BSP switches to a soft-float build so O2 can
|
||||
remain enabled without generating VFP instructions.
|
||||
|
||||
endmenu
|
||||
|
||||
source "$(RTT_DIR)/Kconfig"
|
||||
osource "$PKGS_DIR/Kconfig"
|
||||
# rsource "$(BSP_DIR)/board/Kconfig"
|
||||
source "$(BSP_DIR)/drivers/Kconfig"
|
||||
@@ -0,0 +1,286 @@
|
||||
# S100 BSP 编译与加载运行说明
|
||||
|
||||
本文说明 `bsp/s100` 这个 RT-Thread BSP 如何在主机侧编译,以及如何在 RDK S100 板端加载并运行。
|
||||
|
||||
说明分两部分:
|
||||
|
||||
- 本地 BSP 实际构建方式:以当前仓库中的 `SConstruct`、`rtconfig.py`、`link.lds` 为准
|
||||
- 板端启动流程:参考 D-Robotics 官方文档“[MCU快速入门指南](https://d-robotics.github.io/rdk_doc/rdk_s/Advanced_development/mcu_development/S100/basic_information/)”
|
||||
|
||||
## 1. 背景说明
|
||||
|
||||
官方文档说明了 S100 的 MCU 启动链路:
|
||||
|
||||
- MCU0 负责启动 Acore、MCU1 和电源管理
|
||||
- MCU1 由 Acore 通过 `remoteproc` 框架间接控制
|
||||
- 启动时由 Acore 在 `sysfs` 下给 `remoteproc_mcu0` 写入固件名并触发 `start`
|
||||
|
||||
参考:
|
||||
|
||||
- 官方文档第 “MCU1启动/关闭流程” 章节:`remoteproc_mcu0`、`firmware`、`state`
|
||||
- 本地链接脚本 [link.lds](./link.lds) 也包含 `.resource_table` 段,说明这个镜像是按 remoteproc 风格组织的 MCU1 ELF
|
||||
|
||||
## 2. 主机编译环境
|
||||
|
||||
### 2.1 推荐系统
|
||||
|
||||
官方文档建议主机使用 Ubuntu 22.04。
|
||||
|
||||
### 2.2 依赖安装
|
||||
|
||||
官方文档给出的依赖如下:
|
||||
|
||||
```bash
|
||||
sudo apt-get install -y build-essential make cmake libpcre3 libpcre3-dev bc bison \
|
||||
flex python3-numpy mtd-utils zlib1g-dev debootstrap \
|
||||
libdata-hexdumper-perl libncurses5-dev zip qemu-user-static \
|
||||
curl repo git liblz4-tool apt-cacher-ng libssl-dev checkpolicy autoconf \
|
||||
android-sdk-libsparse-utils mtools parted dosfstools udev rsync python3-pip scons
|
||||
pip install "scons>=4.0.0"
|
||||
pip install ecdsa
|
||||
pip install tqdm
|
||||
```
|
||||
|
||||
### 2.3 交叉工具链
|
||||
|
||||
当前 BSP 的工具链配置在 [rtconfig.py](./rtconfig.py):
|
||||
|
||||
- 架构:`cortex-r52`
|
||||
- 工具链前缀:`arm-none-eabi-`
|
||||
- 默认工具链路径:`/opt/toolchain/gcc-arm-none-eabi-10.3-2021.10/bin`
|
||||
|
||||
如果你的工具链不在这个目录,可以通过环境变量覆盖:
|
||||
|
||||
```bash
|
||||
export RTT_EXEC_PATH=/your/toolchain/bin
|
||||
```
|
||||
|
||||
## 3. BSP 编译方法
|
||||
|
||||
### 3.1 进入目录
|
||||
|
||||
```bash
|
||||
cd <repo>/bsp/s100
|
||||
```
|
||||
|
||||
### 3.2 执行编译
|
||||
|
||||
直接运行:
|
||||
|
||||
```bash
|
||||
scons -j$(nproc)
|
||||
```
|
||||
|
||||
如果你想先清理后重编:
|
||||
|
||||
```bash
|
||||
scons -c
|
||||
scons -j$(nproc)
|
||||
```
|
||||
|
||||
### 3.3 构建入口
|
||||
|
||||
本 BSP 的构建入口是:
|
||||
|
||||
- [SConstruct](./SConstruct)
|
||||
- [rtconfig.py](./rtconfig.py)
|
||||
|
||||
构建特征:
|
||||
|
||||
- 目标文件名:`rtthread.elf`
|
||||
- 后处理会自动生成:`rtthread.bin`
|
||||
|
||||
## 4. 板端加载运行
|
||||
|
||||
### 4.1 固件放置
|
||||
|
||||
根据官方 remoteproc 启动流程,MCU1 固件需要放到板端 `/lib/firmware/`。
|
||||
|
||||
根据官方 RDK S100 硬件说明,板上有两个有线网口:
|
||||
|
||||
- `U43 / eth0`:通用以太网口,IP 需要通过外部 DHCP 获取,或由用户手动配置静态地址
|
||||
- `U45 / eth1`:固定静态 IP 网口,默认地址为 `192.168.127.10`
|
||||
|
||||
如果开发主机直接接在 `U45 / eth1`,可以优先使用固定 IP 方式传文件,这样不需要先查询板端地址。由于当前 BSP 输出文件名是 `rtthread.elf`,可以直接推送这个文件:
|
||||
|
||||
```bash
|
||||
scp rtthread.elf root@192.168.127.10:/lib/firmware/
|
||||
```
|
||||
|
||||
如果你接的是 `U43 / eth0`,则需要先确认板端实际 IP,然后再执行:
|
||||
|
||||
```bash
|
||||
scp rtthread.elf root@<board_ip>:/lib/firmware/
|
||||
```
|
||||
|
||||
### 4.2 启动 MCU1
|
||||
|
||||
参考官方文档中的 `remoteproc_mcu0` 启动步骤,板端执行:
|
||||
|
||||
如果固件名是 `rtthread.elf`:
|
||||
|
||||
```bash
|
||||
cd /sys/class/remoteproc/remoteproc_mcu0
|
||||
echo rtthread.elf > firmware
|
||||
echo start > state
|
||||
```
|
||||
|
||||
### 4.3 停止 MCU1
|
||||
|
||||
> 由于该功能还不完善,此处需要重启设备来完成
|
||||
|
||||
## 5. 一套完整示例
|
||||
|
||||
主机侧:
|
||||
|
||||
```bash
|
||||
cd <repo>/bsp/s100
|
||||
scons -j$(nproc)
|
||||
scp rtthread.elf root@192.168.127.10:/lib/firmware/
|
||||
```
|
||||
|
||||
板端:
|
||||
|
||||
```bash
|
||||
cd /sys/class/remoteproc/remoteproc_mcu0
|
||||
echo rtthread.elf > firmware
|
||||
echo start > state
|
||||
```
|
||||
|
||||
停止:
|
||||
|
||||
```bash
|
||||
reboot
|
||||
```
|
||||
|
||||
## 6. 系统支持外设说明
|
||||
|
||||
- 支持 UART 4、5、6(暂不支持DMA),默认使用串口4作为msh控制台
|
||||
- 支持GPIO输入、输出、外部中断响应功能,但以下引脚不允许被配置
|
||||
|
||||
```shell
|
||||
static const s100_pin_t s100_gpio_blacklist[] =
|
||||
{
|
||||
0, /* S100 Power related pins */
|
||||
5, /* S100 debug uart tx */
|
||||
38, /* S100 Power related pins */
|
||||
15, /* S100 Power related pins */
|
||||
68, /* S100 Power related pins */
|
||||
69, /* S100 Power related pins */
|
||||
71, /* S100 Power related pins */
|
||||
80, /* S100 Power related pins */
|
||||
81, /* S100 Power related pins */
|
||||
82, /* S100 Power related pins */
|
||||
83, /* S100 Power related pins */
|
||||
AON_PIN_NUM(0), /* S100 debug uart rx */
|
||||
AON_PIN_NUM(12), /* S100 Power related pins */
|
||||
};
|
||||
```
|
||||
|
||||
- 支持 CAN5、CAN6、CAN7、CAN8、CAN9(只支持基础CAN通信)
|
||||
|
||||
## 7.测试方法
|
||||
|
||||
### 硬件连接
|
||||
|
||||
RDK S100 需要先连接 MCU 接口扩展版
|
||||
|
||||
### 软件配置
|
||||
|
||||
为了运行当前 `s100` BSP 下的 GPIO、UART、CAN 设备测试,建议至少打开以下配置。
|
||||
|
||||
#### 通用测试开关
|
||||
|
||||
使用 ` scons --menuconfig `打开配置界面
|
||||
|
||||
- 打开内核测试配置:
|
||||

|
||||
|
||||
- 打开外设测试配置:
|
||||

|
||||
|
||||
当前默认配置里,上述 `utest` 基础开关已经打开;如果你重新裁剪过配置,需确认这些选项仍然存在。
|
||||
|
||||
#### GPIO 测试相关配置
|
||||
|
||||
- 使能 `BSP_USING_GPIO`(默认已经打开)
|
||||
|
||||
GPIO 测试文件为:
|
||||
|
||||
- [test_gpio.c](./drivers/utest/test_gpio.c)
|
||||
|
||||
当前测试内容包括:
|
||||
|
||||
- 非法脚/保留脚拒绝逻辑
|
||||
- GPIO 输入输出回环
|
||||
- GPIO 中断上升沿、下降沿、双边沿回环
|
||||
|
||||
运行前要求:
|
||||
|
||||
- 用跳线连接测试输出脚和测试输入脚
|
||||
- 默认测试脚为 `GPIO36 -> GPIO37`
|
||||
- 若板级接线不同,可修改 `test_gpio.c` 中的 `S100_GPIO_TEST_OUT_PIN` 与 `S100_GPIO_TEST_IN_PIN`
|
||||
|
||||
#### UART 测试相关配置
|
||||
|
||||
- 使能 `BSP_USING_UART`
|
||||
- 保持 `BSP_USING_UART4=y`
|
||||
- 额外使能至少一个非控制台串口:
|
||||
- `BSP_USING_UART5`
|
||||
- 或 `BSP_USING_UART6`
|
||||
|
||||
UART 测试文件为:
|
||||
|
||||
- [test_uart.c](./drivers/utest/test_uart.c)
|
||||
|
||||
当前测试约束如下:
|
||||
|
||||
- `uart4` 默认为 `msh` 控制台,不参与设备测试
|
||||
- 测试对象为已启用的 `uart5`、`uart6`
|
||||
- `txrx` 用例发送固定二进制数据帧,并逐字节校验接收内容
|
||||
|
||||
运行前要求:
|
||||
|
||||
- 被测串口需要具备回环条件
|
||||
- 常见做法是将 `UART5_TX` 与 `UART5_RX` 短接,或将 `UART6_TX` 与 `UART6_RX` 短接
|
||||
- 若未打开 `uart5/uart6`,`rdk.s100.drivers.uart` 不会覆盖非控制台串口
|
||||
|
||||
#### CAN 测试相关配置
|
||||
|
||||
- 使能 `BSP_USING_CAN`
|
||||
- 使能至少一个 CAN 控制器:
|
||||
- `BSP_USING_CAN5`
|
||||
- `BSP_USING_CAN6`
|
||||
- `BSP_USING_CAN7`
|
||||
- `BSP_USING_CAN8`
|
||||
- `BSP_USING_CAN9`
|
||||
|
||||
CAN 测试文件为:
|
||||
|
||||
- [test_can.c](./drivers/utest/test_can.c)
|
||||
|
||||
当前测试特点如下:
|
||||
|
||||
- 使用 `RT_CAN_MODE_LOOPBACK` 内部回环模式
|
||||
- 不依赖外部 CAN 对端
|
||||
- 覆盖 `find/open/config/set_mode/set_baud/write/read/get_status/close`
|
||||
- 发送一帧标准 CAN 数据帧,并逐字节校验接收 payload
|
||||
|
||||
#### 构建与运行
|
||||
|
||||
完成配置后重新编译:
|
||||
|
||||
```bash
|
||||
scons -j$(nproc)
|
||||
```
|
||||
|
||||
板端启动后,可在 `msh` 中分别执行:
|
||||
|
||||
```bash
|
||||
utest_run rdk.s100.drivers.gpio
|
||||
utest_run rdk.s100.drivers.uart
|
||||
utest_run rdk.s100.drivers.can
|
||||
```
|
||||
|
||||
如果只想执行单项测试,保留对应驱动开关即可;未启用的设备不会进入对应测试覆盖范围。
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
# for module compiling
|
||||
import os
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
group = []
|
||||
list = os.listdir(cwd)
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
group = group + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,78 @@
|
||||
import os
|
||||
import sys
|
||||
import rtconfig
|
||||
|
||||
if os.getenv('RTT_ROOT'):
|
||||
RTT_ROOT = os.getenv('RTT_ROOT')
|
||||
else:
|
||||
RTT_ROOT = os.path.join(os.getcwd(), '..', '..', '..')
|
||||
|
||||
sys.path = sys.path + [os.path.join(RTT_ROOT, 'tools')]
|
||||
from building import *
|
||||
|
||||
TARGET = 'rtthread.' + rtconfig.TARGET_EXT
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
env = Environment(tools = ['mingw'],
|
||||
AS = rtconfig.AS, ASFLAGS = rtconfig.AFLAGS,
|
||||
CC = rtconfig.CC, CFLAGS = rtconfig.CFLAGS,
|
||||
CXX = rtconfig.CXX, CXXFLAGS = rtconfig.CXXFLAGS,
|
||||
AR = rtconfig.AR, ARFLAGS = '-rc',
|
||||
LINK = rtconfig.LINK, LINKFLAGS = rtconfig.LFLAGS)
|
||||
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
|
||||
env['ASCOM'] = env['ASPPCOM']
|
||||
|
||||
Export('RTT_ROOT')
|
||||
Export('rtconfig')
|
||||
|
||||
# prepare building environment
|
||||
objs = PrepareBuilding(env, RTT_ROOT)
|
||||
|
||||
def _replace_cortex_r52_with_startup(objects):
|
||||
startup_dir = os.path.join(Dir('#').abspath, 'startup')
|
||||
startup_names = set(
|
||||
name for name in os.listdir(startup_dir)
|
||||
if os.path.isfile(os.path.join(startup_dir, name))
|
||||
)
|
||||
cpu_dir = os.path.abspath(os.path.join(RTT_ROOT, 'libcpu', rtconfig.ARCH, rtconfig.CPU))
|
||||
|
||||
def _source_path(node):
|
||||
for attr in ('srcnode', 'rfile'):
|
||||
if hasattr(node, attr):
|
||||
source = getattr(node, attr)()
|
||||
if hasattr(source, 'abspath'):
|
||||
return os.path.abspath(source.abspath)
|
||||
if hasattr(node, 'abspath'):
|
||||
return os.path.abspath(node.abspath)
|
||||
return None
|
||||
|
||||
def _filter(items):
|
||||
filtered = []
|
||||
for item in items:
|
||||
if isinstance(item, list):
|
||||
filtered.append(_filter(item))
|
||||
continue
|
||||
|
||||
if not hasattr(item, 'abspath'):
|
||||
filtered.append(item)
|
||||
continue
|
||||
|
||||
item_path = _source_path(item)
|
||||
if item_path is None:
|
||||
filtered.append(item)
|
||||
continue
|
||||
|
||||
item_name = os.path.basename(item_path)
|
||||
if item_name in startup_names and item_path.startswith(cpu_dir + os.sep):
|
||||
continue
|
||||
|
||||
filtered.append(item)
|
||||
|
||||
return filtered
|
||||
|
||||
return _filter(objects)
|
||||
|
||||
objs = _replace_cortex_r52_with_startup(objs)
|
||||
|
||||
# make a building
|
||||
DoBuilding(TARGET, objs)
|
||||
@@ -0,0 +1,9 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
#include <rtthread.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
rt_kprintf("Hi, RT-Thread!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import os
|
||||
from building import *
|
||||
|
||||
objs = []
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd]
|
||||
src = Glob('*.c')
|
||||
|
||||
objs = DefineGroup('board', src, depend = [''], CPPPATH = CPPPATH)
|
||||
Return('objs')
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "board.h"
|
||||
|
||||
|
||||
void rt_hw_board_init(void)
|
||||
{
|
||||
/* initialize interrupt */
|
||||
rt_hw_interrupt_init();
|
||||
|
||||
#ifdef RT_USING_HEAP
|
||||
rt_system_heap_init(HEAP_BEGIN, HEAP_END);
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_COMPONENTS_INIT
|
||||
rt_components_board_init();
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_CONSOLE
|
||||
rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
#ifndef __BOARD_H__
|
||||
#define __BOARD_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rtdef.h>
|
||||
#include <rthw.h>
|
||||
#include <cp15.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
extern char OS_HEAP_START_ADDR;
|
||||
extern char OS_HEAP_END_ADDR;
|
||||
#define HEAP_BEGIN ((void *)&OS_HEAP_START_ADDR)
|
||||
#define HEAP_END ((void *)&OS_HEAP_END_ADDR)
|
||||
#else
|
||||
#error "GCC support only!"
|
||||
#endif
|
||||
|
||||
#ifndef __DSB
|
||||
#define __DSB() __asm volatile ("dsb" : : : "memory")
|
||||
#endif
|
||||
|
||||
#ifndef __ISB
|
||||
#define __ISB() __asm volatile ("isb" : : : "memory")
|
||||
#endif
|
||||
|
||||
/***********************************************************************************************************************
|
||||
* GIC definitions
|
||||
**********************************************************************************************************************/
|
||||
#define S100_GICD_BASE 0x22000000UL
|
||||
#define S100_GICR0_OFFSET 0x100000UL
|
||||
|
||||
#define GIC_IRQ_START 0
|
||||
#define GIC_ACK_INTID_MASK (0x000003FFU)
|
||||
|
||||
/* number of interrupts on board */
|
||||
#define ARM_GIC_NR_IRQS (448)
|
||||
#define MAX_HANDLERS ARM_GIC_NR_IRQS
|
||||
/* only one GIC available */
|
||||
#define ARM_GIC_MAX_NR 1
|
||||
/* end defined */
|
||||
|
||||
#define GICV3_DISTRIBUTOR_BASE_ADDR (S100_GICD_BASE)
|
||||
#define GICV3_REDISTRIBUTOR_BASE_ADDR (S100_GICD_BASE + S100_GICR0_OFFSET)
|
||||
|
||||
/*
|
||||
* Board-level IRQ description used by the S100 BSP.
|
||||
*
|
||||
* Reason:
|
||||
* The SoC GIC can see many more interrupt IDs than this RT-Thread board
|
||||
* actually uses. MCU0 already occupies part of the required interrupt
|
||||
* resources, so this board only maintains the IRQs used by the current
|
||||
* port. We keep a board whitelist so GICv3 only configures and controls
|
||||
* the interrupts that belong to the current board port, which avoids
|
||||
* touching unrelated SPI lines and reduces the risk of conflicting with
|
||||
* the interrupts used by MCU0.
|
||||
*
|
||||
* Fields:
|
||||
* irq_number: GIC interrupt ID used by the board.
|
||||
* enable: whether this IRQ is expected to be enabled by board-level init.
|
||||
* name: short readable name for debug and dump output.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int irq_number;
|
||||
rt_bool_t enable;
|
||||
const char *name;
|
||||
} s100_rt_irq_config_t;
|
||||
|
||||
/*
|
||||
* Board-supported external IRQ whitelist.
|
||||
*
|
||||
* s100_mcu1_rt_irq_configs records the SPI interrupts currently owned by this
|
||||
* board port. GICv3 uses this table to decide which external interrupts may be
|
||||
* initialized, enabled, masked, dumped, or otherwise managed.
|
||||
* The main purpose is to maintain only the interrupts actually used by this
|
||||
* side, so we do not accidentally configure or disturb interrupt lines that
|
||||
* are already required by MCU0.
|
||||
*
|
||||
* Private interrupts (SGI/PPI, INTID 0-31) are not listed here because they
|
||||
* are CPU-local resources and are handled separately.
|
||||
*/
|
||||
extern const s100_rt_irq_config_t s100_mcu1_rt_irq_configs[];
|
||||
extern const rt_size_t s100_mcu1_rt_irq_configs_count;
|
||||
|
||||
/* Returns RT_TRUE only for IRQs that are managed by the current board port. */
|
||||
rt_bool_t s100_board_irq_is_supported(int irq);
|
||||
|
||||
/* the basic constants and interfaces needed by gic */
|
||||
rt_inline rt_uint32_t platform_get_gic_dist_base(void)
|
||||
{
|
||||
return GICV3_DISTRIBUTOR_BASE_ADDR;
|
||||
}
|
||||
|
||||
rt_inline rt_uint32_t platform_get_gic_redist_base(void)
|
||||
{
|
||||
return GICV3_REDISTRIBUTOR_BASE_ADDR;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
|
||||
#include "rsc_table.h"
|
||||
|
||||
extern uint32_t OS_HEAP_START_ADDR;
|
||||
extern uint32_t OS_HEAP_SIZE;
|
||||
extern uint32_t MCU_LOG_START_ADDR;
|
||||
extern uint32_t MCU_LOG_SIZE;
|
||||
extern uint32_t __SCMI_IPC_START_ADDR;
|
||||
extern uint32_t __SCMI_IPC_SIZE;
|
||||
extern uint32_t ATCM_START_ADDR;
|
||||
extern uint32_t ATCM_SIZE;
|
||||
extern uint32_t CAN_START_ADDR;
|
||||
extern uint32_t FLASH_SEC_ADDR;
|
||||
extern uint32_t FLASH_STARTUP_LEN;
|
||||
|
||||
#define NUM_TABLE_ENTRIES (7)
|
||||
#define HB_SECTION_T(S) __attribute__((__section__(#S)))
|
||||
#define HB_RESOURCE HB_SECTION_T(.resource_table)
|
||||
#define MCU_FLASH_START_BASE_ADDR (0x0CAA5000)
|
||||
#define MCU_FLASH_BASE_ADDR (0x0CAA5400)
|
||||
#define MCU_FREERTOS_HEAP_BASE_ADDR ((uint32_t)&OS_HEAP_START_ADDR)
|
||||
#define MCU_LOG_BASE_ADDR ((uint32_t)&MCU_LOG_START_ADDR)
|
||||
#define MCU_SCMI_BASE_ADDR ((uint32_t)&__SCMI_IPC_START_ADDR)
|
||||
#define MCU_ATCM_ADDR ((uint32_t)&ATCM_START_ADDR)
|
||||
#define MCU_FLASH_START_DDR_ADDR (0x0CAB0000)
|
||||
#define MCU_FLASH_DDR_ADDR ((uint32_t)&FLASH_SEC_ADDR)
|
||||
#define MCU_FREERTOS_HEAP_DDR_ADDR ((uint32_t)&OS_HEAP_START_ADDR)
|
||||
#define MCU_LOG_DDR_ADDR ((uint32_t)&MCU_LOG_START_ADDR)
|
||||
#define MCU_SCMI_DDR_ADDR ((uint32_t)&__SCMI_IPC_START_ADDR)
|
||||
#define MCU_BTCM_ADDR ((uint32_t)&CAN_START_ADDR)
|
||||
#define MCU_FLASH_START_SIZE ((uint32_t)&FLASH_STARTUP_LEN)
|
||||
#define MCU_FLASH_SIZE (0x2AAC00)
|
||||
#define MCU_RTTHREAD_HEAP_ADDR ((uint32_t)&OS_HEAP_START_ADDR)
|
||||
#define MCU_RTTHREAD_HEAP_SIZE ((uint32_t)&OS_HEAP_SIZE)
|
||||
#define MCU_LOG_SIZE ((uint32_t)&MCU_LOG_SIZE)
|
||||
#define MCU_SCMI_SIZE ((uint32_t)&__SCMI_IPC_SIZE)
|
||||
#define MCU_ATCM_SIZE ((uint32_t)&ATCM_SIZE)
|
||||
|
||||
const struct remote_resource_table HB_RESOURCE resources = {
|
||||
/* Version */
|
||||
1,
|
||||
|
||||
/* NUmber of table entries */
|
||||
NUM_TABLE_ENTRIES,
|
||||
/* reserved fields */
|
||||
{0x0, 0x0,},
|
||||
|
||||
/* Offsets of rsc entries */
|
||||
{
|
||||
/* offsetof(struct remote_resource_table, rproc_version), */
|
||||
/* offsetof(struct remote_resource_table, fw_chksum), */
|
||||
/* offsetof(struct remote_resource_table, ddr_devmem), */
|
||||
/* offsetof(struct remote_resource_table, tcm_devmem), */
|
||||
/* offsetof(struct remote_resource_table, rpmsg_vdev), */
|
||||
offsetof(struct remote_resource_table, fw_version),
|
||||
offsetof(struct remote_resource_table, startup_devmem),
|
||||
offsetof(struct remote_resource_table, flash_devmem),
|
||||
offsetof(struct remote_resource_table, freertos_heap_devmem),
|
||||
offsetof(struct remote_resource_table, log_devmem),
|
||||
offsetof(struct remote_resource_table, scmi_devmem),
|
||||
offsetof(struct remote_resource_table, atcm_devmem),
|
||||
},
|
||||
|
||||
{(uint32_t)RSC_VERSION, {0}, {0}, {0}},
|
||||
/* flash_start_mem entry */
|
||||
{(uint32_t)RSC_DEVMEM, MCU_FLASH_START_DDR_ADDR, MCU_FLASH_START_DDR_ADDR, MCU_FLASH_START_SIZE, 0, 0, "startup devmem"},
|
||||
{(uint32_t)RSC_DEVMEM, MCU_FLASH_DDR_ADDR, MCU_FLASH_DDR_ADDR, MCU_FLASH_SIZE, 0, 0, "flash devmem"},
|
||||
{(uint32_t)RSC_DEVMEM, MCU_RTTHREAD_HEAP_ADDR, MCU_RTTHREAD_HEAP_ADDR, MCU_RTTHREAD_HEAP_SIZE, 0, 0, "rtthread_heap devmem"},
|
||||
{(uint32_t)RSC_DEVMEM, MCU_LOG_DDR_ADDR, MCU_LOG_DDR_ADDR, MCU_LOG_SIZE, 0, 0, "log devmem"},
|
||||
{(uint32_t)RSC_DEVMEM, MCU_SCMI_DDR_ADDR, MCU_SCMI_DDR_ADDR, MCU_SCMI_SIZE, 0, 0, "scmi devmem"},
|
||||
{(uint32_t)RSC_DEVMEM, MCU_ATCM_ADDR, MCU_BTCM_ADDR, MCU_ATCM_SIZE, 0, 0, "atcm devmem"},
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Copyright (C) 2015 Xilinx, Inc. All rights reserved.
|
||||
* Copyright (C) 2023, Horizon Robotics
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of Mentor Graphics Corporation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from this
|
||||
* software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This file populates resource table for BM remote
|
||||
* for use by the Linux Master */
|
||||
#ifndef HB_RSC_TABLE_H
|
||||
#define HB_RSC_TABLE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct fw_rsc_version_with_type {
|
||||
uint32_t typefw_rsc_version;
|
||||
uint8_t version[48];
|
||||
uint8_t compile_time[16];
|
||||
uint8_t git_hash_id[40];
|
||||
};
|
||||
|
||||
enum fw_resource_type {
|
||||
RSC_CARVEOUT = 0,
|
||||
RSC_DEVMEM = 1,
|
||||
RSC_TRACE = 2,
|
||||
RSC_VDEV = 3,
|
||||
RSC_RPROC_MEM = 4U,
|
||||
RSC_FW_CHKSUM = 5U,
|
||||
RSC_VERSION = 6U,
|
||||
RSC_LAST = 7U,
|
||||
RSC_VENDOR_START = 128,
|
||||
RSC_VENDOR_END = 512,
|
||||
};
|
||||
|
||||
struct fw_rsc_devmem_with_type {
|
||||
uint32_t typefw_rsc_devmem;
|
||||
uint32_t da;
|
||||
uint32_t pa;
|
||||
uint32_t len;
|
||||
uint32_t flags;
|
||||
uint32_t reserved;
|
||||
uint8_t name[32];
|
||||
};
|
||||
|
||||
#define NO_RESOURCE_ENTRIES (7U)
|
||||
|
||||
/* Resource table for the given remote */
|
||||
struct remote_resource_table {
|
||||
uint32_t version;
|
||||
uint32_t num;
|
||||
uint32_t reserved[2];
|
||||
uint32_t offset[NO_RESOURCE_ENTRIES];
|
||||
struct fw_rsc_version_with_type fw_version; /*PRQA S ALL*/
|
||||
struct fw_rsc_devmem_with_type startup_devmem;
|
||||
struct fw_rsc_devmem_with_type flash_devmem;
|
||||
struct fw_rsc_devmem_with_type freertos_heap_devmem;
|
||||
struct fw_rsc_devmem_with_type log_devmem;
|
||||
struct fw_rsc_devmem_with_type scmi_devmem;
|
||||
struct fw_rsc_devmem_with_type atcm_devmem;
|
||||
}__attribute__((packed, aligned(0x100)));
|
||||
|
||||
extern const struct remote_resource_table resources;
|
||||
|
||||
#endif /* RSC_TABLE_H_ */
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
menu "Onboard Peripheral Drivers"
|
||||
|
||||
config BSP_USING_PINMUX
|
||||
bool "Enable pinmux helper driver"
|
||||
default y
|
||||
help
|
||||
Enable the S100 pinmux and pin configuration helper APIs.
|
||||
|
||||
config BSP_USING_GPIO
|
||||
bool "Enable GPIO/pin driver"
|
||||
default y
|
||||
select RT_USING_PIN
|
||||
help
|
||||
Register the RT-Thread pin device and GPIO interrupt dispatch.
|
||||
|
||||
menuconfig BSP_USING_CAN
|
||||
bool "Enable CAN (S100 FlexCAN)"
|
||||
default y
|
||||
select RT_USING_CAN
|
||||
help
|
||||
Enable the S100 FlexCAN driver using RT-Thread CAN framework.
|
||||
|
||||
if BSP_USING_CAN
|
||||
|
||||
config BSP_USING_CAN5
|
||||
bool "Enable CAN5"
|
||||
default y
|
||||
|
||||
config BSP_USING_CAN6
|
||||
bool "Enable CAN6"
|
||||
default y
|
||||
|
||||
config BSP_USING_CAN7
|
||||
bool "Enable CAN7"
|
||||
default y
|
||||
|
||||
config BSP_USING_CAN8
|
||||
bool "Enable CAN8"
|
||||
default y
|
||||
|
||||
config BSP_USING_CAN9
|
||||
bool "Enable CAN9"
|
||||
default y
|
||||
|
||||
endif
|
||||
|
||||
menuconfig BSP_USING_UART
|
||||
bool "Enable UART"
|
||||
default y
|
||||
depends on RT_USING_SERIAL
|
||||
depends on RT_USING_SERIAL_V2
|
||||
|
||||
if BSP_USING_UART
|
||||
|
||||
config BSP_USING_UART4
|
||||
bool "Enable UART4 (Debugger)"
|
||||
default y
|
||||
|
||||
if BSP_USING_UART4
|
||||
|
||||
config BSP_UART4_RX_BUFSIZE
|
||||
int "Set UART4 RX buffer size"
|
||||
range 64 65535
|
||||
default 1024
|
||||
|
||||
config BSP_UART4_TX_BUFSIZE
|
||||
int "Set UART4 TX buffer size"
|
||||
range 0 65535
|
||||
default 0
|
||||
|
||||
endif
|
||||
|
||||
config BSP_USING_UART5
|
||||
bool "Enable UART5"
|
||||
default n
|
||||
|
||||
if BSP_USING_UART5
|
||||
|
||||
config BSP_UART5_RX_BUFSIZE
|
||||
int "Set UART5 RX buffer size"
|
||||
range 64 65535
|
||||
default 1024
|
||||
|
||||
config BSP_UART5_TX_BUFSIZE
|
||||
int "Set UART5 TX buffer size"
|
||||
range 0 65535
|
||||
default 0
|
||||
|
||||
endif
|
||||
|
||||
config BSP_USING_UART6
|
||||
bool "Enable UART6"
|
||||
default n
|
||||
|
||||
if BSP_USING_UART6
|
||||
|
||||
config BSP_UART6_RX_BUFSIZE
|
||||
int "Set UART6 RX buffer size"
|
||||
range 64 65535
|
||||
default 1024
|
||||
|
||||
config BSP_UART6_TX_BUFSIZE
|
||||
int "Set UART6 TX buffer size"
|
||||
range 0 65535
|
||||
default 0
|
||||
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
endmenu
|
||||
@@ -0,0 +1,28 @@
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
list = os.listdir(cwd)
|
||||
src = []
|
||||
|
||||
src += ['drv_timer.c']
|
||||
|
||||
if GetDepend('BSP_USING_UART'):
|
||||
src += ['drv_uart_v2.c']
|
||||
|
||||
if GetDepend('BSP_USING_PINMUX'):
|
||||
src += ['drv_pinmux.c']
|
||||
|
||||
if GetDepend('BSP_USING_GPIO'):
|
||||
src += ['drv_gpio.c']
|
||||
|
||||
if GetDepend('BSP_USING_CAN'):
|
||||
src += ['drv_can.c']
|
||||
|
||||
objs = DefineGroup('drivers', src, depend=[''], CPPPATH=[cwd])
|
||||
|
||||
for d in list:
|
||||
path = os.path.join(cwd, d)
|
||||
if os.path.isfile(os.path.join(path, 'SConscript')):
|
||||
objs = objs + SConscript(os.path.join(d, 'SConscript'))
|
||||
|
||||
Return('objs')
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
|
||||
#include <rtdevice.h>
|
||||
|
||||
#include "drv_gpio.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
|
||||
#define S100_GPIO_PORT0_BASE 0x23480000U
|
||||
#define S100_GPIO_PORT1_BASE 0x23490000U
|
||||
#define S100_GPIO_PORT2_BASE 0x234A0000U
|
||||
|
||||
#define S100_GPIO_PORT0_IRQ 68
|
||||
#define S100_GPIO_PORT1_IRQ 69
|
||||
#define S100_GPIO_PORT2_IRQ 70
|
||||
|
||||
#define S100_GPIO_PORT_COUNT 3
|
||||
#define S100_GPIO_CHANNELS_PER_PORT 32
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile rt_uint32_t swporta_dr;
|
||||
volatile rt_uint32_t swporta_ddr;
|
||||
volatile rt_uint32_t rsvd0;
|
||||
volatile rt_uint32_t swportb_dr;
|
||||
volatile rt_uint32_t swportb_ddr;
|
||||
volatile rt_uint32_t rsvd1[7];
|
||||
volatile rt_uint32_t inten;
|
||||
volatile rt_uint32_t intmask;
|
||||
volatile rt_uint32_t inttype_level;
|
||||
volatile rt_uint32_t int_polarity;
|
||||
volatile rt_uint32_t intstatus;
|
||||
volatile rt_uint32_t raw_intstatus;
|
||||
volatile rt_uint32_t debounce;
|
||||
volatile rt_uint32_t porta_eoi;
|
||||
volatile rt_uint32_t ext_porta;
|
||||
volatile rt_uint32_t ext_portb;
|
||||
volatile rt_uint32_t rsvd2[2];
|
||||
volatile rt_uint32_t ls_sync;
|
||||
volatile rt_uint32_t id_code;
|
||||
volatile rt_uint32_t int_bothedge;
|
||||
volatile rt_uint32_t ver_id_code;
|
||||
} s100_gpio_reg_t;
|
||||
|
||||
static s100_gpio_reg_t *const s100_gpio_ports[S100_GPIO_PORT_COUNT] =
|
||||
{
|
||||
(s100_gpio_reg_t *)S100_GPIO_PORT0_BASE,
|
||||
(s100_gpio_reg_t *)S100_GPIO_PORT1_BASE,
|
||||
(s100_gpio_reg_t *)S100_GPIO_PORT2_BASE,
|
||||
};
|
||||
|
||||
static const int s100_gpio_port_irqs[S100_GPIO_PORT_COUNT] =
|
||||
{
|
||||
S100_GPIO_PORT0_IRQ,
|
||||
S100_GPIO_PORT1_IRQ,
|
||||
S100_GPIO_PORT2_IRQ,
|
||||
};
|
||||
|
||||
static struct rt_pin_irq_hdr s100_pin_irq_hdr[S100_GPIO_PIN_COUNT];
|
||||
|
||||
static rt_err_t s100_pin_to_gpio(s100_pin_t pin,
|
||||
rt_uint8_t *port_index,
|
||||
rt_uint8_t *bit_index)
|
||||
{
|
||||
rt_uint8_t gpio_pin;
|
||||
|
||||
if (!s100_pin_is_valid(pin))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
/* The MCU GPIO numbering skips pin 79, so pins >= 80 shift by one. */
|
||||
gpio_pin = (pin >= 80U) ? (pin - 1U) : pin;
|
||||
*port_index = gpio_pin / S100_GPIO_CHANNELS_PER_PORT;
|
||||
*bit_index = gpio_pin % S100_GPIO_CHANNELS_PER_PORT;
|
||||
|
||||
if (*port_index >= S100_GPIO_PORT_COUNT)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t s100_gpio_to_pin(rt_uint8_t port_index,
|
||||
rt_uint8_t bit_index,
|
||||
s100_pin_t *pin)
|
||||
{
|
||||
rt_uint8_t gpio_pin;
|
||||
|
||||
if (port_index >= S100_GPIO_PORT_COUNT || bit_index >= S100_GPIO_CHANNELS_PER_PORT)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
gpio_pin = (port_index * S100_GPIO_CHANNELS_PER_PORT) + bit_index;
|
||||
*pin = (gpio_pin >= 79U) ? (gpio_pin + 1U) : gpio_pin;
|
||||
|
||||
if (!s100_pin_is_valid(*pin))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t s100_gpio_config_irq(rt_base_t pin, rt_uint8_t mode)
|
||||
{
|
||||
rt_uint8_t port_index;
|
||||
rt_uint8_t bit_index;
|
||||
rt_uint32_t bit;
|
||||
s100_gpio_reg_t *gpio;
|
||||
rt_err_t ret;
|
||||
|
||||
ret = s100_pin_to_gpio((s100_pin_t)pin, &port_index, &bit_index);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio = s100_gpio_ports[port_index];
|
||||
bit = 1UL << bit_index;
|
||||
|
||||
gpio->inten &= ~bit;
|
||||
gpio->intmask |= bit;
|
||||
gpio->int_bothedge &= ~bit;
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case PIN_IRQ_MODE_RISING:
|
||||
gpio->inttype_level |= bit;
|
||||
gpio->int_polarity |= bit;
|
||||
break;
|
||||
case PIN_IRQ_MODE_FALLING:
|
||||
gpio->inttype_level |= bit;
|
||||
gpio->int_polarity &= ~bit;
|
||||
break;
|
||||
case PIN_IRQ_MODE_RISING_FALLING:
|
||||
gpio->inttype_level |= bit;
|
||||
gpio->int_bothedge |= bit;
|
||||
break;
|
||||
case PIN_IRQ_MODE_HIGH_LEVEL:
|
||||
gpio->inttype_level &= ~bit;
|
||||
gpio->int_polarity |= bit;
|
||||
break;
|
||||
case PIN_IRQ_MODE_LOW_LEVEL:
|
||||
gpio->inttype_level &= ~bit;
|
||||
gpio->int_polarity &= ~bit;
|
||||
break;
|
||||
default:
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
gpio->porta_eoi = bit;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t s100_gpio_set_direction(s100_pin_t pin, s100_pin_direction_t direction)
|
||||
{
|
||||
rt_uint8_t port_index;
|
||||
rt_uint8_t bit_index;
|
||||
rt_uint32_t bit;
|
||||
rt_err_t ret;
|
||||
|
||||
ret = s100_pin_to_gpio(pin, &port_index, &bit_index);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
bit = 1UL << bit_index;
|
||||
if (direction == S100_PIN_DIR_OUT)
|
||||
{
|
||||
s100_gpio_ports[port_index]->swporta_ddr |= bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
s100_gpio_ports[port_index]->swporta_ddr &= ~bit;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t s100_gpio_write_pin(s100_pin_t pin, s100_pin_level_t level)
|
||||
{
|
||||
rt_uint8_t port_index;
|
||||
rt_uint8_t bit_index;
|
||||
rt_uint32_t bit;
|
||||
rt_err_t ret;
|
||||
|
||||
ret = s100_pin_to_gpio(pin, &port_index, &bit_index);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
bit = 1UL << bit_index;
|
||||
if (level == S100_PIN_LEVEL_HIGH)
|
||||
{
|
||||
s100_gpio_ports[port_index]->swporta_dr |= bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
s100_gpio_ports[port_index]->swporta_dr &= ~bit;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t s100_gpio_read_pin(s100_pin_t pin, s100_pin_level_t *level)
|
||||
{
|
||||
rt_uint8_t port_index;
|
||||
rt_uint8_t bit_index;
|
||||
rt_err_t ret;
|
||||
|
||||
if (level == RT_NULL)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
ret = s100_pin_to_gpio(pin, &port_index, &bit_index);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
*level = (s100_gpio_ports[port_index]->ext_porta & (1UL << bit_index)) ?
|
||||
S100_PIN_LEVEL_HIGH : S100_PIN_LEVEL_LOW;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
void s100_gpio_write(rt_uint8_t pin, rt_uint8_t value)
|
||||
{
|
||||
(void)s100_pin_set_function(pin, S100_PIN_FUNC_GPIO);
|
||||
(void)s100_gpio_set_direction(pin, S100_PIN_DIR_OUT);
|
||||
(void)s100_gpio_write_pin(pin, value ? S100_PIN_LEVEL_HIGH : S100_PIN_LEVEL_LOW);
|
||||
}
|
||||
|
||||
rt_uint8_t s100_gpio_read(rt_uint8_t pin)
|
||||
{
|
||||
s100_pin_level_t level = S100_PIN_LEVEL_LOW;
|
||||
|
||||
(void)s100_gpio_read_pin(pin, &level);
|
||||
return (level == S100_PIN_LEVEL_HIGH) ? 1U : 0U;
|
||||
}
|
||||
|
||||
static void s100_pin_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
|
||||
{
|
||||
RT_UNUSED(device);
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case PIN_MODE_OUTPUT:
|
||||
(void)s100_pin_set_function((s100_pin_t)pin, S100_PIN_FUNC_GPIO);
|
||||
(void)s100_gpio_set_direction((s100_pin_t)pin, S100_PIN_DIR_OUT);
|
||||
break;
|
||||
case PIN_MODE_INPUT:
|
||||
(void)s100_pin_set_function((s100_pin_t)pin, S100_PIN_FUNC_GPIO);
|
||||
(void)s100_gpio_set_direction((s100_pin_t)pin, S100_PIN_DIR_IN);
|
||||
(void)s100_pin_set_pull((s100_pin_t)pin, S100_PIN_PULL_NONE);
|
||||
break;
|
||||
case PIN_MODE_INPUT_PULLUP:
|
||||
(void)s100_pin_set_function((s100_pin_t)pin, S100_PIN_FUNC_GPIO);
|
||||
(void)s100_gpio_set_direction((s100_pin_t)pin, S100_PIN_DIR_IN);
|
||||
(void)s100_pin_set_pull((s100_pin_t)pin, S100_PIN_PULL_UP);
|
||||
break;
|
||||
case PIN_MODE_INPUT_PULLDOWN:
|
||||
(void)s100_pin_set_function((s100_pin_t)pin, S100_PIN_FUNC_GPIO);
|
||||
(void)s100_gpio_set_direction((s100_pin_t)pin, S100_PIN_DIR_IN);
|
||||
(void)s100_pin_set_pull((s100_pin_t)pin, S100_PIN_PULL_DOWN);
|
||||
break;
|
||||
case PIN_MODE_OUTPUT_OD:
|
||||
(void)s100_pin_set_function((s100_pin_t)pin, S100_PIN_FUNC_GPIO);
|
||||
(void)s100_gpio_set_direction((s100_pin_t)pin, S100_PIN_DIR_OUT);
|
||||
(void)s100_pin_set_pull((s100_pin_t)pin, S100_PIN_PULL_UP);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void s100_pin_write_device(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
|
||||
{
|
||||
RT_UNUSED(device);
|
||||
(void)s100_gpio_write_pin((s100_pin_t)pin,
|
||||
value ? S100_PIN_LEVEL_HIGH : S100_PIN_LEVEL_LOW);
|
||||
}
|
||||
|
||||
static rt_ssize_t s100_pin_read_device(struct rt_device *device, rt_base_t pin)
|
||||
{
|
||||
s100_pin_level_t level = S100_PIN_LEVEL_LOW;
|
||||
|
||||
RT_UNUSED(device);
|
||||
if (s100_gpio_read_pin((s100_pin_t)pin, &level) != RT_EOK)
|
||||
{
|
||||
return PIN_LOW;
|
||||
}
|
||||
|
||||
return (level == S100_PIN_LEVEL_HIGH) ? PIN_HIGH : PIN_LOW;
|
||||
}
|
||||
|
||||
static rt_err_t s100_pin_attach_irq(struct rt_device *device,
|
||||
rt_base_t pin,
|
||||
rt_uint8_t mode,
|
||||
void (*hdr)(void *args),
|
||||
void *args)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
RT_UNUSED(device);
|
||||
if (!s100_pin_is_valid((s100_pin_t)pin))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
s100_pin_irq_hdr[pin].pin = pin;
|
||||
s100_pin_irq_hdr[pin].mode = mode;
|
||||
s100_pin_irq_hdr[pin].hdr = hdr;
|
||||
s100_pin_irq_hdr[pin].args = args;
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t s100_pin_detach_irq(struct rt_device *device, rt_base_t pin)
|
||||
{
|
||||
rt_base_t level;
|
||||
|
||||
RT_UNUSED(device);
|
||||
if (!s100_pin_is_valid((s100_pin_t)pin))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
level = rt_hw_interrupt_disable();
|
||||
s100_pin_irq_hdr[pin].pin = -1;
|
||||
s100_pin_irq_hdr[pin].mode = 0;
|
||||
s100_pin_irq_hdr[pin].hdr = RT_NULL;
|
||||
s100_pin_irq_hdr[pin].args = RT_NULL;
|
||||
rt_hw_interrupt_enable(level);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t s100_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled)
|
||||
{
|
||||
rt_uint8_t port_index;
|
||||
rt_uint8_t bit_index;
|
||||
rt_uint32_t bit;
|
||||
s100_gpio_reg_t *gpio;
|
||||
rt_err_t ret;
|
||||
|
||||
RT_UNUSED(device);
|
||||
ret = s100_pin_to_gpio((s100_pin_t)pin, &port_index, &bit_index);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio = s100_gpio_ports[port_index];
|
||||
bit = 1UL << bit_index;
|
||||
|
||||
if (enabled == PIN_IRQ_ENABLE)
|
||||
{
|
||||
ret = s100_gpio_config_irq(pin, s100_pin_irq_hdr[pin].mode);
|
||||
if (ret != RT_EOK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
gpio->intmask &= ~bit;
|
||||
gpio->inten |= bit;
|
||||
}
|
||||
else if (enabled == PIN_IRQ_DISABLE)
|
||||
{
|
||||
gpio->intmask |= bit;
|
||||
gpio->inten &= ~bit;
|
||||
gpio->porta_eoi = bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static const struct rt_pin_ops s100_pin_ops =
|
||||
{
|
||||
s100_pin_mode,
|
||||
s100_pin_write_device,
|
||||
s100_pin_read_device,
|
||||
s100_pin_attach_irq,
|
||||
s100_pin_detach_irq,
|
||||
s100_pin_irq_enable,
|
||||
RT_NULL,
|
||||
};
|
||||
|
||||
static void s100_gpio_irq_dispatch(rt_uint8_t port_index)
|
||||
{
|
||||
rt_uint32_t status;
|
||||
rt_uint8_t bit;
|
||||
s100_gpio_reg_t *gpio;
|
||||
|
||||
gpio = s100_gpio_ports[port_index];
|
||||
status = gpio->intstatus;
|
||||
gpio->porta_eoi = status;
|
||||
|
||||
for (bit = 0; bit < S100_GPIO_CHANNELS_PER_PORT; bit++)
|
||||
{
|
||||
s100_pin_t pin;
|
||||
rt_uint32_t mask = 1UL << bit;
|
||||
|
||||
if ((status & mask) == 0U)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s100_gpio_to_pin(port_index, bit, &pin) != RT_EOK)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s100_pin_irq_hdr[pin].hdr != RT_NULL)
|
||||
{
|
||||
s100_pin_irq_hdr[pin].hdr(s100_pin_irq_hdr[pin].args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void s100_gpio_irq0_isr(int vector, void *param)
|
||||
{
|
||||
RT_UNUSED(vector);
|
||||
RT_UNUSED(param);
|
||||
s100_gpio_irq_dispatch(0);
|
||||
}
|
||||
|
||||
static void s100_gpio_irq1_isr(int vector, void *param)
|
||||
{
|
||||
RT_UNUSED(vector);
|
||||
RT_UNUSED(param);
|
||||
s100_gpio_irq_dispatch(1);
|
||||
}
|
||||
|
||||
static void s100_gpio_irq2_isr(int vector, void *param)
|
||||
{
|
||||
RT_UNUSED(vector);
|
||||
RT_UNUSED(param);
|
||||
s100_gpio_irq_dispatch(2);
|
||||
}
|
||||
|
||||
int rt_hw_pin_init(void)
|
||||
{
|
||||
rt_size_t i;
|
||||
rt_isr_handler_t handlers[S100_GPIO_PORT_COUNT] =
|
||||
{
|
||||
s100_gpio_irq0_isr,
|
||||
s100_gpio_irq1_isr,
|
||||
s100_gpio_irq2_isr,
|
||||
};
|
||||
|
||||
for (i = 0; i < S100_GPIO_PIN_COUNT; i++)
|
||||
{
|
||||
s100_pin_irq_hdr[i].pin = -1;
|
||||
s100_pin_irq_hdr[i].mode = 0;
|
||||
s100_pin_irq_hdr[i].hdr = RT_NULL;
|
||||
s100_pin_irq_hdr[i].args = RT_NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Each GPIO block reports through one parent interrupt. The per-pin RT-
|
||||
* Thread callbacks are dispatched in s100_gpio_irq_dispatch() after the
|
||||
* block-level status register is decoded.
|
||||
*/
|
||||
for (i = 0; i < S100_GPIO_PORT_COUNT; i++)
|
||||
{
|
||||
rt_hw_interrupt_install(s100_gpio_port_irqs[i], handlers[i], RT_NULL, "gpio");
|
||||
rt_hw_interrupt_set_triger_mode(s100_gpio_port_irqs[i], IRQ_MODE_TRIG_LEVEL);
|
||||
rt_hw_interrupt_umask(s100_gpio_port_irqs[i]);
|
||||
}
|
||||
|
||||
return rt_device_pin_register("pin", &s100_pin_ops, RT_NULL);
|
||||
}
|
||||
INIT_DEVICE_EXPORT(rt_hw_pin_init);
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef DRV_GPIO_H__
|
||||
#define DRV_GPIO_H__
|
||||
|
||||
#include "drv_pinmux.h"
|
||||
|
||||
/*
|
||||
* MCU GPIO access layer used by both the RT-Thread pin device and simple
|
||||
* board-level helpers.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
S100_PIN_DIR_IN = 0,
|
||||
S100_PIN_DIR_OUT,
|
||||
S100_PIN_DIR_HIGH_Z,
|
||||
} s100_pin_direction_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
S100_PIN_LEVEL_LOW = 0,
|
||||
S100_PIN_LEVEL_HIGH,
|
||||
} s100_pin_level_t;
|
||||
|
||||
rt_err_t s100_gpio_set_direction(s100_pin_t pin, s100_pin_direction_t direction);
|
||||
rt_err_t s100_gpio_write_pin(s100_pin_t pin, s100_pin_level_t level);
|
||||
rt_err_t s100_gpio_read_pin(s100_pin_t pin, s100_pin_level_t *level);
|
||||
|
||||
void s100_gpio_write(rt_uint8_t pin, rt_uint8_t value);
|
||||
rt_uint8_t s100_gpio_read(rt_uint8_t pin);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
|
||||
#include "drv_pinmux.h"
|
||||
|
||||
#define S100_PIN_MUX_REG_BASE 0x234C0060U
|
||||
#define S100_PIN_CONFIG_REG_BASE 0x234D0010U
|
||||
|
||||
#define S100_PORT_IP_NUM 2
|
||||
#define S100_PORT_LLD_IP_NUM 6
|
||||
#define S100_PORT_PIN_NUM (uint8_t)124U
|
||||
#define S100_PORT_MCU_PIN_NUM (uint8_t)88U
|
||||
#define S100_PORT_AON_PIN_NUM (uint8_t)18U
|
||||
|
||||
#define AON_PIN_NUM(aon_gpio_idx) ((aon_gpio_idx) + (S100_PORT_MCU_PIN_NUM))
|
||||
/*
|
||||
* Keep the same MCU GPIO blacklist as the SDK Port subsystem.
|
||||
* These pins are reserved for power/debug or other board-critical uses
|
||||
* and must not be reconfigured as generic GPIO from RT-Thread.
|
||||
*
|
||||
* Note:
|
||||
* The SDK also blacklists a few AON pins. The current cpu1_rtthread BSP
|
||||
* driver only manages MCU GPIO pins, so only the MCU-side blacklist is
|
||||
* enforced here.
|
||||
*/
|
||||
static const s100_pin_t s100_gpio_blacklist[] =
|
||||
{
|
||||
0, /* S100 Power related pins */
|
||||
5, /* S100 debug uart tx */
|
||||
38, /* S100 Power related pins */
|
||||
15, /* S100 Power related pins */
|
||||
68, /* S100 Power related pins */
|
||||
69, /* S100 Power related pins */
|
||||
71, /* S100 Power related pins */
|
||||
80, /* S100 Power related pins */
|
||||
81, /* S100 Power related pins */
|
||||
82, /* S100 Power related pins */
|
||||
83, /* S100 Power related pins */
|
||||
AON_PIN_NUM(0), /* S100 debug uart rx */
|
||||
AON_PIN_NUM(12), /* S100 Power related pins */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
volatile rt_uint32_t reg_pin_mux_func;
|
||||
} s100_pin_mux_reg_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
volatile rt_uint32_t ds : 4;
|
||||
volatile rt_uint32_t ie : 1;
|
||||
volatile rt_uint32_t pd : 1;
|
||||
volatile rt_uint32_t pu : 1;
|
||||
volatile rt_uint32_t st : 1;
|
||||
volatile rt_uint32_t rsvd: 24;
|
||||
} type0;
|
||||
volatile rt_uint32_t value;
|
||||
} s100_pin_cfg_reg_t;
|
||||
|
||||
static s100_pin_mux_reg_t *const s100_pin_mux_regs =
|
||||
(s100_pin_mux_reg_t *)S100_PIN_MUX_REG_BASE;
|
||||
static s100_pin_cfg_reg_t *const s100_pin_cfg_regs =
|
||||
(s100_pin_cfg_reg_t *)S100_PIN_CONFIG_REG_BASE;
|
||||
|
||||
static rt_bool_t s100_pin_is_blacklisted(s100_pin_t pin)
|
||||
{
|
||||
rt_size_t i;
|
||||
|
||||
for (i = 0; i < sizeof(s100_gpio_blacklist) / sizeof(s100_gpio_blacklist[0]); i++)
|
||||
{
|
||||
if (pin == s100_gpio_blacklist[i])
|
||||
{
|
||||
return RT_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
rt_bool_t s100_pin_is_valid(s100_pin_t pin)
|
||||
{
|
||||
if (pin >= S100_GPIO_PIN_COUNT)
|
||||
{
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
/* Pin 79 is a hole in the MCU GPIO numbering and must be skipped. */
|
||||
if (pin == 79U)
|
||||
{
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
if (s100_pin_is_blacklisted(pin) == RT_TRUE)
|
||||
{
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
rt_err_t s100_pin_set_function(s100_pin_t pin, s100_pin_function_t function)
|
||||
{
|
||||
if (!s100_pin_is_valid(pin))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
s100_pin_mux_regs[pin].reg_pin_mux_func = (rt_uint32_t)function & 0x3U;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
rt_err_t s100_pin_set_pull(s100_pin_t pin, s100_pin_pull_t pull)
|
||||
{
|
||||
s100_pin_cfg_reg_t cfg;
|
||||
|
||||
if (!s100_pin_is_valid(pin))
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
cfg = s100_pin_cfg_regs[pin];
|
||||
cfg.type0.ie = 1U;
|
||||
cfg.type0.st = 1U;
|
||||
cfg.type0.pu = 0U;
|
||||
cfg.type0.pd = 0U;
|
||||
|
||||
if (pull == S100_PIN_PULL_UP)
|
||||
{
|
||||
cfg.type0.pu = 1U;
|
||||
}
|
||||
else if (pull == S100_PIN_PULL_DOWN)
|
||||
{
|
||||
cfg.type0.pd = 1U;
|
||||
}
|
||||
|
||||
s100_pin_cfg_regs[pin].value = cfg.value;
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef DRV_PINMUX_H__
|
||||
#define DRV_PINMUX_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
/*
|
||||
* Shared S100 pinctrl helpers.
|
||||
*
|
||||
* GPIO, UART, SPI and other MCU-side drivers can reuse this layer to switch
|
||||
* mux function and electrical attributes without duplicating pin register
|
||||
* knowledge in every peripheral driver.
|
||||
*/
|
||||
typedef rt_uint8_t s100_pin_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
S100_PIN_PULL_NONE = 0,
|
||||
S100_PIN_PULL_DOWN,
|
||||
S100_PIN_PULL_UP,
|
||||
} s100_pin_pull_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
S100_PIN_FUNC0 = 0,
|
||||
S100_PIN_FUNC1,
|
||||
S100_PIN_FUNC2,
|
||||
S100_PIN_FUNC_GPIO,
|
||||
} s100_pin_function_t;
|
||||
|
||||
#define S100_GPIO_PIN_COUNT 88U
|
||||
|
||||
/* Returns RT_FALSE for reserved/unsupported pins, including the SDK blacklist. */
|
||||
rt_bool_t s100_pin_is_valid(s100_pin_t pin);
|
||||
rt_err_t s100_pin_set_function(s100_pin_t pin, s100_pin_function_t function);
|
||||
rt_err_t s100_pin_set_pull(s100_pin_t pin, s100_pin_pull_t pull);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#define S100_SYSCNT_BASE 0x23110000U
|
||||
#define S100_SYSCNT_CTRL_OSCON_MASK (0x1U)
|
||||
#define S100_SYSCNT_CLK_HZ (40000000U)
|
||||
#define S100_GENERIC_TIMER_PPI 30
|
||||
|
||||
#define CNTP_CTL_ENABLE (1U << 0)
|
||||
|
||||
struct s100_syscnt
|
||||
{
|
||||
volatile rt_uint32_t ctrl;
|
||||
volatile rt_uint32_t stat;
|
||||
volatile rt_uint32_t cntcvl;
|
||||
volatile rt_uint32_t cntcvu;
|
||||
rt_uint8_t reserved[16];
|
||||
volatile rt_uint32_t cntfid0;
|
||||
};
|
||||
|
||||
static volatile struct s100_syscnt *const s100_syscnt =
|
||||
(volatile struct s100_syscnt *)S100_SYSCNT_BASE;
|
||||
|
||||
static rt_uint32_t s100_tick_interval;
|
||||
static rt_uint64_t s100_read_cntpct(void)
|
||||
{
|
||||
rt_uint32_t low;
|
||||
rt_uint32_t high;
|
||||
|
||||
__asm volatile ("mrrc p15, 0, %0, %1, c14" : "=r"(low), "=r"(high));
|
||||
|
||||
return (((rt_uint64_t)high) << 32) | low;
|
||||
}
|
||||
|
||||
static void s100_write_cntp_cval(rt_uint64_t value)
|
||||
{
|
||||
rt_uint32_t low = (rt_uint32_t)value;
|
||||
rt_uint32_t high = (rt_uint32_t)(value >> 32);
|
||||
|
||||
__asm volatile ("mcrr p15, 2, %0, %1, c14" :: "r"(low), "r"(high));
|
||||
}
|
||||
|
||||
static void s100_write_cntp_ctl(rt_uint32_t value)
|
||||
{
|
||||
__asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r"(value));
|
||||
}
|
||||
|
||||
static void s100_program_next_tick(rt_uint32_t delta)
|
||||
{
|
||||
s100_write_cntp_cval(s100_read_cntpct() + delta);
|
||||
}
|
||||
|
||||
static void rt_hw_timer_isr(int vector, void *param)
|
||||
{
|
||||
RT_UNUSED(vector);
|
||||
RT_UNUSED(param);
|
||||
|
||||
s100_program_next_tick(s100_tick_interval);
|
||||
rt_tick_increase();
|
||||
}
|
||||
|
||||
int rt_hw_timer_init(void)
|
||||
{
|
||||
s100_tick_interval = S100_SYSCNT_CLK_HZ / RT_TICK_PER_SECOND;
|
||||
RT_ASSERT(s100_tick_interval > 0U);
|
||||
|
||||
s100_syscnt->cntfid0 = S100_SYSCNT_CLK_HZ;
|
||||
s100_syscnt->ctrl |= S100_SYSCNT_CTRL_OSCON_MASK;
|
||||
|
||||
s100_write_cntp_ctl(0U);
|
||||
s100_program_next_tick(s100_tick_interval);
|
||||
s100_write_cntp_ctl(CNTP_CTL_ENABLE);
|
||||
|
||||
rt_hw_interrupt_install(S100_GENERIC_TIMER_PPI, rt_hw_timer_isr, RT_NULL, "tick");
|
||||
rt_hw_interrupt_umask(S100_GENERIC_TIMER_PPI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
INIT_BOARD_EXPORT(rt_hw_timer_init);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
from building import *
|
||||
|
||||
src = []
|
||||
|
||||
if GetDepend('BSP_USING_GPIO'):
|
||||
src += ['test_gpio.c']
|
||||
|
||||
if GetDepend('BSP_USING_CAN5') or GetDepend('BSP_USING_CAN6') or GetDepend('BSP_USING_CAN7') or GetDepend('BSP_USING_CAN8') or GetDepend('BSP_USING_CAN9'):
|
||||
src += ['test_can.c']
|
||||
|
||||
if GetDepend('BSP_USING_UART'):
|
||||
src += ['test_uart.c']
|
||||
|
||||
group = DefineGroup('utestcases', src, depend = ['RT_UTEST_DRIVERS_CORE'])
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
|
||||
#include <rtdevice.h>
|
||||
#include <utest.h>
|
||||
|
||||
/*
|
||||
* S100 CAN utest 说明
|
||||
*
|
||||
* 1. 本测试面向当前 rdk/s100 BSP 的 RT-Thread CAN 设备驱动,覆盖设备发现、
|
||||
* open、配置、模式切换、发送、接收、状态读取和 close 的基础路径。
|
||||
* 2. 为避免依赖外部 CAN 对端,本测试使用驱动支持的 RT_CAN_MODE_LOOPBACK 内部回环模式。
|
||||
* 因此测试默认不要求外部收发器回环或两节点组网。
|
||||
* 3. 测试对象仅包含当前配置中启用的 can5/can6/can7/can8/can9。
|
||||
* 4. 发送内容使用一帧标准数据帧(11-bit ID,8 字节 payload),接收后逐字段校验:
|
||||
* - IDE/RTR
|
||||
* - 标准 ID
|
||||
* - DLC
|
||||
* - data[0..7]
|
||||
* 5. 若需要改成外部总线联调,请把 loopback 模式切回 normal,并去掉本用例的回环假设。
|
||||
*/
|
||||
|
||||
static const struct rt_can_msg s100_can_test_msg =
|
||||
{
|
||||
.id = 0x123,
|
||||
.ide = RT_CAN_STDID,
|
||||
.rtr = RT_CAN_DTR,
|
||||
.len = 8,
|
||||
.priv = 0,
|
||||
.hdr_index = -1,
|
||||
.rxfifo = 0,
|
||||
.reserved = 0,
|
||||
.nonblocking = 0,
|
||||
.data = {0x55, 0xAA, 0x00, 0xFF, 0x11, 0x22, 0x33, 0x44},
|
||||
};
|
||||
|
||||
struct s100_can_test_port
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#if defined(BSP_USING_CAN5) || defined(BSP_USING_CAN6) || defined(BSP_USING_CAN7) || defined(BSP_USING_CAN8) || defined(BSP_USING_CAN9)
|
||||
static const struct s100_can_test_port s100_can_test_ports[] =
|
||||
{
|
||||
#ifdef BSP_USING_CAN5
|
||||
{ "can5" },
|
||||
#endif
|
||||
#ifdef BSP_USING_CAN6
|
||||
{ "can6" },
|
||||
#endif
|
||||
#ifdef BSP_USING_CAN7
|
||||
{ "can7" },
|
||||
#endif
|
||||
#ifdef BSP_USING_CAN8
|
||||
{ "can8" },
|
||||
#endif
|
||||
#ifdef BSP_USING_CAN9
|
||||
{ "can9" },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define S100_CAN_TEST_PORT_COUNT \
|
||||
(sizeof(s100_can_test_ports) / sizeof(s100_can_test_ports[0]))
|
||||
#else
|
||||
static const struct s100_can_test_port s100_can_test_ports[] =
|
||||
{
|
||||
{ RT_NULL },
|
||||
};
|
||||
|
||||
#define S100_CAN_TEST_PORT_COUNT 0u
|
||||
#endif
|
||||
|
||||
static void s100_can_prepare_config(struct can_configure *cfg)
|
||||
{
|
||||
RT_ASSERT(cfg != RT_NULL);
|
||||
|
||||
cfg->baud_rate = CAN1MBaud;
|
||||
cfg->mode = RT_CAN_MODE_LOOPBACK;
|
||||
cfg->privmode = RT_CAN_MODE_NOPRIV;
|
||||
}
|
||||
|
||||
static void s100_can_check_port_basic(const char *name)
|
||||
{
|
||||
rt_device_t can_dev;
|
||||
struct can_configure cfg = CANDEFAULTCONFIG;
|
||||
struct rt_can_status status;
|
||||
rt_err_t ret;
|
||||
|
||||
can_dev = rt_device_find(name);
|
||||
uassert_not_null(can_dev);
|
||||
|
||||
s100_can_prepare_config(&cfg);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_DEVICE_CTRL_CONFIG, &cfg);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_LOOPBACK);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_CAN_CMD_GET_STATUS, &status);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_close(can_dev);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
}
|
||||
|
||||
static void s100_can_check_port_loopback(const char *name)
|
||||
{
|
||||
rt_device_t can_dev;
|
||||
struct can_configure cfg = CANDEFAULTCONFIG;
|
||||
struct rt_can_msg rx_msg;
|
||||
rt_err_t ret;
|
||||
rt_ssize_t wr_len;
|
||||
rt_ssize_t rd_len;
|
||||
rt_size_t i;
|
||||
|
||||
can_dev = rt_device_find(name);
|
||||
uassert_not_null(can_dev);
|
||||
|
||||
s100_can_prepare_config(&cfg);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_DEVICE_CTRL_CONFIG, &cfg);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_LOOPBACK);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(can_dev, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
rt_memset(&rx_msg, 0, sizeof(rx_msg));
|
||||
|
||||
rt_kprintf("%s tx can id=0x%03X len=%d\n", name, (unsigned int)s100_can_test_msg.id, (int)s100_can_test_msg.len);
|
||||
LOG_HEX("can.tx", 16, s100_can_test_msg.data, s100_can_test_msg.len);
|
||||
|
||||
wr_len = rt_device_write(can_dev, 0, &s100_can_test_msg, sizeof(s100_can_test_msg));
|
||||
uassert_int_equal((int)wr_len, (int)sizeof(s100_can_test_msg));
|
||||
|
||||
rd_len = rt_device_read(can_dev, 0, &rx_msg, sizeof(rx_msg));
|
||||
uassert_int_equal((int)rd_len, (int)sizeof(rx_msg));
|
||||
|
||||
rt_kprintf("%s rx can id=0x%03X len=%d\n", name, (unsigned int)rx_msg.id, (int)rx_msg.len);
|
||||
LOG_HEX("can.rx", 16, rx_msg.data, rx_msg.len);
|
||||
|
||||
uassert_int_equal((int)rx_msg.ide, (int)s100_can_test_msg.ide);
|
||||
uassert_int_equal((int)rx_msg.rtr, (int)s100_can_test_msg.rtr);
|
||||
uassert_int_equal((int)rx_msg.id, (int)s100_can_test_msg.id);
|
||||
uassert_int_equal((int)rx_msg.len, (int)s100_can_test_msg.len);
|
||||
|
||||
for (i = 0; i < s100_can_test_msg.len; i++)
|
||||
{
|
||||
rt_kprintf("%s compare[%d]: tx=0x%02X rx=0x%02X\n",
|
||||
name,
|
||||
(int)i,
|
||||
s100_can_test_msg.data[i],
|
||||
rx_msg.data[i]);
|
||||
uassert_int_equal((int)rx_msg.data[i], (int)s100_can_test_msg.data[i]);
|
||||
}
|
||||
|
||||
ret = rt_device_close(can_dev);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
}
|
||||
|
||||
static void can_basic_demo(void)
|
||||
{
|
||||
rt_size_t i;
|
||||
|
||||
if (S100_CAN_TEST_PORT_COUNT == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < S100_CAN_TEST_PORT_COUNT; i++)
|
||||
{
|
||||
s100_can_check_port_basic(s100_can_test_ports[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void can_loopback_demo(void)
|
||||
{
|
||||
rt_size_t i;
|
||||
|
||||
if (S100_CAN_TEST_PORT_COUNT == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < S100_CAN_TEST_PORT_COUNT; i++)
|
||||
{
|
||||
s100_can_check_port_loopback(s100_can_test_ports[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void can_testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(can_basic_demo);
|
||||
UTEST_UNIT_RUN(can_loopback_demo);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(can_testcase, "rdk.s100.drivers.can", utest_tc_init, utest_tc_cleanup, 20);
|
||||
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
#include <rtdevice.h>
|
||||
#include <utest.h>
|
||||
|
||||
#include "drv_gpio.h"
|
||||
#include "drv_pinmux.h"
|
||||
|
||||
/*
|
||||
* S100 GPIO utest 说明
|
||||
*
|
||||
* 1. 本文件合并了原先独立的 GPIO 基础功能测试和 GPIO IRQ 测试,统一面向当前
|
||||
* rdk/s100 BSP 的 RT-Thread pin 驱动接口。
|
||||
* 2. 测试维度按驱动能力组织:
|
||||
* - driver basic:校验 s100 私有驱动对非法/保留 pin 的拒绝逻辑;
|
||||
* - pin io loopback:校验 rt_pin_mode/write/read 基础输入输出路径;
|
||||
* - pin irq loopback:校验 rt_pin_attach_irq/irq_enable 在上升沿、下降沿、
|
||||
* 双边沿模式下的中断分发行为。
|
||||
* 3. 为了避免依赖旧板级 LED/KEY 资源,IO/IRQ 测试采用“一个输出脚 + 一个输入脚”
|
||||
* 的跳线回环方式。运行前请用杜邦线连接测试输出脚和测试输入脚。
|
||||
* 4. 默认使用 GPIO36 作为输出、GPIO37 作为输入;它们在当前 s100 驱动的黑名单和
|
||||
* 空洞编号之外。若板级接线需要变更,可在编译时覆盖下面两个宏。
|
||||
* 5. IRQ 测试通过切换输出脚电平来触发输入脚中断,因此不需要人工按键操作。
|
||||
*/
|
||||
|
||||
#ifndef S100_GPIO_TEST_OUT_PIN
|
||||
#define S100_GPIO_TEST_OUT_PIN 36
|
||||
#endif
|
||||
|
||||
#ifndef S100_GPIO_TEST_IN_PIN
|
||||
#define S100_GPIO_TEST_IN_PIN 37
|
||||
#endif
|
||||
|
||||
#define S100_GPIO_INVALID_PIN 79
|
||||
#define S100_GPIO_RESERVED_PIN 0
|
||||
#define S100_GPIO_SETTLE_DELAY_MS 2
|
||||
#define S100_GPIO_IRQ_TIMEOUT_TICKS (RT_TICK_PER_SECOND / 2)
|
||||
|
||||
static struct rt_completion s100_gpio_irq_completion;
|
||||
static volatile rt_uint32_t s100_gpio_irq_count;
|
||||
|
||||
static void s100_gpio_irq_handler(void *args)
|
||||
{
|
||||
RT_UNUSED(args);
|
||||
s100_gpio_irq_count++;
|
||||
rt_completion_done(&s100_gpio_irq_completion);
|
||||
}
|
||||
|
||||
static void s100_gpio_prepare_loopback(void)
|
||||
{
|
||||
uassert_true(s100_pin_is_valid(S100_GPIO_TEST_OUT_PIN) == RT_TRUE);
|
||||
uassert_true(s100_pin_is_valid(S100_GPIO_TEST_IN_PIN) == RT_TRUE);
|
||||
uassert_true(S100_GPIO_TEST_OUT_PIN != S100_GPIO_TEST_IN_PIN);
|
||||
|
||||
rt_pin_mode(S100_GPIO_TEST_OUT_PIN, PIN_MODE_OUTPUT);
|
||||
rt_pin_mode(S100_GPIO_TEST_IN_PIN, PIN_MODE_INPUT);
|
||||
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_LOW);
|
||||
rt_thread_mdelay(S100_GPIO_SETTLE_DELAY_MS);
|
||||
}
|
||||
|
||||
static void s100_gpio_cleanup_irq(rt_base_t pin)
|
||||
{
|
||||
rt_err_t ret;
|
||||
|
||||
ret = rt_pin_irq_enable(pin, PIN_IRQ_DISABLE);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_pin_detach_irq(pin);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
}
|
||||
|
||||
static void s100_gpio_wait_irq_once(void)
|
||||
{
|
||||
rt_err_t ret;
|
||||
|
||||
ret = rt_completion_wait(&s100_gpio_irq_completion, S100_GPIO_IRQ_TIMEOUT_TICKS);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
}
|
||||
|
||||
static void s100_gpio_trigger_rising(void)
|
||||
{
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_LOW);
|
||||
rt_thread_mdelay(S100_GPIO_SETTLE_DELAY_MS);
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_HIGH);
|
||||
}
|
||||
|
||||
static void s100_gpio_trigger_falling(void)
|
||||
{
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_HIGH);
|
||||
rt_thread_mdelay(S100_GPIO_SETTLE_DELAY_MS);
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_LOW);
|
||||
}
|
||||
|
||||
static void gpio_driver_rejects_invalid_pins(void)
|
||||
{
|
||||
rt_err_t ret;
|
||||
|
||||
uassert_true(s100_pin_is_valid(S100_GPIO_INVALID_PIN) == RT_FALSE);
|
||||
uassert_true(s100_pin_is_valid(S100_GPIO_RESERVED_PIN) == RT_FALSE);
|
||||
|
||||
ret = s100_gpio_set_direction(S100_GPIO_INVALID_PIN, S100_PIN_DIR_OUT);
|
||||
uassert_int_equal(ret, -RT_EINVAL);
|
||||
|
||||
ret = s100_gpio_write_pin(S100_GPIO_INVALID_PIN, S100_PIN_LEVEL_HIGH);
|
||||
uassert_int_equal(ret, -RT_EINVAL);
|
||||
|
||||
ret = s100_gpio_set_direction(S100_GPIO_RESERVED_PIN, S100_PIN_DIR_OUT);
|
||||
uassert_int_equal(ret, -RT_EINVAL);
|
||||
}
|
||||
|
||||
static void gpio_loopback_io(void)
|
||||
{
|
||||
rt_ssize_t level;
|
||||
|
||||
s100_gpio_prepare_loopback();
|
||||
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_LOW);
|
||||
rt_thread_mdelay(S100_GPIO_SETTLE_DELAY_MS);
|
||||
level = rt_pin_read(S100_GPIO_TEST_IN_PIN);
|
||||
uassert_int_equal(level, PIN_LOW);
|
||||
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_HIGH);
|
||||
rt_thread_mdelay(S100_GPIO_SETTLE_DELAY_MS);
|
||||
level = rt_pin_read(S100_GPIO_TEST_IN_PIN);
|
||||
uassert_int_equal(level, PIN_HIGH);
|
||||
|
||||
rt_pin_write(S100_GPIO_TEST_OUT_PIN, PIN_LOW);
|
||||
}
|
||||
|
||||
static void gpio_irq_rising_loopback(void)
|
||||
{
|
||||
rt_err_t ret;
|
||||
|
||||
s100_gpio_prepare_loopback();
|
||||
rt_completion_init(&s100_gpio_irq_completion);
|
||||
s100_gpio_irq_count = 0;
|
||||
|
||||
ret = rt_pin_attach_irq(S100_GPIO_TEST_IN_PIN, PIN_IRQ_MODE_RISING,
|
||||
s100_gpio_irq_handler, RT_NULL);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_pin_irq_enable(S100_GPIO_TEST_IN_PIN, PIN_IRQ_ENABLE);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
s100_gpio_trigger_rising();
|
||||
s100_gpio_wait_irq_once();
|
||||
uassert_int_equal((int)s100_gpio_irq_count, 1);
|
||||
|
||||
s100_gpio_cleanup_irq(S100_GPIO_TEST_IN_PIN);
|
||||
}
|
||||
|
||||
static void gpio_irq_falling_loopback(void)
|
||||
{
|
||||
rt_err_t ret;
|
||||
|
||||
s100_gpio_prepare_loopback();
|
||||
rt_completion_init(&s100_gpio_irq_completion);
|
||||
s100_gpio_irq_count = 0;
|
||||
|
||||
ret = rt_pin_attach_irq(S100_GPIO_TEST_IN_PIN, PIN_IRQ_MODE_FALLING,
|
||||
s100_gpio_irq_handler, RT_NULL);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_pin_irq_enable(S100_GPIO_TEST_IN_PIN, PIN_IRQ_ENABLE);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
s100_gpio_trigger_falling();
|
||||
s100_gpio_wait_irq_once();
|
||||
uassert_int_equal((int)s100_gpio_irq_count, 1);
|
||||
|
||||
s100_gpio_cleanup_irq(S100_GPIO_TEST_IN_PIN);
|
||||
}
|
||||
|
||||
static void gpio_irq_both_edge_loopback(void)
|
||||
{
|
||||
rt_err_t ret;
|
||||
|
||||
s100_gpio_prepare_loopback();
|
||||
rt_completion_init(&s100_gpio_irq_completion);
|
||||
s100_gpio_irq_count = 0;
|
||||
|
||||
ret = rt_pin_attach_irq(S100_GPIO_TEST_IN_PIN, PIN_IRQ_MODE_RISING_FALLING,
|
||||
s100_gpio_irq_handler, RT_NULL);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_pin_irq_enable(S100_GPIO_TEST_IN_PIN, PIN_IRQ_ENABLE);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
s100_gpio_trigger_rising();
|
||||
s100_gpio_wait_irq_once();
|
||||
|
||||
rt_completion_init(&s100_gpio_irq_completion);
|
||||
s100_gpio_trigger_falling();
|
||||
s100_gpio_wait_irq_once();
|
||||
|
||||
uassert_int_equal((int)s100_gpio_irq_count, 2);
|
||||
|
||||
s100_gpio_cleanup_irq(S100_GPIO_TEST_IN_PIN);
|
||||
}
|
||||
|
||||
static void testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(gpio_driver_rejects_invalid_pins);
|
||||
UTEST_UNIT_RUN(gpio_loopback_io);
|
||||
UTEST_UNIT_RUN(gpio_irq_rising_loopback);
|
||||
UTEST_UNIT_RUN(gpio_irq_falling_loopback);
|
||||
UTEST_UNIT_RUN(gpio_irq_both_edge_loopback);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(testcase, "rdk.s100.drivers.gpio", utest_tc_init, utest_tc_cleanup, 20);
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2026-04-20 rcitach first version
|
||||
*/
|
||||
|
||||
#include <rtdevice.h>
|
||||
#include <rtdbg.h>
|
||||
#include <utest.h>
|
||||
|
||||
/*
|
||||
* S100 UART utest 说明
|
||||
*
|
||||
* 1. 本测试面向当前 BSP 的 UART v2 驱动实现,覆盖非控制台串口的基础访问流程。
|
||||
* 2. 根据 BSP 约定,uart4 默认为 msh 控制台,本测试不会对 uart4 做 open/read/write
|
||||
* 覆盖,避免干扰交互终端。
|
||||
* 3. 测试对象仅包含启用的 uart5 和 uart6;若两者都未使能,测试会打印跳过提示。
|
||||
* 4. 测试分为两部分:
|
||||
* - basic:验证 rt_device_find/open/control(close) 这条基础控制路径;
|
||||
* - txrx smoke:验证配置成功后能够执行一次 write,并检查 read 接口可调用。
|
||||
* 5. 当前 S100 UART BSP 不支持 DMA,因此这里不覆盖 DMA 模式。
|
||||
* 6. txrx smoke 现在要求被测串口具备回环条件(硬件短接 TX/RX 或外部回环),测试会校验
|
||||
* 接收到的数据内容与发送 payload 完全一致。
|
||||
*/
|
||||
|
||||
#define S100_UART_TEST_BAUD_RATE 115200
|
||||
#define S100_UART_READ_BUF_SIZE 16
|
||||
#define S100_UART_RX_TIMEOUT_TICKS (RT_TICK_PER_SECOND / 2)
|
||||
|
||||
static const rt_uint8_t s100_uart_test_frame[] =
|
||||
{
|
||||
0x55, 0xAA, 0x00, 0xFF, 0x31, 0x32, 0x33, 0x0D, 0x0A,
|
||||
};
|
||||
|
||||
struct s100_uart_test_port
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
#if defined(BSP_USING_UART5) || defined(BSP_USING_UART6)
|
||||
static const struct s100_uart_test_port s100_uart_test_ports[] =
|
||||
{
|
||||
#ifdef BSP_USING_UART5
|
||||
{ "uart5" },
|
||||
#endif
|
||||
#ifdef BSP_USING_UART6
|
||||
{ "uart6" },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define S100_UART_TEST_PORT_COUNT \
|
||||
(sizeof(s100_uart_test_ports) / sizeof(s100_uart_test_ports[0]))
|
||||
#else
|
||||
static const struct s100_uart_test_port s100_uart_test_ports[] =
|
||||
{
|
||||
{ RT_NULL },
|
||||
};
|
||||
|
||||
#define S100_UART_TEST_PORT_COUNT 0u
|
||||
#endif
|
||||
|
||||
static void s100_uart_prepare_config(struct serial_configure *config)
|
||||
{
|
||||
RT_ASSERT(config != RT_NULL);
|
||||
|
||||
config->baud_rate = S100_UART_TEST_BAUD_RATE;
|
||||
config->data_bits = DATA_BITS_8;
|
||||
config->stop_bits = STOP_BITS_1;
|
||||
config->parity = PARITY_NONE;
|
||||
config->flowcontrol = RT_SERIAL_FLOWCONTROL_NONE;
|
||||
}
|
||||
|
||||
static void s100_uart_check_port_basic(const char *name)
|
||||
{
|
||||
rt_device_t uart_dev;
|
||||
struct serial_configure config;
|
||||
rt_err_t ret;
|
||||
|
||||
uart_dev = rt_device_find(name);
|
||||
uassert_not_null(uart_dev);
|
||||
|
||||
ret = rt_device_control(uart_dev, RT_SERIAL_CTRL_GET_CONFIG, &config);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
s100_uart_prepare_config(&config);
|
||||
|
||||
ret = rt_device_open(uart_dev, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(uart_dev, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_close(uart_dev);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
}
|
||||
|
||||
static void s100_uart_check_port_txrx_smoke(const char *name)
|
||||
{
|
||||
rt_uint8_t rx_buf[sizeof(s100_uart_test_frame)];
|
||||
rt_device_t uart_dev;
|
||||
struct serial_configure config;
|
||||
rt_err_t ret;
|
||||
rt_ssize_t len;
|
||||
rt_size_t rx_total;
|
||||
rt_size_t i;
|
||||
rt_tick_t deadline;
|
||||
|
||||
uart_dev = rt_device_find(name);
|
||||
uassert_not_null(uart_dev);
|
||||
|
||||
ret = rt_device_control(uart_dev, RT_SERIAL_CTRL_GET_CONFIG, &config);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
s100_uart_prepare_config(&config);
|
||||
|
||||
ret = rt_device_open(uart_dev, RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
ret = rt_device_control(uart_dev, RT_DEVICE_CTRL_CONFIG, &config);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
|
||||
LOG_HEX("uart.tx", 16, s100_uart_test_frame, sizeof(s100_uart_test_frame));
|
||||
len = rt_device_write(uart_dev, 0, s100_uart_test_frame, sizeof(s100_uart_test_frame));
|
||||
uassert_int_equal(len, (rt_ssize_t)sizeof(s100_uart_test_frame));
|
||||
|
||||
rx_total = 0;
|
||||
deadline = rt_tick_get() + S100_UART_RX_TIMEOUT_TICKS;
|
||||
while ((rx_total < sizeof(s100_uart_test_frame)) && (rt_tick_get() < deadline))
|
||||
{
|
||||
len = rt_device_read(uart_dev, 0, rx_buf + rx_total, sizeof(s100_uart_test_frame) - rx_total);
|
||||
uassert_true(len >= 0);
|
||||
|
||||
if (len == 0)
|
||||
{
|
||||
rt_thread_mdelay(10);
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG_HEX("uart.rx.chunk", 16, rx_buf + rx_total, (rt_size_t)len);
|
||||
rx_total += (rt_size_t)len;
|
||||
}
|
||||
|
||||
if (rx_total > 0)
|
||||
{
|
||||
LOG_HEX("uart.rx.total", 16, rx_buf, rx_total);
|
||||
}
|
||||
|
||||
uassert_int_equal((int)rx_total, (int)sizeof(s100_uart_test_frame));
|
||||
for (i = 0; i < sizeof(s100_uart_test_frame); i++)
|
||||
{
|
||||
rt_kprintf("%s compare[%d]: tx=0x%02X rx=0x%02X\n",
|
||||
name,
|
||||
(int)i,
|
||||
s100_uart_test_frame[i],
|
||||
rx_buf[i]);
|
||||
uassert_int_equal((int)rx_buf[i], (int)s100_uart_test_frame[i]);
|
||||
}
|
||||
|
||||
ret = rt_device_close(uart_dev);
|
||||
uassert_int_equal(ret, RT_EOK);
|
||||
}
|
||||
|
||||
static void uart_non_console_basic_demo(void)
|
||||
{
|
||||
rt_size_t i;
|
||||
|
||||
if (S100_UART_TEST_PORT_COUNT == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < S100_UART_TEST_PORT_COUNT; i++)
|
||||
{
|
||||
s100_uart_check_port_basic(s100_uart_test_ports[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_non_console_txrx_demo(void)
|
||||
{
|
||||
rt_size_t i;
|
||||
|
||||
if (S100_UART_TEST_PORT_COUNT == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < S100_UART_TEST_PORT_COUNT; i++)
|
||||
{
|
||||
s100_uart_check_port_txrx_smoke(s100_uart_test_ports[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_testcase(void)
|
||||
{
|
||||
UTEST_UNIT_RUN(uart_non_console_basic_demo);
|
||||
UTEST_UNIT_RUN(uart_non_console_txrx_demo);
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_init(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t utest_tc_cleanup(void)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
UTEST_TC_EXPORT(uart_testcase, "rdk.s100.drivers.uart", utest_tc_init, utest_tc_cleanup, 10);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* S100 MCU1 linker script for RT-Thread on Cortex-R52.
|
||||
*
|
||||
* This keeps the current MCU1 memory layout from the FreeRTOS image and
|
||||
* adds the symbols/sections RT-Thread's Cortex-R52 GCC port expects.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(EL2_core_exceptions_table)
|
||||
|
||||
STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : 0x0000C000;
|
||||
STACK_SIZE_EXC = DEFINED(__stack_size_exc__) ? __stack_size_exc__ : 0x0000C000;
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH_STARTUP (rx) : ORIGIN = 0x0CAB0000, LENGTH = 4K
|
||||
FLASH (rwx) : ORIGIN = 0x0CAB1000, LENGTH = 2154K
|
||||
RTOS_HEAP (rw) : ORIGIN = 0x0CCCB000, LENGTH = 512K
|
||||
CAN_Reserved (rw) : ORIGIN = 0x0CD4B000, LENGTH = 64K
|
||||
LOG_SHARE_Reserved (rw) : ORIGIN = 0x0CD5B000, LENGTH = 8K
|
||||
SCMI_IPC_Reserved (rw) : ORIGIN = 0x0CD5D000, LENGTH = 12K
|
||||
ATCM_Reserved (rwx) : ORIGIN = 0x0A000000, LENGTH = 64K
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.startup :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
__startup_start = .;
|
||||
KEEP(*(.EL2_core_exceptions_table))
|
||||
|
||||
. = ALIGN(32);
|
||||
KEEP(*(.EL1_core_exceptions_table))
|
||||
|
||||
. = ALIGN(32);
|
||||
KEEP(*(.EL2_Reset_Handler))
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.text.entrypoint))
|
||||
KEEP(*(.vectors))
|
||||
|
||||
. = ALIGN(32);
|
||||
__startup_end = .;
|
||||
} > FLASH_STARTUP
|
||||
|
||||
.text :
|
||||
{
|
||||
PROVIDE(__text_start = .);
|
||||
*(.text) /* remaining code */
|
||||
*(.text.*) /* remaining code */
|
||||
*(.glue_7)
|
||||
*(.glue_7t)
|
||||
|
||||
/* section information for utest */
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__rt_utest_tc_tab_start = .);
|
||||
KEEP(*(UtestTcTab))
|
||||
PROVIDE(__rt_utest_tc_tab_end = .);
|
||||
|
||||
/* section information for finsh shell */
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__fsymtab_start = .);
|
||||
KEEP(*(FSymTab))
|
||||
PROVIDE(__fsymtab_end = .);
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__vsymtab_start = .);
|
||||
KEEP(*(VSymTab))
|
||||
PROVIDE(__vsymtab_end = .);
|
||||
. = ALIGN(8);
|
||||
|
||||
/* section information for modules */
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__rtmsymtab_start = .);
|
||||
KEEP(*(RTMSymTab))
|
||||
PROVIDE(__rtmsymtab_end = .);
|
||||
|
||||
/* section information for initialization */
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__rt_init_start = .);
|
||||
KEEP(*(SORT(.rti_fn*)))
|
||||
PROVIDE(__rt_init_end = .);
|
||||
|
||||
/* section information for usb usbh_class_info */
|
||||
. = ALIGN(4);
|
||||
__usbh_class_info_start__ = .;
|
||||
KEEP(*(.usbh_class_info))
|
||||
. = ALIGN(4);
|
||||
__usbh_class_info_end__ = .;
|
||||
|
||||
PROVIDE(__text_end = .);
|
||||
} > FLASH
|
||||
|
||||
.resource_table :
|
||||
{
|
||||
. = ALIGN(8);
|
||||
__resource_table_start = .;
|
||||
KEEP(*(.resource_table))
|
||||
KEEP(*(.resource_table.*))
|
||||
. = ALIGN(8);
|
||||
__resource_table_end = .;
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
.ARM.exidx :
|
||||
{
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
__exidx_end = .;
|
||||
} > FLASH
|
||||
|
||||
.const :
|
||||
{
|
||||
. = ALIGN(32);
|
||||
*(.const)
|
||||
*(.rodata .rodata.*)
|
||||
} > FLASH
|
||||
|
||||
.data :
|
||||
{
|
||||
. = ALIGN(64);
|
||||
__image_rw_start__ = .;
|
||||
__data_start__ = .; /* Create a global symbol at data start. */
|
||||
*(.data .data.*) /* .data sections */
|
||||
. = ALIGN(64);
|
||||
__data_end__ = .; /* Define a global symbol at data end. */
|
||||
} > FLASH
|
||||
|
||||
.bss (NOLOAD):
|
||||
{
|
||||
/*
|
||||
* We need some free space to page or cpu stack, move .bss.noclean.*
|
||||
* to optimize size.
|
||||
*/
|
||||
. = ALIGN(16);
|
||||
PROVIDE(__bss_noclean_start = .);
|
||||
*(.bss.noclean.*)
|
||||
PROVIDE(__bss_noclean_end = .);
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__bss_start = .);
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.dynbss)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
PROVIDE(__bss_end = .);
|
||||
} > FLASH
|
||||
|
||||
.stack (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(64);
|
||||
__STACK_START = .;
|
||||
__StackLimit = .;
|
||||
__stack_start__ = .;
|
||||
. += STACK_SIZE;
|
||||
__stack_end__ = .;
|
||||
__StackTop = .;
|
||||
} > FLASH
|
||||
|
||||
.stack_exc (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(64);
|
||||
__StackLimit_exc = .;
|
||||
__stack_start_exc__ = .;
|
||||
. += STACK_SIZE_EXC;
|
||||
__stack_end_exc__ = .;
|
||||
__StackTop_exc = .;
|
||||
. = ALIGN(64);
|
||||
__image_rw_end__ = .;
|
||||
} > FLASH
|
||||
|
||||
_end = .;
|
||||
/*-------- LABELS USED IN CODE -------------------------------*/
|
||||
SRAM_START_ADDR = ORIGIN(FLASH_STARTUP);
|
||||
FLASH_STARTUP_LEN = LENGTH(FLASH_STARTUP);
|
||||
FLASH_SEC_ADDR = ORIGIN(FLASH);
|
||||
MCU_LOG_START_ADDR = ORIGIN(LOG_SHARE_Reserved);
|
||||
MCU_LOG_SIZE = LENGTH(LOG_SHARE_Reserved);
|
||||
__SCMI_IPC_START_ADDR = ORIGIN(SCMI_IPC_Reserved);
|
||||
__SCMI_IPC_SIZE = LENGTH(SCMI_IPC_Reserved);
|
||||
NON_SECURE_START_ADDR = ORIGIN(LOG_SHARE_Reserved);
|
||||
CAN_START_ADDR = ORIGIN(CAN_Reserved);
|
||||
ATCM_START_ADDR = ORIGIN(ATCM_Reserved);
|
||||
ATCM_SIZE = LENGTH(ATCM_Reserved);
|
||||
OS_HEAP_START_ADDR = ORIGIN(RTOS_HEAP);
|
||||
OS_HEAP_END_ADDR = ORIGIN(RTOS_HEAP) + LENGTH(RTOS_HEAP);
|
||||
OS_HEAP_SIZE = LENGTH(RTOS_HEAP);
|
||||
|
||||
/* Keep __image_rw_end__ ~ OS_HEAP_START_ADDR unmapped as a guard gap. */
|
||||
|
||||
PROVIDE(SRAM_SIZE = 0x34FFFF);
|
||||
PROVIDE(MCU0_LOG_START_ADDR = 0x0CAAB000); /* Base addr from MCU0 link region "LOG_SHARE_Reserved" */
|
||||
PROVIDE(MCU_STATE_START_ADDR = 0x0C800800);/* Base addr from MCU0 link region "MCU_STATE_Reserved" */
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
* Symbols in the DWARF debugging sections are relative to the beginning
|
||||
* of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
#ifndef RT_CONFIG_H__
|
||||
#define RT_CONFIG_H__
|
||||
|
||||
#define SOC_S100
|
||||
|
||||
/* S100 BSP Options */
|
||||
|
||||
#define RT_USING_FPU
|
||||
/* end of S100 BSP Options */
|
||||
|
||||
/* RT-Thread Kernel */
|
||||
|
||||
/* klibc options */
|
||||
|
||||
/* rt_vsnprintf options */
|
||||
|
||||
/* end of rt_vsnprintf options */
|
||||
|
||||
/* rt_vsscanf options */
|
||||
|
||||
/* end of rt_vsscanf options */
|
||||
|
||||
/* rt_memset options */
|
||||
|
||||
/* end of rt_memset options */
|
||||
|
||||
/* rt_memcpy options */
|
||||
|
||||
/* end of rt_memcpy options */
|
||||
|
||||
/* rt_memmove options */
|
||||
|
||||
/* end of rt_memmove options */
|
||||
|
||||
/* rt_memcmp options */
|
||||
|
||||
/* end of rt_memcmp options */
|
||||
|
||||
/* rt_strstr options */
|
||||
|
||||
/* end of rt_strstr options */
|
||||
|
||||
/* rt_strcasecmp options */
|
||||
|
||||
/* end of rt_strcasecmp options */
|
||||
|
||||
/* rt_strncpy options */
|
||||
|
||||
/* end of rt_strncpy options */
|
||||
|
||||
/* rt_strcpy options */
|
||||
|
||||
/* end of rt_strcpy options */
|
||||
|
||||
/* rt_strncmp options */
|
||||
|
||||
/* end of rt_strncmp options */
|
||||
|
||||
/* rt_strcmp options */
|
||||
|
||||
/* end of rt_strcmp options */
|
||||
|
||||
/* rt_strlen options */
|
||||
|
||||
/* end of rt_strlen options */
|
||||
|
||||
/* rt_strnlen options */
|
||||
|
||||
/* end of rt_strnlen options */
|
||||
/* end of klibc options */
|
||||
#define RT_NAME_MAX 16
|
||||
#define RT_CPUS_NR 1
|
||||
#define RT_ALIGN_SIZE 8
|
||||
#define RT_THREAD_PRIORITY_32
|
||||
#define RT_THREAD_PRIORITY_MAX 32
|
||||
#define RT_TICK_PER_SECOND 1000
|
||||
#define RT_USING_OVERFLOW_CHECK
|
||||
#define RT_USING_HOOK
|
||||
#define RT_HOOK_USING_FUNC_PTR
|
||||
#define RT_USING_IDLE_HOOK
|
||||
#define RT_IDLE_HOOK_LIST_SIZE 4
|
||||
#define IDLE_THREAD_STACK_SIZE 1024
|
||||
|
||||
/* kservice options */
|
||||
|
||||
/* end of kservice options */
|
||||
#define RT_USING_DEBUG
|
||||
#define RT_DEBUGING_ASSERT
|
||||
#define RT_DEBUGING_COLOR
|
||||
#define RT_DEBUGING_CONTEXT
|
||||
|
||||
/* Inter-Thread communication */
|
||||
|
||||
#define RT_USING_SEMAPHORE
|
||||
#define RT_USING_MUTEX
|
||||
#define RT_USING_EVENT
|
||||
#define RT_USING_MAILBOX
|
||||
#define RT_USING_MESSAGEQUEUE
|
||||
/* end of Inter-Thread communication */
|
||||
|
||||
/* Memory Management */
|
||||
|
||||
#define RT_USING_MEMPOOL
|
||||
#define RT_USING_SMALL_MEM
|
||||
#define RT_USING_SMALL_MEM_AS_HEAP
|
||||
#define RT_USING_HEAP
|
||||
/* end of Memory Management */
|
||||
#define RT_USING_DEVICE
|
||||
#define RT_USING_DEVICE_OPS
|
||||
#define RT_USING_CONSOLE
|
||||
#define RT_CONSOLEBUF_SIZE 512
|
||||
#define RT_CONSOLE_DEVICE_NAME "uart4"
|
||||
#define RT_USING_CONSOLE_OUTPUT_CTL
|
||||
#define RT_VER_NUM 0x50300
|
||||
#define RT_BACKTRACE_LEVEL_MAX_NR 32
|
||||
/* end of RT-Thread Kernel */
|
||||
|
||||
/* RT-Thread Components */
|
||||
|
||||
#define RT_USING_COMPONENTS_INIT
|
||||
#define RT_USING_USER_MAIN
|
||||
#define RT_MAIN_THREAD_STACK_SIZE 2048
|
||||
#define RT_MAIN_THREAD_PRIORITY 10
|
||||
#define RT_USING_MSH
|
||||
#define RT_USING_FINSH
|
||||
#define FINSH_USING_MSH
|
||||
#define FINSH_THREAD_NAME "tshell"
|
||||
#define FINSH_THREAD_PRIORITY 20
|
||||
#define FINSH_THREAD_STACK_SIZE 4096
|
||||
#define FINSH_USING_HISTORY
|
||||
#define FINSH_HISTORY_LINES 5
|
||||
#define FINSH_USING_SYMTAB
|
||||
#define FINSH_CMD_SIZE 80
|
||||
#define MSH_USING_BUILT_IN_COMMANDS
|
||||
#define FINSH_USING_DESCRIPTION
|
||||
#define FINSH_ARG_MAX 10
|
||||
#define FINSH_USING_OPTION_COMPLETION
|
||||
|
||||
/* DFS: device virtual file system */
|
||||
|
||||
/* end of DFS: device virtual file system */
|
||||
|
||||
/* Device Drivers */
|
||||
|
||||
#define RT_USING_DEVICE_IPC
|
||||
#define RT_UNAMED_PIPE_NUMBER 64
|
||||
#define RT_USING_SYSTEM_WORKQUEUE
|
||||
#define RT_SYSTEM_WORKQUEUE_STACKSIZE 2048
|
||||
#define RT_SYSTEM_WORKQUEUE_PRIORITY 23
|
||||
#define RT_USING_SERIAL
|
||||
#define RT_USING_SERIAL_V2
|
||||
#define RT_SERIAL_BUF_STRATEGY_OVERWRITE
|
||||
#define RT_USING_CAN
|
||||
#define RT_CANMSG_BOX_SZ 16
|
||||
#define RT_CANSND_BOX_NUM 32
|
||||
#define RT_CANSND_MSG_TIMEOUT 100
|
||||
#define RT_CAN_NB_TX_FIFO_SIZE 256
|
||||
#define RT_USING_PIN
|
||||
/* end of Device Drivers */
|
||||
|
||||
/* C/C++ and POSIX layer */
|
||||
|
||||
/* ISO-ANSI C layer */
|
||||
|
||||
/* Timezone and Daylight Saving Time */
|
||||
|
||||
/* end of Timezone and Daylight Saving Time */
|
||||
/* end of ISO-ANSI C layer */
|
||||
|
||||
/* POSIX (Portable Operating System Interface) layer */
|
||||
|
||||
|
||||
/* Interprocess Communication (IPC) */
|
||||
|
||||
|
||||
/* Socket is in the 'Network' category */
|
||||
|
||||
/* end of Interprocess Communication (IPC) */
|
||||
/* end of POSIX (Portable Operating System Interface) layer */
|
||||
/* end of C/C++ and POSIX layer */
|
||||
|
||||
/* Network */
|
||||
|
||||
/* end of Network */
|
||||
|
||||
/* Memory protection */
|
||||
|
||||
/* end of Memory protection */
|
||||
|
||||
/* Utilities */
|
||||
|
||||
/* end of Utilities */
|
||||
|
||||
/* Using USB legacy version */
|
||||
|
||||
/* end of Using USB legacy version */
|
||||
/* end of RT-Thread Components */
|
||||
|
||||
/* RT-Thread Utestcases */
|
||||
|
||||
/* end of RT-Thread Utestcases */
|
||||
|
||||
/* RT-Thread online packages */
|
||||
|
||||
/* IoT - internet of things */
|
||||
|
||||
|
||||
/* Wi-Fi */
|
||||
|
||||
/* Marvell WiFi */
|
||||
|
||||
/* end of Marvell WiFi */
|
||||
|
||||
/* Wiced WiFi */
|
||||
|
||||
/* end of Wiced WiFi */
|
||||
|
||||
/* CYW43012 WiFi */
|
||||
|
||||
/* end of CYW43012 WiFi */
|
||||
|
||||
/* BL808 WiFi */
|
||||
|
||||
/* end of BL808 WiFi */
|
||||
|
||||
/* CYW43439 WiFi */
|
||||
|
||||
/* end of CYW43439 WiFi */
|
||||
/* end of Wi-Fi */
|
||||
|
||||
/* IoT Cloud */
|
||||
|
||||
/* end of IoT Cloud */
|
||||
/* end of IoT - internet of things */
|
||||
|
||||
/* security packages */
|
||||
|
||||
/* end of security packages */
|
||||
|
||||
/* language packages */
|
||||
|
||||
/* JSON: JavaScript Object Notation, a lightweight data-interchange format */
|
||||
|
||||
/* end of JSON: JavaScript Object Notation, a lightweight data-interchange format */
|
||||
|
||||
/* XML: Extensible Markup Language */
|
||||
|
||||
/* end of XML: Extensible Markup Language */
|
||||
/* end of language packages */
|
||||
|
||||
/* multimedia packages */
|
||||
|
||||
/* LVGL: powerful and easy-to-use embedded GUI library */
|
||||
|
||||
/* end of LVGL: powerful and easy-to-use embedded GUI library */
|
||||
|
||||
/* u8g2: a monochrome graphic library */
|
||||
|
||||
/* end of u8g2: a monochrome graphic library */
|
||||
/* end of multimedia packages */
|
||||
|
||||
/* tools packages */
|
||||
|
||||
/* end of tools packages */
|
||||
|
||||
/* system packages */
|
||||
|
||||
/* enhanced kernel services */
|
||||
|
||||
/* end of enhanced kernel services */
|
||||
|
||||
/* acceleration: Assembly language or algorithmic acceleration packages */
|
||||
|
||||
/* end of acceleration: Assembly language or algorithmic acceleration packages */
|
||||
|
||||
/* CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
|
||||
|
||||
/* end of CMSIS: ARM Cortex-M Microcontroller Software Interface Standard */
|
||||
|
||||
/* Micrium: Micrium software products porting for RT-Thread */
|
||||
|
||||
/* end of Micrium: Micrium software products porting for RT-Thread */
|
||||
/* end of system packages */
|
||||
|
||||
/* peripheral libraries and drivers */
|
||||
|
||||
/* HAL & SDK Drivers */
|
||||
|
||||
/* STM32 HAL & SDK Drivers */
|
||||
|
||||
/* end of STM32 HAL & SDK Drivers */
|
||||
|
||||
/* Infineon HAL Packages */
|
||||
|
||||
/* end of Infineon HAL Packages */
|
||||
|
||||
/* Kendryte SDK */
|
||||
|
||||
/* end of Kendryte SDK */
|
||||
|
||||
/* WCH HAL & SDK Drivers */
|
||||
|
||||
/* end of WCH HAL & SDK Drivers */
|
||||
|
||||
/* AT32 HAL & SDK Drivers */
|
||||
|
||||
/* end of AT32 HAL & SDK Drivers */
|
||||
|
||||
/* HC32 DDL Drivers */
|
||||
|
||||
/* end of HC32 DDL Drivers */
|
||||
|
||||
/* NXP HAL & SDK Drivers */
|
||||
|
||||
/* end of NXP HAL & SDK Drivers */
|
||||
|
||||
/* NUVOTON Drivers */
|
||||
|
||||
/* end of NUVOTON Drivers */
|
||||
|
||||
/* GD32 Drivers */
|
||||
|
||||
/* end of GD32 Drivers */
|
||||
|
||||
/* HPMicro SDK */
|
||||
|
||||
/* end of HPMicro SDK */
|
||||
|
||||
/* FT32 HAL & SDK Drivers */
|
||||
|
||||
/* end of FT32 HAL & SDK Drivers */
|
||||
/* end of HAL & SDK Drivers */
|
||||
|
||||
/* sensors drivers */
|
||||
|
||||
/* end of sensors drivers */
|
||||
|
||||
/* touch drivers */
|
||||
|
||||
/* end of touch drivers */
|
||||
/* end of peripheral libraries and drivers */
|
||||
|
||||
/* AI packages */
|
||||
|
||||
/* end of AI packages */
|
||||
|
||||
/* Signal Processing and Control Algorithm Packages */
|
||||
|
||||
/* end of Signal Processing and Control Algorithm Packages */
|
||||
|
||||
/* miscellaneous packages */
|
||||
|
||||
/* project laboratory */
|
||||
|
||||
/* end of project laboratory */
|
||||
|
||||
/* samples: kernel and components samples */
|
||||
|
||||
/* end of samples: kernel and components samples */
|
||||
|
||||
/* entertainment: terminal games and other interesting software packages */
|
||||
|
||||
/* end of entertainment: terminal games and other interesting software packages */
|
||||
/* end of miscellaneous packages */
|
||||
|
||||
/* Arduino libraries */
|
||||
|
||||
|
||||
/* Projects and Demos */
|
||||
|
||||
/* end of Projects and Demos */
|
||||
|
||||
/* Sensors */
|
||||
|
||||
/* end of Sensors */
|
||||
|
||||
/* Display */
|
||||
|
||||
/* end of Display */
|
||||
|
||||
/* Timing */
|
||||
|
||||
/* end of Timing */
|
||||
|
||||
/* Data Processing */
|
||||
|
||||
/* end of Data Processing */
|
||||
|
||||
/* Data Storage */
|
||||
|
||||
/* Communication */
|
||||
|
||||
/* end of Communication */
|
||||
|
||||
/* Device Control */
|
||||
|
||||
/* end of Device Control */
|
||||
|
||||
/* Other */
|
||||
|
||||
/* end of Other */
|
||||
|
||||
/* Signal IO */
|
||||
|
||||
/* end of Signal IO */
|
||||
|
||||
/* Uncategorized */
|
||||
|
||||
/* end of Arduino libraries */
|
||||
/* end of RT-Thread online packages */
|
||||
|
||||
/* Onboard Peripheral Drivers */
|
||||
|
||||
#define BSP_USING_PINMUX
|
||||
#define BSP_USING_GPIO
|
||||
#define BSP_USING_CAN
|
||||
#define BSP_USING_CAN5
|
||||
#define BSP_USING_CAN6
|
||||
#define BSP_USING_CAN7
|
||||
#define BSP_USING_CAN8
|
||||
#define BSP_USING_CAN9
|
||||
#define BSP_USING_UART
|
||||
#define BSP_USING_UART4
|
||||
#define BSP_UART4_RX_BUFSIZE 1024
|
||||
#define BSP_UART4_TX_BUFSIZE 0
|
||||
/* end of Onboard Peripheral Drivers */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def _config_enabled(symbol, default=False):
|
||||
config_path = os.path.join(os.path.dirname(__file__), '.config')
|
||||
|
||||
try:
|
||||
with open(config_path, 'r', encoding='utf-8') as cfg:
|
||||
text = cfg.read()
|
||||
if f'CONFIG_{symbol}=y' in text:
|
||||
return True
|
||||
if f'# CONFIG_{symbol} is not set' in text:
|
||||
return False
|
||||
return default
|
||||
except OSError:
|
||||
return default
|
||||
|
||||
# toolchains options
|
||||
ARCH='arm'
|
||||
CPU='cortex-r52'
|
||||
CROSS_TOOL='gcc'
|
||||
|
||||
if os.getenv('RTT_CC'):
|
||||
CROSS_TOOL = os.getenv('RTT_CC')
|
||||
if os.getenv('RTT_ROOT'):
|
||||
RTT_ROOT = os.getenv('RTT_ROOT')
|
||||
|
||||
# cross_tool provides the cross compiler
|
||||
if CROSS_TOOL == 'gcc':
|
||||
PLATFORM = 'gcc'
|
||||
EXEC_PATH = r'/opt/toolchain/gcc-arm-none-eabi-10.3-2021.10/bin'
|
||||
|
||||
if os.getenv('RTT_EXEC_PATH'):
|
||||
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
|
||||
|
||||
# BUILD = 'debug'
|
||||
BUILD = 'release'
|
||||
|
||||
if PLATFORM == 'gcc':
|
||||
# toolchains
|
||||
PREFIX = 'arm-none-eabi-'
|
||||
CC = PREFIX + 'gcc'
|
||||
AS = PREFIX + 'gcc'
|
||||
AR = PREFIX + 'ar'
|
||||
CXX = PREFIX + 'g++'
|
||||
LINK = PREFIX + 'gcc'
|
||||
TARGET_EXT = 'elf'
|
||||
SIZE = PREFIX + 'size'
|
||||
OBJDUMP = PREFIX + 'objdump'
|
||||
OBJCPY = PREFIX + 'objcopy'
|
||||
NM = PREFIX + 'nm'
|
||||
|
||||
if _config_enabled('RT_USING_FPU', default=True):
|
||||
DEVICE = ' -mcpu=cortex-r52 -marm -mfloat-abi=hard -mfpu=vfpv3-d16 -mlittle-endian'
|
||||
else:
|
||||
DEVICE = ' -mcpu=cortex-r52 -marm -mfloat-abi=soft -mgeneral-regs-only -mlittle-endian'
|
||||
COMMON_CFLAGS = (
|
||||
' -fno-inline'
|
||||
' -ffunction-sections'
|
||||
' -fdata-sections'
|
||||
' -fdiagnostics-parseable-fixits'
|
||||
' -fmessage-length=0'
|
||||
' -funsigned-char'
|
||||
' -funsigned-bitfields'
|
||||
' -fno-common'
|
||||
' -fno-strict-aliasing'
|
||||
' -funwind-tables'
|
||||
' -Dgcc'
|
||||
)
|
||||
|
||||
CFLAGS = DEVICE + COMMON_CFLAGS
|
||||
AFLAGS = ' -c' + DEVICE + ' -x assembler-with-cpp'
|
||||
LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vector -lgcc -T link.lds'
|
||||
|
||||
if BUILD == 'debug':
|
||||
CFLAGS += ' -Og -ggdb3 -gdwarf-4'
|
||||
AFLAGS += ' -ggdb3 -gdwarf-4'
|
||||
else:
|
||||
CFLAGS += ' -O2'
|
||||
CXXFLAGS = CFLAGS
|
||||
|
||||
POST_ACTION = OBJCPY + ' -O binary $TARGET rtthread.bin\n' + SIZE + ' $TARGET \n'
|
||||
@@ -0,0 +1,13 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
Import('rtconfig')
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c') + Glob('*.S')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('startup', src, depend = [''], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2024, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2024-03-01 Wangyuqiang first version
|
||||
*/
|
||||
|
||||
#include "rtconfig.h"
|
||||
|
||||
.syntax unified
|
||||
.text
|
||||
|
||||
.globl rt_thread_switch_interrupt_flag
|
||||
.globl rt_interrupt_from_thread
|
||||
.globl rt_interrupt_to_thread
|
||||
.globl rt_interrupt_enter
|
||||
.globl rt_interrupt_leave
|
||||
.globl rt_hw_trap_irq
|
||||
|
||||
/*
|
||||
* rt_base_t rt_hw_interrupt_disable();
|
||||
*/
|
||||
.globl rt_hw_interrupt_disable
|
||||
rt_hw_interrupt_disable:
|
||||
mrs r0, cpsr
|
||||
cpsid i
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* void rt_hw_interrupt_enable(rt_base_t level);
|
||||
*/
|
||||
.globl rt_hw_interrupt_enable
|
||||
rt_hw_interrupt_enable:
|
||||
msr cpsr, r0
|
||||
bx lr
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch(rt_uint32 from, rt_uint32 to)
|
||||
* r0 --> from
|
||||
* r1 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch
|
||||
rt_hw_context_switch:
|
||||
clrex
|
||||
stmfd sp!, {lr} @ push pc (lr should be pushed in place of PC)
|
||||
stmfd sp!, {r0-r12, lr} @ push lr & register file
|
||||
|
||||
mrs r4, cpsr
|
||||
tst lr, #0x01
|
||||
orrne r4, r4, #0x20 @ it's thumb code
|
||||
|
||||
stmfd sp!, {r4} @ push cpsr
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
/* fpu context */
|
||||
vmrs r6, fpexc
|
||||
tst r6, #(1<<30)
|
||||
beq __no_vfp_frame1
|
||||
vstmdb sp!, {d0-d15}
|
||||
vmrs r5, fpscr
|
||||
stmfd sp!, {r5}
|
||||
__no_vfp_frame1:
|
||||
stmfd sp!, {r6}
|
||||
#endif
|
||||
str sp, [r0] @ store sp in preempted tasks TCB
|
||||
ldr sp, [r1] @ get new task stack pointer
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
/* fpu context */
|
||||
ldmfd sp!, {r6}
|
||||
vmsr fpexc, r6
|
||||
tst r6, #(1<<30)
|
||||
beq __no_vfp_frame2
|
||||
ldmfd sp!, {r5}
|
||||
vmsr fpscr, r5
|
||||
vldmia sp!, {d0-d15}
|
||||
__no_vfp_frame2:
|
||||
#endif
|
||||
|
||||
ldmfd sp!, {r1}
|
||||
msr spsr_cxsf, r1 /* original mode */
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ /* irq return */
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_to(rt_uint32 to)
|
||||
* r0 --> to
|
||||
*/
|
||||
.globl rt_hw_context_switch_to
|
||||
rt_hw_context_switch_to:
|
||||
LDR sp, [r0] @ get new task stack pointer
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
ldmfd sp!, {r6}
|
||||
vmsr fpexc, r6
|
||||
tst r6, #(1<<30)
|
||||
beq __no_vfp_frame_to
|
||||
ldmfd sp!, {r5}
|
||||
vmsr fpscr, r5
|
||||
vldmia sp!, {d0-d15}
|
||||
__no_vfp_frame_to:
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r4} @ pop new task cpsr to spsr
|
||||
MSR spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ /* irq return */
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to)@
|
||||
*/
|
||||
|
||||
.globl rt_hw_context_switch_interrupt
|
||||
rt_hw_context_switch_interrupt:
|
||||
LDR r2, =rt_thread_switch_interrupt_flag
|
||||
LDR r3, [r2]
|
||||
CMP r3, #1
|
||||
BEQ _reswitch
|
||||
MOV r3, #1 @ set rt_thread_switch_interrupt_flag to 1
|
||||
STR r3, [r2]
|
||||
LDR r2, =rt_interrupt_from_thread @ set rt_interrupt_from_thread
|
||||
|
||||
STR r0, [r2]
|
||||
_reswitch:
|
||||
LDR r2, =rt_interrupt_to_thread @ set rt_interrupt_to_thread
|
||||
STR r1, [r2]
|
||||
BX lr
|
||||
|
||||
.globl IRQ_Handler
|
||||
IRQ_Handler:
|
||||
STMDB sp!, {r0-r12,lr}
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
VMRS r0, fpexc
|
||||
TST r0, #0x40000000
|
||||
BEQ __no_vfp_frame_str_irq
|
||||
VSTMDB sp!, {d0-d15}
|
||||
VMRS r1, fpscr
|
||||
@ TODO: add support for Common VFPv3.
|
||||
@ Save registers like FPINST, FPINST2
|
||||
STMDB sp!, {r1}
|
||||
__no_vfp_frame_str_irq:
|
||||
STMDB sp!, {r0}
|
||||
#endif
|
||||
|
||||
BL rt_interrupt_enter
|
||||
BL rt_hw_trap_irq
|
||||
BL rt_interrupt_leave
|
||||
|
||||
@ if rt_thread_switch_interrupt_flag set, jump to
|
||||
@ rt_hw_context_switch_interrupt_do and don't return
|
||||
LDR r0, =rt_thread_switch_interrupt_flag
|
||||
LDR r1, [r0]
|
||||
CMP r1, #1
|
||||
BEQ rt_hw_context_switch_interrupt_do
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
LDMIA sp!, {r0} @ get fpexc
|
||||
VMSR fpexc, r0
|
||||
TST r0, #0x40000000
|
||||
BEQ __no_vfp_frame_ldr_irq
|
||||
LDMIA sp!, {r1} @ get fpscr
|
||||
VMSR fpscr, r1
|
||||
VLDMIA sp!, {d0-d15}
|
||||
__no_vfp_frame_ldr_irq:
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r0-r12,lr}
|
||||
SUBS pc, lr, #4
|
||||
|
||||
/*
|
||||
* void rt_hw_context_switch_interrupt_do(rt_base_t flag)
|
||||
*/
|
||||
.globl rt_hw_context_switch_interrupt_do
|
||||
rt_hw_context_switch_interrupt_do:
|
||||
MOV r1, #0 @ clear flag
|
||||
STR r1, [r0]
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
LDMIA sp!, {r0} @ get fpexc
|
||||
VMSR fpexc, r0
|
||||
TST r0, #0x40000000
|
||||
BEQ __no_vfp_frame_do1
|
||||
LDMIA sp!, {r1} @ get fpscr
|
||||
VMSR fpscr, r1
|
||||
VLDMIA sp!, {d0-d15}
|
||||
__no_vfp_frame_do1:
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r0-r12,lr} @ reload saved registers
|
||||
STMDB sp, {r0-r3} @ save r0-r3. We will restore r0-r3 in the SVC
|
||||
@ mode so there is no need to update SP.
|
||||
SUB r1, sp, #16 @ save the right SP value in r1, so we could restore r0-r3.
|
||||
SUB r2, lr, #4 @ save old task's pc to r2
|
||||
|
||||
MRS r3, spsr @ get cpsr of interrupt thread
|
||||
|
||||
@ switch to SVC mode and no interrupt
|
||||
CPSID IF, #0x13
|
||||
|
||||
STMDB sp!, {r2} @ push old task's pc
|
||||
STMDB sp!, {r4-r12,lr} @ push old task's lr,r12-r4
|
||||
LDMIA r1!, {r4-r7} @ restore r0-r3 of the interrupted thread
|
||||
STMDB sp!, {r4-r7} @ push old task's r3-r0. We don't need to push/pop them to
|
||||
@ r0-r3 because we just want to transfer the data and don't
|
||||
@ use them here.
|
||||
STMDB sp!, {r3} @ push old task's cpsr
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
VMRS r0, fpexc
|
||||
TST r0, #0x40000000
|
||||
BEQ __no_vfp_frame_do2
|
||||
VSTMDB sp!, {d0-d15}
|
||||
VMRS r1, fpscr
|
||||
@ TODO: add support for Common VFPv3.
|
||||
@ Save registers like FPINST, FPINST2
|
||||
STMDB sp!, {r1}
|
||||
__no_vfp_frame_do2:
|
||||
STMDB sp!, {r0}
|
||||
#endif
|
||||
|
||||
LDR r4, =rt_interrupt_from_thread
|
||||
LDR r5, [r4]
|
||||
STR sp, [r5] @ store sp in preempted tasks's TCB
|
||||
|
||||
LDR r6, =rt_interrupt_to_thread
|
||||
LDR r6, [r6]
|
||||
LDR sp, [r6] @ get new task's stack pointer
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
ldmfd sp!, {r6}
|
||||
vmsr fpexc, r6
|
||||
tst r6, #(1<<30)
|
||||
beq __no_vfp_frame_do3
|
||||
ldmfd sp!, {r5}
|
||||
vmsr fpscr, r5
|
||||
vldmia sp!, {d0-d15}
|
||||
|
||||
__no_vfp_frame_do3:
|
||||
#endif
|
||||
|
||||
LDMIA sp!, {r4} @ pop new task's cpsr to spsr
|
||||
MSR spsr_cxsf, r4
|
||||
|
||||
ldmfd sp!, {r0-r12,lr,pc}^ /* irq return */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2026, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-06 Bernard first version
|
||||
* 2018-11-22 Jesven add smp support
|
||||
*/
|
||||
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
#include "interrupt.h"
|
||||
|
||||
#include "gicv3.h"
|
||||
|
||||
/* exception and interrupt handler table */
|
||||
struct rt_irq_desc isr_table[MAX_HANDLERS];
|
||||
|
||||
#ifndef RT_USING_SMP
|
||||
/* Those varibles will be accessed in ISR, so we need to share them. */
|
||||
rt_uint32_t rt_interrupt_from_thread = 0;
|
||||
rt_uint32_t rt_interrupt_to_thread = 0;
|
||||
rt_uint32_t rt_thread_switch_interrupt_flag = 0;
|
||||
|
||||
#ifdef RT_USING_HOOK
|
||||
static void (*rt_interrupt_switch_hook)(void);
|
||||
|
||||
void rt_interrupt_switch_sethook(void (*hook)(void))
|
||||
{
|
||||
rt_interrupt_switch_hook = hook;
|
||||
}
|
||||
#endif
|
||||
|
||||
void rt_interrupt_hook(void)
|
||||
{
|
||||
RT_OBJECT_HOOK_CALL(rt_interrupt_switch_hook, ());
|
||||
}
|
||||
#endif
|
||||
|
||||
const unsigned int VECTOR_BASE = 0x00;
|
||||
extern void rt_cpu_vector_set_base(unsigned int addr);
|
||||
extern int system_vectors;
|
||||
|
||||
void rt_hw_vector_init(void)
|
||||
{
|
||||
rt_cpu_vector_set_base((unsigned int)&system_vectors);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will initialize hardware interrupt
|
||||
* Called by the primary cpu(cpu0)
|
||||
*/
|
||||
void rt_hw_interrupt_init(void)
|
||||
{
|
||||
rt_uint32_t gic_redist_base;
|
||||
rt_int32_t cpu_id;
|
||||
|
||||
/* initialize vector table */
|
||||
/* rt_hw_vector_init(); */
|
||||
|
||||
/* initialize exceptions table */
|
||||
rt_memset(isr_table, 0x00, sizeof(isr_table));
|
||||
/* initialize ARM GIC */
|
||||
gic_redist_base = platform_get_gic_redist_base();
|
||||
cpu_id = rt_hw_cpu_id();
|
||||
|
||||
arm_gic_dist_init(0, platform_get_gic_dist_base(), 0);
|
||||
arm_gic_redist_address_set(0, gic_redist_base, cpu_id);
|
||||
|
||||
arm_gic_cpu_init(0);
|
||||
arm_gic_redist_init(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_mask(int vector)
|
||||
{
|
||||
arm_gic_mask(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will un-mask a interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_umask(int vector)
|
||||
{
|
||||
arm_gic_umask(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function returns the active interrupt number.
|
||||
* @param none
|
||||
*/
|
||||
int rt_hw_interrupt_get_irq(void)
|
||||
{
|
||||
return arm_gic_get_active_irq(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function acknowledges the interrupt.
|
||||
* @param vector the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_ack(int vector)
|
||||
{
|
||||
arm_gic_ack(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function set interrupt CPU targets.
|
||||
* @param vector: the interrupt number
|
||||
* cpu_mask: target cpus mask, one bit for one core
|
||||
*/
|
||||
void rt_hw_interrupt_set_target_cpus(int vector, unsigned int cpu_mask)
|
||||
{
|
||||
arm_gic_set_cpu(0, vector, cpu_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get interrupt CPU targets.
|
||||
* @param vector: the interrupt number
|
||||
* @return target cpus mask, one bit for one core
|
||||
*/
|
||||
unsigned int rt_hw_interrupt_get_target_cpus(int vector)
|
||||
{
|
||||
return arm_gic_get_target_cpu(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function set interrupt triger mode.
|
||||
* @param vector: the interrupt number
|
||||
* mode: interrupt triger mode; 0: level triger, 1: edge triger
|
||||
*/
|
||||
void rt_hw_interrupt_set_triger_mode(int vector, unsigned int mode)
|
||||
{
|
||||
arm_gic_set_configuration(0, vector, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get interrupt triger mode.
|
||||
* @param vector: the interrupt number
|
||||
* @return interrupt triger mode; 0: level triger, 1: edge triger
|
||||
*/
|
||||
unsigned int rt_hw_interrupt_get_triger_mode(int vector)
|
||||
{
|
||||
return arm_gic_get_configuration(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function set interrupt pending flag.
|
||||
* @param vector: the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_set_pending(int vector)
|
||||
{
|
||||
arm_gic_set_pending_irq(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get interrupt pending flag.
|
||||
* @param vector: the interrupt number
|
||||
* @return interrupt pending flag, 0: not pending; 1: pending
|
||||
*/
|
||||
unsigned int rt_hw_interrupt_get_pending(int vector)
|
||||
{
|
||||
return arm_gic_get_pending_irq(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function clear interrupt pending flag.
|
||||
* @param vector: the interrupt number
|
||||
*/
|
||||
void rt_hw_interrupt_clear_pending(int vector)
|
||||
{
|
||||
arm_gic_clear_pending_irq(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function set interrupt priority value.
|
||||
* @param vector: the interrupt number
|
||||
* priority: the priority of interrupt to set
|
||||
*/
|
||||
void rt_hw_interrupt_set_priority(int vector, unsigned int priority)
|
||||
{
|
||||
arm_gic_set_priority(0, vector, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get interrupt priority.
|
||||
* @param vector: the interrupt number
|
||||
* @return interrupt priority value
|
||||
*/
|
||||
unsigned int rt_hw_interrupt_get_priority(int vector)
|
||||
{
|
||||
return arm_gic_get_priority(0, vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function set priority masking threshold.
|
||||
* @param priority: priority masking threshold
|
||||
*/
|
||||
void rt_hw_interrupt_set_priority_mask(unsigned int priority)
|
||||
{
|
||||
arm_gic_set_interface_prior_mask(0, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get priority masking threshold.
|
||||
* @param none
|
||||
* @return priority masking threshold
|
||||
*/
|
||||
unsigned int rt_hw_interrupt_get_priority_mask(void)
|
||||
{
|
||||
return arm_gic_get_interface_prior_mask(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function set priority grouping field split point.
|
||||
* @param bits: priority grouping field split point
|
||||
* @return 0: success; -1: failed
|
||||
*/
|
||||
int rt_hw_interrupt_set_prior_group_bits(unsigned int bits)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (bits < 8)
|
||||
{
|
||||
arm_gic_set_binary_point(0, (7 - bits));
|
||||
status = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = -1;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function get priority grouping field split point.
|
||||
* @param none
|
||||
* @return priority grouping field split point
|
||||
*/
|
||||
unsigned int rt_hw_interrupt_get_prior_group_bits(void)
|
||||
{
|
||||
unsigned int bp;
|
||||
|
||||
bp = arm_gic_get_binary_point(0) & 0x07;
|
||||
|
||||
return (7 - bp);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will install a interrupt service routine to a interrupt.
|
||||
* @param vector the interrupt number
|
||||
* @param new_handler the interrupt service routine to be installed
|
||||
* @param old_handler the old interrupt service routine
|
||||
*/
|
||||
rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
|
||||
void *param, const char *name)
|
||||
{
|
||||
rt_isr_handler_t old_handler = RT_NULL;
|
||||
|
||||
if (vector < MAX_HANDLERS)
|
||||
{
|
||||
old_handler = isr_table[vector].handler;
|
||||
|
||||
if (handler != RT_NULL)
|
||||
{
|
||||
#ifdef RT_USING_INTERRUPT_INFO
|
||||
rt_strncpy(isr_table[vector].name, name, RT_NAME_MAX);
|
||||
#endif /* RT_USING_INTERRUPT_INFO */
|
||||
isr_table[vector].handler = handler;
|
||||
isr_table[vector].param = param;
|
||||
}
|
||||
}
|
||||
|
||||
return old_handler;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2011-2026, Shanghai Real-Thread Electronic Technology Co.,Ltd
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2022-08-29 RT-Thread first version
|
||||
*/
|
||||
|
||||
#include "armv8.h"
|
||||
#include <rtthread.h>
|
||||
/* #include <board.h> */
|
||||
|
||||
/**
|
||||
* This function will initialize thread stack
|
||||
*
|
||||
* @param tentry the entry of thread
|
||||
* @param parameter the parameter of entry
|
||||
* @param stack_addr the beginning stack address
|
||||
* @param texit the function will be called when thread exit
|
||||
*
|
||||
* @return stack address
|
||||
*/
|
||||
rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
|
||||
rt_uint8_t *stack_addr, void *texit)
|
||||
{
|
||||
rt_uint32_t *stk;
|
||||
|
||||
stack_addr += sizeof(rt_uint32_t);
|
||||
stack_addr = (rt_uint8_t *)RT_ALIGN_DOWN((rt_uint32_t)stack_addr, 8);
|
||||
stk = (rt_uint32_t *)stack_addr;
|
||||
*(--stk) = (rt_uint32_t)tentry; /* entry point */
|
||||
*(--stk) = (rt_uint32_t)texit; /* lr */
|
||||
*(--stk) = 0xdeadbeef; /* r12 */
|
||||
*(--stk) = 0xdeadbeef; /* r11 */
|
||||
*(--stk) = 0xdeadbeef; /* r10 */
|
||||
*(--stk) = 0xdeadbeef; /* r9 */
|
||||
*(--stk) = 0xdeadbeef; /* r8 */
|
||||
*(--stk) = 0xdeadbeef; /* r7 */
|
||||
*(--stk) = 0xdeadbeef; /* r6 */
|
||||
*(--stk) = 0xdeadbeef; /* r5 */
|
||||
*(--stk) = 0xdeadbeef; /* r4 */
|
||||
*(--stk) = 0xdeadbeef; /* r3 */
|
||||
*(--stk) = 0xdeadbeef; /* r2 */
|
||||
*(--stk) = 0xdeadbeef; /* r1 */
|
||||
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
||||
/* cpsr */
|
||||
if ((rt_uint32_t)tentry & 0x01)
|
||||
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
||||
else
|
||||
*(--stk) = SVCMODE; /* arm mode */
|
||||
|
||||
#ifdef RT_USING_OSA
|
||||
*(--stk) = 0; /* user lr */
|
||||
*(--stk) = 0; /* user sp*/
|
||||
#endif
|
||||
#ifdef RT_USING_FPU
|
||||
rt_uint32_t i;
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
*(--stk) = 0; /* d0-d15 initial state */
|
||||
}
|
||||
*(--stk) = 0; /* fpscr */
|
||||
*(--stk) = 0x40000000; /* eager-enable FPU for every new thread */
|
||||
#endif
|
||||
|
||||
/* return task's current stack address */
|
||||
return (rt_uint8_t *)stk;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
|
||||
@@ -0,0 +1,476 @@
|
||||
#include "rtconfig.h"
|
||||
.text
|
||||
.align 4
|
||||
.section ".EL2_core_exceptions_table", "ax"
|
||||
.globl EL2_core_exceptions_table
|
||||
.type EL2_core_exceptions_table, %function
|
||||
EL2_core_exceptions_table:
|
||||
b EL2_Reset_Handler /* Reset Handler */
|
||||
b EL2_Undefined_Handler /* Undefined Handler */
|
||||
b EL2_HVC_Handler /* SVCall Handler */
|
||||
b EL2_Prefetch_Handler /* Prefetch Handler */
|
||||
b EL2_Abort_Handler /* Abort Handler */
|
||||
b EL2_Trap_Handler /* Reserved */
|
||||
b EL2_IRQ_Handler /* IRQ Handler */
|
||||
b EL2_FIQ_Handler /* FIQ Handler */
|
||||
|
||||
.arm
|
||||
.align 4
|
||||
.section ".EL1_core_exceptions_table", "ax"
|
||||
EL1_core_exceptions_table:
|
||||
b EL1_Reset_Handler
|
||||
b Undefined_Handler
|
||||
b SVC_Handler
|
||||
b Prefetch_Handler
|
||||
b Abort_Handler
|
||||
b Reserved_Handler
|
||||
b IRQ_Handler
|
||||
b FIQ_Handler
|
||||
|
||||
/* Reset Handler */
|
||||
.text
|
||||
.align 4
|
||||
.section ".EL2_Reset_Handler", "ax"
|
||||
.globl EL2_Reset_Handler
|
||||
.type EL2_Reset_Handler, %function
|
||||
EL2_Reset_Handler:
|
||||
mov r0, #0
|
||||
mov r1, r0
|
||||
mov r2, r0
|
||||
mov r3, r0
|
||||
mov r4, r0
|
||||
mov r5, r0
|
||||
mov r6, r0
|
||||
mov r7, r0
|
||||
mov r8, r0
|
||||
mov r9, r0
|
||||
mov r10, r0
|
||||
mov r11, r0
|
||||
mov r12, r0
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
mrc p15, #0x00, r2, c1, c0, #0x02
|
||||
orr r2, r2, #0xF00000
|
||||
mcr p15, #0x00, r2, c1, c0, #0x02
|
||||
|
||||
fmrx r2, fpexc
|
||||
orr r2, r2, #0x40000000
|
||||
fmxr fpexc, r2
|
||||
#endif
|
||||
|
||||
ldr r0, =0x23000003
|
||||
MCR p15, 0, r0, c15, c0, 0
|
||||
|
||||
/*---------------TCM Initialization-------------------*/
|
||||
ldr r0, =0x0A000000 /* ATCM base address */
|
||||
ldr r1, =0x00010000 /* TCM size: 64KB */
|
||||
mov r2, #0 /* Clear value */
|
||||
tcm_init_loop:
|
||||
str r2, [r0], #4 /* Write and increment */
|
||||
subs r1, r1, #4 /* Decrement counter */
|
||||
bne tcm_init_loop /* Continue if not zero */
|
||||
dsb /* Data synchronization barrier */
|
||||
isb /* Instruction synchronization barrier */
|
||||
|
||||
b MPU_Init
|
||||
|
||||
MPU_Init:
|
||||
mrc p15, 4, r0, c1, c0, 0 /* Read HSCTLR */
|
||||
and r0, r0, #0xFFFFFFFE /* set HSCTLR.M bit to 0, disable EL2 MPU */
|
||||
mcr p15, 4, r0, c1, c0, 0 /* write HSCTLR */
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 /* Read SCTLR */
|
||||
and r0, r0, #0xFFFFFFFE /* set SCTLR.M bit to 0, disable EL1 MPU */
|
||||
mcr p15, 0, r0, c1, c0, 0 /* write SCTLR */
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0
|
||||
orr r0, r0, #(0x1 << 12) /*icache */
|
||||
orr r0, r0, #(0x1 << 2) /*dcache */
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
disalbe_mpu_region_loop:
|
||||
mov r0, r3 /* select region */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
mrc p15, 4, r0, c6, c3, 1 /* Read From HPRLAR */
|
||||
and r0, r0, #0xFFFFFFFE
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
|
||||
mrc p15, 0, r0, c6, c3, 1 /* Read From PRLAR */
|
||||
and r0, r0, #0xFFFFFFFE
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
add r3, r3, #1
|
||||
cmp r3, #24 /* hsm has only 16 mpu regions */
|
||||
blt disalbe_mpu_region_loop
|
||||
|
||||
/* region 0 cluster0/cluster1 tcm */
|
||||
/* normal memory attribute */
|
||||
ldr r0, =0 /* Region 0 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x08000000 /* Start address */
|
||||
orr r0, r0, #0x2 /* SH=0, AP=1, XN=0*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x0AFFFFFF /* End address */
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x3 /* AttrIndex=1, non-cacheable, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 1 mcu sram (uncacheable)---------------*/
|
||||
/* normal memory attribute */
|
||||
ldr r0, =1 /* Region 1 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x0C800000 /* Start address */
|
||||
orr r0, r0, #0x2 /* SH=0, AP=1, XN=0*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x0CAAFFFF /* End address */
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x3 /* AttrIndex=1, non-cacheable, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 2 image read-only (cacheable, executable)---------------*/
|
||||
/* 0x0CAB0000 ~ (__image_rw_start__ - 64), startup/text/rodata */
|
||||
ldr r0, =2 /* Region 2 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x0CAB0000 /* Start: FLASH_STARTUP (64-byte aligned) */
|
||||
orr r0, r0, #0x6 /* SH=0, AP=3, XN=0 */
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =__image_rw_start__ /* End address: __image_rw_start__ is 64-byte aligned */
|
||||
sub r0, r0, #0x40 /* Limit = __image_rw_start__ - 64 */
|
||||
orr r0, r0, #0x1 /* AttrIndex=0, cacheable, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 4 image read-write (cacheable, XN)----------------*/
|
||||
ldr r0, =4 /* Region 4 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =__image_rw_start__ /* __image_rw_start__ is 64-byte aligned */
|
||||
and r0, r0, #0xFFFFFFC0 /* Ensure 64-byte alignment */
|
||||
orr r0, r0, #0x12 /* SH=0, AP=1, XN=1 */
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =__image_rw_end__ /* End address: __image_rw_end__ is 64-byte aligned */
|
||||
sub r0, r0, #0x40 /* Limit = __image_rw_end__ - 64 */
|
||||
orr r0, r0, #0x1 /* AttrIndex=0, cacheable, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/* Keep __image_rw_end__ ~ OS_HEAP_START_ADDR unmapped as a guard gap. */
|
||||
|
||||
/*---------------region 5 RTOS heap (cacheable, XN)----------------*/
|
||||
ldr r0, =5 /* Region 5 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =OS_HEAP_START_ADDR /* OS_HEAP_START_ADDR is 64-byte aligned */
|
||||
and r0, r0, #0xFFFFFFC0 /* Ensure 64-byte alignment */
|
||||
orr r0, r0, #0x12 /* SH=0, AP=1, XN=1 */
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =OS_HEAP_END_ADDR /* End address: OS_HEAP_END_ADDR is 64-byte aligned */
|
||||
sub r0, r0, #0x40 /* Limit = OS_HEAP_END_ADDR - 64 */
|
||||
orr r0, r0, #0x1 /* AttrIndex=0, cacheable, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 11 shared/reserved SRAM (non-cacheable, XN)----------------*/
|
||||
ldr r0, =11 /* Region 11 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =OS_HEAP_END_ADDR /* OS_HEAP_END_ADDR is 64-byte aligned */
|
||||
and r0, r0, #0xFFFFFFC0 /* Ensure 64-byte alignment */
|
||||
orr r0, r0, #0x12 /* SH=0, AP=1, XN=1 */
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x0CDFFFFF /* End address */
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x3 /* AttrIndex=1, non-cacheable, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 6 internal gic & peripheral---------------*/
|
||||
/* device memory attribute */
|
||||
ldr r0, =6 /* Region 6 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x22000000 /* Start address */
|
||||
orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x223FFFFF /* End address */
|
||||
sub r0, r0, #1
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 7 peripheral---------------*/
|
||||
/* device memory attribute */
|
||||
ldr r0, =7 /* Region 7 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x23000000 /* Start address */
|
||||
orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x2FFFFFFF /* End address */
|
||||
sub r0, r0, #1
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 8 CPUSYS------------------*/
|
||||
ldr r0, =8 /* Region 8 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x30000000 /* Start address */
|
||||
orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x3FFFFFFF /* End address */
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 9 DDR-------------------*/
|
||||
ldr r0, =9 /* Region 9 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x80000000 /* Start address */
|
||||
orr r0, r0, #0x2 /* SH=0, AP=1, XN=0*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0xFFFFFFFF /* End address */
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x3 /* AttrIndex=1, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------region 10 xspi-------------------*/
|
||||
/* device memory attribute */
|
||||
ldr r0, =10 /* Region 10 */
|
||||
mcr p15, 4, r0, c6, c2, 1 /* Write HPRSELR */
|
||||
mcr p15, 0, r0, c6, c2, 1 /* Write PRSELR */
|
||||
|
||||
ldr r0, =0x18000000 /* Start address */
|
||||
orr r0, r0, #0x13 /* SH=2, AP=1, XN=1*/
|
||||
mcr p15, 4, r0, c6, c3, 0 /* Write HPRBAR */
|
||||
mcr p15, 0, r0, c6, c3, 0 /* Write PRBAR */
|
||||
|
||||
ldr r0, =0x1FFFFFFF /* End address */
|
||||
and r0, r0, #0xFFFFFFC0
|
||||
orr r0, r0, #0x7 /* AttrIndex=3, device memory, enable region */
|
||||
mcr p15, 4, r0, c6, c3, 1 /* Write HPRLAR */
|
||||
mcr p15, 0, r0, c6, c3, 1 /* Write PRLAR */
|
||||
|
||||
/*---------------SET MAIR/HMAIR-------------------*/
|
||||
ldr r0, =0x44FF /* attr0(FF): normal memory, write-back non-transient */
|
||||
/* attr1(44): normal memory, non-cacheable */
|
||||
/* attr2~3(00): Device-nGnRnE memory */
|
||||
mcr p15, 4, r0, c10, c2, 0 /* Write HMAIR0 */
|
||||
mcr p15, 0, r0, c10, c2, 0 /* Write MAIR0 */
|
||||
|
||||
ldr r0, =0x04 /* attr4~7(04/00): Device-nGnRnE memory */
|
||||
mcr p15, 4, r0, c10, c2, 1 /* Write HMAIR1 */
|
||||
mcr p15, 0, r0, c10, c2, 1 /* Write MAIR1 */
|
||||
|
||||
mpu_enable:
|
||||
mrc p15, 4, r0, c1, c0, 0 /* Read HSCTLR */
|
||||
orr r0, r0, #0x1 /* Enable MPU */
|
||||
dsb
|
||||
mcr p15, 4, r0, c1, c0, 0 /* Write HSCTLR */
|
||||
isb
|
||||
|
||||
mrc p15, 0, r0, c1, c0, 0 /* Read SCTLR */
|
||||
orr r0, r0, #0x1 /* Enable MPU */
|
||||
dsb
|
||||
mcr p15, 0, r0, c1, c0, 0 /* Write SCTLR */
|
||||
isb
|
||||
|
||||
/* ARMv8-R cores are in EL2 (hypervisor mode) after reset, and we need
|
||||
to descend to EL1 (supervisor mode) or EL0 (user mode) */
|
||||
|
||||
/* Init HVBAR (Hypervisor Vector Base Address Register) */
|
||||
ldr r0, =EL2_core_exceptions_table
|
||||
mcr p15, 4, r0, c12, c0, 0 /* Move to Coprocessor from ARM Register */
|
||||
|
||||
/* Init VBAR (Vector Base Address Register) */
|
||||
ldr r0, =EL1_core_exceptions_table
|
||||
mcr p15, 0, r0, c12, c0, 0 /* Move to Coprocessor from ARM Register */
|
||||
|
||||
init_mcu_stack:
|
||||
ldr r3, =__StackTop
|
||||
mov SP, r3
|
||||
|
||||
bl init_bss
|
||||
|
||||
/* Init ELR_hyp with EL1_Reset_Handler so eret can descend from EL2 to EL1. */
|
||||
ldr r0, =EL1_Reset_Handler
|
||||
msr ELR_hyp, r0
|
||||
|
||||
mrs r0, SPSR_hyp
|
||||
and r0, r0, #~0x00FF /* r0 = r0 & FFFF FFE0. Clear SPSR_hyp bits [4:0] -> Execution state bit + Mode bits. */
|
||||
|
||||
/* Return to EL1 system mode with interrupts masked until EL1 stack setup is done. */
|
||||
orr r0, r0, #0x1f
|
||||
bic r0, r0, #(0x1 << 5)
|
||||
msr SPSR_hyp, r0
|
||||
|
||||
/* Configure the GIC CPU Interface */
|
||||
/* Disable group 0 interrupts */
|
||||
mov r0, #0x00
|
||||
mcr p15, 0, r0, c12, c12, 6 /* Write to ICC_IGRPEN0 */
|
||||
|
||||
/* Enable group 1 interrupts */
|
||||
mov r0, #0x01
|
||||
mcr p15, 0, r0, c12, c12, 7 /* Write to ICC_IGRPEN1 */
|
||||
|
||||
/* Set the interrupt priority mask to biggest value - 0x1F */
|
||||
/* Interrupts with all priorities are allowed. */
|
||||
|
||||
mov r0, #0xF8 /* The priority bitfield is shifted with 3 bits - 0x1F becomes 0xF8 */
|
||||
mcr p15, 0, r0, c4, c6, 0 /* Write to ICC_PMR */
|
||||
|
||||
/* Set the binary point for group 0 and group 1 interrupts */
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c12, c8, 3 /* Write to ICC_BPR0 */
|
||||
mcr p15, 0, r0, c12, c12, 3 /* Write to ICC_BPR1 */
|
||||
|
||||
/* Exception return - will jump to address pointed by ELR_hyp (main) */
|
||||
eret /* When executed in Hyp mode, ERET loads the PC from ELR_hyp and loads the CPSR from SPSR_hyp */
|
||||
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl EL1_Reset_Handler
|
||||
.type EL1_Reset_Handler, %function
|
||||
EL1_Reset_Handler:
|
||||
/* Divide the non-USR mode stack area between the 5 non-USR modes */
|
||||
/* ABT,UND get 1/10 each. HYP, SVC,FIQ,IRQ get 1/5 each. */
|
||||
ldr r3, =__StackTop
|
||||
ldr r2, =__StackLimit
|
||||
sub r2, r3, r2 /* r2 : size in bytes */
|
||||
mov r4, #2
|
||||
udiv r1, r2, r4 /* r1 : size divided by 2 */
|
||||
and r1, r1, #~0x0f /* r1 size alligned to 16 bytes */
|
||||
|
||||
/* Setup the stack for supervisor mode (entered from reset) */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x00FF
|
||||
orr r0, r0, #0x0033
|
||||
msr cpsr_c, r0
|
||||
sub r3, r3, r1
|
||||
mov SP, r3 /* top of stack to SP_svc */
|
||||
|
||||
ldr r3, =__StackTop_exc
|
||||
ldr r2, =__StackLimit_exc
|
||||
sub r2, r3, r2 /* r2 : size in bytes */
|
||||
mov r4, #4
|
||||
udiv r1, r2, r4 /* r1 : size divided by 4 */
|
||||
and r1, r1, #~0x0f /* r1 size alligned to 16 bytes */
|
||||
|
||||
/* Go to FIQ mode and set stack (below the previous one) */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x003F
|
||||
orr r0, r0, #0x0031
|
||||
msr cpsr_c, r0
|
||||
sub r3, r3, r1
|
||||
mov SP, r3
|
||||
|
||||
/* Go to IRQ mode and set stack (below the previous one) */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x003F
|
||||
orr r0, r0, #0x0032
|
||||
msr cpsr_c, r0
|
||||
sub r3, r3, r1
|
||||
mov SP, r3
|
||||
|
||||
/* Go to ABORT mode and set stack (below the previous one) */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x003F
|
||||
orr r0, r0, #0x0037
|
||||
msr cpsr_c, r0
|
||||
sub r3, r3, r1
|
||||
mov SP, r3
|
||||
|
||||
/* Go to UNDEF mode and set stack (below the previous one) */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x003F
|
||||
orr r0, r0, #0x003b
|
||||
msr cpsr_c, r0
|
||||
sub r3, r3, r1
|
||||
mov SP, r3
|
||||
|
||||
/* Go to SYSTEM mode and set stack to the top of the reserved area */
|
||||
/* This is also the stack for user mode */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x003F
|
||||
orr r0, r0, #0x003F
|
||||
msr cpsr_c, r0
|
||||
|
||||
ldr r3, =__StackTop_exc
|
||||
mov SP, r3
|
||||
|
||||
/* Enable IRQ and FIQ interrupts for the system/user mode */
|
||||
cpsie i /* Unmask interrupts (IRQ)*/
|
||||
cpsie f /* Unmask fast interrupts (FIQ)*/
|
||||
|
||||
/* Go to supervisor mode */
|
||||
mrs r0, cpsr
|
||||
and r0, r0, #~0x00FF
|
||||
orr r0, r0, #0x0033
|
||||
msr cpsr_c, r0
|
||||
/* Jump to the entry() method */
|
||||
bl entry
|
||||
|
||||
/* Should never get here */
|
||||
b .
|
||||
|
||||
.text
|
||||
.align 4
|
||||
.globl init_bss
|
||||
.type init_bss, %function
|
||||
init_bss:
|
||||
ldr r1, =__bss_start
|
||||
ldr r2, =__bss_end
|
||||
mov r0, #0
|
||||
|
||||
.clear_bss_loop:
|
||||
cmp r1, r2
|
||||
bcs .init_done
|
||||
str r0, [r1], #4
|
||||
b .clear_bss_loop
|
||||
|
||||
.init_done:
|
||||
bx lr
|
||||
@@ -0,0 +1,136 @@
|
||||
#include <rtthread.h>
|
||||
#include "board.h"
|
||||
#include "gicv3.h"
|
||||
|
||||
/* MCU1 interrupt numbers extracted from the original SDK configuration. */
|
||||
|
||||
#define Os_IntChannel_PDMA0_Ch0Isr 213U
|
||||
#define Os_IntChannel_Pps_IcuRtcIsr 221U
|
||||
#define Os_IntChannel_Pps_IcuEthIsr 229U
|
||||
#define Os_IntChannel_Spi0_Isr 171U
|
||||
#define Os_IntChannel_Spi1_Isr 172U
|
||||
#define Os_IntChannel_Spi2_Isr 173U
|
||||
#define Os_IntChannel_Spi3_Isr 174U
|
||||
#define Os_IntChannel_Uart4_Isr 45U
|
||||
#define Os_IntChannel_Uart5_Isr 46U
|
||||
#define Os_IntChannel_Adc_Ch0WdIsr 48U
|
||||
#define Os_IntChannel_Adc_Ch1WdIsr 49U
|
||||
#define Os_IntChannel_Adc_Ch2WdIsr 50U
|
||||
#define Os_IntChannel_Adc_Ch3WdIsr 51U
|
||||
#define Os_IntChannel_Adc_Ch4WdIsr 52U
|
||||
#define Os_IntChannel_Adc_Ch5WdIsr 53U
|
||||
#define Os_IntChannel_Adc_Ch6WdIsr 54U
|
||||
#define Os_IntChannel_Adc_Ch7WdIsr 55U
|
||||
#define Os_IntChannel_Adc_Ch8WdIsr 56U
|
||||
#define Os_IntChannel_Adc_Ch9WdIsr 57U
|
||||
#define Os_IntChannel_Adc_Ch10WdIsr 58U
|
||||
#define Os_IntChannel_Adc_Ch11WdIsr 59U
|
||||
#define Os_IntChannel_Adc_Ch12WdIsr 60U
|
||||
#define Os_IntChannel_Adc_Ch13WdIsr 61U
|
||||
#define Os_IntChannel_Adc_InjIsr 62U
|
||||
#define Os_IntChannel_Adc_NorIsr 63U
|
||||
#define Os_IntChannel_I2c0_Isr 64U
|
||||
#define Os_IntChannel_I2c1_Isr 65U
|
||||
#define Os_IntChannel_I2c2_Isr 66U
|
||||
#define Os_IntChannel_I2c3_Isr 67U
|
||||
#define Os_IntChannel_Gpio_Icu0ExtIsr 68U
|
||||
#define Os_IntChannel_Gpio_Icu1ExtIsr 69U
|
||||
#define Os_IntChannel_Gpio_Icu2ExtIsr 70U
|
||||
#define Os_IntChannel_Mdma1_Ch1Isr 212U
|
||||
#define Os_IntChannel_Ipc_CpuIpc0Ch0Isr 254U
|
||||
#define Os_IntChannel_Ipc_CpuIpc0Ch4Isr 258U
|
||||
#define Os_IntChannel_Ipc_CpuIpc0Ch7Isr 261U
|
||||
#define Os_IntChannel_Ipc_CpuIpc0Ch10Isr 264U
|
||||
#define Os_Cross_Core_Ins0_Isr 237U
|
||||
#define Os_Cross_Core_Ins1_Isr 238U
|
||||
#define Os_Cross_Core_Ins2_Isr 239U
|
||||
#define Os_Cross_Core_Ins3_Isr 234U
|
||||
#define Os_Cross_Core_Ins4_Isr 235U
|
||||
#define Os_Cross_Core_Ins5_Isr 236U
|
||||
#define Os_IntChannel_Can5_DataIsr 136U
|
||||
#define Os_IntChannel_Can6_DataIsr 140U
|
||||
#define Os_IntChannel_Can7_DataIsr 144U
|
||||
#define Os_IntChannel_Can8_DataIsr 148U
|
||||
#define Os_IntChannel_Can9_DataIsr 152U
|
||||
|
||||
/*
|
||||
* MCU1 interrupt whitelist extracted from the original SDK interrupt map.
|
||||
* The current BSP only manages these SPI IDs; everything else is treated as
|
||||
* out-of-scope to avoid colliding with resources still owned by MCU0.
|
||||
*/
|
||||
|
||||
const s100_rt_irq_config_t s100_mcu1_rt_irq_configs[] =
|
||||
{
|
||||
{Os_IntChannel_PDMA0_Ch0Isr, RT_TRUE, "PDMA0_Ch0"},
|
||||
{Os_IntChannel_Pps_IcuRtcIsr, RT_TRUE, "Pps_IcuRtc"},
|
||||
{Os_IntChannel_Pps_IcuEthIsr, RT_TRUE, "Pps_IcuEth"},
|
||||
{Os_IntChannel_Spi0_Isr, RT_TRUE, "Spi0"},
|
||||
{Os_IntChannel_Spi1_Isr, RT_TRUE, "Spi1"},
|
||||
{Os_IntChannel_Spi2_Isr, RT_TRUE, "Spi2"},
|
||||
{Os_IntChannel_Spi3_Isr, RT_TRUE, "Spi3"},
|
||||
{Os_IntChannel_Uart4_Isr, RT_TRUE, "Uart4"},
|
||||
{Os_IntChannel_Uart5_Isr, RT_TRUE, "Uart5"},
|
||||
{Os_IntChannel_Adc_Ch0WdIsr, RT_TRUE, "Adc_Ch0Wd"},
|
||||
{Os_IntChannel_Adc_Ch1WdIsr, RT_TRUE, "Adc_Ch1Wd"},
|
||||
{Os_IntChannel_Adc_Ch2WdIsr, RT_TRUE, "Adc_Ch2Wd"},
|
||||
{Os_IntChannel_Adc_Ch3WdIsr, RT_TRUE, "Adc_Ch3Wd"},
|
||||
{Os_IntChannel_Adc_Ch4WdIsr, RT_TRUE, "Adc_Ch4Wd"},
|
||||
{Os_IntChannel_Adc_Ch5WdIsr, RT_TRUE, "Adc_Ch5Wd"},
|
||||
{Os_IntChannel_Adc_Ch6WdIsr, RT_TRUE, "Adc_Ch6Wd"},
|
||||
{Os_IntChannel_Adc_Ch7WdIsr, RT_TRUE, "Adc_Ch7Wd"},
|
||||
{Os_IntChannel_Adc_Ch8WdIsr, RT_TRUE, "Adc_Ch8Wd"},
|
||||
{Os_IntChannel_Adc_Ch9WdIsr, RT_TRUE, "Adc_Ch9Wd"},
|
||||
{Os_IntChannel_Adc_Ch10WdIsr, RT_TRUE, "Adc_Ch10Wd"},
|
||||
{Os_IntChannel_Adc_Ch11WdIsr, RT_TRUE, "Adc_Ch11Wd"},
|
||||
{Os_IntChannel_Adc_Ch12WdIsr, RT_TRUE, "Adc_Ch12Wd"},
|
||||
{Os_IntChannel_Adc_Ch13WdIsr, RT_TRUE, "Adc_Ch13Wd"},
|
||||
{Os_IntChannel_Adc_InjIsr, RT_TRUE, "Adc_Inj"},
|
||||
{Os_IntChannel_Adc_NorIsr, RT_TRUE, "Adc_Nor"},
|
||||
{Os_IntChannel_I2c0_Isr, RT_TRUE, "I2c0"},
|
||||
{Os_IntChannel_I2c1_Isr, RT_TRUE, "I2c1"},
|
||||
{Os_IntChannel_I2c2_Isr, RT_TRUE, "I2c2"},
|
||||
{Os_IntChannel_I2c3_Isr, RT_TRUE, "I2c3"},
|
||||
{Os_IntChannel_Gpio_Icu0ExtIsr, RT_TRUE, "Gpio_Icu0Ext"},
|
||||
{Os_IntChannel_Gpio_Icu1ExtIsr, RT_TRUE, "Gpio_Icu1Ext"},
|
||||
{Os_IntChannel_Gpio_Icu2ExtIsr, RT_TRUE, "Gpio_Icu2Ext"},
|
||||
{Os_IntChannel_Mdma1_Ch1Isr, RT_TRUE, "Mdma1_Ch1"},
|
||||
{Os_IntChannel_Ipc_CpuIpc0Ch0Isr, RT_TRUE, "Ipc_CpuIpc0Ch0"},
|
||||
{Os_IntChannel_Ipc_CpuIpc0Ch4Isr, RT_TRUE, "Ipc_CpuIpc0Ch4"},
|
||||
{Os_IntChannel_Ipc_CpuIpc0Ch7Isr, RT_TRUE, "Ipc_CpuIpc0Ch7"},
|
||||
{Os_IntChannel_Ipc_CpuIpc0Ch10Isr, RT_TRUE, "Ipc_CpuIpc0Ch10"},
|
||||
{Os_Cross_Core_Ins0_Isr, RT_TRUE, "Cross_Core_Ins0"},
|
||||
{Os_Cross_Core_Ins1_Isr, RT_TRUE, "Cross_Core_Ins1"},
|
||||
{Os_Cross_Core_Ins2_Isr, RT_TRUE, "Cross_Core_Ins2"},
|
||||
{Os_Cross_Core_Ins3_Isr, RT_TRUE, "Cross_Core_Ins3"},
|
||||
{Os_Cross_Core_Ins4_Isr, RT_TRUE, "Cross_Core_Ins4"},
|
||||
{Os_Cross_Core_Ins5_Isr, RT_TRUE, "Cross_Core_Ins5"},
|
||||
{Os_IntChannel_Can5_DataIsr, RT_TRUE, "Can5_Data"},
|
||||
{Os_IntChannel_Can6_DataIsr, RT_TRUE, "Can6_Data"},
|
||||
{Os_IntChannel_Can7_DataIsr, RT_TRUE, "Can7_Data"},
|
||||
{Os_IntChannel_Can8_DataIsr, RT_TRUE, "Can8_Data"},
|
||||
{Os_IntChannel_Can9_DataIsr, RT_TRUE, "Can9_Data"},
|
||||
};
|
||||
|
||||
const rt_size_t s100_mcu1_rt_irq_configs_count =
|
||||
sizeof(s100_mcu1_rt_irq_configs) / sizeof(s100_mcu1_rt_irq_configs[0]);
|
||||
|
||||
rt_bool_t s100_board_irq_is_supported(int irq)
|
||||
{
|
||||
rt_size_t i;
|
||||
|
||||
if ((irq >= 0) && (irq < 32))
|
||||
{
|
||||
return RT_TRUE;
|
||||
}
|
||||
|
||||
for (i = 0; i < s100_mcu1_rt_irq_configs_count; i++)
|
||||
{
|
||||
if (s100_mcu1_rt_irq_configs[i].irq_number == irq)
|
||||
{
|
||||
return RT_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return RT_FALSE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2018, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2013-07-05 Bernard the first version
|
||||
*/
|
||||
|
||||
.macro push_svc_reg pc_adjust
|
||||
sub sp, sp, #17 * 4 @/* Sizeof(struct rt_hw_exp_stack) */
|
||||
stmia sp, {r0 - r12} @/* Calling r0-r12 */
|
||||
mov r0, sp
|
||||
mrs r6, spsr @/* Save CPSR */
|
||||
sub r5, lr, #\pc_adjust
|
||||
str r5, [r0, #15*4] @/* Push fault PC */
|
||||
str r6, [r0, #16*4] @/* Push CPSR */
|
||||
cps #0x13 @/* Switch to SVC mode */
|
||||
str sp, [r0, #13*4] @/* Save calling SP */
|
||||
str lr, [r0, #14*4] @/* Save calling PC */
|
||||
.endm
|
||||
|
||||
/*
|
||||
* EL2 exceptions are unexpected in the normal RT-Thread runtime because
|
||||
* the core has already descended into EL1. Keep the SDK policy simple:
|
||||
* capture a minimal register frame for diagnostics, then stop.
|
||||
*/
|
||||
.macro push_hyp_reg pc_adjust
|
||||
mov r7, sp
|
||||
sub sp, sp, #17 * 4
|
||||
stmia sp, {r0 - r12}
|
||||
mov r0, sp
|
||||
str r7, [r0, #13*4]
|
||||
str lr, [r0, #14*4]
|
||||
sub r6, lr, #\pc_adjust
|
||||
str r6, [r0, #15*4]
|
||||
mrs r6, spsr
|
||||
str r6, [r0, #16*4]
|
||||
.endm
|
||||
|
||||
.globl SWI_Handler
|
||||
SWI_Handler:
|
||||
push_svc_reg 4
|
||||
bl rt_hw_trap_swi
|
||||
b .
|
||||
|
||||
.globl Undefined_Handler
|
||||
Undefined_Handler:
|
||||
push_svc_reg 4
|
||||
bl rt_hw_trap_undef
|
||||
b .
|
||||
|
||||
.globl SVC_Handler
|
||||
SVC_Handler:
|
||||
push_svc_reg 4
|
||||
b rt_hw_trap_svc
|
||||
b .
|
||||
|
||||
.globl Prefetch_Handler
|
||||
Prefetch_Handler:
|
||||
push_svc_reg 4
|
||||
b rt_hw_trap_pabt
|
||||
b .
|
||||
|
||||
.globl Abort_Handler
|
||||
Abort_Handler:
|
||||
push_svc_reg 8
|
||||
b rt_hw_trap_dabt
|
||||
b .
|
||||
|
||||
.globl Reserved_Handler
|
||||
Reserved_Handler:
|
||||
push_svc_reg 4
|
||||
b rt_hw_trap_resv
|
||||
b .
|
||||
|
||||
.globl FIQ_Handler
|
||||
FIQ_Handler:
|
||||
stmdb sp!, {r0-r12, lr}
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
vmrs r0, fpexc
|
||||
tst r0, #0x40000000
|
||||
beq __no_vfp_frame_str_fiq
|
||||
vstmdb sp!, {d0-d15}
|
||||
vmrs r1, fpscr
|
||||
stmdb sp!, {r1}
|
||||
__no_vfp_frame_str_fiq:
|
||||
stmdb sp!, {r0}
|
||||
#endif
|
||||
|
||||
bl rt_interrupt_enter
|
||||
bl rt_hw_trap_fiq
|
||||
bl rt_interrupt_leave
|
||||
|
||||
#ifdef RT_USING_FPU
|
||||
ldmia sp!, {r0}
|
||||
vmsr fpexc, r0
|
||||
tst r0, #0x40000000
|
||||
beq __no_vfp_frame_ldr_fiq
|
||||
ldmia sp!, {r1}
|
||||
vmsr fpscr, r1
|
||||
vldmia sp!, {d0-d15}
|
||||
__no_vfp_frame_ldr_fiq:
|
||||
#endif
|
||||
|
||||
ldmia sp!, {r0-r12, lr}
|
||||
subs pc, lr, #4
|
||||
|
||||
.globl EL2_Undefined_Handler
|
||||
EL2_Undefined_Handler:
|
||||
push_hyp_reg 4
|
||||
mov r1, #0
|
||||
b .
|
||||
|
||||
.globl EL2_Prefetch_Handler
|
||||
EL2_Prefetch_Handler:
|
||||
push_hyp_reg 4
|
||||
mov r1, #1
|
||||
b .
|
||||
|
||||
.globl EL2_Abort_Handler
|
||||
EL2_Abort_Handler:
|
||||
push_hyp_reg 8
|
||||
mov r1, #2
|
||||
b .
|
||||
|
||||
.globl EL2_IRQ_Handler
|
||||
EL2_IRQ_Handler:
|
||||
push_hyp_reg 4
|
||||
mov r1, #3
|
||||
b .
|
||||
|
||||
.globl EL2_FIQ_Handler
|
||||
EL2_FIQ_Handler:
|
||||
push_hyp_reg 4
|
||||
mov r1, #4
|
||||
b .
|
||||
|
||||
.globl EL2_HVC_Handler
|
||||
EL2_HVC_Handler:
|
||||
push_hyp_reg 4
|
||||
mov r1, #5
|
||||
b .
|
||||
|
||||
.globl EL2_Trap_Handler
|
||||
EL2_Trap_Handler:
|
||||
push_hyp_reg 4
|
||||
mov r1, #6
|
||||
b .
|
||||
Reference in New Issue
Block a user