FreeRtos学习笔记(12)systemView 分析任务调度情况

2024-03-26 17:12

本文主要是介绍FreeRtos学习笔记(12)systemView 分析任务调度情况,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FreeRtos学习笔记(12)systemView 分析任务调度情况

使用stm32f429 + freertosV10.5.1 + systemView 3.5 + keil AC5

systemView 移植

  1. 从官网下载 systemView 软件
    在这里插入图片描述
  2. 将下面文件添加到工程中

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

freertos 修改

  1. systemView 需要 FreeRTOSConfig.h 开启如下宏, 并添加头文件 “SEGGER_SYSVIEW_FreeRTOS.h”
#define configCHECK_FOR_STACK_OVERFLOW         2
#define configUSE_TRACE_FACILITY               1
#define INCLUDE_uxTaskGetStackHighWaterMark    1
#define INCLUDE_xTaskGetIdleTaskHandle         1
#define INCLUDE_eTaskGetState                  1
#define INCLUDE_pxTaskGetStackStart            1
#include "SEGGER_SYSVIEW_FreeRTOS.h"

此时工程应该可以通过编译

  1. 对freertos 的源码打补丁,来更好的适配systemView

下载对应版本的 SystemView, Target Sources,或者打开systemView软件的安装目录,找到freertos对应版本的补丁文件, 这里用的是freertosV10.4, 因此使用 Src\Sample\FreeRTOSV10.4\Patch 文件

在这里插入图片描述
在这里插入图片描述

