2017-08-17 80 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