其他分享
首页 > 其他分享> > Freertos Trace任务可视化分析(三)互斥量 SystemView

Freertos Trace任务可视化分析(三)互斥量 SystemView

作者:互联网

SystemView 记录Trace通过Event进行事件记录。
举个简单的例子
prvAddCurrentTaskToDelayedList函数中
traceMOVED_TASK_TO_DELAYED_LIST();
Freertos内核代码中有很多traceXXX的函数,SystemView重新定义这些函数。
SEGGER_SYSVIEW_FreeRTOS.h

#define traceMOVED_TASK_TO_DELAYED_LIST()           SEGGER_SYSVIEW_OnTaskStopReady((U32)pxCurrentTCB,  (1u << 2))
#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST()  SEGGER_SYSVIEW_OnTaskStopReady((U32)pxCurrentTCB,  (1u << 2))
#define traceMOVED_TASK_TO_SUSPENDED_LIST(pxTCB)    SEGGER_SYSVIEW_OnTaskStopReady((U32)pxTCB,         ((3u << 3) | 3))

当Freertos的tracexxxxxx函数运行的时候,会执行SEGGER_SYSVIEW定义的trace函数。把对应的 事件写入到指定的事件缓冲区域。所以我们可以人为去增加trace的位点。调试器会读取内存区域的数据传输到PC上,完成图形界面的变化。

trace大致的工作原理就是这样。
1.记录的是tracexxxx,所有没有trace函数的地方不会有trace
2.事件时间不是非常的精确,但是一定程度上已经非常够用了。

代码如下,这里建立两个任务LED0_Task ,LED1_Task
SystemView 记录的文档 点击这里

  xTaskCreate(LED0_Task, "LED0_Blink", 128, (void*)NULL,4 , NULL);
  xTaskCreate(LED1_Task, "LED1_Blink", 128, (void*)NULL,5 , NULL);
LED0_Task 优先级4
LED1_Task 优先级5
void do_things(int i)
{	
    int k,n;
	for(n=0;n<i;n++)
	{
		k=0;
		while(k<655)
		{
			k++;
		}
	}
		
}

static void LED0_Task(void *args) {
  while (1) {
  	
	xSemaphoreTake(mutex_1, 0xffff);

	do_things(10);
	xSemaphoreGive(mutex_1);
	vTaskDelay(4);
	
  };
}
static void LED1_Task(void *args) {
  while (1) {
  	
  	vTaskDelay(2);
	xSemaphoreTake(mutex_1, 0xffff);
	do_things(10);
  	
    xSemaphoreGive(mutex_1);
  
  };
  
}

运行程序,进行记录
在这里插入图片描述
sysTick ,是ARM cortex-M3内核专门用来提供操作系统tick的定时器,Freertos在调度器的初始化中对它的间隔进行了设定。上图可以看到每个systick 1ms运行一次,每一次运行都会打断用户函数的运行,并且systick handler处理函数执行也需要花费时间。
在这里插入图片描述
这里需要耗费23us的时间执行。
在这里插入图片描述
先看Event 这个时候LED1任务接收了队列,对应大码是line85,获取互斥量。然后执行do_things。
在这里插入图片描述
经过了多个systick LED1任务释放了信号量,跳回while(1)开头的taskdelay(2),也就是说任务要进入阻塞状态,任务的切换是由调度器完成的。可以看到调度器的执行也需要耗费时间
在这里插入图片描述
下一个事件,LED0任务获取了 互斥量,开始执行dothings。
在这里插入图片描述
dothings(10)还没完成。systick计数器+1,LED1的Delay2超时解除阻塞状态。调度器执行上下文切换LED1任务执行。
在这里插入图片描述
箭头时刻,LED1 尝试获取互斥量,这时互斥量的拥有着LED0 继承优先级,那么LED0优先执行。
在这里插入图片描述
直到下一个时刻LED0 do_things(10);执行完成释放互斥量。这个时候优先级回复成原始优先级 。LED1是最高优先级,马上切换运行,获取互斥量。
在这里插入图片描述
下一个时间,LED1释放了互斥量进入taskdelay(2),那么任务LED0运行执行delay(4).这个时候所有的用户任务都在阻塞状态,那么空闲任务Idea task运行。
在这里插入图片描述
下一个时刻LED1 的Taskdelay(2) 完成切换LED1运行。

上面的过程可以理解以下内容
1.任务的切换需要CPU运行一段时间的调度器任务
2.systick周期性的唤醒短暂的打断正在运行的任务
3.systick,调度器的设计要精简,减少耗时
4.taskdelay计数依赖systick 计数误差1 tick
5.互斥量的优先级继承机制
6.Freertos的 API可以直接发起PendSV,进行上下文切换,不需要在下一个systick来触发

标签:LED1,LED0,Task,Freertos,Trace,void,互斥,systick
来源: https://blog.csdn.net/denghuajing/article/details/121719742