【瑞萨RA-eco-RA6M4评测】Uart串口外设使用&& CoreMark移植
本帖最后由 短笛君 于 2026-7-26 22:31 编辑# RA6M4 CoreMark移植
## 1. CoreMark基准信息
| 项目 | 规格 |
| -------------- | -------------------------------------------------- |
| MCU | Renesas R7FA6M4AF |
| 内核 | Arm Cortex-M33,单核 |
| 最高主频 | 200 MHz |
| Flash / SRAM | 1 MB / 256 KB |
| FPU | fpv5-sp-d16,hard-float ABI |
| 开发板 |RA6M4 |
| 工具链 | Renesas LLVM/Clang 21.1.1 (ATfE-21.1.1),Windows |
| FSP | 6.5.0,e2studio 2026-04.2 |
## 2. 时钟树
```
HOCO (片内)20 MHz
→ PLL ÷2 ×20 → 200 MHz
├── ICLK÷1 → 200 MHz(CPU / DWT)
├── PCLKA ÷2 → 100 MHz
├── PCLKB ÷4 →50 MHz(SCI)
└── PCLKD ÷2 → 100 MHz
```
时钟源使用HOXC内部时钟
## 3. 串口外设 (SCI9)
### 3.1 硬件
| 参数 | 值 |
| -------- | ------------------------------ |
| 模块 | SCI9,使用 r\_sci\_uart 驱动 |
| 数据位 | 8 |
| 校验 | 无 |
| 停止位 | 1 |
| 流控 | 无 |
| 中断 | TX 完成中断 + RX 字符中断 |
### 3.2 初始化
FSP 配置器生成 g\_uart9\_ctrl 和 g\_uart9\_cfg,hal\_entry() 调用:
```c
void init_uart(void)
{
R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
}
```
!(//m.qjumbo.com/forum/data/attachment/forum/202607/26/223013jbnz3tl66g1xkr9n.png)
### 3.3 回调
```c
volatile bool uart9_send_complete_flag = false;
void g_uart9_callback(uart_callback_args_t *p_args)
{
switch (p_args->event) {
case UART_EVENT_RX_CHAR:
R_SCI_UART_Write(&g_uart9_ctrl,
(uint8_t *)&(p_args->data), 1);
break;
case UART_EVENT_TX_COMPLETE:
uart9_send_complete_flag = true;
break;
default:
break;
}
}
```
### 3.4 stdout 重定向
picolibc (tinystdio) 在裸机上不提供 stdout 定义,printf → puts 引用 stdout 会导致链接错误 "undefined symbol: stdout"。
用 FDEV\_SETUP\_STREAM 构造 FILE 对象并赋值给 stdout/stdin/stderr:
```c
static int uart_putchar(char c, FILE *f)
{
(void)f;
R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&c, 1);
while (!uart9_send_complete_flag);
uart9_send_complete_flag = false;
return (unsigned char)c;
}
static FILE __stdio = FDEV_SETUP_STREAM(
uart_putchar, NULL, NULL, _FDEV_SETUP_WRITE);
FILE *const stdout = &__stdio;
FILE *const stdin= &__stdio;
FILE *const stderr = &__stdio;
```
## 4. CoreMark 配置
源码: CoreMark 1.0
| 参数 | 值 |
| -------- | -------------------------------------------- |
| 模式 | PERFORMANCE\_RUN,TOTAL\_DATA\_SIZE = 2000 |
| 迭代 | 0(自动校准,目标 ≥10 秒) |
| 内存 | MEM\_STATIC(BSS 段,避免栈溢出) |
| 种子 | SEED\_VOLATILE |
| 定时器 | Arm DWT CYCCNT,5 ns @ 200 MHz |
## 5. 移植实现
### 5.1 入口链路
```
Reset_Handler
→ main() (ra_gen/main.c)
→ hal_entry() (src/hal_entry.c)
→ init_uart()
→ R_BSP_SoftwareDelay(3000ms)
→ coremark_run()(src/coremark/core_main.c)
→ portable_init()
→ 校准迭代次数
→ start_time()
→ [迭代 × (list + matrix + state)]
→ stop_time()
→ 输出分数
```
### 5.2 main 冲突
RA 工程和 CoreMark 各有一个 main()。通过 COREMARK\_NO\_MAIN 宏 在 core\_main.c 中将 main 重命名为 coremark\_run:
```c
// core_portme.h
#define ITERATIONS 0
#define COREMARK_NO_MAIN 1
#define PERFORMANCE_RUN 1
```
```c
// core_main.c —— 条件编译分支
#if defined(COREMARK_NO_MAIN)
int coremark_run(void)
{
int argc = 0;
char *argv = { "" };
#elif MAIN_HAS_NOARGC
MAIN_RETURN_TYPE main(void)
{
...
```
### 5.3 DWT 周期计数器
不占用外设定时器,直接操作 Cortex-M33 调试寄存器:
```c
#define DWT_CTRL (*(volatile uint32_t *)0xE0001000U)
#define DWT_CYCCNT (*(volatile uint32_t *)0xE0001004U)
#define DEMCR (*(volatile uint32_t *)0xE000EDFCU)
void portable_init(core_portable *p, int *argc, char *argv[])
{
DEMCR |= (1UL << 24); // TRCENA
DWT_CYCCNT = 0;
DWT_CTRL |= (1UL << 0); // CYCCNTENA
p->portable_id = 1;
ee_printf("CoreMark running on RA6M4 @ 200 MHz (DWT CYCCNT)\r\n");
}
```
计时接口——直接读取 CYCCNT 并算差值:
```c
static CORE_TICKS start_time_val, stop_time_val;
static inline ee_u32 read_cyccnt(void) { return DWT_CYCCNT; }
void start_time(void) { start_time_val = read_cyccnt(); }
void stop_time(void) { stop_time_val= read_cyccnt(); }
CORE_TICKS get_time(void) { return stop_time_val - start_time_val; }
secs_ret time_in_secs(CORE_TICKS ticks) { return (secs_ret)ticks / 200000000.0; }
```
### 5.4 内存
MEM\_STATIC 将 2000 字节 benchmark 数据放入 BSS 段——RA6M4 的 256 KB SRAM 绰绰有余,同时避免 MEM\_STACK 在函数栈帧上分配约 4800 字节导致栈溢出。
## 6. 编译优化
e2studio 生成工程时会重写 subdir.mk,需要生成后手动替换编译选项。
编译选项 (Debug/src/coremark/subdir.mk):
```
-O3 -funroll-loops -flto
```
链接选项 (Debug/makefile):
```makefile
$(file > UART.elf.in, ... -Wl,--icf=none -flto -I"...")
```
| 选项 | 作用 |
| ---------------- | ---------------------------------------- |
| -O3 | 激进内联、循环向量化、指令调度 |
| -funroll-loops | 完全展开小循环,直接加速 matrix / list |
| -flto | 跨编译单元内联 + 死代码消除 |
仅 CoreMark 源文件使用以上选项;FSP 栈其余代码沿用默认的 -Os。
## 7. 基准分项
### List (core\_list\_join.c)
200 节点双向链表。每轮迭代根据 hash 值选择:查找、反转、插入、删除+撤销。
```c
typedef struct list_data_s { ee_s16 data16; ee_s16 idx; } list_data;
typedef struct list_head_s {
struct list_head_s *next;
struct list_data_s*info;
} list_head;
```
### Matrix (core\_matrix.c)
16×16 矩阵 (ee\_s16),含加法、乘法、向量乘、转置。矩阵乘法 O(N³) 是 计算密度最高的子项。
```c
typedef ee_s16 MATDAT;
typedef ee_s32 MATRES;
```
### State (core\_state.c)
8 状态有限状态机,每轮 128 次转移,混合位运算和 CRC16 更新。
```c
typedef enum CORE_STATE {
CORE_START=0, CORE_INVALID, CORE_S1, CORE_S2,
CORE_INT, CORE_FLOAT, CORE_EXPONENT, CORE_SCIENTIFIC
} core_state_e;```
```
## 8. 使用
```
直接在eestudio中debug烧录 使用串口工具观察log
```
打开枚举的 COM 口,波特率与 UART9 一致。上电 3 秒后自动输出:
!(//m.qjumbo.com/forum/data/attachment/forum/202607/26/222635f2kxoi8msfs12f2g.png)
```
Starting in 3 seconds...
CoreMark running on RA6M4 @ 200 MHz (DWT CYCCNT)
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 3559881938
Total time (secs): 17.799410
Iterations/Sec : 337.089831
Iterations : 6000
Compiler version : Clang/LLVM 21.1.1
Compiler flags : -mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 -O2
Memory location: STATIC
seedcrc : 0xe9f5
crclist : 0xe714
crcmatrix : 0x1fd7
crcstate : 0x8e3a
crcfinal : 0xa14c
Correct operation validated. See README.md for run and reporting rules.
CoreMark 1.0 : 337.089831 / Clang/LLVM 21.1.1 -mcpu=cortex-m33 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 -O2 / STATIC
```
CoreMark性能基准约为337.089831这算Mhz为1.685/Mhz 性能属于中规中矩的一档
结尾附上工程代码
测试工程代码 使用EEStudio导入
页:
[1]