首頁(yè) > 評(píng)測(cè) > 【AT-START-F437測(cè)評(píng)】性能強(qiáng)者雅特力AT32F437試用和性能評(píng)測(cè)

【AT-START-F437測(cè)評(píng)】性能強(qiáng)者雅特力AT32F437試用和性能評(píng)測(cè)

  
  • 作者:
  • 來(lái)源:
  • [導(dǎo)讀]
  • 本帖最后由 Geralt 于 2023-2-2 10:42 編輯 #技術(shù)資源# #申請(qǐng)?jiān)瓌?chuàng)# 性能強(qiáng)者雅特力AT32F437試用和性能評(píng)測(cè) 本文首發(fā)于21ic,轉(zhuǎn)載請(qǐng)保留原始連接和作者ID。 前言 在這次本次21ic的雅特力開(kāi)發(fā)板評(píng)測(cè)

本帖最后由 Geralt 于 2023-2-2 10:42 編輯

#技術(shù)資源# #申請(qǐng)?jiān)瓌?chuàng)#
性能強(qiáng)者雅特力AT32F437試用和性能評(píng)測(cè)

本文首發(fā)于21ic,轉(zhuǎn)載請(qǐng)保留原始連接和作者ID。

前言

在這次本次21ic的雅特力開(kāi)發(fā)板評(píng)測(cè)活動(dòng)中,我很榮幸的申請(qǐng)到了AT-START-F437這款開(kāi)發(fā)板。作為一個(gè)業(yè)余電子愛(ài)好者,我一直對(duì)高性能通用MCU有著濃厚的興趣。可惜的是,該領(lǐng)域之前大多被國(guó)外廠商所把控。但隨著這兩年局勢(shì)的變化和國(guó)內(nèi)相關(guān)產(chǎn)業(yè)的發(fā)展,越來(lái)越多的國(guó)產(chǎn)MCU廠商開(kāi)始涉足此領(lǐng)域并推出了相應(yīng)的產(chǎn)品。而本文的主角,AT-START-F437開(kāi)發(fā)板的核心雅特力AT32F437便是其中的代表之一。



根據(jù)官方的數(shù)據(jù)表。AT32F437的核心為帶有單精度浮點(diǎn)運(yùn)算單元和DSP指令集的的Cortex-M4內(nèi)核,擁有最高288MHz的主頻、4032KB的Flash和512KB SRAM。除此之外,該型號(hào)還支持通過(guò)外擴(kuò)SDRAM/NAND/QSPI-FLASH/QSPI-PSRAM等常見(jiàn)存儲(chǔ)器。本次到手的AT-START-F437開(kāi)發(fā)板搭載的MCU的具體型號(hào)為AT32F437ZMT7,是AT32F437產(chǎn)品線中最高端的型號(hào)。



開(kāi)發(fā)板板載的資源除了常見(jiàn)的LED燈和按鍵和GPIO排針外,還帶有3個(gè)USB接口(一個(gè)HOST兩個(gè)OTG,其中HOST和OTG1使用同一外設(shè))、一個(gè)RJ-45以太網(wǎng)接口和PHY、還有一顆QSPI-Flash,對(duì)于START開(kāi)發(fā)板的定位來(lái)說(shuō)還算夠用。開(kāi)發(fā)板自帶了AT-Link,可以支持程序的下載、調(diào)試以及串口通訊,十分方便。不過(guò)這里還是想吐槽一下,都202x年了,咱就不能把AT-LINK的USB接口換成TYPE-C的嘛。。。。。



點(diǎn)燈:開(kāi)發(fā)環(huán)境的建立和GPIO速度測(cè)試

上手一款MCU,最好的方式就是“點(diǎn)燈”了。作為嵌入式領(lǐng)域的“Hello World”,通過(guò)點(diǎn)燈不僅可以快速熟悉MCU的基本開(kāi)發(fā)流程、而且可以幫助我們?cè)u(píng)估一款MCU資料的豐富程度和開(kāi)發(fā)的難易程度。

