引言
上下文切换是实时操作系统的核心功能,它决定了系统的实时性能和响应速度。FreeRTOS通过精心设计的上下文切换机制,实现了高效的任务调度。本文将深入分析FreeRTOS在ARM Cortex-M处理器上的上下文切换实现,揭示其底层机制和优化技巧。
1. 上下文切换概述
1.1 什么是上下文切换
上下文切换是指CPU从执行一个任务切换到执行另一个任务的过程。这个过程包括:
-
保存当前任务的上下文:寄存器、栈指针、程序计数器等
-
选择下一个要运行的任务:调度器决策
-
恢复新任务的上下文:加载新任务的寄存器状态
-
跳转到新任务执行:更新程序计数器
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 /* 指令同步屏障 *

最低0.47元/天 解锁文章
151

被折叠的 条评论
为什么被折叠?



