freeRTOS
裸机开发:
-
裸机开发缺点:
对于裸机开发不同任务之间的干扰和耦合是很严重的且难以避免的在轮询模式下,如果某个任务的程序因为条件不足而等待在某处,就会导致整个CPU的资源浪费在那个地方,其他的任务就没办法实现了;而且轮训模式对于人物处理速度受限于我们使用的处理器,处理器主频越高,处理速度自然越快;也受限于我们的代码,代码写的好,优化程度高,执行效率也会提高
-
中断处理的基本流程:
将一些紧急的任务选择使用事件或者中断的方式去处理,这样就可以脱离轮训模式,随时大端普通任务,抢占处理器的字图案去优先执行这些紧急的事情
-
硬件优先级:
cortex-M3的中断优先级用 来表示,前一个参数代表抢占优先级,后一个参数代表子优先级,优先级数值越低,代表的优先级越高,这与freeRTOS中的任务优先级是相反的(任务优先级是数值越大,优先级越高)。
这里,抢占优先级可以实现中断的嵌套。中断嵌套是什么意思呢?就是一个中断可以打断另一个正在被cpu处理的中断,将cpu资源抢夺过来,在前一个中断的处理过程中,优先处理当前这个抢占优先级更高的中断;当前这个抢占优先级更高的中断处理完之后,cpu才会去处理上一个被打断的、抢占优先级略低的中断
同等抢占等级的前后触发,先处理线面的再处理后面的
同等抢占等级同时触发,先处理任务在中断向量表中的位置,谁靠前先执行谁,即谁的中断号小,优先执行谁
不同抢占等级同时或者前后触发,都会先处理抢占等级高的,再处理抢占等级低的。
具体中断优先级相关的知识可以去看http://t.csdn.cn/KGjaG
-
针对以下按键实验的理解
ps:加上了weak 修饰符的函数,用户可以在用户文件中重新定义一个同名函数,最终编译器编译的时候,会选择用户定义的函数,如果用户没有重新定义这个函数,那么编译器就会执行weak 声明的函数,并且编译器不会报错。所以我们可以在别的地方定义一个相同名字的函数,而不必也尽量不要修改之前的函数,。
[06_keypolling_ctrl_t]
首先是配置方面:
-
通过图片我们可以看到将PA0配置成为外部触发中断的模式
-
来到具体内容中我们可以看到GPIO被配置成下降沿触发外部中断
-
将外部中断使能,并且可以设置优先级分组和抢占优先级
-
同理定时器也可以在打开后在NVIC里使能中断和设置优先级
然后是代码具体运行流程:
-
首先略过初始化部分
-
整体思路就是按键抬起瞬间GPIO检测到下降沿-》触发中断(省略具体流程)-》执行HAL_GPIO_EXTI_Callback将标志位置1-》主函数部分进入if语句开起tim2的计数-》tim2按计时触发中断,更改标志位的值-》主函数中的switch语句输出对应case的文字-》再次按下按键将状态位都取反-》tim2停止计-》周期性进中断停止。
-
反映到现实功能就是按键然后开始执行设定好的周期性任务,再按就停止
-
软件仿真如图,对GPIOApin0进行使能和去能就能模拟出上述的过程
-
-
因为对于中断服务函数,我们有一个潜规则,就是:不能在中断中处理耗时长的事情
-
定时器在不同时刻处理的不同的耗时长的任务,如果相互之间是没有例如数据互通、信号通信这种情况,是相互独立的,那么CPU要处理这些任务所消耗的时间资源,就是所有任务消耗时间的总长
-
实验8
[08_polling_process_longtime_task] D:\QQDATA\864039635\FileRecv
-
实验8是计算每个任务完成的时间和最后的总时间
-
看代码的时候问题出现在timer2计数上,根据配置来看timer2时钟频率是1mHZ,计数是1000,在cubeMX中的配置是预分频72-1和计数1000-1。也就是1ms一个timer2中断
-
当时思考的问题时5个任务基本遵循每个任务执行1000ms,但是明明timer2需要1ms增一个数,要完成所有任务的标志位置位需要1000ms分到每个任务也就是200ms,但是这个想法是错误的。
-
!!!因为在任务执行的1000ms内中断也在不断的执行,所以当第一个任务执行过中,其他标志位都已经被callback置位完毕,while里就顺序执行了
-
FreeRTOS
-
FreeRTOS配置:
-
对于st的处理器,要想使用rtos开发产品,快速开发还是蛮简单的,可以通过cubemx直接配置
-
首先是CMSIS标准的版本选择,根据一下这两点,我们一般会选择V2版本,便于往后移植到高版本的内核或者低版本的内核;
-
然后是配置参数,config parameters,需要我们去选择rtos使用的滴答定时器的频率、任务最小的栈空间大小,单位是words,4个字节,往后创建任务的时候,必须是这个最小栈空间大小的整数倍;
-
RTOS使用的最大的堆空间,rtos任务、队列、互斥量等等里面的静态变量、全局变量等就是通过我们选择的内存管理方案heap1/2/3/4/5从这个堆空间中分配内存;
-
-
创建任务,cubemx有一个默认任务,我们无法删除,只能修改里面的参数,任务名称、优先级、栈大小、入口函数名称、代码类型、参数和内存分配方式,代码类型那里只有两种可选,默认模式就是直接在代码中定义实现入口函数,as weak则是将入口函数弱化,我们开发者可以在别的地方重新实现这个入口函数。
-
-
而内存分配,根据RTOS的应用规则,也就两个可选:动态分配堆栈内存和静态分配堆栈,如果需要较好的内存管理方案,可能会选择静态分配
-
-
而创建一个自己的任务,总体和那个默认任务差不多,唯一不同的就是代码类型有一个as external,这个类型的意思是,使用cubemx生成代码后,我们的这个自己的任务入口函数是没有实现的,只是用external声明了下好让freertos创建任务的时候使用,需要我们自己在应用程序中实现,如果没有实现的话编译会报错,
-
-
而default 和 as weak,是已经有了入口函数的实体,即便是as weak修饰的,我们也没有实现,编译器也不会报错
-
Freertos堆空间使用情况,这一栏我们可以看到我们配置的rtos的内容占用了总共多少堆空间
-
-
我们再config parameters里面分配的最大堆空间是否够用,如果不够我们就需要去增加最大堆空间或者减小我们配置的rtos的内容堆堆空间的使用
-
关于使用cubemx配置rtos的其他功能,比如队列、互斥量、软件定时器等,大家可以自己去尝试体验下。
-
很感谢百问网的老师的视频课还有文字直播课,能把问题讲的很清楚,学到不少