diff -rupN org/config/FreeRTOSConfig.h new/config/FreeRTOSConfig.h
--- org/config/FreeRTOSConfig.h	2020-12-15 19:53:08.000000000 +0100
+++ new/config/FreeRTOSConfig.h	2021-03-10 13:28:14.645130255 +0100
@@ -91,6 +91,10 @@ to exclude the API function. */#define INCLUDE_vTaskDelayUntil			1#define INCLUDE_vTaskDelay				1#define INCLUDE_eTaskGetState			1
+#define INCLUDE_xTaskGetIdleTaskHandle                          1
+#define INCLUDE_pxTaskGetStackStart                             1
+
+#include "SEGGER_SYSVIEW_FreeRTOS.h"/* Cortex-M specific definitions. */#ifdef __NVIC_PRIO_BITS
diff -rupN org/FreeRTOS/Source/include/FreeRTOS.h new/FreeRTOS/Source/include/FreeRTOS.h
--- org/FreeRTOS/Source/include/FreeRTOS.h	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/include/FreeRTOS.h	2021-03-10 14:58:58.000000000 +0100
@@ -182,6 +182,10 @@#define INCLUDE_uxTaskGetStackHighWaterMark2    0#endif+#ifndef INCLUDE_pxTaskGetStackStart
+	#define INCLUDE_pxTaskGetStackStart 0
+#endif
+#ifndef INCLUDE_eTaskGetState#define INCLUDE_eTaskGetState    0#endif
@@ -448,6 +452,23 @@#define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )#endif+#ifndef traceREADDED_TASK_TO_READY_STATE
+	#define traceREADDED_TASK_TO_READY_STATE( pxTCB )	traceMOVED_TASK_TO_READY_STATE( pxTCB )
+#endif
+
+#ifndef traceMOVED_TASK_TO_DELAYED_LIST
+	#define traceMOVED_TASK_TO_DELAYED_LIST()
+#endif
+
+#ifndef traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST
+	#define traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST()
+#endif
+
+#ifndef traceMOVED_TASK_TO_SUSPENDED_LIST
+	#define traceMOVED_TASK_TO_SUSPENDED_LIST( pxTCB )
+#endif
+
+#ifndef traceQUEUE_CREATE#define traceQUEUE_CREATE( pxNewQueue )#endif
@@ -696,6 +717,18 @@#define traceTASK_NOTIFY_GIVE_FROM_ISR( uxIndexToNotify )#endif+#ifndef traceISR_EXIT_TO_SCHEDULER
+	#define traceISR_EXIT_TO_SCHEDULER()
+#endif
+
+#ifndef traceISR_EXIT
+	#define traceISR_EXIT()
+#endif
+
+#ifndef traceISR_ENTER
+	#define traceISR_ENTER()
+#endif
+#ifndef traceSTREAM_BUFFER_CREATE_FAILED#define traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer )#endif
diff -rupN org/FreeRTOS/Source/include/task.h new/FreeRTOS/Source/include/task.h
--- org/FreeRTOS/Source/include/task.h	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/include/task.h	2021-03-03 10:07:46.000000000 +0100
@@ -1538,6 +1538,25 @@ UBaseType_t uxTaskGetStackHighWaterMark(*/configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;+/**
+ * task.h
+ * <PRE>uint8_t* pxTaskGetStackStart( TaskHandle_t xTask);</PRE>
+ *
+ * INCLUDE_pxTaskGetStackStart must be set to 1 in FreeRTOSConfig.h for
+ * this function to be available.
+ *
+ * Returns the start of the stack associated with xTask.  That is,
+ * the highest stack memory address on architectures where the stack grows down
+ * from high memory, and the lowest memory address on architectures where the
+ * stack grows up from low memory.
+ *
+ * @param xTask Handle of the task associated with the stack returned.
+ * Set xTask to NULL to return the stack of the calling task.
+ *
+ * @return A pointer to the start of the stack.
+ */
+uint8_t* pxTaskGetStackStart( TaskHandle_t xTask) PRIVILEGED_FUNCTION;
+/* When using trace macros it is sometimes necessary to include task.h before* FreeRTOS.h.  When this is done TaskHookFunction_t will not yet have been defined,* so the following two prototypes will cause a compilation error.  This can be
diff -rupN org/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c new/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c
--- org/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c	2021-03-03 10:20:34.000000000 +0100
@@ -359,13 +359,19 @@ void xPortSysTickHandler( void )uint32_t ulPreviousMask;ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    traceISR_ENTER();{/* Increment the RTOS tick. */if( xTaskIncrementTick() != pdFALSE ){
+            traceISR_EXIT_TO_SCHEDULER();/* Pend a context switch. */portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;}
+        else
+        {
+            traceISR_EXIT();
+        }}portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );}
diff -rupN org/FreeRTOS/Source/portable/GCC/ARM_CM0/portmacro.h new/FreeRTOS/Source/portable/GCC/ARM_CM0/portmacro.h
--- org/FreeRTOS/Source/portable/GCC/ARM_CM0/portmacro.h	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/portable/GCC/ARM_CM0/portmacro.h	2021-03-03 10:21:08.000000000 +0100
@@ -82,7 +82,7 @@#define portNVIC_INT_CTRL_REG     ( *( ( volatile uint32_t * ) 0xe000ed04 ) )#define portNVIC_PENDSVSET_BIT    ( 1UL << 28UL )#define portYIELD()                                 vPortYield()
-    #define portEND_SWITCHING_ISR( xSwitchRequired )    if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT
+    #define portEND_SWITCHING_ISR( xSwitchRequired ) { if( xSwitchRequired ) { traceISR_EXIT_TO_SCHEDULER(); portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } else { traceISR_EXIT(); } }#define portYIELD_FROM_ISR( x )                     portEND_SWITCHING_ISR( x )/*-----------------------------------------------------------*/diff -rupN org/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c new/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c
--- org/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c	2021-03-03 10:17:16.000000000 +0100
@@ -436,14 +436,19 @@ void xPortSysTickHandler( void )* save and then restore the interrupt mask value as its value is already* known. */portDISABLE_INTERRUPTS();
+    traceISR_ENTER();{/* Increment the RTOS tick. */if( xTaskIncrementTick() != pdFALSE ){
+            traceISR_EXIT_TO_SCHEDULER();/* A context switch is required.  Context switching is performed in* the PendSV interrupt.  Pend the PendSV interrupt. */portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;}
+        else {
+            traceISR_EXIT();
+        }}portENABLE_INTERRUPTS();}
diff -rupN org/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h new/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h
--- org/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/portable/GCC/ARM_CM3/portmacro.h	2021-03-03 10:18:26.000000000 +0100
@@ -90,7 +90,7 @@#define portNVIC_INT_CTRL_REG     ( *( ( volatile uint32_t * ) 0xe000ed04 ) )#define portNVIC_PENDSVSET_BIT    ( 1UL << 28UL )
-    #define portEND_SWITCHING_ISR( xSwitchRequired )    if( xSwitchRequired != pdFALSE ) portYIELD()
+    #define portEND_SWITCHING_ISR( xSwitchRequired )    { if( xSwitchRequired != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); portYIELD() } else { traceISR_EXIT(); } }#define portYIELD_FROM_ISR( x )                     portEND_SWITCHING_ISR( x )/*-----------------------------------------------------------*/diff -rupN org/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c new/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
--- org/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c	2021-03-03 10:25:28.000000000 +0100
@@ -498,14 +498,20 @@ void xPortSysTickHandler( void )* save and then restore the interrupt mask value as its value is already* known. */portDISABLE_INTERRUPTS();
+    traceISR_ENTER();{/* Increment the RTOS tick. */if( xTaskIncrementTick() != pdFALSE ){
+            traceISR_EXIT_TO_SCHEDULER();/* A context switch is required.  Context switching is performed in* the PendSV interrupt.  Pend the PendSV interrupt. */portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;}
+        else
+        {
+            traceISR_EXIT();
+        }}portENABLE_INTERRUPTS();}
diff -rupN org/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h new/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h
--- org/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h	2020-12-15 19:54:26.000000000 +0100
+++ new/FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h	2021-03-03 10:26:06.000000000 +0100
@@ -90,7 +90,7 @@#define portNVIC_INT_CTRL_REG     ( *( ( volatile uint32_t * ) 0xe000ed04 ) )#define portNVIC_PENDSVSET_BIT    ( 1UL << 28UL )
-    #define portEND_SWITCHING_ISR( xSwitchRequired )    if( xSwitchRequired != pdFALSE ) portYIELD()
+    #define portEND_SWITCHING_ISR( xSwitchRequired ) { if( xSwitchRequired != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); portYIELD(); } else { traceISR_EXIT(); } }#define portYIELD_FROM_ISR( x )                     portEND_SWITCHING_ISR( x )/*-----------------------------------------------------------*/diff -rupN org/FreeRTOS/Source/tasks.c new/FreeRTOS/Source/tasks.c
--- org/FreeRTOS/Source/tasks.c	2020-12-15 19:54:28.000000000 +0100
+++ new/FreeRTOS/Source/tasks.c	2021-03-10 14:59:11.000000000 +0100
@@ -1735,7 +1735,7 @@ static void prvAddNewTaskToReadyList( TC{mtCOVERAGE_TEST_MARKER();}
-
+            traceMOVED_TASK_TO_SUSPENDED_LIST(pxTCB);vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );#if ( configUSE_TASK_NOTIFICATIONS == 1 )
@@ -3927,6 +3927,20 @@ static void prvCheckTasksWaitingTerminat#endif /* INCLUDE_uxTaskGetStackHighWaterMark *//*-----------------------------------------------------------*/+#if (INCLUDE_pxTaskGetStackStart == 1)
+	uint8_t* pxTaskGetStackStart( TaskHandle_t xTask)
+	{
+	    TCB_t *pxTCB;
+	    UBaseType_t uxReturn;
+        (void)uxReturn;
+
+		pxTCB = prvGetTCBFromHandle( xTask );
+		return ( uint8_t * ) pxTCB->pxStack;
+	}
+
+#endif /* INCLUDE_pxTaskGetStackStart */
+/*-----------------------------------------------------------*/
+#if ( INCLUDE_vTaskDelete == 1 )static void prvDeleteTCB( TCB_t * pxTCB )
@@ -5311,12 +5325,14 @@ static void prvAddCurrentTaskToDelayedLi{/* Wake time has overflowed.  Place this item in the overflow* list. */
+                    traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST();vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );}else{/* The wake time has not overflowed, so the current block list* is used. */
+                    traceMOVED_TASK_TO_DELAYED_LIST();vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );/* If the task entering the blocked state was placed at the
@@ -5345,11 +5361,13 @@ static void prvAddCurrentTaskToDelayedLiif( xTimeToWake < xConstTickCount ){
+                traceMOVED_TASK_TO_OVERFLOW_DELAYED_LIST();/* Wake time has overflowed.  Place this item in the overflow list. */vListInsert( pxOverflowDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );}else{
+                traceMOVED_TASK_TO_DELAYED_LIST();/* The wake time has not overflowed, so the current block list is used. */vListInsert( pxDelayedTaskList, &( pxCurrentTCB->xStateListItem ) );

由于使用的是STMF429 和keil 的AC5, 因此按照上述补丁文件,逐条对以下文件进行修改(由于补丁是V10.4.3的,而实际使用的freertos版本为10.5.1,因此补丁的行数信息不准确,需要根据上下文搜索确定文件修改位置)

  • config/FreeRTOSConfig.h

此文件上面已经修改过了

  • FreeRTOS/Source/include/FreeRTOS.h

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • FreeRTOS/Source/include/task.h

在这里插入图片描述

  • FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c

在这里插入图片描述

  • FreeRTOS/Source/portable/GCC/ARM_CM4F/portmacro.h

  • FreeRTOS/Source/tasks.c

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

systemView 使用

  • 配置
    systemView 可以简单看成当RTOS进行任务切换、消息队列发送接收时,会向RAM写入时间戳等信息,systemView通过jlink直接读取RAM,将RAM中的时间戳等信息翻译成图表信息。因此时间戳怎么获取是很重要的,cortex-M3/M4/M7内核中有一个DWT定时器,分辨率是系统时钟,systemView就是使用的这个定时器。
    在这里插入图片描述
    在这里插入图片描述

systemView通过jlink直接读取RAM时,会从该地址开始进行查找。
在这里插入图片描述

  • 初始化
traceSTART();

打开 systemView 即可
在这里插入图片描述

  • 添加想要测量的中断
  1. 添加描述符
    在这里插入图片描述

在这里插入图片描述
SysTick_IRQn 为15, 所以 TIM8_TRG_COM_TIM14_IRQn 为 16 + 45 = 61
2. 中断服务函数中添加trace
在这里插入图片描述

在这里插入图片描述

  • 测量代码段运行时长
    在这里插入图片描述
    在这里插入图片描述

systemView 溢出

  • 提高 jlink 速度
    在这里插入图片描述

  • 增大RAM缓冲区
    在这里插入图片描述

  • 如果使用了SEGGER RTT打印log,关闭RTT打印

这篇关于FreeRtos学习笔记(12)systemView 分析任务调度情况的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/849252

相关文章

Springboot中分析SQL性能的两种方式详解

《Springboot中分析SQL性能的两种方式详解》文章介绍了SQL性能分析的两种方式:MyBatis-Plus性能分析插件和p6spy框架,MyBatis-Plus插件配置简单,适用于开发和测试环... 目录SQL性能分析的两种方式:功能介绍实现方式:实现步骤:SQL性能分析的两种方式:功能介绍记录

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

C#使用DeepSeek API实现自然语言处理,文本分类和情感分析

《C#使用DeepSeekAPI实现自然语言处理,文本分类和情感分析》在C#中使用DeepSeekAPI可以实现多种功能,例如自然语言处理、文本分类、情感分析等,本文主要为大家介绍了具体实现步骤,... 目录准备工作文本生成文本分类问答系统代码生成翻译功能文本摘要文本校对图像描述生成总结在C#中使用Deep

Redis主从/哨兵机制原理分析

《Redis主从/哨兵机制原理分析》本文介绍了Redis的主从复制和哨兵机制,主从复制实现了数据的热备份和负载均衡,而哨兵机制可以监控Redis集群,实现自动故障转移,哨兵机制通过监控、下线、选举和故... 目录一、主从复制1.1 什么是主从复制1.2 主从复制的作用1.3 主从复制原理1.3.1 全量复制

Redis主从复制的原理分析

《Redis主从复制的原理分析》Redis主从复制通过将数据镜像到多个从节点,实现高可用性和扩展性,主从复制包括初次全量同步和增量同步两个阶段,为优化复制性能,可以采用AOF持久化、调整复制超时时间、... 目录Redis主从复制的原理主从复制概述配置主从复制数据同步过程复制一致性与延迟故障转移机制监控与维

Redis连接失败:客户端IP不在白名单中的问题分析与解决方案

《Redis连接失败:客户端IP不在白名单中的问题分析与解决方案》在现代分布式系统中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、消息队列、会话存储等场景,然而,在实际使用过程中,我们可能... 目录一、问题背景二、错误分析1. 错误信息解读2. 根本原因三、解决方案1. 将客户端IP添加到Re

Redis主从复制实现原理分析

《Redis主从复制实现原理分析》Redis主从复制通过Sync和CommandPropagate阶段实现数据同步,2.8版本后引入Psync指令,根据复制偏移量进行全量或部分同步,优化了数据传输效率... 目录Redis主DodMIK从复制实现原理实现原理Psync: 2.8版本后总结Redis主从复制实

锐捷和腾达哪个好? 两个品牌路由器对比分析

《锐捷和腾达哪个好?两个品牌路由器对比分析》在选择路由器时,Tenda和锐捷都是备受关注的品牌,各自有独特的产品特点和市场定位,选择哪个品牌的路由器更合适,实际上取决于你的具体需求和使用场景,我们从... 在选购路由器时,锐捷和腾达都是市场上备受关注的品牌,但它们的定位和特点却有所不同。锐捷更偏向企业级和专

Spring中Bean有关NullPointerException异常的原因分析

《Spring中Bean有关NullPointerException异常的原因分析》在Spring中使用@Autowired注解注入的bean不能在静态上下文中访问,否则会导致NullPointerE... 目录Spring中Bean有关NullPointerException异常的原因问题描述解决方案总结