freertos学习笔记——任务切换

目录

第一种情况分析(第二种情况遇到了可自行标记一下)

xPortSysTickHandler中断服务函数:

下面是PendSV的中断服务函数xPortPendSVHandler函数:

vTaskSwitchContext函数分析:(获取最高优先级的TCB并赋值给pxCurrentTCB)


任务之间的切换实际上是将不同的任务栈中保存的寄存器赋值到CPU的寄存器中的一个过程。

前提:

        1.任务切换是在第一个任务启动之后的一种rtos的行为,在启动任务是已经配置了Systick的中断

        2.由于freertos使用的双指针,所以要先了解一下MSP和PSP指针。只要记住一点即可MSP是中断时使用的指针,PSP是任务之间使用的指针。

下面是详细分析:

        任务切换只有两种情况。一种是触发Systick中断在中断服务函数中进行任务切换(xPortSysTickHandler函数),另一种是用户调用任务切换函数(taskYIELD_IF_USING_PREEMPTION函数、portYIELD_WITHIN_API函数、queueYIELD_IF_USING_PREEMPTION函数、portYIELD函数等)上面的函数包括Systick中断服务函数本质是将PendSV的中断标志置1,触发PendSV中断

第一种情况分析(第二种情况遇到了可自行标记一下)

在Systick中断服务函数中触发PendSv中断,所以我们要了解啥时候Systick中断触发

记得在启动第一个任务的时候吗

当时在xPortStartScheduler函数中调用的vPortSetupTimerInterrupt函数就是Systick的配置

不清楚的可以查询freertos学习笔记——启动第一个任务_天分天涯的博客-CSDN博客

也就是一秒中触发configTICK_RATE_HZ次

终于开始到了函数分析的过程:

xPortSysTickHandler中断服务函数:

        a.屏蔽中断

        b.判断xTaskIncrementTick(后面分析,其功能是恢复阻塞列表任务,计数心跳值,时间片任务轮转)函数返回值是否为pdFALSE

                否

                        将PendSV的中断标志置1,触发PendSV中断

                是

                        啥也不干

        c.开启中断

下面是PendSV的中断服务函数xPortPendSVHandler函数:

        a.八字节对齐

        b.将PSP的值存入r0

        c.获取当前任务控制块的地址并且保存到r3中(在创建任务是当前任务控制块就是优先级最高的任务控制块)

        d.获取r3指向的地址内容存储在r2中(存储的内容就是当前任务控制块的内容(栈顶指针的地址))
        e.手动入栈r4-r11(r0-r3,r12-r15,xPSR自动入栈)

        f.将r0的值赋给r2(r0的值就是psp的指针)

        g.入栈r3和r14(r3中保存的是当前任务控制块变量的地址,r14是连接寄存器,由于下面要调用别的函数,所以暂时入栈r14)

        h.屏蔽中断

        i.调用vTaskSwitchContext函数(更新最高优先级的任务控制块到当前任务控制块中)

        j.开启中断

        k.出栈r3和r14(此时的r3值还是当前任务控制的地址,r14是连接寄存器)

        l.将当前任务控制块的值赋值给r0(此时的任务控制块已经是切换了的任务控制块)

        m.手动出栈r4-r11(要运行的任务栈)

        n.更新psp指针

        o.返回r14连接寄存器

vTaskSwitchContext函数分析:(获取最高优先级的TCB并赋值给pxCurrentTCB)

核心:taskSELECT_HIGHEST_PRIORITY_TASK函数

        a.通过前导置零指令获取硬件优先级

        b.判读该就优先级绪列表是否有列表项

        c.获取优先级任务TCB并且赋值给pxCurrentTCB

你可能感兴趣的:(学习,笔记)