2017-08-17 77 views
1

我最近在閱讀有關微控制器(特別是AVR)中的實時操作系統的內容,我正在嘗試爲(AVR)編寫一個簡單的操作系統。我的問題是關於上下文切換...第一個任務的代碼在RTOS中切換

所以,taskA執行並被ISR中斷,它決定另一個任務(即任務B)現在應該運行,然後上下文(寄存器文件,堆棧指針,狀態寄存器)的任務B被加載,並且在退出ISR時,因爲「堆棧指針」被設置在正確的位置(正好在taskB被ISR中斷時保存在堆棧中的任務B的程序計數器的上方),代碼將執行taskB。這是我閱讀互聯網迄今爲止所瞭解的內容。

我的問題是:一切如何開始?如果這是第一次taskA被中斷,那麼爲taskB加載了什麼?在堆棧中沒有任務B的程序計數器,因此沒有堆棧指針要加載。如何編碼?

+0

它由bootloader作爲任何其他操作系統啓動。 – user0042

+0

也許不清楚這個問題,但我正在嘗試編寫自己的RTOS ...並且我不知道如何編寫該部分:) –

+0

爲什麼要投票? –

回答

0

在像AVR這樣的嵌入式系統中,通常需要在程序開始時創建任務。這些任務可以創建或終止新任務。

int main() { 
    Task *A = createTask(.....); 
    while(1) { 
     processTasks(); 
    } 
} 

這裏createTask(.....);函數插入任務A至尚未完成的任務的任務隊列,並且processTasks();功能從任務隊列需要的任務(即A)和執行它們。 .....意味着RTOS所需的很多參數,如函數句柄,TCB,優先級等...

此外,main()實際上也是一項任務。

當然有很多東西,這不是簡單的問題。

+0

這並沒有真正回答這個問題。它僅僅是一個典型的RTOS任務創建和調度啓動的僞代碼。他似乎在問的是沒有現有環境的任務如何開始第一次。 「通過調用functionX」並不能真正回答這個問題。 – Clifford

2

通常情況下,它是這樣的:

線程A調用OS'的CreateThread()API,(讓我們假設有效參數:)。

新的線程B將需要一個堆棧,因此調用內存管理來爲調用中傳遞的堆棧大小(或某些默認值)提供足夠的虛擬內存。

然後,該堆棧頂部將加載所有線程專用的東西,OS設計認爲這是任何線程使用線程API訪問所需的東西。

將代碼開始地址,標誌寄存器或任何線程代碼加載到B堆棧中,以使B堆棧的底部看起來像線程B之前已經存在並且被中斷到內核中。

然後可以首次啓動新線程B,就好像它不是第一次,例如。通過加載堆棧指針和中斷返回。

[注 - 假設堆棧向下增長,就像86]

+0

謝謝你的回答! –

1

之後,你有你的任務/線程主要設置(),您將需要調用一個OS.start()或類似的。必要時,運行任務調度程序來查找準備運行的最高優先級任務。

此調度程序需要辨別從未運行的任務(因此沒有線程上下文以彈出堆棧)和已被搶佔的任務。

void scheduler(void) 
{ 
    //find the next ready task 
    ...code... 

    if(theReadyTask.hasPreviouslyRun) 
    { 
     //the task was preempted and needs its context restored 
     ...code to load load the registers off of the stack... 
    } 
    //whether it has run before or not we need to change the stack pointer so the return jumps to the function associated with the thread. 
    ...code to set stack pointer... 
} 

因此,一旦任務第一次啓動,它將始終有一個上下文返回。但在它第一次需要特殊處理...

+0

謝謝你的回答! –

+0

沒問題。如果它對您有用,請隨時註冊或接受。 – Ross

+0

在AVR uC的情況下,每個任務的內存使用malloc獲得?然後在創建任務時,堆棧指針會被malloc函數返回的指針加載? –

2

在任務創建初始上下文建立(在任務控制塊 - TCB - 的任務),與設置的地址的程序計數器任務入口點以及設置爲任務堆棧起始地址的堆棧指針。這些初始值是首次安排任務時加載的值。

總之,初始任務上下文是合成而不是保存從以前的執行。

通常情況下,初始上下文內置在一個createTask函數中,初始任務的上下文由一個函數startSheduler加載。

+0

先生,謝謝你的關注......這實際上是我所做的。當我創建一個新任務時,我正在爲新任務堆棧分配64(應該足夠)的內存字節(使用malloc()...:D),然後我將堆棧指針設置爲指向該內存位置由malloc返回(它應該是那個或那個+ 64 ??),然後我推入處理函數指針的「新堆棧」,然後在TCB結構中保存已經修改(由於PUSH)堆棧指針。 ..可以嗎? –

+0

也許我應該改變回棧指針與它的值,當第一次進入「createNewTask(...)」?! –

+0

@CMarius:SO不是論壇。你問了一個關於RTOS的通用問題。如果您對_具體實施有進一步問題,請發佈一個新問題。評論並不是持續冗長的討論。 – Clifford