【问题标题】:Context Switching上下文切换
【发布时间】:2021-04-07 08:40:44
【问题描述】:

我正在尝试按照stm32f407 发现板上的教程实现任务计划。

有四个函数,每次执行一个1ms,然后切换到下一个函数。

教程定义了整个流程,我们将保存每个函数的每个堆栈寄存器,即这些寄存器xpsrpclrR0...R13,然后将下一个函数的这个值加载到PSP(处理器堆栈指针)在上下文切换时(这将发生在 systick_handler 内部,它将以 1 毫秒的间隔触发)。

我不明白的是,我认为寄存器是全局的,而不是像函数内部的变量那样私有的。那么他如何为每个函数保存这些寄存器值。这是给定的代码https://github.com/niekiran/CortexMxProgramming/blob/master/Source_code/015_task_scheduler/Src/main.c 如果有人可以向我简要介绍一下上下文切换部分,那么我将对我正在做的事情非常有信心

谢谢

【问题讨论】:

    标签: c embedded stm32 cortex-m


    【解决方案1】:

    想象一下,您可以在某个时间点拍摄 CPU 的照片,并且该照片可以显示当时 CPU 中的各个 1 和 0。如果你有办法在未来某个时候将照片中的 1 和 0 恢复到 CPU 中,然后你可以让 CPU 运行,那么假设 RAM 和 ROM 内容没有改变,它将继续做以前的事情拍摄照片的地点。

    这本质上就是上下文切换的作用。它保存了 CPU 的所有“易失性上下文”:所有通用寄存器的内容(包括告诉它正在执行的指令的程序计数器,粗略地说,还有堆栈指针)以及处理器状态寄存器(PSR)。这些信息足以让 CPU 在未来某个时间从该确切点再次恢复。

    在 Cortex-M 上,有两个堆栈指针,它们的存在是为了使这个过程更容易。其中一个或另一个始终可以作为sp (r13) 访问。此示例的配置方式,处理程序模式代码使用 MSP(主堆栈指针),线程模式代码使用 PSP(进程堆栈指针)。寄存器r0-r3r12lr (r14)、pc (r15) 和 PSR 在进入处理程序模式时被推送到活动堆栈。只剩下r4-r11 和堆栈指针(r13 处于线程模式,但现在通过专用的PSP 寄存器访问,因为处理程序正在使用 MSP)。

    因此上下文切换获取PSP 的值,然后r4-r11 推入任务自己的堆栈,然后将更新后的任务堆栈指针值保存在其任务控制块中。现在 CPU 在进入处理程序模式时的整个 volatile 上下文已保存到正在运行的任务的堆栈中,并且堆栈指针已保存在 TCB 中。剩下的就是找到一个新的任务来运行,从它的 TCB 中取出它的堆栈指针,用它来弹出r4-r11,然后在返回之前更新PSP。退出处理程序模式时,r0-r3r12lrpc 和 PSR 都会被硬件自动弹出。

    所以是的,寄存器是“全局的”,在某种程度上,每个任务都使用相同的寄存器。但是当一个任务没有运行时,这些寄存器的内容存储在它的堆栈中,并在下一次准备运行时恢复到寄存器中。这就是上下文切换的目的。

    【讨论】:

    • 当我们进入handler模​​式,即在pendSv handler中,这意味着我们的寄存器值一定已经改变了,特别是LRPC,所以现在如果我保存这些值那就不正确了对吧?
    • 我建议您阅读您正在使用的内核的通用手册的“异常进入和返回”部分(例如,here 是 M3 的那个)。正如我在回答中所说,LR 和 PC 与其他一些寄存器一起被推送进入处理程序模式,所以是的,它们会改变,但它们已经被推送,所以没问题.特别是 LR 以一种有趣的方式变化;它包含一个代码,触发处理程序末尾的所有内容。
    • 我有一个疑问,是否有必要将处理器堆栈指针用于处理程序(任务和异常)。我读过处理器堆栈指针通常用于避免主堆栈指针损坏
    • process 堆栈指针 (PSP) 在您的示例中用于 task 堆栈。这是由switch_sp_to_psp() 函数选择的。主堆栈指针 (MSP) 由处理程序使用,并且无法更改。上下文切换访问 PSP 以便与任务堆栈交互以在切换期间堆栈和取消堆栈r4-r11
    猜你喜欢
    • 2011-07-23
    • 2013-04-21
    • 2017-06-13
    • 1970-01-01
    • 1970-01-01
    • 2017-09-09
    • 2011-07-27
    • 2011-11-18
    相关资源
    最近更新 更多