本文是《ALIENTEK STM32F429 FreeRTOS 开发教程》第十章学习笔记
第一章笔记–FreeRTOS简介与源码下载
第二章笔记–FreeRTOS在STM32F4上移植
第三章笔记-FreeRTOS系统配置
第四章笔记-FreeRTOS中断分析
第四章笔记补充-FreeRTOS临界段代码
第五章笔记-FreeRTOS任务基础
第六章笔记-FreeRTOS任务API函数的使用
第七章笔记-FreeRTOS列表和列表项
第八章笔记-1-FreeRTOS任务创建
第八章笔记-2-FreeRTOS任务调度器开启
第九章笔记-FreeRTOS任务切换
FreeRTOS内核控制函数就是内核使用的函数,一般应用程序不使用这些函数
函数 | 描述 |
---|---|
taskTIELD() | 任务切换 |
taskENTER_CRITICAL() | 进入临界区,用于任务中 |
taskEXIT_CRITICAL() | 退出临界区,用于任务中 |
taskENTER_CRITICAL_FROM_ISR() | 进入临界区,用于中断服务函数中 |
taskEXIT_CRITICAL_FROM_ISR() | 退出临界区,用于中断服务函数中 |
taskDISABLE_INTERRUPTS() | 关闭中断 |
taskENABLE_INTERRUPTS() | 打开中断 |
vTaskStartScheduler() | 开启任务调度器 |
vTaskEndScheduler() | 关闭任务调度器 |
vTaskSuspendAll() | 挂起任务调度器 |
xTaskResumeAll() | 恢复任务调度器 |
vTaskStepTick() | 设置系统节拍值 |
taskYIELD()
#define taskYIELD() portYIELD()
#define portYIELD()
{
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
__dsb( portSY_FULL_READ_WRITE );
__isb( portSY_FULL_READ_WRITE );
}
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT:
#define portNVIC_INT_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000ed04 ) )
#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL )
中断控制及状态寄存器ICSR(地址:0xE000_ED04),向ICSR的第28位写入1悬起PendSV(启动PendSV中断),这样即可在PendSV中断服务函数中进行任务切换
__dsb( portSY_FULL_READ_WRITE );__isb( portSY_FULL_READ_WRITE ): dsb和isb 完成数据同步隔离和指令同步隔离 完成作用是保证之前存储器访问操作和指令都执行完(个人认为是要确保开启了PendSV)
中断级任务切换函数为portYIELD_FROM_ISR():
#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired != pdFALSE ) portYIELD()
#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x )
可以看到中断级任务切换函数也是通过调用函数portYIELD()来完成
taskENTER_CRITICAL() & taskEXIT_CRITICAL()
用做任务级临界段代码保护
进入临界段:taskENTER_CRITICAL()
退出临界段:taskEXIT_CRITICAL()
这两个函数其实是一个宏定义,定义为:
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()
分别封装了个函数portENTER_CRITICAL()和portEXIT_CRITICAL(),而被封装的两个函数也是宏定义,定义为:
#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()
函数vPortEnterCritical()和vPortExitCritical()在文件port.c里,函数原型为:
void vPortEnterCritical( void )
{
portDISABLE_INTERRUPTS();
uxCriticalNesting++;
if( uxCriticalNesting == 1 )
{
configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
}
}
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
进入函数vPortEnterCritical()先执行portDISABLE_INTERRUPTS()函数(关闭中断
再执行uxCriticalNesting++ 将变量加一 变量表示临界段嵌套次数
接下来如果为1,进入一个断言函数
config