Doravmon · 2022年11月28日 · 四川

【GD32F427开发板试用】移植CoreMark验证0等待区Flash大小

引言

非常荣幸能够参与到此次GD32F427开发板试用的活动中来,在拿到开发板之前就翻了翻手册,一直有个疑问困惑着我。

  • 在GD32F4xx用户手册中,描述了零等待区域最大支持1024KB
    image-20221120170101287.png
  • 在GD32F427xx数据手册中,描述了Flash的Code area只有512KB
    image-20221120184407946.png

根据经验来看,GD32的Code area应该就是零等待区,GD32F427的零等待区可能只有512KB,用户手册是针对整个F4系列的,1024KB零等待区是其他型号。
为了验证上面的想法,计划将CoreMark代码分别固定到0~512KB和512KB~1024KB的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出厂时没有焊接的,需要自己找排针来焊接(#^.^#)
image-20221128213303703.png

串口实现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

/* configure COM port */
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};

/*!
    \brief    configure COM port
    \param[in]  COM: COM on the board
      \arg        START_COM0: COM on the board
    \param[out] none
    \retval     none
*/
void gd_eval_com_init(uint32_t com)
{
    /* enable GPIO clock */
    uint32_t COM_ID = 0;
    if(START_COM0 == com)
    {
        COM_ID = 0U;
    }

    rcu_periph_clock_enable( START_COM0_GPIO_CLK);

    /* enable USART clock */
    rcu_periph_clock_enable(COM_CLK[COM_ID]);

    /* connect port to USARTx_Tx */
    gpio_af_set(START_COM0_GPIO_PORT, START_COM0_AF, COM_TX_PIN[COM_ID]);

    /* connect port to USARTx_Rx */
    gpio_af_set(START_COM0_GPIO_PORT, START_COM0_AF, COM_RX_PIN[COM_ID]);

    /* configure USART Tx as alternate function push-pull */
    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]);

    /* configure USART Rx as alternate function push-pull */
    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 configure */
    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重定向代码

/* retarget the C library printf function to the USART */
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的不同地址。
image-20221122203229850.png
可以看到,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
推荐阅读
关注数
10697
内容数
187
中国高性能通用微控制器领域的领跑者兆易创新GD系列芯片技术专栏。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息