[N32G43x] 【N32G43x】手把手教你移植CoreMark到N32G435

[复制链接]
 楼主| Litthins 发表于 2021-12-26 22:54 | 显示全部楼层 |阅读模式
本帖最后由 Litthins 于 2022-2-11 18:32 编辑
#技术资源#

N32G435是国民技术新推出的通用型MCU,采用ARM Cortex-M4内核+FPU,单周期硬件乘除法,最高主频108MHz。数据手册中使用Dhrystone作为性能评价指标(135DMIPS);却没有CoreMark的相关数据。那么N32G435能跑多少分?本文介绍使用Keil将CoreMark移植到N32G43XCL-STB开发板的一般方法。
01.png

第一部分 工程创建
N32G435的支持包需要单独安装,目前版本为0.9.2,pack全称“Nationstech.N32G43x_DFP.0.9.2.pack”,安装pack后使用Keil创建新工程,选择N32G435CB,如下图所示。
02.png
新建工程下是没有资源文件的,需要手动添加。依赖文件、中间件和参考例程打包在压缩文件Nationstech.N32G43x_Library中,目前的版本是1.1.0,全称“Nationstech.N32G43x_Library.1.1.0.7z”。解压后找到firmware\CMSIS\core、firmware\CMSIS\device和firmware\n32g43x_std_periph_driver,依次复制到工程目录下,从projects\n32g43x_EVAL\examples中获取main.c\main.h\n32g43x_it.c和n32g43x_it.h文件。
02.1.png
完成资源整理后,打开工程配置选项,设置编译器版本为V6.16,勾选使用MicroLIB。
03.png
点选C/C++选项卡,在预处理符号中添加:N32G43X, USE_STDPERIPH_DRIVER, USE_FULL_ASSERT
采用-Ofast优化,勾选优化选项中的Link-Time Optimization,资源包含路径可参考下图。
04.png
打开调试选项卡,右侧调试器选择CMSIS-DAP Debugger。点击Settings进入调试器配置页面。
05.png
在配置页面中选择CMSIS-DAP-NSLink,点击OK即可。至此新工程创建完成。
06.png

第二部分 工程测试
CoreMark的测试结果最终表示为Iterations/Sec,也就是每秒迭代数,因此需要为其提供计时功能。这里使用TIM2以每1ms产生一个中断,控制PC15反转电平,使用虚拟示波器观察波形以测试工程配置是否正确。设置系统时钟为108MHz,APB1四分频27M,注意如果APB1的分频系数大于1,则TIM2的时钟频率加倍,即TIM2时钟为54M。
07.png
时钟初始化代码:
  1. RCC_ConfigPclk1(RCC_HCLK_DIV4);
  2. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);
  3. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
定时器初始化代码:
  1. void TIM_CFG(void)
  2. {
  3.     TIM_TimeBaseStructure.Period    = 1000-1;
  4.     TIM_TimeBaseStructure.Prescaler = 54-1;
  5.     TIM_TimeBaseStructure.ClkDiv    = 0;
  6.     TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;

  7.     TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);
  8.     TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);
  9. }
设置定时器中断:
  1. void NVIC_CFG(void)
  2. {
  3.     NVIC_InitType NVIC_InitStructure;

  4.     NVIC_InitStructure.NVIC_IRQChannel                   = TIM2_IRQn;
  5.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  6.     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
  7.     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
  8.     NVIC_Init(&NVIC_InitStructure);
  9. }
在虚拟示波器中观察输出波形,频率为500Hz,即中断每1ms触发1次,工程测试成功。
08.png

