FreeRTOS-port.c
FreeRTOS-port.c文件分析
StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
功能:初始化任务堆栈
参数:
1. pxTopOfStack 栈顶指针
2. pxCode 任务指针
3. pvParameters 任务参数指针
返回:
返回当前栈顶
static void prvTaskExitError( void )
功能:任务退出处理代码,在任务堆栈初始化时会保存在LR寄存器关联位置。
void vPortSVCHandler( void )
功能:SVC中断处理代码,实际是个空函数,没有使用,只是为了
兼容以前的代码而存在。
__asm void prvPortStartFirstTask( void )
功能:调度器启动后,执行第一个任务。
BaseType_t xPortStartScheduler( void )
功能:启动调度器,配置PENDSV、SYSTICK中断,设置低功耗定时器中断
执行第一个任务。
返回值:返回0。
其实这是个不会返回的函数,执行不到返回位置。系统中至少存在一个空闲任务,启动调度器后就会有任务执行。
void vPortEndScheduler( void )
功能:结束调度器
void vPortYield( void )
功能:触发一次任务调度
void vPortEnterCritical( void )
功能:进入临界区
void vPortExitCritical( void )
功能:退出临界区
__asm uint32_t ulSetInterruptMaskFromISR( void )
功能:中断上下文进入临界区
__asm void vClearInterruptMaskFromISR( uint32_t ulMask )
功能:中断上下文退出临界区
__asm void xPortPendSVHandler( void )
功能:PendSVC中断处理函数,保存旧任务上下文,恢复最高就绪任务
上下文,即实现了任务切换的功能。
void xPortSysTickHandler( void )
功能:systickz中断处理函数,给系统时间增加一个tick,如果有更高优先级
的就绪任务则触发一次任务调度。
__weak void vPortSetupTimerInterrupt( void )
功能:设置systick定时器中断
void LPTIM32Init(void)
功能:低功耗定时器初始化
void LPTIM_IRQHandler()
功能:低功耗定时器中断处理函数
void prvStopTickInterruptTimer ( void )
功能:停止systick中断
__INLINE void disable_interrupts ( void )
功能:禁止中断
void prvStartTickInterruptTimer ( void )
功能:启动systick中断
__INLINE void enable_interrupts ( void )
功能:使能中断
void vSetWakeTimeInterrupt(TickType_t xExpectedIdleTime)
功能:设置低功耗定时器唤醒时间
参数:
1. xExpectedIdleTime 能够进入休眠的时间
void DeepSleep(void)
功能:进入深度休眠
void vApplicationSleep ( TickType_t xExpectedIdleTime )
功能:根据xExpectedIdleTime 指示的时间进行休眠,并在被唤醒时
补偿systick。
参数:
1.xExpectedIdleTime 能够进入休眠的时间
重点解析:
StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, void * pvParameters )
{
/* Simulate the stack frame as it would be created by a context switch
* interrupt. */
pxTopOfStack--; 因为堆栈类型是满减栈,先把减栈指针再存内容。
*pxTopOfStack = portINITIAL_XPSR; /* 初始的进程状态寄存器值*/
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) pxCode; /* PC 指针*/
pxTopOfStack--;
*pxTopOfStack = ( StackType_t ) prvTaskExitError; /* LR 指针*/
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11..R4. */
return pxTopOfStack;
}
任务堆栈初始化后,堆栈中保存的内容如下:
|
1 |
XPSR |
|
2 |
PC |
|
3 |
LR |
|
4 |
R12 |
|
5 |
R3 |
|
6 |
R2 |
|
7 |
R1 |
|
8 |
R0 |
|
9 |
R11 |
|
10 |
R10 |
|
11 |
R9 |
|
12 |
R8 |
|
13 |
R7 |
|
14 |
R6 |
|
15 |
R5 |
|
16 |
R4 |
|
|
__asm void prvPortStartFirstTask( void )
{
extern pxCurrentTCB;
PRESERVE8
ldr r3, = pxCurrentTCB /* 把当前任务控制块指针拷贝到R3 */
ldr r1, [ r3 ] /*把任务控制块的堆栈指针的指针拷贝到R1*/
ldr r0, [ r1 ] /*把堆栈指针拷贝到R0*/
adds r0, # 32 /* 舍弃掉堆栈中的R4 - R11值*/
msr psp, r0 /* 把计算出来的堆栈指针拷贝到PSP寄存器 */
movs r0, # 2 /* */
msr CONTROL, r0 /*切换到使用PSP模式*/
isb
pop { r0 - r5 } /* 把堆栈中的6个值弹出到R0 - R5*/
mov lr, r5 /*把R5的值赋值给LR*/
pop { r3 } /* 把堆栈中的PC值弹出到R3*/
pop { r2 } /* 把堆栈中的XPSR弹出R2并舍弃*/
cpsie i /* 使能中断 */
bx r3 /* 调转到用户定义的代码*/
ALIGN
/* *INDENT-ON* */
}
__asm void xPortPendSVHandler( void )
{
extern vTaskSwitchContext
extern pxCurrentTCB
/* *INDENT-OFF* */
PRESERVE8
mrs r0, psp /*把进程堆栈指针拷贝到R0*/
ldr r3, = pxCurrentTCB /* 把当前任务控制块指针拷贝到R3 */
ldr r2, [ r3 ] /*把任务控制块的堆栈指针的指针拷贝到R2*/
subs r0, # 32 /*为保存寄存器创造8个字的空间 */
str r0, [ r2 ] /* 把任务控制块的堆栈指针拷贝到堆栈 */
stmia r0 !, { r4 - r7 } /*保存R4 - R7到值到堆栈*/
mov r4, r8 /* Store the high registers. */
mov r5, r9
mov r6, r10
mov r7, r11
stmia r0 !, { r4 - r7 } /*保存R8 - R11 的值到堆栈*/
push { r3, r14 } /*把TCB指针和LR入栈*/
cpsid I /*关中断*/
bl vTaskSwitchContext /*切换上下文,把当前优先级最高的就绪任务控制块赋值给pxCurrentTCB,即R3*/
cpsie i
pop { r2, r3 } /* 把当前任务控制块指针弹出到R2,连接指针弹到R3 */
ldr r1, [ r2 ]
ldr r0, [ r1 ] /* R0指向当前任务控制块指针*/
adds r0, # 16 /* Move to the high registers. */
ldmia r0 !, { r4 - r7 } /* 弹出R8 - R11 */
mov r8, r4
mov r9, r5
mov r10, r6
mov r11, r7
msr psp, r0 /* 任务控制块指针赋值给PSP寄存器 */
subs r0, # 32 /* Go back for the low registers that are not automatically restored. */
ldmia r0 !, { r4 - r7 } /* 弹出R4 - R7 */
bx r3 /*调整到当前任务上次执行的断点处继续执行。*/
ALIGN
}
浙公网安备 33010602011771号