天天看點

在STM32F401上移植uC/OS的一個小問題 [原創www.cnblogs.com/helesheng]

在STM32F401上移植uC/OS的一個小問題 [原創www.cnblogs.com/helesheng]

本文給出了在STM32F401上使用探索者開發闆移植的uC/OS時遇到的一個問題的解決過程和方法。

STM32F401xx是意法半導體新推出的Cortex-M4核心的MCU,相較于已經非常流行的STM32F407xx和STM32F427xx等相同核心的MCU而言,其特點是功耗僅為128uA/MHz,且存在64pin封裝的小封裝器件。我設計一款新産品使用了STM32F401xx,想把自己熟悉的uC/OS-II實時作業系統移植到這款MCU上。懶得從底層開始從頭移植,偷懶從原子的“探索者”開發闆移植的uC/OS-II開始修改。完成後在闆子上一跑,發現系統時鐘總存在約5%的偏差。仔細搜尋代碼後才發現,問題在把原子的uC/OS-II移植直接用在STM32F401上時的一個小bug,把發現問題的過程和解決辦法分享給大家。

以下原創内容歡迎網友轉載,但請注明出處:http://cnblogs.com/helesheng

一、把探索者開發闆移植的uC/OS-II用在STM32F401xx上

原子的探索者開發闆使用了STM32F407ZG,其核心是和32F401xx 相同的Cortex-M4,外設也基本相同。簡單地将原子在探索者開發闆上移植的uC/OS-II工程中的Device修改為STM32F401RC,編譯後發現大量的預定義找不到。想到可能是代表處理器的預定義的宏沒有修改,在Option中的C/C++頁中,将Preprocessor Symbols改為代表401的“STM32F401xx,USE_STDPERIPH_DRIVER”,直接編譯通過,心中一陣竊喜。

在STM32F401上移植uC/OS的一個小問題 [原創www.cnblogs.com/helesheng]

圖1 修改預定義

二、uC/OS-II系統時鐘偏差的小問題

運作之前在其它款STM32上寫的uC/OS-II程式,開始一切順利,但随後用示波器仔細分析各個任務内部及互相間的時間關系時,發現總存在+5%左右的時間誤差,即實際系統時鐘的周期隻有理論系統時鐘的95%左右。以每秒系統節拍數OS_TICKS_PER_SEC設定為200為例,每個OSTimeDly(1);的任務延遲僅為4750us。

開始以為是原子編寫的延遲函數void delay_ms(u16 nms);的問題,仔細閱讀代碼後發現,這個函數隻是在調用系統延遲函數OSTimeDly();的基礎之上,将無法由系統延遲實作的us級延遲改由硬延遲實作。雖然我個人非常不贊同這種做法,因為這會造成uC/OS-II時間排程的盲區,進而影響uC/OS-II系統的實時性。但這不至于造成系統時鐘的偏差,繼續查找問題的原因。

既然調用系統延遲函數OSTimeDly的過程沒有問題,那麼隻可能是系統時鐘本身出了問題。Cortex-M核心的uC/OS移植都會用了SysTick定時器的中斷建構系統時鐘,是以在SysTick上找原因。打開MDK,連接配接自制的STM32F401電路闆和仿真器,進入Debug模式,運作程式,讓uC/OS完成初始化配置,然後暫停程式;在外設(peripheral)菜單中找到SysTick定時器,界面如下圖所示。

在STM32F401上移植uC/OS的一個小問題 [原創www.cnblogs.com/helesheng]

圖2 System tick定時器狀态螢幕

其中重裝寄存器中的值為0xC350,即50_000,仔細一想發現有問題——STM32F401的主頻為84MHz,那要達到200Hz的系統時鐘,無論如何都不可能把System Tick的初值配置為50_000啊!于是開始查找uC/OS移植代碼中配置System Tick的部分,原來在探索者開發闆移植代碼中初始化延遲函數delay_init();中。看看原子的代碼。

在STM32F401上移植uC/OS的一個小問題 [原創www.cnblogs.com/helesheng]

圖3 delay_init();函數原來的代碼

原子的代碼簡潔清晰,将System Tick的時鐘配置為AHB時鐘的1/8,在計算System Tick的初值。其中紅圈中的一句是計算AHB時鐘的八分之一,為後續計算定時器初始值做準備。但進一步仔細檢視後發現變量SYSCLK中存放的AHB時鐘數是以MHz作為機關的,對STM32F401xx而言,就是84。84無法整除8,而指派語句左邊的變量reload卻是int型變量,進而導緻了紅圈中的一句計算誤差。這樣即使後一句将reload的機關切換回了Hz,也無法挽回前一句無法整除造成的計算誤差。而這真是uC/OS系統時鐘誤差5%的真正原因!對這兩句進行簡單修改——現将SYSCLK折算為以Hz為機關,即可保證足夠的計算精度。

在STM32F401上移植uC/OS的一個小問題 [原創www.cnblogs.com/helesheng]

圖4 修改過的delay_init();函數代碼

修改過後,uC/OS的系統時鐘又恢複了原有的準确性。

究其原因并不是原子探索者開發闆移植的uC/OS的問題,因為探索者采用的STM32F407ZG運作在168MHz,能夠整除8,不存在這個問題。這裡給大家展示這個過程,一是給大家在STM32F401上移植uC/OS做些探索,二是分享一下嵌入式調試和查找問題的點滴思路和心得。