文章目录
- 🔴🟡🟢其他文章链接,独家吐血整理
- 1、Systick滴答定时器
- 2、SVC中断
- 3、PendSV中断
- 4、❤ Systick、SVC、PendSV小结
- 5、时间片调度
- 6、🧡 韦东山FreeRTOS部分
- 7、💛 其它博主文章链接【转载】
- 1、FreeRTOS任务切换——PendSV
- 2、RTOS系列文章(2):PendSV功能,为什么需要PendSV
- 3、有了Systick中断为什么还要PendSV中断?(==此文章有问题,仅作为参考==)
- 4、【FreeRTOS】FreeRTOS 源码学习笔记 (5) 任务调度器 + vTaskStartScheduler、xPortPendSVHandler、xPortSysTickHandler
- 5、FreeRTOS对系统异常优先级寄存器的PendSV和SysTick 的优先级设置过程
🔴🟡🟢其他文章链接,独家吐血整理
【吐血总结】FreeRTOS难点、Systick中断-滴答定时器、PendSV中断-任务切换、SVC中断-系统底层、时间片调度-时钟节拍【已完结】
(第1-8讲)STM32F4单片机,FreeRTOS基础知识总结【视频笔记、代码讲解】【正点原子】【原创】
(第9-10讲)STM32F4单片机,FreeRTOS任务创建和删除(动态方法)【视频笔记、代码讲解】【正点原子】【原创】
(第12讲)STM32F4单片机,FreeRTOS任务创建和删除(静态方法)【视频笔记、代码讲解】【正点原子】【原创】
(第13-14讲)STM32F4单片机,FreeRTOS任务挂起和恢复【视频笔记、代码讲解】【正点原子】【原创】
(第16-17讲)STM32F4单片机,FreeRTOS中断管理简介【视频笔记、代码讲解】【正点原子】【原创】
(第18-19讲)32单片机,FreeRTOS临界段代码保护、任务调度器的挂起和恢复【视频笔记、代码讲解】【原创】
(第20-22讲)STM32F4单片机,FreeRTOS列表和列表项API函数讲解【视频笔记、代码讲解、正点原子】【原创】
(第40-44讲)STM32F4单片机,FreeRTOS信号量【二值、计数、翻转、互斥】【代码讲解】【正点原子】【原创】
1、Systick滴答定时器
Systick异常请求=滴答定时器中断,原子的这颗F429芯片晶振是180MHZ,重装载值是18000,从18000计数减到0是一次心跳周期=1/1000s=1ms,这个systick定时器开启是在开启任务调度函数里面的
这个空任务就是空闲任务,任务优先级是0,即任务最低优先级(不是中断优先级)
其实我仍然不太明白嵌套计数器的含义,前几篇文章也分析过,总觉得理解不对
这个时间片计数轮询表述不恰当,这里其实是开启滴答定时器中断,用于PendSV任务切换使用
至于Systick和PendSV两者之间谁的优先级高?这个我也不知道,待补充
开启定时器中断就是滴答定时器,里面有PendSV切换, 第6步里面全是汇编语言,反正我看不懂,待补充
2、SVC中断
已经创建好任务了,才进入的SVC中断,SVC中断是讲任务结构体数据依次按地址pop到cpu寄存器中(SVC中断只在启动第一次任务时会调用一次,以后均不调用),这里的使能全局中断相当于汇编语言开启中断,因为前面有进入临界区保护时关掉了中断,此时手动又开启了(具体为什么,我没有详细研究,会用大致上理解就行了)
绿色颜色很重要,这块原子讲得很详细,建议去看下视频
3、PendSV中断
上图中的if( xTaskIncrementTick() != pdFALSE )判断中的xTaskIncrementTick() 函数里面就是一些链表的操作,即列表项之间的判断,插入,删除,阻塞之类的,因为列表项之间判断决定了是否进行任务切换,因为创建任务就是创建了列表
原子中的delay延时函数内部调用了上面橙色圈的函数,也就是说delay可以导致任务切换
这个是宏替换之后的PendSV中断函数,全是汇编语言,后面不想看了,太细了也很难
4、❤ Systick、SVC、PendSV小结
定时器中断是在开启任务调度器时开启的Systick中断函数(寄存器开启,1ms进入一次),里面有PendSV中断函数(寄存器开启,用来根据列表项操作进行任务函数切换),开启任务调度器之后创建了任务(创建任务的同时也就保存了数据),之后打开了SVC中断(汇编语言,获取任务堆栈地址,将任务数据进行出栈处理给cpu寄存器,用于操作硬件底层)(SVC中断只在启动第一次任务时会调用一次,以后均不调用)
5、时间片调度
没用完的时间片丢掉
时间片设置的是50ms,这个实验还是比较容易理解滴!因为没有加临界区,导致task1打印一半被阻塞跳到task2接着打印了
taskENTER_CRITICAL();
printf("task1运行次数:%d\r\n",++task1_num);
taskEXIT_CRITICAL();
taskENTER_CRITICAL();
printf("task2运行次数:%d\r\n",++task2_num);
taskEXIT_CRITICAL();
解决办法是printf上下加上临界区保护即可
6、🧡 韦东山FreeRTOS部分
void vTask1( void *pvParameters )
{
const TickType_t xDelay100ms = pdMS_TO_TICKS( 100UL );
BaseType_t ret;
for( ;; )
{
printf("Task1 is running\r\n");
ret = xTaskCreate( vTask2, "Task 2", 1000, NULL, 2, &xTask2Handle );
if (ret != pdPASS)
printf("Create Task2 Failed\r\n");
vTaskDelay( xDelay100ms );
}
void vTask2( void *pvParameters )
{
printf("Task2 is running and about to delete itself\r\n");
vTaskDelete(xTask2Handle);
}
int main( void )
{
prvSetupHardware();
xTaskCreate(vTask1, "Task 1", 1000, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}
阻塞≠挂起(挂起只能使用具体的挂起函数,阻塞无需),只有freertos自带的taskdelay函数实现了任务切换,即task1被taskdelay挂起,task2执行完之后就delete了自己,因为taskdelay里面调用了vTaskSuspendAll();挂起函数,这里的阻塞就是PendSV里面的列表项操作
这个tick中断,时间片就是taskdelay延时,taskdelay(1000)就是1000个时间片,这1000ms内这个任务被阻塞,其它任务可以执行,这就是实时操作系统的妙处所在
svs操作系统底层,pendsv用于任务切换,任务的重要程度肯定比不上系统内核底层,根据上面的小节可知,svs就是获取任务堆栈地址,将任务数据进行出栈处理,用于操作硬件底层
7、💛 其它博主文章链接【转载】
1、FreeRTOS任务切换——PendSV
FreeRTOS任务切换——PendSV
这篇文章主要就是解释了上面张图,中断可打断PendSV,PendSV的作用,以及具有延时特点。
2、RTOS系列文章(2):PendSV功能,为什么需要PendSV
RTOS系列文章(2):PendSV功能,为什么需要PendSV
这篇文章写得很详细了,和我看完原子视频理解的大差不差
1、将Systick的优先级设置成高于IRQ
缺点,IRQ=外部中断被耽误,不可容忍
2、将Systick和PendSV的优先级设置为最低
缺点,IRQ影响Systick时钟,可容忍
3、将SysTick的优先级设置成最高,PendSV的优先级设置为低
缺点,耽误IRQ,不可容忍
1 PendSV是可悬起系统中断,具有【缓期执行】特征。
2 PendSV一般被嵌入式OS用于 任务调度的上下文切换。
3 使用PendSV时,一般会将PendSV的优先级设置为最低,让外部IRQ先执行,等到没有外部中断后,在执行上下文切换。
4 嵌入式实时操作系统的【实时】概念,并不仅仅指应用程序、任务的调度实时,而是指整个系统的实时性高,具备【可剥夺】特点,当有高优先级的中断、任务具备执行条件时,立刻中断当前正在运行的任务,去执行高优先级的IRQ和高优先级任务。
5 嵌入式OS一般会将SysTick的优先级也设置为最低,保证外部中断IRQ优先,详细的分析,我们下一篇文章讨论。
至于sys中断和pendsv中断谁的优先级更高?不清楚,还是没明白,反正两个都是设置最低!
3、有了Systick中断为什么还要PendSV中断?(此文章有问题,仅作为参考)
有了Systick中断为什么还要PendSV中断?
4、【FreeRTOS】FreeRTOS 源码学习笔记 (5) 任务调度器 + vTaskStartScheduler、xPortPendSVHandler、xPortSysTickHandler
文章1
5、FreeRTOS对系统异常优先级寄存器的PendSV和SysTick 的优先级设置过程
文章2
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)