RT-Thread內核移植關鍵代碼解析(3) ---- 實現 rt_hw_context_switch_to()

一、源碼

rt_hw_context_switch_to()沒有來源線程,切換到目標線程,在調度器啓動第一個線程的時候被調用。只使用一次。其執行邏輯流程圖如下所示:

其採用彙編語言來實現,如下所示:

;/*
; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to
; * this fucntion is used to perform the first thread switch
; */
rt_hw_context_switch_to    PROC
    EXPORT rt_hw_context_switch_to
    ; set to thread
    LDR     r1, =rt_interrupt_to_thread
    STR     r0, [r1]

    ; set from thread to 0
    LDR     r1, =rt_interrupt_from_thread
    MOV     r0, #0x0
    STR     r0, [r1]

    ; set interrupt flag to 1
    LDR     r1, =rt_thread_switch_interrupt_flag
    MOV     r0, #1
    STR     r0, [r1]

    ; set the PendSV exception priority
    LDR     r0, =NVIC_SYSPRI2
    LDR     r1, =NVIC_PENDSV_PRI
    LDR.W   r2, [r0,#0x00]       ; read
    ORR     r1,r1,r2             ; modify
    STR     r1, [r0]             ; write-back

    ; trigger the PendSV exception (causes context switch)
    LDR     r0, =NVIC_INT_CTRL
    LDR     r1, =NVIC_PENDSVSET
    STR     r1, [r0]

    ; restore MSP
    LDR     r0, =SCB_VTOR
    LDR     r0, [r0]
    LDR     r0, [r0]
    MSR     msp, r0

    ; enable interrupts at processor level
    CPSIE   F
    CPSIE   I

    ; never reach here!
    ENDP

二、代碼實現解釋

2.1  函數定義與聲明

;/*
; * void rt_hw_context_switch_to(rt_uint32 to);
; * r0 --> to
; * this fucntion is used to perform the first thread switch
; */
rt_hw_context_switch_to PROC   ;PROC定義子程序,與ENDP成對使用,表示子程序結束
EXPORT rt_hw_context_switch_to ;導出rt_hw_context_switch_to,讓其具有全局屬性,可以在C文件調用

該函數輸入參數的是線程結構體to_thread的棧指針(sp),進入該函數,該棧指針自動賦值給CPU的r0寄存器。

2.2  獲取要切換到的線程的sp指針

; r0的值是一個指針,該指針指向to線程的線程控制塊的SP成員
LDR r1, =rt_interrupt_to_thread    ;將 rt_interrupt_to_thread 的地址(不是其本身的值)加載到 r1
STR r0, [r1]                       ;將 r0 的值存儲到 rt_interrupt_to_thread 


; 設置 rt_interrupt_from_thread 的值爲 0,表示啓動第一次線程切換
LDR r1, =rt_interrupt_from_thread  ;將 rt_interrupt_from_thread 的地址加載到 r1
MOV r0, #0x0                       ;配置 r0 等於 0(意味着該線程不存在)
STR r0, [r1]                       ;將 r0 的值存儲到 rt_interrupt_from_thread

rt_interrupt_from_thread和rt_interrupt_to_thread是一個32位的全局變量(初始值都爲0),用於作爲保存相應線程指針的容器。

2.3  設置中斷標誌位爲1

;設置標誌爲1,表示需要切換,這個變量將在PendSV異常處理函數裏切換時被清零
LDR r1, =rt_thread_switch_interrupt_flag   ;將rt_thread_switch_interrupt_flag的地址加載到r1
MOV r0, #1                                 ;配置 r0 等於 1,相當於使能切換標誌
STR r0, [r1]                               ;將 r0的值存儲到rt_thread_switch_interrupt_flag

rt_thread_switch_interrupt_flag是一個32位的全局變量(初始值都爲0),用於標示是否切換。

2.4  

; 設置PendSV異常優先級爲最低優先級
LDR r0, =NVIC_SYSPRI2       ;把system priority register(2)的地址加載到r0 
LDR r1, =NVIC_PENDSV_PRI    ;把PendSV priority value (lowest)的地址加載到r1
LDR.W r2, [r0,#0x00] ; read
ORR r1,r1,r2 ; modify
STR r1, [r0] ; write-back

 

 

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