RT-Thread移植到S5P4418(一):調度器

S5P4418,Cortex-A9系列。
結合了 RT-Thread內核實現(六):時間片S5P4418裸機開發(十四):TIMER 的代碼。

SysTick & PendSV

RT-Thread實現線程調度兩個比較核心的中斷。
SysTick更新系統時基。PendSV做上下文切換。

  • SysTick在S5P4418中用timer0代替。週期10ms,注意中斷服務函數要清除中斷標誌位。
void SysTick_Config(){ // 只是換了個名字
    IP_RESET_REGISTER1 |= (1 << 4);     // 關閉復位

    TCFG0 |= (250 - 1);     // PCLK = 200MHz 200000000 / 16 / 250 = 50000;
    TCFG1 |= 0x4;
    TCNTB0 = 500;          // 500 = 10ms
    TCON |= (1 << 1);

    // vic_init(23, (u32)timer0_ISR);  // 註冊VIC
    vic_init(23, (u32)SysTick_Handler);  // 註冊VIC

    TINT_CSTAT |= (1 << 0); // 中斷使能
    TCON &= ~(1 << 1);
    TCON |= ((1 << 3) | (1 << 0));  // 自動重裝載,啓動定時器
}

void SysTick_Handler(void)
{
    /* 進入中斷 */
    rt_interrupt_enter();

    rt_tick_increase();

    TINT_CSTAT |= (1 << 5); // 清除中斷標誌

    /* 離開中斷 */
    rt_interrupt_leave();
}
  • 再選一個能替代PendSV的中斷,因爲S5P4418上的中斷都可以軟件觸發,所以選一個沒人用的即可,我選擇了63號中斷。重點是中斷服務程序的修改。

PendSV_Handler

  • Coterx-M3調度在 RT-Thread內核實現(一):線程與調度 中描述的比較清楚。切換上下文的幾個步驟:
    • 硬件自動保存xPSR, PC, LR, R12以及R3‐R0到線程棧中。
    • 取出源線程的psp,即棧頂sp,保存r4 - r11到sp指向的位置。這就完成了保存上文的工作。
    • 下文切換,取即將運行的線程的sp值,不是sp寄存器,裝載r4 - r11,再將sp值寫回sp寄存器。
    • 退出中斷後,硬件再從棧中自動裝載xPSR, PC, LR, R12以及R3‐R0。

  • 而A9在響應中斷時沒有自動保存的操作,也沒有MSP和PSP寄存器。移植時也可以按上面4個步驟來操作。
    • 第一步,保存CPSR, PC, LR, R12以及R3‐R0到線程棧中。CPU進入IRQ模式後,sp寄存器是該模式下的r13_irq。我設置的線程是運行在特權模式下,其sp寄存器應該r13_svc。所以先切回中斷前的模式。
    • 然後push那8個寄存器,這裏要注意一下順序,後一步講解。
    • 第二步,保存r4 - r11,此時通過模式切換,已經是源線程的棧了,直接push。
    • 第三步,下文切換,和M3的操作一樣。
    • 第四步,A9進中斷時會自動保存上一個模式的CPSR到SPSR,在退出中斷時,如果LDMFD等指令帶’^’,CPSR由硬件自動寫回。所以恢復PC, LR, R12以及R3‐R0時,先將原CPSR寫入SPSR中,爲了方便取cpsr的值,在第一步保存時CPSR最後一個push。同時struct exception_stack_frame 中的rt_uint32_t psr放在最上面。

其他細節後續再補。

工程

103_rtt2a9

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章