引言
非常荣幸能够参与到此次GD32F427开发板试用的活动中来,在拿到开发板之前就翻了翻手册,一直有个疑问困惑着我。
在GD32F4xx用户手册中,描述了零等待区域最大支持1024KB
在GD32F427xx数据手册中,描述了Flash的Code area只有512KB
根据经验来看,GD32的Code area应该就是零等待区,GD32F427的零等待区可能只有512KB,用户手册是针对整个F4系列的,1024KB零等待区是其他型号。
为了验证上面的想法,计划将CoreMark代码分别固定到0512KB和512KB1024KB的Flash区间内,根据在不同区间的CoreMark跑分来确定此款开发板上搭载的GD32F427VK芯片的零等待区大小。
开发环境
IDE:Keil v5.36.0.0
编译器:ARMCC v5.06 update 7
参考工程:官方GD32F4xx_Demo_Suites_V2.6.1中的LED工程
CoreMark源码:从RT-Thread的组件中下载
验证猜想
焊接IO
由于需要使用串口打印CoreMark跑分,首先需要将芯片串口接出。开发板上用GD32F103实现的CMSIS-DAP调试器貌似没有CDC功能,只能将芯片串口外接USB转TTL电平串口了。但此款开发板两侧引出的IO出厂时没有焊接的,需要自己找排针来焊接
串口实现printf
将开发板PB6和PB7复用为串口1,代码如下
#define COMn 1U
#define START_COM0 USART0
#define START_COM0_CLK RCU_USART0
#define START_COM0_TX_PIN GPIO_PIN_6
#define START_COM0_RX_PIN GPIO_PIN_7
#define START_COM0_GPIO_PORT GPIOB
#define START_COM0_GPIO_CLK RCU_GPIOB
#define START_COM0_AF GPIO_AF_7
void gd_start_com_init(uint32_t com);
static rcu_periph_enum COM_CLK[COMn] = {START_COM0_CLK};
static uint32_t COM_TX_PIN[COMn] = {START_COM0_TX_PIN};
static uint32_t COM_RX_PIN[COMn] = {START_COM0_RX_PIN};
void gd_eval_com_init(uint32_t com)
{
uint32_t COM_ID = 0;
if(START_COM0 == com)
{
COM_ID = 0U;
}
rcu_periph_clock_enable( START_COM0_GPIO_CLK);
rcu_periph_clock_enable(COM_CLK[COM_ID]);
gpio_af_set(START_COM0_GPIO_PORT, START_COM0_AF, COM_TX_PIN[COM_ID]);
gpio_af_set(START_COM0_GPIO_PORT, START_COM0_AF, COM_RX_PIN[COM_ID]);
gpio_mode_set(START_COM0_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP,COM_TX_PIN[COM_ID]);
gpio_output_options_set(START_COM0_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,COM_TX_PIN[COM_ID]);
gpio_mode_set(START_COM0_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP,COM_RX_PIN[COM_ID]);
gpio_output_options_set(START_COM0_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,COM_RX_PIN[COM_ID]);
usart_deinit(com);
usart_baudrate_set(com,115200U);
usart_receive_config(com, USART_RECEIVE_ENABLE);
usart_transmit_config(com, USART_TRANSMIT_ENABLE);
usart_enable(com);
}
printf重定向代码
int fputc(int ch, FILE *f)
{
usart_data_transmit(START_COM0, (uint8_t)ch);
while(RESET == usart_flag_get(START_COM0, USART_FLAG_TBE));
return ch;
}
移植CoreMark
CoreMark代码移植的部分已经有大佬写过了,而且我这里移植CoreMark的目的只是为了对比程序放到不同的Flash地址对性能的影响,因此不再赘述。
移植完后,整体程序也只有几十KB,没有超过512KB,必定是在零等待区的,跑分情况如下:
Benchmark started, please make sure it runs for at least 10s.
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 11491
Total time (secs): 11.490
Iterations/Sec : 522.147
Iterations : 6000
Compiler version : ARMCC V5.06
Compiler flags : -O3 -Otime
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0xa14c
Correct operation validated. See README.md for run and reporting rules.
Iterations/Sec : 522.147
CoreMark 1.0 : 2.610 DMIPS/MHz / ARMCC V5.06 -O3 -Otime / STACK
这里主要讲一下如何将CoreMark代码定位到Flash的不同地址。
可以看到,CoreMark代码文件都是以core_
开头的,那其编译出的.o
文件也是以此命名。在Keil中使用scatter分散加载文件来定位程序在Flash中的位置,修改scatter文件,将CoreMark代码定位到Flash的512KB位置
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00030000 { ; RW data
.ANY (+RW +ZI)
}
}
LR_COREMARK 0x08080000 0x00010000 { ; load region size_region
ER_COREMARK 0x08080000 0x00010000 {
core_*.o
}
}
再次跑分,肉眼可见分数极低。也就验证了一开始的猜想,此款开发板上搭载的GD32F427VK芯片的零等待区就只有512KB大小。
Benchmark started, please make sure it runs for at least 10s.
2K performance run parameters for coremark.
CoreMark Size : 666
Total ticks : 44315
Total time (secs): 44.314
Iterations/Sec : 135.394
Iterations : 6000
Compiler version : ARMCC V5.06
Compiler flags : -O3 -Otime
Memory location : STACK
seedcrc : 0xe9f5
[0]crclist : 0xe714
[0]crcmatrix : 0x1fd7
[0]crcstate : 0x8e3a
[0]crcfinal : 0xa14c
Correct operation validated. See README.md for run and reporting rules.
Iterations/Sec : 135.394
CoreMark 1.0 : 0.676 DMIPS/MHz / ARMCC V5.06 -O3 -Otime / STACK
原作者:兆易创新GD32 MCU Doravmon