基本内容:任务的创建、控制块、删除、挂起、恢复的使用
创建任务函数的核心
栈的增长方向为向下的则portSTACK_GROWTH>0,而我们stm32使用的就是向下因此执行这个,下面的就是向上不执行
核心函数prvInitialiseNewTask()
configCHECK_FOR_STACK_OVERFLOW > 1堆栈溢出监测,监测到剩余的空间,原理是:使用memset把当前任务的堆栈空间全部赋值为tskSTACK_FILL_BYTE值
#define tskSTACK_FILL_BYTE ( 0xa5U ),只要值改变了,说明被使用了,那么就可以知道剩余多少了
pxTopOfStack是栈顶,pxNewTCB->pxStack 是首地址,此时的地址就是为栈顶了,向下从高地址-低地址
下面一句是八字节对齐,提高我们效率
把创建的任务的信息全部装入任务控制块
栈的保存内容,其实就是把各个寄存器的值保存下来,有些是硬件保存而有些是软件保存,软件是PSR\PC\LR\R0,其余的是硬件,源码的注释写清楚了
PC保存的是任务函数的地址,而PC保存的是下一条执行的指令地址,因此此时PC的内容就是需要执行的函数地址
这些顺序是内核规定的,因此最好栈顶的位置其实是最后R4下面的地址,再下面就是起始地址,如果来了一个数据,那么栈顶向下移动
FreeRTOS - 免费的实时操作系统配置常量和配置选项 - 适用于小型实时嵌入式系统的免费开源实时操作系统学会看官方文档,学习所写知识。这是我们需要学习的函数
疑问:为什么解挂的函数有两种,一种是中断一种是任务型的
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
void vTaskResume( TaskHandle_t xTaskToResume );
BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume );
typedef long BaseType_t;
挂起不支持嵌套,多次挂起,一次恢复就可以了,但是
调用了多少次 vTaskSuspendAll() 函数就必须同样调用多少次 xTaskResumeAll() 函数。
两个函数是不一样的,后者的支持嵌套
使用 xTaskResumeFromISR()的时候有几个需要注意的地方:
- 当函数的返回值为 pdTRUE 时:恢复运行的任务的优先级等于或高于正在运行的任务,表明在中断服务函数退出后必 须进行一次上下文切换 , 使用 portYIELD_FROM_ISR() 进行上下文切换。当函数的返回值为 pdFALSE 时:恢复运行的任务的优先级低于当前正在运行的任务,表明在中断服务函数退出后不需 要进行上下文切换。
- xTaskResumeFromISR() 通常被认为是一个危险的函数,因为它的调用并非是固定的,中断可能随时来来临。所以 xTaskResumeFromISR()不能用于任务和中断间的同步,如果中断恰巧在任务被挂起之前到达,这就会导致一次中断丢失(任务还没有挂起,调用 xTaskResumeFromISR()函数是没有意义的,只能等下一次中断)。这种情况下,可以使用信号量或者任务通知来同步就可以避免这种情况。
不能用于任务和中断间的同步理解方式为:
中断中:flag = 1;
任务中:if(flag == 1) fun();
在文件中有这样一段英文介绍--大致内容其实就是:如果你想在中断中使用API函数(如xTaskResumeFromISR)那么你需要保证你的中断函数的优先级是在FreeRTOS的管理范围内,这里的管理范围一般是5-15,数值越高,优先级越低,0-4是紧急中断(操作系统不管理的中断)
之所以有这个,是因为临界段保护-需要屏蔽中断,屏蔽中断的范围就是5-15(可以自己调)
项目:按键、EXTI中断、LED
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)