[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

* 添加 rdk_s100 bsp

* 添加 CI 看护
This commit is contained in:
rcitach
2026-05-20 15:42:17 +08:00
committed by GitHub
parent 3345bbc423
commit f6cb95b5b4
40 changed files with 9935 additions and 0 deletions
+7
View File
@@ -525,6 +525,13 @@
"SUB_RTT_BSP": [
"novosns/ns800/ns800rt7p65-nssinepad"
]
},
{
"RTT_BSP": "RDK",
"RTT_TOOL_CHAIN": "sourcery-arm",
"SUB_RTT_BSP": [
"rdk/s100"
]
}
]
}
+1450
View File
File diff suppressed because it is too large Load Diff
+37
View File
@@ -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"
+286
View File
@@ -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 `打开配置界面
- 打开内核测试配置:
![kernel_test](./figure/kernel_test.png)
- 打开外设测试配置:
![device_test](./figure/device_test.png)
当前默认配置里,上述 `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
```
如果只想执行单项测试,保留对应驱动开关即可;未启用的设备不会进入对应测试覆盖范围。
+14
View File
@@ -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')
+78
View File
@@ -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)
+9
View File
@@ -0,0 +1,9 @@
from building import *
cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
Return('group')
+17
View File
@@ -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;
}
+10
View File
@@ -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')
+32
View File
@@ -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
}
+107
View File
@@ -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
+74
View File
@@ -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"},
};
+90
View File
@@ -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_ */
+111
View File
@@ -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
+28
View File
@@ -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
+495
View File
@@ -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);
+31
View File
@@ -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
+148
View File
@@ -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;
}
+38
View File
@@ -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
+93
View File
@@ -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
+16
View File
@@ -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')
+227
View File
@@ -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);
+229
View File
@@ -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);
+214
View File
@@ -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

+233
View File
@@ -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) }
}
+429
View File
@@ -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
+83
View File
@@ -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'
+13
View File
@@ -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')
+248
View File
@@ -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
+282
View File
@@ -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;
}
+72
View File
@@ -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;
}
/*@}*/
+476
View File
@@ -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
+136
View File
@@ -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;
}
+151
View File
@@ -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 .