首页 > 评测 > 【AT-START-F437测评】性能强者雅特力AT32F437试用和性能评测

【AT-START-F437测评】性能强者雅特力AT32F437试用和性能评测

  
  • 作者:
  • 来源:
  • [导读]
  • 本帖最后由 Geralt 于 2023-2-2 10:42 编辑 #技术资源# #申请原创# 性能强者雅特力AT32F437试用和性能评测 本文首发于21ic,转载请保留原始连接和作者ID。 前言 在这次本次21ic的雅特力开发板评测

本帖最后由 Geralt 于 2023-2-2 10:42 编辑

#技术资源# #申请原创#
性能强者雅特力AT32F437试用和性能评测

本文首发于21ic,转载请保留原始连接和作者ID。

前言

在这次本次21ic的雅特力开发板评测活动中,我很荣幸的申请到了AT-START-F437这款开发板。作为一个业余电子爱好者,我一直对高性能通用MCU有着浓厚的兴趣。可惜的是,该领域之前大多被国外厂商所把控。但随着这两年局势的变化和国内相关产业的发展,越来越多的国产MCU厂商开始涉足此领域并推出了相应的产品。而本文的主角,AT-START-F437开发板的核心雅特力AT32F437便是其中的代表之一。



根据官方的数据表。AT32F437的核心为带有单精度浮点运算单元和DSP指令集的的Cortex-M4内核,拥有最高288MHz的主频、4032KB的Flash和512KB SRAM。除此之外,该型号还支持通过外扩SDRAM/NAND/QSPI-FLASH/QSPI-PSRAM等常见存储器。本次到手的AT-START-F437开发板搭载的MCU的具体型号为AT32F437ZMT7,是AT32F437产品线中最高端的型号。



开发板板载的资源除了常见的LED灯和按键和GPIO排针外,还带有3个USB接口(一个HOST两个OTG,其中HOST和OTG1使用同一外设)、一个RJ-45以太网接口和PHY、还有一颗QSPI-Flash,对于START开发板的定位来说还算够用。开发板自带了AT-Link,可以支持程序的下载、调试以及串口通讯,十分方便。不过这里还是想吐槽一下,都202x年了,咱就不能把AT-LINK的USB接口换成TYPE-C的嘛。。。。。



点灯:开发环境的建立和GPIO速度测试

上手一款MCU,最好的方式就是“点灯”了。作为嵌入式领域的“Hello World”,通过点灯不仅可以快速熟悉MCU的基本开发流程、而且可以帮助我们评估一款MCU资料的丰富程度和开发的难易程度。

在传统的印象里,资料是国产MCU最大的短板。具体表现有官网难用、资料难找、文档不全/错误多、中文文档偏少、缺乏例程,外设库不完善,开发流程复杂等等等等。令人感到惊喜的是,雅特力在这方面做得相当不错。官网非常好用,通过顶部的导航栏就可以快速找到对应的产品线:然后在产品的主页上就可以把所有的相关文档、库和工具一并下载下来,**没有多级隐藏菜单,不需要会员**。




雅特力的MCU除了传统的MDK开发方式外,也自行开发了基于Eclipse平台的专用IDEAT32 IDE,这在国产品牌中也是比较少见的,自行开发IDE可以针对自己产品的特点对开发环境进行深度定制,这也是研发实力的一种体现。




目前AT32-IDE的完成度还是很高的,通过File->New C Project,我们可以很轻松的基于内置的项目模板来创建一个AT32F437的项目,默认的代码已经完成了MCU的基本初始化,并且提供了基于START开发板的点灯代码,这倒是省事儿了。





将开发板连接至PC,点击IDE上的编译按钮,等待编译结束后点击下载,就可以把代码下载到开发板上了,整个过程非常流畅。



代码运行效果:



基本的点灯完成了,来测试一下AT32F437通过寄存器控制GPIO的最大翻转速度,也就是GPIO的软件翻转速度。大多数情况下,我们并没有单纯使用软件代码来高频翻转GPIO的需求。但在某些场合,比如需要模拟某些MCU不支持的物理协议时,GPIO的软件翻转速度就很重要了。在绝大多数型号的MCU上,GPIO的软件翻转速率都远远低于使用外设(如SPI或者TIMER)时的翻转速率。这其中最鼎鼎大名的就是STM32H750,虽然拥有高达480MHz的主频和125MHz的GPIO物理速度,但是通过GPIO寄存器控制电平反转时,其翻转速率只有16~20MHz,不到主频的1/24,表现十分糟糕。让我们来看看AT32F437的表现如何。

测试选用的GPIO为PE2, 初始化和测试代码如下:

  1. gpio_init_type gpio_init_struct;
  2.  
  3.   /* enable the led clock */
  4.   crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
  5.  
  6.   /* set default parameter */
  7.   gpio_default_para_init(&gpio_init_struct);
  8.  
  9.   /* configure the led gpio */
  10.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  11.   gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  12.   gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  13.   gpio_init_struct.gpio_pins = GPIO_PINS_2;
  14.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  15.   gpio_init(GPIOE, &gpio_init_struct);
  16.  
  17.   for(;;)
  18.   {
  19.           GPIOE->scr = GPIO_PINS_2;
  20.           GPIOE->clr = GPIO_PINS_2;
  21.   }
复制代码




通过示波器在PE2引脚测得结果如下:



72MHz的软件速度,达到了主频288MHz的1/4,平均2个周期翻转一次(这个周期包含了循环消耗的指令周期),可以说是非常优秀的成绩了。


跑分:CoreMark的移植

CoreMark是一个专为嵌入式处理器设计的性能基准测试软件,它内部包含了一套全面的性能测试案例,是嵌入式领域性能测试的事实标准之一。CoreMark以代码形式分发,我们可以下载之后将其加入工程中编译并运行。运行之后,CoreMark会生成一个分数,使用这个分数可以直观的进行性能的对比,方面我们了解不同处理器或者编译器之间的性能差距。

在AT32-IDE进行CoreMark的移植是相当简单的,首先我们需要保证串口打印功能正常,这里我们可以直接调用IDE为我们自动生成的开发板初始化函数:

  1.         uart_print_init(115200);
复制代码



CoreMark的打印输出需要浮点支持,我们在项目的build setting中将其开启:



接着我们在用户代码文件夹下新建“CoreMark”文件夹,将CoreMark代码复制进去:



CoreMark的运行需要一个时间基准,我们初始化TIMER1,生成一个以1毫秒为单位的时间基准:

TIMER初始化部分

  1.         /* enable tmr1 clock */
  2.         crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE);
  3.  
  4.         /* tmr1 configuration */
  5.         /* time base configuration */
  6.         tmr_base_init(TMR1, 999, 288 - 1);
  7.         tmr_cnt_dir_set(TMR1, TMR_COUNT_UP);
  8.  
  9.         /* overflow interrupt enable */
  10.         tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE);
  11.  
  12.         /* tmr1 hall interrupt nvic init */
  13.         nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  14.         nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0);
  15.  
  16.         /* enable tmr1 */
  17.         tmr_counter_enable(TMR1, TRUE);
复制代码




时间基准相关函数

  1.     volatile uint32_t uwTick = 0;
  2.  
  3.     uint32_t HAL_GetTick(){
  4.         return uwTick;
  5.     }
  6.  
  7.     /**
  8.     * <a href="home.php?mod=space&uid=247401" target="_blank">@brief</a>  this function handles timer1 overflow handler.
  9.     * @param  none
  10.     * @retval none
  11.     */
  12.     void TMR1_OVF_TMR10_IRQHandler(void) {
  13.         if (tmr_flag_get(TMR1, TMR_OVF_FLAG) == SET) {
  14.             uwTick++;
  15.             tmr_flag_clear(TMR1, TMR_OVF_FLAG);
  16.         }
  17.     }
复制代码