在傳統(tǒng)的印象里,資料是國(guó)產(chǎn)MCU最大的短板。具體表現(xiàn)有官網(wǎng)難用、資料難找、文檔不全/錯(cuò)誤多、中文文檔偏少、缺乏例程,外設(shè)庫(kù)不完善,開(kāi)發(fā)流程復(fù)雜等等等等。令人感到驚喜的是,雅特力在這方面做得相當(dāng)不錯(cuò)。官網(wǎng)非常好用,通過(guò)頂部的導(dǎo)航欄就可以快速找到對(duì)應(yīng)的產(chǎn)品線:然后在產(chǎn)品的主頁(yè)上就可以把所有的相關(guān)文檔、庫(kù)和工具一并下載下來(lái),**沒(méi)有多級(jí)隱藏菜單,不需要會(huì)員**。




雅特力的MCU除了傳統(tǒng)的MDK開(kāi)發(fā)方式外,也自行開(kāi)發(fā)了基于Eclipse平臺(tái)的專(zhuān)用IDEAT32 IDE,這在國(guó)產(chǎn)品牌中也是比較少見(jiàn)的,自行開(kāi)發(fā)IDE可以針對(duì)自己產(chǎn)品的特點(diǎn)對(duì)開(kāi)發(fā)環(huán)境進(jìn)行深度定制,這也是研發(fā)實(shí)力的一種體現(xiàn)。




目前AT32-IDE的完成度還是很高的,通過(guò)File->New C Project,我們可以很輕松的基于內(nèi)置的項(xiàng)目模板來(lái)創(chuàng)建一個(gè)AT32F437的項(xiàng)目,默認(rèn)的代碼已經(jīng)完成了MCU的基本初始化,并且提供了基于START開(kāi)發(fā)板的點(diǎn)燈代碼,這倒是省事兒了。





將開(kāi)發(fā)板連接至PC,點(diǎn)擊IDE上的編譯按鈕,等待編譯結(jié)束后點(diǎn)擊下載,就可以把代碼下載到開(kāi)發(fā)板上了,整個(gè)過(guò)程非常流暢。



代碼運(yùn)行效果:



基本的點(diǎn)燈完成了,來(lái)測(cè)試一下AT32F437通過(guò)寄存器控制GPIO的最大翻轉(zhuǎn)速度,也就是GPIO的軟件翻轉(zhuǎn)速度。大多數(shù)情況下,我們并沒(méi)有單純使用軟件代碼來(lái)高頻翻轉(zhuǎn)GPIO的需求。但在某些場(chǎng)合,比如需要模擬某些MCU不支持的物理協(xié)議時(shí),GPIO的軟件翻轉(zhuǎn)速度就很重要了。在絕大多數(shù)型號(hào)的MCU上,GPIO的軟件翻轉(zhuǎn)速率都遠(yuǎn)遠(yuǎn)低于使用外設(shè)(如SPI或者TIMER)時(shí)的翻轉(zhuǎn)速率。這其中最鼎鼎大名的就是STM32H750,雖然擁有高達(dá)480MHz的主頻和125MHz的GPIO物理速度,但是通過(guò)GPIO寄存器控制電平反轉(zhuǎn)時(shí),其翻轉(zhuǎn)速率只有16~20MHz,不到主頻的1/24,表現(xiàn)十分糟糕。讓我們來(lái)看看AT32F437的表現(xiàn)如何。

測(cè)試選用的GPIO為PE2, 初始化和測(cè)試代碼如下:

  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.   }
復(fù)制代碼




通過(guò)示波器在PE2引腳測(cè)得結(jié)果如下:



72MHz的軟件速度,達(dá)到了主頻288MHz的1/4,平均2個(gè)周期翻轉(zhuǎn)一次(這個(gè)周期包含了循環(huán)消耗的指令周期),可以說(shuō)是非常優(yōu)秀的成績(jī)了。


跑分:CoreMark的移植

