这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» 国产MCU» 手把手教你移植CoreMark到N32G435

共1条 1/1 1 跳转至

手把手教你移植CoreMark到N32G435

高工
2023-06-04 13:48:30 打赏

手把手教你移植CoreMark到N32G435

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文件。

跑分03.png

完成资源整理后,打开工程配置选项,设置编译器版本为V6.16,勾选使用MicroLIB。

跑分04.png

点选C/C++选项卡,在预处理符号中添加:N32G43X, USE_STDPERIPH_DRIVER, USE_FULL_ASSERT

采用-Ofast优化,勾选优化选项中的Link-Time Optimization,资源包含路径可参考下图。

跑分05.png

打开调试选项卡,右侧调试器选择CMSIS-DAP Debugger。点击Settings进入调试器配置页面。

跑分06.png

在配置页面中选择CMSIS-DAP-NSLink,点击OK即可。至此新工程创建完成。

跑分07.png

第二部分 工程测试

CoreMark的测试结果最终表示为Iterations/Sec,也就是每秒迭代数,因此需要为其提供计时功能。这里使用TIM2以每1ms产生一个中断,控制PC15反转电平,使用虚拟示波器观察波形以测试工程配置是否正确。设置系统时钟为108MHz,APB1四分频27M,注意如果APB1的分频系数大于1,则TIM2的时钟频率加倍,即TIM2时钟为54M。

跑分08.png

时钟初始化代码:

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次,工程测试成功。

跑分09.png

第三部分 CoreMark移植

CoreMark是衡量嵌入式系统中微控制器性能的基准。通过列表处理、矩阵处理、状态机和CRC等算法测试系统性能。测试软件是开源的,可以在官方网站EEMBC’s CoreMark®找到。网页截图如下。

跑分10.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等文件复制进去。

跑分11.png完成文件复制后,新文件分组可参考下图,注意工程路径中也要添加COREMARK文件夹。

跑分12.png

由于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"

编译并下载程序,测试结果如下图所示:

跑分13.png

N32G435,108MHz,267.35分!参考N32G45x系列144MHz,180DMIPS,CoreMark跑分480分;N32G435在108MHz下135DMIPS,初略估算,135/180*108/144*480=270分,与测试结果接近。测试工程已通过附件分享,如有需要可下载参考。





关键词: CoreMark N32G435 移植 手把手

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]