1.這是一個有許多經驗的攻城獅都遇到過的坑,本文教你正確繞過這個坑;
2.教大家了解__get_CONTROL的用法,及xQueueSend和xQueueSendFromISR的區別;
Ⅰ問題來源
今天在FreeRTOS系統上移植了部分別人寫的代碼,移植前仔細看了下源碼,確認沒問題后,編譯,下載,運行,突然“死機了”······
于是,我又再次確認了移植的代碼,沒有發現Bug所在。此時,我開啟了在線調試功能,發現程序死在了“vPortEnterCritical”函數中的斷言語句里。如下:
Ⅱ解決問題的過程
我解決問題還是按照常規思維,一步一步跟蹤,很多問題其實都是類似道理,有規律可循。
1.查看configASSERT斷言做了什么事?
跟蹤代碼:
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ); }
其中,里面taskDISABLE_ INTERRUPTS();就是關中斷的意思。緊跟著后面執行了for( ;; );
看到這里,我明白了一點,就是死在for( ;; );里面了。
2.進一步查找問題
我又開始了思考,為什么會執行到這里來呢?為什么會執行portDISABLE_INTERRUPTS(); uxCriticalNesting++; if( uxCriticalNesting == 1 )等這些語句呢?
這就是我們常說的“臨界段”,這一點我學習RTOS的時候已經明白了,這一個函數肯定會被調用。于是,我把目標鎖定了portNVIC_INT_CTRL_REG這個參數:
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
0xe000ed04? 這個地址,相信之前了解過NVIC的都知道,就是Interrupt control state register.即中斷控制狀態寄存器。
3.確定問題點
從上面的分析,其實問題都已經浮現出來了。于是查看了【Cortex-M3權威指南】中相關的內容。(PS:這本手冊真的能解決很多問題,翻譯成中文,對大部分朋友來說是一件好事)
其實,有這個一個寄存器:控制寄存器(CONTROL),里面講述的非常清楚:
看上圖,大概意思就是:在中斷模式下,CONTROL[1]為0。于是,又把思路轉向了core_cm3.c文件中的源碼:
__ASM uint32_t __get_CONTROL(void){ mrs r0, control bx lr}
懂一點匯編的,相信在這里都已經明白,大概意思就是過去控制寄存器狀態,這也是我開篇說的,讓大家了解的__get_CONTROL。
4.在線調試,分析結論
上面分析出來控制寄存器CONTROL,那么我們需要驗證是否符合我們預期的效果,通過在線調試,斷電就可得出,如下面兩圖:
a.在非中斷情況下的值0x02
b.在中斷情況下的值0x00
至此,問題已經查明就是CONTROL。
Ⅲget_CONTROL的應用
一般在RTOS實時操作系統中,常常使用隊列來處理我們的數據,也就是常說的FIFO(先入先出)。
比如:我們在FreeRTOS系統中,要將UART發送、或者接收的數據加入隊列:在中斷里加入隊列,在非中斷里加入隊列。這個時候,就需要使用get_CONTROL來判斷當前是否處于中斷函數里。
當然,類似的情況很多,像CAN、I2C、SPI等一樣的道理。
舉例,CAN總線發送數據加入隊列:
Ⅳ多說兩句
以上的分析,看似很簡單,其實包含的內容很多,可能有很多人覺得:這些問題對于我來說是小菜一碟。
說句實話,我和大家一樣,都是慢慢學習過來的,這里面跳過的坑其實很多,是因為我跳過了太多的坑,所以才會對一些問題更加了解。
上面類似的問題,在我學習RTOS、移植CANOpen等等那些時候都有遇到過,想要知道我遇到那些問題,處理起來難不難,明確回答:很多問題在初學的時候都很難,但我還是走過來了。
說到這里,多說一句,關于問問題的話,后臺每天都有許多人問我問題,但是有些問題其實真的很簡單,比如:編譯有個變量未調用的警告、重復定義,多了一個分號等,這些看一下提示都知道。不要告訴我你英語差,我英語初高中從來都沒有及格過,依然還是得看英文手冊。確實不懂,安裝一個翻譯軟件不難吧。
-
cpu
+關注
關注
68文章
10824瀏覽量
211138 -
RTOS
+關注
關注
21文章
809瀏覽量
119431 -
FreeRTOS
+關注
關注
12文章
483瀏覽量
62001
發布評論請先 登錄
相關推薦
評論