CoreMark是一個(gè)專(zhuān)為嵌入式處理器設(shè)計(jì)的性能基準(zhǔn)測(cè)試軟件,它內(nèi)部包含了一套全面的性能測(cè)試案例,是嵌入式領(lǐng)域性能測(cè)試的事實(shí)標(biāo)準(zhǔn)之一。CoreMark以代碼形式分發(fā),我們可以下載之后將其加入工程中編譯并運(yùn)行。運(yùn)行之后,CoreMark會(huì)生成一個(gè)分?jǐn)?shù),使用這個(gè)分?jǐn)?shù)可以直觀的進(jìn)行性能的對(duì)比,方面我們了解不同處理器或者編譯器之間的性能差距。

在AT32-IDE進(jìn)行CoreMark的移植是相當(dāng)簡(jiǎn)單的,首先我們需要保證串口打印功能正常,這里我們可以直接調(diào)用IDE為我們自動(dòng)生成的開(kāi)發(fā)板初始化函數(shù):

  1.         uart_print_init(115200);
復(fù)制代碼



CoreMark的打印輸出需要浮點(diǎn)支持,我們?cè)陧?xiàng)目的build setting中將其開(kāi)啟:



接著我們?cè)谟脩?hù)代碼文件夾下新建“CoreMark”文件夾,將CoreMark代碼復(fù)制進(jìn)去:



CoreMark的運(yùn)行需要一個(gè)時(shí)間基準(zhǔn),我們初始化TIMER1,生成一個(gè)以1毫秒為單位的時(shí)間基準(zhǔn):

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);
復(fù)制代碼




時(shí)間基準(zhǔn)相關(guān)函數(shù)

  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.     }
復(fù)制代碼




修改CoreMark的core_portme.c中的相關(guān)代碼,添加我們的時(shí)間基準(zhǔn)

  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. }
復(fù)制代碼




因?yàn)槲覀円呀?jīng)自行完成了硬件的初始化,此處根據(jù)需要修改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. }
復(fù)制代碼




最后,在main函數(shù)中調(diào)用CoreMark的主函數(shù):

  1. CoreMark_Main(0, 0);
復(fù)制代碼




編譯,下載,運(yùn)行,通過(guò)串口監(jiān)視器,我們可以得到最終跑分:



在AT32-IDE默認(rèn)的GCC編譯器下,AT32F437跑出了715分的分?jǐn)?shù),介于STM32U575和STM32F756之間:



這已經(jīng)是一個(gè)相當(dāng)恐怖的分?jǐn)?shù)了,要知道STM32F756可是Coretex-M7內(nèi)核,還帶有L1-Cache的高性能跨界型MCU,而且分?jǐn)?shù)還是使用IAR編譯器跑出來(lái)的。如果使用同樣的GCC編譯器,那么F756分?jǐn)?shù)也就700~800分左右。AT32F437居然用不帶cache的M4內(nèi)核逼近了M7內(nèi)核的分?jǐn)?shù),性能可以說(shuō)是非常強(qiáng)悍了。

結(jié)語(yǔ)

AT32F437的性能強(qiáng)悍,配置也非常豐富,已經(jīng)足以支撐類(lèi)似HMI之類(lèi)的應(yīng)用場(chǎng)景。因?yàn)橘Y料豐富,所以可玩性很強(qiáng)。配套的IDE用起來(lái)也很方便。之后,我會(huì)嘗試移植一些圖形庫(kù)如LVGL進(jìn)來(lái),到時(shí)再與大家分享。

附件為移植好的CoreMark工程。

AT32F437ZM-Blink.zip (513.13 KB)

  • 本文系21ic原創(chuàng),未經(jīng)許可禁止轉(zhuǎn)載!

網(wǎng)友評(píng)論

  • 聯(lián)系人:巧克力娃娃
  • 郵箱:board@21ic.com
  • 我要投稿
  • 歡迎入駐,開(kāi)放投稿

熱門(mén)標(biāo)簽
項(xiàng)目外包 more+