打印
[N32G43x]

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

[复制链接]
2813|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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开发板的一般方法。

第一部分 工程创建
N32G435的支持包需要单独安装,目前版本为0.9.2,pack全称“Nationstech.N32G43x_DFP.0.9.2.pack”,安装pack后使用Keil创建新工程,选择N32G435CB,如下图所示。
新建工程下是没有资源文件的,需要手动添加。依赖文件、中间件和参考例程打包在压缩文件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文件。
完成资源整理后,打开工程配置选项,设置编译器版本为V6.16,勾选使用MicroLIB。
点选C/C++选项卡,在预处理符号中添加:N32G43X, USE_STDPERIPH_DRIVER, USE_FULL_ASSERT
采用-Ofast优化,勾选优化选项中的Link-Time Optimization,资源包含路径可参考下图。
打开调试选项卡,右侧调试器选择CMSIS-DAP Debugger。点击Settings进入调试器配置页面。
在配置页面中选择CMSIS-DAP-NSLink,点击OK即可。至此新工程创建完成。

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

    TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);
    TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);
}
设置定时器中断:
void NVIC_CFG(void)
{
    NVIC_InitType NVIC_InitStructure;

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

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

    GPIO_InitStruct(&GPIO_InitStructure);

    /* Configure USARTx Tx as alternate function push-pull */
    GPIO_InitStructure.Pin            = GPIO_PIN_9;
    GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART1;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
   
    /* Configure USARTx Rx as alternate function push-pull and pull-up */
    GPIO_InitStructure.Pin            = GPIO_PIN_10;
    GPIO_InitStructure.GPIO_Pull      = GPIO_Pull_Up;
    GPIO_InitStructure.GPIO_Alternate = GPIO_AF4_USART1;
    GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);
}
设置串口:
void USART_CFG(void)
{
    USART_StructInit(&USART_InitStructure);
    USART_InitStructure.BaudRate            = 115200;
    USART_InitStructure.WordLength          = USART_WL_8B;
    USART_InitStructure.StopBits            = USART_STPB_1;
    USART_InitStructure.Parity              = USART_PE_NO;
    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
    USART_InitStructure.Mode                = USART_MODE_RX | USART_MODE_TX;

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

    TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);

    /* TIM2 enable update irq */
    TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);
}
设置定时器中断:
void NVIC_CFG(void)
{
    NVIC_InitType NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel                   = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;

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

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

N32G43xCoreMark.zip (380.55 KB)



使用特权

评论回复
沙发
yljon| | 2021-12-27 10:23 | 只看该作者
不错啊

使用特权

评论回复
板凳
怀揣少年梦| | 2021-12-27 11:45 | 只看该作者
参考一下

使用特权

评论回复
地板
zhangjsh| | 2021-12-28 06:58 | 只看该作者
感谢分享

使用特权

评论回复
5
沧桑小草| | 2022-1-17 11:33 | 只看该作者
打错啦,是最高108MHz

使用特权

评论回复
评论
Litthins 2022-2-11 18:31 回复TA
确实打错了,谢谢提醒。 
6
6552918| | 2022-1-17 12:50 | 只看该作者
强 厉害 赞 真棒强 厉害 赞 真棒强 厉害 赞 真棒

使用特权

评论回复
7
东裕光大张浩| | 2022-1-17 13:36 | 只看该作者
最高108MHz,厉害

使用特权

评论回复
8
kyzhd| | 2022-1-26 09:20 | 只看该作者
请教这玩意测试的意义何在?不是太懂。谢谢

使用特权

评论回复
9
lazyduck| | 2022-1-28 15:41 | 只看该作者
不错不错,厉害了!

使用特权

评论回复
10
match007| | 2022-2-11 16:34 | 只看该作者
学习了,感觉好高级

使用特权

评论回复
11
youtome| | 2022-2-13 09:57 | 只看该作者
主要使用以下三种,MIPS、Dhrystone、Coremark

使用特权

评论回复
12
fengm| | 2022-2-13 11:18 | 只看该作者
有机会亲测coremark代码            

使用特权

评论回复
13
dzfansman| | 2022-2-13 11:27 | 只看该作者
想要尝试CoreMark的

使用特权

评论回复
14
wangdezhi| | 2022-3-3 22:46 | 只看该作者
还有其他的测评程序吗?

使用特权

评论回复
15
tabmone| | 2022-3-3 22:56 | 只看该作者
N32G435性能还可以啊。  

使用特权

评论回复
16
juliestephen| | 2022-3-3 23:13 | 只看该作者
这个有参考依据吗?

使用特权

评论回复
17
uiint| | 2022-3-3 23:35 | 只看该作者
CoreMark排行榜有吗  

使用特权

评论回复
18
biechedan| | 2022-3-4 19:48 | 只看该作者
CoreMark测评是基于什么原理

使用特权

评论回复
19
丙丁先生| | 2023-5-28 15:57 | 只看该作者
跑分main.c怎么写?

使用特权

评论回复
20
fengm| | 2023-6-13 20:53 | 只看该作者
首先通过RCC_APB2PeriphClockCmd函数使能GPIOC时钟,然后初始化PC13引脚为输出模式。在main函数中,执行CoreMark测试,并将结果打印到串口上。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

74

帖子

8

粉丝