第三部分 CoreMark移植
CoreMark是衡量嵌入式系统中微控制器性能的基准。通过列表处理、矩阵处理、状态机和CRC等算法测试系统性能。测试软件是开源的,可以在官方网站EEMBC’s CoreMark®找到。网页截图如下。
09.PNG
解压下载好的压缩包,得到文件结构如下图左侧所示。将simple文件夹下的core_portme.c和core_portme.h复制到USER文件夹中。新建COREMARK文件夹,将core_list_join.c、core_main.c、core_matrix.c、core_state.c、core_util.c、coremark.h等文件复制进去。
10.png
完成文件复制后,新文件分组可参考下图,注意工程路径中也要添加COREMARK文件夹。
11.png
由于core_main.c文件已提供了main()函数,因此原main()函数将无法使用。作为替代,新main()函数执行时会调用core_portme.c中的portable_init()函数,移植时需要将原工程中MCU初始化代码复制到portable_init()函数中并删除原main.c文件。 相关初始化函数如下,设置时钟相关:
  1. void RCC_CFG(void)
  2. {
  3.     RCC_ConfigPclk1(RCC_HCLK_DIV4);
  4.     RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);
  5.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOC, ENABLE);
  6.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOA, ENABLE);
  7.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_USART1,ENABLE);
  8. }
设置串口关联的GPIO:
  1. void GPIO_CFG(void)
  2. {
  3.     GPIO_InitType GPIO_InitStructure;

  4.     GPIO_InitStruct(&GPIO_InitStructure);

  5.     /* Configure USARTx Tx as alternate function push-pull */
  6.     GPIO_InitStructure.Pin            = GPIO_PIN_9;
  7.     GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
  8.     GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART1;
  9.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
  10.    
  11.     /* Configure USARTx Rx as alternate function push-pull and pull-up */
  12.     GPIO_InitStructure.Pin            = GPIO_PIN_10;
  13.     GPIO_InitStructure.GPIO_Pull      = GPIO_Pull_Up;
  14.     GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART1;
  15.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
  16. }
设置串口:
  1. void USART_CFG(void)
  2. {
  3.     USART_StructInit(&USART_InitStructure);
  4.     USART_InitStructure.BaudRate            = 115200;
  5.     USART_InitStructure.WordLength          = USART_WL_8B;
  6.     USART_InitStructure.StopBits            = USART_STPB_1;
  7.     USART_InitStructure.Parity              = USART_PE_NO;
  8.     USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
  9.     USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

  10.     /* Configure USARTx */
  11.     USART_Init(USART1, &USART_InitStructure);
  12.     /* Enable the USARTx */
  13.     USART_Enable(USART1, ENABLE);
  14. }
设置定时器,每1ms一个中断:
  1. void TIM_CFG(void)
  2. {
  3.     /* Time base configuration */
  4.     TIM_TimeBaseStructure.Period    = 1000-1;
  5.     TIM_TimeBaseStructure.Prescaler = 54-1;
  6.     TIM_TimeBaseStructure.ClkDiv    = 0;
  7.     TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;

  8.     TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);

  9.     /* TIM2 enable update irq */
  10.     TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);
  11. }
设置定时器中断:
  1. void NVIC_CFG(void)
  2. {
  3.     NVIC_InitType NVIC_InitStructure;

  4.     NVIC_InitStructure.NVIC_IRQChannel                   = TIM2_IRQn;
  5.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  6.     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
  7.     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

  8.     NVIC_Init(&NVIC_InitStructure);
  9. }
printf重定向:
  1. int fputc(int ch, FILE* f)
  2. {
  3.     USART_SendData(USART1, (uint8_t)ch);
  4.     while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET)
  5.         ;
  6.     return (ch);
  7. }
core_portme.c中,与定时相关的函数有以下三个,在start_time()里实现定时器启动功能,在stop_time()里实现定时器停止功能,在get_time()中获取中断计数值,相关实现如下:
  1. unsigned long time_ms_ticks=0;
  2. void start_time(void)
  3. {
  4.     TIM_Enable(TIM2, ENABLE);
  5. }
  6. Void stop_time(void)
  7. {
  8.     TIM_Enable(TIM2, DISABLE);
  9. }
  10. CORE_TICKS get_time(void)
  11. {
  12.     return time_ms_ticks;
  13. }
  14. void TIM2_IRQHandler(void)
  15. {
  16.     TIM_ClrIntPendingBit(TIM2, TIM_INT_UPDATE);
  17.     time_ms_ticks=time_ms_ticks+1;
  18. }
