首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

STM32 + uC/OS-II:開啟定時器中斷後任務不執行?排查中斷衝突、優先級配置、SysTick 被佔用

     編輯:程式設計疑難解答

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())

排查步驟(按順序)

  1. 確認 SysTick 配置: SysTick_Config(SystemCoreClock / OS_TICKS_PER_SEC),優先級設置為最低(數值最大,如 0xF0)。
  2. 自定義定時器優先級 低於 SysTick: 數值 大於 SysTick 優先級值(如 SysTick=0xF0,TIM2=0xE0)。
    NVIC_SetPriority(TIM2_IRQn, 0xE0); // 0xE0 > 0xF0 數值大 = 優先級低
  3. ISR 標準模板:
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 退出中斷,觸發調度
}
  1. 檢查向量表: 启动文件 startup_stm32f2xx.s 中 TIM2_IRQHandler 向量正確,無重定義。
  2. 打斷點調試: 在 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()。」

避坑清單

  • 不要在 ISR 內調用 OSTimeDly()、printf()、malloc() 等阻塞/非重入函數。
  • 共享變量用 OS_ENTER_CRITICAL()/OS_EXIT_CRITICAL() 或信號量/互斥鎖保護。
  • 定時器週期不要過短(< 1ms),頻繁中斷會佔用過多 CPU,導致任務飢餓。
  • 用 OSStatInit() 開啟統計任務,監控 CPU 使用率、任務堆棧剩餘。

按優先級配置、ISR 規範、向量表三步走,定時器中斷與 uC/OS-II 完美共存。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved