FreeRTOS连载06:上下文切换机制 - 从汇编代码看任务切换的底层实现

引言

上下文切换是实时操作系统的核心功能,它决定了系统的实时性能和响应速度。FreeRTOS通过精心设计的上下文切换机制,实现了高效的任务调度。本文将深入分析FreeRTOS在ARM Cortex-M处理器上的上下文切换实现,揭示其底层机制和优化技巧。

1. 上下文切换概述

1.1 什么是上下文切换

上下文切换是指CPU从执行一个任务切换到执行另一个任务的过程。这个过程包括:

  1. 保存当前任务的上下文:寄存器、栈指针、程序计数器等

  2. 选择下一个要运行的任务:调度器决策

  3. 恢复新任务的上下文:加载新任务的寄存器状态

  4. 跳转到新任务执行:更新程序计数器

1.2 ARM Cortex-M处理器架构

ARM Cortex-M处理器提供了硬件支持来简化上下文切换:

/* ARM Cortex-M寄存器组 */
typedef struct
{
    /* 自动保存的寄存器(硬件处理) */
    uint32_t r0;     /* 参数/返回值寄存器 */
    uint32_t r1;     /* 参数寄存器 */
    uint32_t r2;     /* 参数寄存器 */
    uint32_t r3;     /* 参数寄存器 */
    uint32_t r12;    /* 内部过程调用寄存器 */
    uint32_t lr;     /* 链接寄存器 */
    uint32_t pc;     /* 程序计数器 */
    uint32_t psr;    /* 程序状态寄存器 */
} AutoSavedRegisters_t;
​
/* 手动保存的寄存器(软件处理) */
typedef struct
{
    uint32_t r4;     /* 通用寄存器 */
    uint32_t r5;
    uint32_t r6;
    uint32_t r7;
    uint32_t r8;
    uint32_t r9;
    uint32_t r10;
    uint32_t r11;
} ManualSavedRegisters_t;

2. FreeRTOS上下文切换实现

2.1 栈帧结构

FreeRTOS在ARM Cortex-M上使用双栈模式:

/* 栈帧结构示意图 */
/*
 * 高地址
 * +------------------+
 * |      PSR         | <- 硬件自动保存
 * +------------------+
 * |      PC          |
 * +------------------+
 * |      LR          |
 * +------------------+
 * |      R12         |
 * +------------------+
 * |      R3          |
 * +------------------+
 * |      R2          |
 * +------------------+
 * |      R1          |
 * +------------------+
 * |      R0          |
 * +------------------+
 * |      R11         | <- 软件手动保存
 * +------------------+
 * |      R10         |
 * +------------------+
 * |      R9          |
 * +------------------+
 * |      R8          |
 * +------------------+
 * |      R7          |
 * +------------------+
 * |      R6          |
 * +------------------+
 * |      R5          |
 * +------------------+
 * |      R4          | <- pxTopOfStack指向这里
 * +------------------+
 * 低地址
 */
​
/* 初始化任务栈 */
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, 
                                   TaskFunction_t pxCode, 
                                   void *pvParameters )
{
    /* 模拟中断栈帧 */
    pxTopOfStack--;
    *pxTopOfStack = portINITIAL_XPSR;   /* xPSR */
    pxTopOfStack--;
    *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */
    pxTopOfStack--;
    *pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR */
    
    /* R12, R3, R2, R1 */
    pxTopOfStack -= 5;
    
    /* R0 - 任务参数 */
    *pxTopOfStack = ( StackType_t ) pvParameters;
    
    /* R11, R10, R9, R8, R7, R6, R5, R4 */
    pxTopOfStack -= 8;
    
    return pxTopOfStack;
}

2.2 PendSV中断处理

FreeRTOS使用PendSV中断来实现上下文切换:

/* PendSV中断服务程序 - ARM Cortex-M4 */
__asm void xPortPendSVHandler( void )
{
    extern uxCriticalNesting;
    extern pxCurrentTCB;
    extern vTaskSwitchContext;
​
    PRESERVE8
​
    mrs r0, psp                     /* 获取进程栈指针 */
    isb                             /* 指令同步屏障 */
    
    ldr r3, =pxCurrentTCB           /* 获取当前TCB指针 */
    ldr r2, [r3]
​
    /* 保存剩余的寄存器到任务栈 */
    stmdb r0!, {r4-r11}             /* 保存r4-r11到栈 */
    str r0, [r2]                    /* 更新TCB中的栈顶指针 */
​
    stmdb sp!, {r3, r14}            /* 保存r3和lr到主栈 */
    mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
    msr basepri, r0                 /* 屏蔽中断 */
    dsb                             /* 数据同步屏障 */
    isb                             /* 指令同步屏障 *
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VehSwHwDeveloper

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值