【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中。