在ARM Cortex-M上实现FreeRTOS性能计数器
說明:本文翻譯自Erich Styger的文章《Implementing FreeRTOS Performance Counters on ARM Cortex-M》,文章的權屬屬于原作者。
當使用像FreeRTOS這樣的RTOS時,遲早要問一個問題:每個任務花費多少時間?基于Eclipse的MCUXpresso IDE具有很好的視圖,準確顯示了此類信息:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? FreeRTOS運行時信息
為了使FreeRTOS(或“任務列表”視圖)顯示非常有用的信息,開發人員必須提供幫助,以便RTOS可以收集此信息。本文說明如何在ARM Cortex-M上完成此操作。
1、概述
不久前,我從處理器專家的角度討論了FreeRTOS的性能和運行時分析中的該主題。這次是關于使用“本機” FreeRTOS和使用NXP MCUXpresso SDK,但是相同的原理將適用于Cortex-M處理器和微控制器的所有其他環境。至于FreeRTOS端口,我正在使用https://github.com/ErichStyger/McuOnEclipseLibrary中的端口,因為該端口已經存在所有需要的鉤子。GitHub上提供了本文中使用的所有文件和源。
2、如何工作
操作系統使用計數器來衡量任務執行時間。因此,在任務上下文切換時間,此計數器用于確定該任務使用的時間。重要的一點是,該時間不是絕對的(例如37毫秒),而是一些“滴答聲”(例如241個滴答聲)。RTOS知道總體上使用了多少“滴答聲”。RTOS知道系統中有多少個任務,因此它可以顯示每個任務花費了總時間的百分比。另一個要注意的是,時間*包括*在中斷中花費的時間。
這是一種非常簡單但功能強大的估算任務執行時間的方法,通常就是您所需要的。它可以通過一種非常簡單的方式來實現:使用一個使計數器遞增的計時器和一個用于讀取計數器值的函數。
要打開性能測量,我必須啟用兩個FreeRTOS配置設置:
#define configUSE_TRACE_FACILITY 1 /* 1: include additional structure members and functions to assist with execution visualization and tracing, 0: no runtime stats/trace */#define configGENERATE_RUN_TIME_STATS 1 /* 1: generate runtime statistics; 0: no runtime statistics */要配置計時器并讀取計數器,我必須使用兩個宏來告訴函數名稱:
#define configGET_RUNTIMER_COUNTER_VALUE_FROM_ISR?? AppGetRuntimeCounterValueFromISR#define configCONFIGURE_TIMER_FOR_RUNTIME_STATS???? AppConfigureTimerForRuntimeStats3、使用“滴答”計數器
一種非常簡單的衡量任務執行情況的方法是使用FreeRTOS滴答計數器本身。可以通過以下方式啟用
#define configGENERATE_RUN_TIME_STATS_USE_TICKS???? (1)但是,這僅在任務執行時間超過RTOS滴答周期時才能測量任務執行時間。對于更快的任務,此方法沒有用。根據Nyquist-Shannon采樣定理,我最好使用2倍(更好:10倍)的測量頻率。
4、使用Cortex-M周期計數器
實現該計數器的另一種方法是使用Cortex-M周期計數器,該計數器已在許多設備上實現,并給出了很好的結果。最好的是:無需中斷或額外的計時器。可能的實現如下所示:
static uint32_t prevCycleCounter, cycleCntCounter = 0;void AppConfigureTimerForRuntimeStats(void) {cycleCntCounter = 0;McuArmTools_InitCycleCounter();prevCycleCounter = McuArmTools_GetCycleCounter(); }uint32_t AppGetRuntimeCounterValueFromISR(void) {uint32_t newCntr, diff;newCntr = McuArmTools_GetCycleCounter();diff = newCntr-prevCycleCounter;prevCycleCounter = newCntr;cycleCntCounter += diff>>12; /* scale down the counter */return cycleCntCounter; }5、使用定期定時器中斷
標準方法是使用定期中斷計時器,該計時器增加計數器。對于1 kHz滴答計時器,推薦的頻率是FreeRTOS滴答計時器頻率的10倍,在這種情況下為10 kHz(100 us):
static uint32_t perfCounter = 0;#define PIT_BASEADDR?????? PIT #define PIT_SOURCE_CLOCK?? CLOCK_GetFreq(kCLOCK_BusClk) #define PIT_CHANNEL??????? kPIT_Chnl_0 #define PIT_HANDLER??????? PIT0_IRQHandler #define PIT_IRQ_ID???????? PIT0_IRQnvoid PIT_HANDLER(void) {PIT_ClearStatusFlags(PIT_BASEADDR, PIT_CHANNEL, kPIT_TimerFlag);perfCounter++;__DSB(); }void AppConfigureTimerForRuntimeStats(void) {pit_config_t config;PIT_GetDefaultConfig(&config);config.enableRunInDebug = false;PIT_Init(PIT_BASEADDR, &config);PIT_SetTimerPeriod(PIT_BASEADDR, PIT_CHANNEL, USEC_TO_COUNT(100U, PIT_SOURCE_CLOCK));PIT_EnableInterrupts(PIT_BASEADDR, PIT_CHANNEL, kPIT_TimerInterruptEnable);NVIC_SetPriority(PIT_IRQ_ID, 0);EnableIRQ(PIT_IRQ_ID);PIT_StartTimer(PIT_BASEADDR, PIT_CHANNEL); }uint32_t AppGetRuntimeCounterValueFromISR(void) {return perfCounter; }6、摘要
FreeRTOS包含一項功能,可以測量相對于系統中其他任務的任務執行時間。我需要提供的是計時器或某種計數器的初始化例程,以及獲取計數器值的方法。如果您對檢查FreeRTOS計時的其他方式感興趣,請查看Percepio Tracealyzer或Segger?SystemView。如果您希望應用程序本身顯示性能數據,請查看“?使用FreeRTOS進行性能和運行時分析”中介紹的Shell / Commandline實現。
7、鏈接
- GitHub上的項目:https?:?//github.com/ErichStyger/mcuoneclipse/tree/master/Examples/MCUXpresso/tinyK22/tinyK22_FreeRTOS
- FreeRTOS的性能和運行時分析
- 在Eclipse中更好的FreeRTOS調試
- ARM SWO性能計數器
- GitHub上的McuLib:https?:?//github.com/ErichStyger/McuOnEclipseLibrary
- MCUXpresso IDE和SDK:https?://mcuxpresso.nxp.com
歡迎關注:
總結
以上是生活随笔為你收集整理的在ARM Cortex-M上实现FreeRTOS性能计数器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 区块链读书笔记四
- 下一篇: 最优化学习笔记(三)最速下降法