STM32F2xx 移植 uC/OS-II,開啟自定義定時器中斷(如 TIM2)後,系統任務調度停轉。經典原因:**定時器中斷優先級高於/等於 SysTick(OS Tick),或中斷服務程序 (ISR) 過長導致調度器無法響應**。本文給出完整排查清單與修正代碼。
| 衝突類型 | 現象 | 根因 |
|---|---|---|
| 優先級搶佔 | 任務不切換、系統卡死 | 自定義中斷優先級 ≥ OS_CPU_SYSTICK_PRIO (通常最低優先級數值最大),搶佔 SysTick,導致 OSTimeTick() 不執行 |
| 中斷共用 | 硬故障/複位 | 誤將 TIMx 中斷向量表條目指向 SysTick 處理函數,或反之 |
| ISR 過長/阻塞 | 任務延遲響應、看門狗複位 | 定時器 ISR 內執行耗時操作 (printf、延遲、複雜運算),未調用 OSIntEnter()/Exit() |
| 關鍵變量損壞 | 隨機崩潰 | ISR 與任務共享變量無保護(無 OS_ENTER_CRITICAL()) |
SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC),優先級設置為最低(數值最大,如 0xF0)。NVIC_SetPriority(TIM2_IRQn, 0xE0); // 0xE0 > 0xF0 數值大 = 優先級低void TIM2_IRQHandler(void) {
OSIntEnter(); // 告知 OS 進入中斷
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
// 僅做極簡操作:標誌位、發信號量、計數
OSTaskQPost(&TaskTCB, (void*)MSG_TIM2_TICK, sizeof(MSG_TIM2_TICK), OS_OPT_POST_FIFO, &err);
}
OSIntExit(); // 告知 OS 退出中斷,觸發調度
}
startup_stm32f2xx.s 中 TIM2_IRQHandler 向量正確,無重定義。OSTimeTick()、OSIntExit()、任務入口打斷點,觀察執行流。// 系統初始化早期調用
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // 4位搶佔優先級,0位子優先級
// SysTick (OS Tick) - 最低搶佔優先級
NVIC_SetPriority(SysTick_IRQn, 0xF0); // 15
// PendSV (上下文切換) - 次低
NVIC_SetPriority(PendSV_IRQn, 0xE0); // 14
// SVC (系統服務調用) - 中等
NVIC_SetPriority(SVCall_IRQn, 0x80); // 8
// 自定義定時器 - 低於 SysTick
NVIC_SetPriority(TIM2_IRQn, 0xF0); // 同級或更低,但必須調用 OSIntEnter/Exit
// 外設中斷 (USART, DMA 等) - 業務優先級
NVIC_SetPriority(USART1_IRQn, 0x60); // 6
「所有調用 uC/OS-II API 的中斷,優先級必須 ≤ OS_CPU_SYSTICK_PRIO(數值 ≥),且必須成對調用 OSIntEnter()/OSIntExit()。」
OSTimeDly()、printf()、malloc() 等阻塞/非重入函數。OS_ENTER_CRITICAL()/OS_EXIT_CRITICAL() 或信號量/互斥鎖保護。OSStatInit() 開啟統計任務,監控 CPU 使用率、任務堆棧剩餘。按優先級配置、ISR 規範、向量表三步走,定時器中斷與 uC/OS-II 完美共存。