1. 项目概述
在嵌入式开发中,性能评估是一个关键环节。最近我在瑞萨RA8D1开发板上实现了一个有趣的功能:在FreeRTOS实时操作系统环境下运行CoreMark基准测试,并将测试结果实时显示在LVGL图形界面上。这个项目不仅验证了处理器的运算能力,还展示了如何将命令行工具与图形界面无缝集成。
CoreMark是业界广泛认可的嵌入式处理器性能基准测试工具,它通过执行一系列标准算法来评估CPU的核心性能。而LVGL则是一个轻量级的开源图形库,非常适合嵌入式设备的GUI开发。将两者结合,可以直观地展示处理器的性能表现。
这个方案特别适合需要展示设备性能的产品原型开发,比如智能家居控制面板、工业HMI设备等场景。通过图形界面直接显示跑分结果,比传统的串口输出方式更加直观和专业。
2. 开发环境准备
2.1 硬件配置
项目使用的是瑞萨电子的CPK-RA8D1开发套件,包含:
- RA8D1微控制器核心板(基于Arm Cortex-M85内核)
- 扩展板(提供外设接口和调试支持)
- 5英寸电容触摸屏(用于LVGL界面显示)
RA8D1是瑞萨新一代高性能MCU,主频高达480MHz,内置2MB Flash和1MB SRAM,完全能够满足FreeRTOS、LVGL和CoreMark同时运行的需求。
2.2 软件工具链
开发环境搭建步骤如下:
-
IDE安装:
- 使用瑞萨官方的e² studio作为开发环境
- 安装FSP(Flexible Software Package)2.0以上版本
-
工具链配置:
bash复制# 安装ARM GCC工具链 sudo apt-get install gcc-arm-none-eabi # 安装OpenOCD用于调试 sudo apt-get install openocd -
必要库下载:
- FreeRTOS v10.4.3(通过FSP直接集成)
- LVGL v8.3(从GitHub获取最新稳定版)
- CoreMark基准测试代码(从EEMBC官方仓库克隆)
提示:建议使用FSP配置工具初始化项目基础框架,可以自动生成时钟配置、外设驱动等基础代码,大幅减少手动配置的工作量。
3. CoreMark移植详解
3.1 源码获取与工程集成
CoreMark的官方代码托管在GitHub上:
bash复制git clone https://github.com/eembc/coremark.git
将以下核心文件复制到项目src目录:
- core_list_join.c
- core_main.c
- core_matrix.c
- core_state.c
- core_util.c
- core_portme.h
- coremark.h
在e² studio中需要配置编译路径:
- 右键项目 → Properties → C/C++ Build → Settings
- 在GNU ARM C Compiler的Includes中添加CoreMark源码路径
- 在Symbols中添加
ITERATIONS=1000定义(控制测试迭代次数)
3.2 关键适配修改
CoreMark需要适配目标平台的计时和输出功能。主要修改集中在core_portme.h文件中:
c复制/* 修改计时器实现,使用FreeRTOS的Tick计数 */
#include "FreeRTOS.h"
#include "task.h"
typedef TickType_t CORE_TICKS;
#define GETMYTIME(_t) (*_t = xTaskGetTickCount())
#define MYTIMEDIFF(fin, ini) ((fin) - (ini))
串口输出重定向是实现调试信息输出的关键。在RA8D1上,我们使用UART3作为调试输出端口:
c复制// 串口初始化代码(FSP自动生成)
void uart_init(void) {
fsp_err_t err = R_SCI_B_UART_Open(&g_uart3_ctrl, &g_uart3_cfg);
assert(FSP_SUCCESS == err);
}
// 实现putchar函数重定向
int __io_putchar(int ch) {
uint8_t c = (uint8_t)ch;
R_SCI_B_UART_Write(&g_uart3_ctrl, &c, 1);
while(!g_uart_transfer_complete);
g_uart_transfer_complete = false;
return ch;
}
3.3 主函数改造
由于项目在FreeRTOS环境中运行,需要将CoreMark的main函数改造为任务函数:
c复制void coremark_task(void *pvParameters) {
/* 重命名main函数避免冲突 */
extern int coremark_main(void);
/* 执行基准测试 */
coremark_main();
/* 测试完成后挂起任务 */
vTaskSuspend(NULL);
}
在系统初始化时创建CoreMark任务:
c复制xTaskCreate(coremark_task, "CoreMark", 2048, NULL, 2, NULL);
4. LVGL界面集成
4.1 界面设计
使用SquareLine Studio设计包含以下元素的界面:
- 标题Label(显示"CoreMark性能测试")
- 结果显示Label(用于显示跑分结果)
- 开始测试Button(触发基准测试)
- 返回Button(回到主界面)
界面布局采用LVGL的Flex布局,确保在不同分辨率下都能正确显示:
c复制/* 创建核心容器 */
lv_obj_t *cont = lv_obj_create(lv_scr_act());
lv_obj_set_size(cont, LV_PCT(100), LV_PCT(100));
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
/* 添加标题 */
lv_obj_t *title = lv_label_create(cont);
lv_label_set_text(title, "CoreMark性能测试");
lv_obj_set_style_text_font(title, &lv_font_montserrat_24, 0);
/* 添加结果Label */
lv_obj_t *result_label = lv_label_create(cont);
lv_label_set_text(result_label, "点击测试按钮开始基准测试");
lv_obj_set_style_text_font(result_label, &lv_font_montserrat_16, 0);
/* 添加按钮 */
lv_obj_t *test_btn = lv_btn_create(cont);
lv_obj_t *btn_label = lv_label_create(test_btn);
lv_label_set_text(btn_label, "开始测试");
4.2 事件绑定
将按钮点击事件与CoreMark测试函数绑定:
c复制static void test_btn_event_handler(lv_event_t *e) {
lv_event_code_t code = lv_event_get_code(e);
if(code == LV_EVENT_CLICKED) {
/* 更新界面提示 */
lv_label_set_text(guider_ui.coremark_screen_label, "测试进行中...");
/* 执行CoreMark测试 */
coremark_main();
}
}
void events_init(lv_ui *ui) {
lv_obj_add_event_cb(ui->coremark_screen_btn,
test_btn_event_handler,
LV_EVENT_CLICKED,
NULL);
}
4.3 结果显示优化
修改CoreMark输出函数,将结果直接显示到LVGL界面:
c复制/* 在core_main.c中修改输出部分 */
if (known_id == 3) {
char result_str[128];
float score = default_num_contexts * results[0].iterations / time_in_secs(total_time);
/* 格式化输出字符串 */
snprintf(result_str, sizeof(result_str),
"CoreMark 1.0 : %.2f\n"
"Compiler: %s\n"
"Flags: %s\n"
"Iterations: %d\n"
"Total Time: %.2f sec",
score, COMPILER_VERSION, COMPILER_FLAGS,
results[0].iterations, time_in_secs(total_time));
/* 更新界面显示 */
lv_label_set_text(guider_ui.coremark_screen_label, result_str);
}
5. 系统整合与优化
5.1 FreeRTOS任务调度
合理配置任务优先级确保系统响应:
- LVGL刷新任务:优先级3(最高)
- CoreMark测试任务:优先级2
- 其他后台任务:优先级1
内存分配调整:
c复制#define LVGL_TASK_STACK 4096
#define CORE_MARK_STACK 2048
#define MAIN_TASK_STACK 1024
5.2 性能优化技巧
-
缓存优化:
- 启用RA8D1的指令和数据缓存
- 将CoreMark代码和LVGL资源放到RAM中执行
-
编译器优化:
makefile复制
CFLAGS += -O3 -flto -ffunction-sections -fdata-sections LDFLAGS += -Wl,--gc-sections -
实时性保障:
- 在CoreMark测试期间暂时提升LVGL任务优先级
- 使用二值信号量保护共享资源
5.3 实测结果分析
在480MHz主频下,RA8D1的典型CoreMark得分约为:
- GCC优化等级-O0:约450
- GCC优化等级-O3:约1200
影响得分的因素包括:
- 编译器优化选项
- 是否启用FPU
- 缓存配置状态
- 后台任务负载
6. 常见问题与解决方案
6.1 串口输出乱码
现象:CoreMark结果在串口终端显示为乱码
排查步骤:
- 检查波特率设置(通常为115200)
- 验证时钟配置(确保UART时钟源正确)
- 检查流控设置(通常禁用硬件流控)
解决方案:
c复制// 在FSP配置中确认UART参数
const uart_cfg_t g_uart3_cfg = {
.baud_rate = 115200,
.data_bits = UART_DATA_BITS_8,
.parity = UART_PARITY_OFF,
.stop_bits = UART_STOP_BITS_1,
/* ...其他配置... */
};
6.2 LVGL界面卡顿
现象:运行CoreMark时界面响应变慢
优化方案:
- 增加LVGL任务优先级
- 缩短CoreMark的时间片:
c复制// 在coremark_main循环中添加延时 for(i=0; i<iterations; i++) { perform_coremark(); vTaskDelay(1); // 每轮测试让出CPU } - 降低LVGL刷新率(从60Hz降到30Hz)
6.3 测试结果不稳定
现象:多次运行得分波动较大
稳定化措施:
- 关闭所有中断(测试期间)
c复制__disable_irq(); // 运行CoreMark __enable_irq(); - 预热缓存(先运行一次测试不计分)
- 固定CPU频率(禁用动态调频)
7. 项目扩展思路
这个基础框架可以进一步扩展:
-
多核测试:
- RA8D1支持双核,可以开发对比测试界面
- 显示每个核心的独立得分
-
历史记录功能:
- 将测试结果保存到Flash
- 绘制性能变化曲线图
-
自动化测试套件:
- 定时运行测试
- 生成PDF测试报告
- 通过Wi-Fi上传云端
-
功耗监测集成:
- 连接电流探头
- 计算能效比(CoreMark/mA)
在实际产品开发中,这种性能监控机制可以用于:
- 生产线的质量检测
- 固件升级前后的性能对比
- 温度对性能影响的评估
通过这个项目,我深刻体会到嵌入式开发中系统级整合的重要性。将底层性能测试与上层用户界面有机结合,不仅提升了开发效率,也为最终用户提供了更直观的产品体验。特别是在资源受限的嵌入式环境中,合理分配CPU时间和内存资源是保证系统流畅运行的关键。