【FreeRTOS学习笔记 】创建任务、任务切换


如图,在keil中使用内联汇编时,有错误提示,但实际编译并没有报错:

注意,使用内联汇编用

__asm

但在编写portPendSV的过程中,出现了另一个错误:

error: A1215E: Bad register list symbol

error: A1154E: Unexpected operand, operator expected

error: A1163E: Unknown opcode lamia , expecting opcode or Macro

 修改prvStartFirstTask、后无error

extern的使用:

整理工程后在线调试:

 把调试过程更新了一下,在启动文件的跳转main处打上断点,在main里需要调试的部分前一行打上断点;

然后在Debug处选择不烧写进Flash;选择reset and run

将整个工程重新编译,按住单片机复位键,点击烧写,松开复位键;

按住单片机复位键,点击在线调试,松开复位键;

成功进入调试状态,并且创建任务和插入链表的过程正确执行,如图:

接下来调试含有汇编的部分,

 在编程手册中找到0xE000ED20地址的寄存器:

发现该地址其实是SCB_SHPR3寄存器,和命名的SYSPRI2好像不一样,后面看看有什么差异

可以通过查看NVIC状态,检查优先级是否被成功设置;

 调试过程中,发现启动文件SVCHandler对应的freertos的xPortSVCHandler,被我打错名字x打成v,导致函数找不到;

修改后运行正常;以下是调试信息:

发现加载任务后(任务信息出栈,指针往上移),任务的栈顶指针并没有第一时间更新到TCB中,如图

 还发现,在调用任务让步后,程序又执行了一遍,可能是中断延迟?等会一步一步跑看看

任务让步,进入PendSVHandler:

 上图标注的有细节不清楚,因为是r0寄存器拿到psp的值,通过r0进行信息保存,所以最新的堆栈信息在r0,更新完后,把r0也就是此时的堆栈指针保存在TCB中

注意在TaskSwitch过程中,freertos选择只关了一部分中断,:

#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 15
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5

#define configKERNEL_INTERRUPT_PRIORITY \
( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))

只要通过PendSV进入了Handler模式,就会一直默认使用MSP、Handler模式,直到通过使用 R14 指定的模式和使用堆栈,进行返回;

这就是CM3 和 RTOS 结合的 系统-用户 模型。

 

总结:TCB在任务加载的过程中不改变,此时的堆栈变化用PSP记录,在任务退出过程中,PSP自动、手动变化后的信息才被更新到TCB中。