前面的提到了关于FreeRtos的任务的挂起与恢复,消息队列,软件定时器等内容,今天就继续介绍其他几个参数吧!
这里基本的还是配置按键作为事件触发,然后LED作为展示,cubemx中配置如下所示:
下一步我们来配置任务,这里使用默认的任务即可,当然我这里新建了一个任务但是没有用到
第二个部分就是中断的切换这里不要的影响好像不是很大,没什么大的问题,因为这里是中断中发布,所以用的函数不太一样
在设置另一个函数用来接收,这里是收到通知就就会有反应,还有一个函数是收到通知的内容,详情可以查看一些官方教程和二维码
最终我们将程序下载到开发板就可以看到效果了,按下我们led之后,就可以看到电平翻转。
消息队列就是通过 RTOS 内核提供的服务,任务或中断服务子程序可以将一个消息放入到队列。
同样, 一个或者多个任务可以通过 RTOS 内核服务从队列中得到消息。注意这里消息队列传递的是真正的数据,不是和其他RTOS一样传递的地址信息,通常, 先进入消息队列的消息先传给任务,也就是说,任务先得到的是最先进入到消息队列的消息,即先进先出的原则( FIFO) , FreeRTOS的消息队列支持 FIFO 和 LIFO 两种数据存取方式。
在这里消息队列和数组很像,我们使用消息队列要注意,一般我们在裸机中需要一个变量北反复使用一般就直接定义相关的数组了,但是对于RTOS消息队列则更好,优点总结如下:
关于FIFO的数据存取可以看下面的动图
这里我们还是用上面的两个任务来进行数据的收发,同时我们可以看到就是cube中其实可以配置消息队列 的函数,这里我们先不进行配置,直接在代码中来实现,这个等之后在图形化配置。
下面我们首先还是新建一个消息,如下所示
创建句柄如下
这里我们在一个任务中发送消息,并准备另一个任务用于接收任务
将程序下载到开发板,效果如下所示:
下面我们来尝试使用cube的图形化来配置信号量
下面是新建消息队列
在任务中发送函数如下所示
我们可以使用打印任务状态用来查看任务执行情况,这里将程序下载到开发板,可以看到效果如下所示
参数说明:
X | running |
---|---|
B | blocked |
R | ready |
D | deleted |
S | suspended |
这样需要先配置一些宏,主要是任务追踪的宏,全部设置为enable
然后我们初始化一个定时器用于计数
这里我们需要开启中断计数
在tim.c中加入如下代码用于计数
代码如下:
volatile unsigned long long FreeRTOSRunTimeTicks=0;
__weak void configureTimerForRunTimeStats(void)
{
HAL_TIM_Base_Start_IT(&htim6);
FreeRTOSRunTimeTicks = 0;
}
__weak unsigned long getRunTimeCounterValue(void)
{
return FreeRTOSRunTimeTicks;
}
然后在中断回调加入计数,对上面定义的全局变量进行计数
代码如下:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM7) {
HAL_IncTick();
}
/* USER CODE BEGIN Callback 1 */
if (htim->Instance == TIM6) {
// HAL_IncTick();
FreeRTOSRunTimeTicks++;
}
/* USER CODE END Callback 1 */
}
我们单片机一般都是单核的,那么系统调度的时候用的其实就是cpu不算的在任务之间进行切换,但是有的任务可能就会占用过高的资源,然后有的任务就没有这么高的占用,但是这个占用可能是异常的,就像任务死机了一样,因此我们就很有必要去监控CPU的这个占用率了!,调试的时候很有必要得到当前系统的CPU利用率相关信息,但是在产品发布时,就可以去掉CPU利用率统计功能,以避免消耗系统资源。
整个过程的思路大概如下:
**FreeRTOS 是使用一个外部的变量进行时间统计,并且消耗一个高精度的定时器,其用于定时的精度是系统时钟节拍的10-20倍。**这里选择一个50us的之中,上面已经配置过了,这里要注意的就是计数变量的累加在freertos里面:
这个东西千万不要放在其他地方测试,不然就会失效,就会获取不到任务信息,然后就会打印一个空的字符串,具体现象为
这样之后我们就可以打印我们需要的信息了,我们把他放到一个专门的任务里面
源码如下:
for(;;)
{
memset(InfoBuffer, 0, 400);
vTaskGetRunTimeStats((char*) InfoBuffer);
printf("Name Abs Time Time\r\n");
printf("******************************************************\r\n");
printf("%s", InfoBuffer);
printf("******************************************************\r\n");
osDelay(1000);
}
这里简单的做下说明,因为其他任务啥也没干,基本就是转转led,所以占用的资源就很少,这样我们系统的富余资源就比较多了