修改CoreMark的core_portme.c中的相关代码,添加我们的时间基准

  1. /* Function : start_time
  2.         This function will be called right before starting the timed portion of the benchmark.
  3.  
  4.         Implementation may be capturing a system timer (as implemented in the example code)
  5.         or zeroing some system parameters - e.g. setting the cpu clocks cycles to 0.
  6. */
  7. void start_time(void) {
  8.         Tick = HAL_GetTick();
  9. }
  10. /* Function : stop_time
  11.         This function will be called right after ending the timed portion of the benchmark.
  12.  
  13.         Implementation may be capturing a system timer (as implemented in the example code)
  14.         or other system parameters - e.g. reading the current value of cpu cycles counter.
  15. */
  16. void stop_time(void) {
  17. }
  18. /* Function : get_time
  19.         Return an abstract "ticks" number that signifies time on the system.
  20.         
  21.         Actual value returned may be cpu cycles, milliseconds or any other value,
  22.         as long as it can be converted to seconds by <time_in_secs>.
  23.         This methodology is taken to accomodate any hardware or simulated platform.
  24.         The sample implementation returns millisecs by default,
  25.         and the resolution is controlled by <TIMER_RES_DIVIDER>
  26. */
  27. CORE_TICKS get_time(void) {
  28.         CORE_TICKS elapsed = (CORE_TICKS)(HAL_GetTick()-Tick);
  29.         return elapsed;
  30. }
  31. /* Function : time_in_secs
  32.         Convert the value returned by get_time to seconds.
  33.  
  34.         The <secs_ret> type is used to accomodate systems with no support for floating point.
  35.         Default implementation implemented by the EE_TICKS_PER_SEC macro above.
  36. */
  37. secs_ret time_in_secs(CORE_TICKS ticks) {
  38.         secs_ret retval=((secs_ret)ticks) / (secs_ret)EE_TICKS_PER_SEC;
  39.         return retval;
  40. }
复制代码




因为我们已经自行完成了硬件的初始化,此处根据需要修改portable_init即可

  1. extern crm_clocks_freq_type crm_clocks_freq_struct;
  2.  
  3. /* Function : portable_init
  4.         Target specific initialization code
  5.         Test for some common mistakes.
  6. */
  7. void portable_init(core_portable *p, int *argc, char *argv[])
  8. {
  9.         ee_printf("CoreMark run on AT32F437ZMT7 <a href="home.php?mod=space&uid=72445" target="_blank">@</a> %luHz\r\n",  crm_clocks_freq_struct.sclk_freq);
  10.  
  11.         if (sizeof(ee_ptr_int) != sizeof(ee_u8*)) {
  12.                 ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\r\n");
  13.         }
  14.         if (sizeof(ee_u32) != 4) {
  15.                 ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\r\n");
  16.         }
  17.         p->portable_id = 1;
  18. }
复制代码




最后,在main函数中调用CoreMark的主函数:

  1. CoreMark_Main(0, 0);
复制代码




编译,下载,运行,通过串口监视器,我们可以得到最终跑分:



在AT32-IDE默认的GCC编译器下,AT32F437跑出了715分的分数,介于STM32U575和STM32F756之间:



这已经是一个相当恐怖的分数了,要知道STM32F756可是Coretex-M7内核,还带有L1-Cache的高性能跨界型MCU,而且分数还是使用IAR编译器跑出来的。如果使用同样的GCC编译器,那么F756分数也就700~800分左右。AT32F437居然用不带cache的M4内核逼近了M7内核的分数,性能可以说是非常强悍了。

结语

AT32F437的性能强悍,配置也非常丰富,已经足以支撑类似HMI之类的应用场景。因为资料丰富,所以可玩性很强。配套的IDE用起来也很方便。之后,我会尝试移植一些图形库如LVGL进来,到时再与大家分享。

附件为移植好的CoreMark工程。

AT32F437ZM-Blink.zip (513.13 KB)

  • 本文系21ic原创,未经许可禁止转载!

网友评论