告知程序,每1000个tick为1s,修改以下宏定义:
  1. #define EE_TICKS_PER_SEC           1000
注释部分不使用的代码。以下代码位于core_portme.c中,需要注释掉:
  1. //#define NSECS_PER_SEC              CLOCKS_PER_SEC
  2. //#define CORETIMETYPE               clock_t
  3. //#define GETMYTIME(_t)              (*_t = clock())
  4. //#define MYTIMEDIFF(fin, ini)       ((fin) - (ini))
  5. //#define TIMER_RES_DIVIDER          1
  6. //#define SAMPLE_TIME_IMPLEMENTATION 1

  7. //static CORETIMETYPE start_time_val, stop_time_val;
运行CoreMark时,测试时间低于10s会抛出错误,经测试N32G435设置迭代次数为3000较为合适:
  1. volatile ee_s32 seed4_volatile = 3000;
打印测试结果时,编译器优化等级在core_portme.h中通过宏COMPILER_FLAGS定义并打印。对应工程设置,修改如下:
  1. #define COMPILER_VERSION "Clang 13.0.0"
  2. #define COMPILER_FLAGS "-Ofast"
编译并下载程序,测试结果如下图所示:
12.png
N32G435,108MHz,267.35分!参考N32G45x系列144MHz,180DMIPS,CoreMark跑分480分;N32G435在108MHz下135DMIPS,初略估算,135/180*108/144*480=270分,与测试结果接近。测试工程已通过附件分享,如有需要可下载参考。

N32G43xCoreMark.zip (380.55 KB, 下载次数: 38)



yljon 发表于 2021-12-27 10:23 | 显示全部楼层
不错啊
怀揣少年梦 发表于 2021-12-27 11:45 | 显示全部楼层
参考一下
zhangjsh 发表于 2021-12-28 06:58 | 显示全部楼层
感谢分享
沧桑小草 发表于 2022-1-17 11:33 | 显示全部楼层
打错啦,是最高108MHz

评论

确实打错了,谢谢提醒。  发表于 2022-2-11 18:31
6552918 发表于 2022-1-17 12:50 | 显示全部楼层
强 厉害 赞 真棒强 厉害 赞 真棒强 厉害 赞 真棒
东裕光大张浩 发表于 2022-1-17 13:36 | 显示全部楼层
最高108MHz,厉害
kyzhd 发表于 2022-1-26 09:20 | 显示全部楼层
请教这玩意测试的意义何在?不是太懂。谢谢
lazyduck 发表于 2022-1-28 15:41 | 显示全部楼层
不错不错,厉害了!
match007 发表于 2022-2-11 16:34 | 显示全部楼层
学习了,感觉好高级
youtome 发表于 2022-2-13 09:57 | 显示全部楼层
主要使用以下三种,MIPS、Dhrystone、Coremark
fengm 发表于 2022-2-13 11:18 | 显示全部楼层
有机会亲测coremark代码            
dzfansman 发表于 2022-2-13 11:27 | 显示全部楼层
想要尝试CoreMark的
wangdezhi 发表于 2022-3-3 22:46 | 显示全部楼层
还有其他的测评程序吗?
tabmone 发表于 2022-3-3 22:56 | 显示全部楼层
N32G435性能还可以啊。  
juliestephen 发表于 2022-3-3 23:13 | 显示全部楼层
这个有参考依据吗?
uiint 发表于 2022-3-3 23:35 | 显示全部楼层
CoreMark排行榜有吗  
biechedan 发表于 2022-3-4 19:48 | 显示全部楼层
CoreMark测评是基于什么原理
丙丁先生 发表于 2023-5-28 15:57 | 显示全部楼层
跑分main.c怎么写?
fengm 发表于 2023-6-13 20:53 | 显示全部楼层
首先通过RCC_APB2PeriphClockCmd函数使能GPIOC时钟,然后初始化PC13引脚为输出模式。在main函数中,执行CoreMark测试,并将结果打印到串口上。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

75

帖子

8

粉丝
快速回复 在线客服 返回列表 返回顶部