12 FreeRTOS 调试与优化

1、调试

1.1 打印

        在FreeRTOS工程中使用了microlib,里面实现了printf函数。

        只需要实现一下以下函数即可使用printf。

int fputc(int ch; FILE *f);

        假如要从串口实现打印函数:

int fputc( int ch, FILE *f )
{
	//指定串口
	USART_TypeDef* USARTx = USART1;
	//等待数据发送出去,数据发送完时SR的bit7=1
	while((USARTx->SR & (1<<7)) == 0);
	
	//往DR寄存器中写入字符
	USARTx->DR = ch;
		
	return ch;
}

1.2 断言

        一般的C库中,断言就是一个函数。

void assert(scalar expression);

        它的作用是:确认expression必须为真,如果expression为假的话就中止程序。

        在FreeRTOS中,使用configASSERT(),比如:

#define configASSERT(x)  if (!x) while(1);

        也可以让它提供更多的信息:

#define configASSERT(x)  \
	if (!x) \
	{
		printf("%s %s %d\r\n", __FILE__, __FUNCTION__, __LINE__); \
        while(1); \
 	}

1.3 Trace

        FreeRTOS中定义了很多trace开头的宏,这些宏被放在系统个关键位置。

        它们一般都是空的宏,这不会影响代码:不影响编程处理的程序大小、不影响运行时间。

        我们要调试某些功能时,可以修改宏:修改某些标记变量、打印信息等待。

1.4 Malloc Hook函数

        编程时,一般的逻辑错误都容易解决。难以处理的是内存越界、栈溢出等。

        内存越界经常发生在堆的使用过程中:堆,就是使用malloc得到的内存。

        并没有很好的方法检测内存越界,但是可以提供一些回调函数:使用pvPortMalloc失败时,如果在FreeRTOSConfig.h里配置`configUSE_MALLOC_FAILED_HOOK`为1,会调用:

void vApplicationMallocFailedHook( void );

1.5 栈溢出Hook函数

        在切换任务(vTaskSwitchContext)时调用taskCHECK_FOR_STACK_OVERFLOW来检测栈是否溢出,如果溢出会调用:

void vApplicationStackOverflowHook( TaskHandle_t xTask, char * pcTaskName );

        判断栈溢出可以有两种方法:

        方法一:当前任务被切换出去之前,它的整个运行现场都被保存在栈里,这时很可能就是它对栈的使用到达了峰值。这方法很高效,但是并不精确。比如:任务在运行过程中调用了函数A大量地使用了栈,调用完函数A后才被调度。 

        方法二:创建任务时,它的栈被填入固定的值,比如:0xa5。检测栈里最后16字节的数据,如果不是0xa5的话表示栈即将、或者已经被用完了。没有方法1快速,但是也足够快。能捕获几乎所有的栈溢出。为什么是几乎所有?可能有些函数使用栈时,非常凑巧地把栈设置为0xa5:几乎不可能

2、优化

        在Windows中,当系统卡顿时我们可以查看任务管理器找到最消耗CPU资源的程序。

        在FreeRTOS中,我们也可以查看任务使用CPU的情况、使用栈的情况,然后针对性地进行优化。

2.1 栈使用情况

        在创建任务时分配了栈,可以填入固定的数值比如0xa5,以后可以使用以下函数查看"栈的高水位",也就是还有多少空余的栈空间。原理是:从栈底往栈顶逐个字节地判断,它们的值持续是0xa5就表示它是空闲的。 

//xTask 哪个任务  
//返回值 
    //任务运行时、任务被切换时,都会用到栈。栈里原来值(0xa5)就会被覆盖。
    //逐个函数从栈的尾部判断栈的值连续为0xa5的个数,它就是任务运行过程中空闲内存容量的最小值。
    //注意:假设从栈尾开始连续为0xa5的栈空间是N字节,返回值是N/4。
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );

2.2 任务运行时间统计

        对于同优先级的任务,它们按照时间片轮流运行:你执行一个Tick,我执行一个Tick。是否可以在Tick中断函数中,统计当前任务的累计运行时间?不行!很不精确,因为有更高优先级的任务就绪时,当前任务还没运行一个完整的Tick就被抢占了。

        我们需要比Tick更快的时钟,比如Tick周期时1ms,我们可以使用另一个定时器,让它发生中断的周期时0.1ms甚至更短。使用这个定时器来衡量一个任务的运行时间,原理如下图所示:

        切换到Task1时,使用更快的定时器记录当前时间T1;Task1被切换出去时,使用更快的定时器记录当前时间T4;(T4-T1)就是它运行的时间,累加起来。关键点:在vTaskSwitchContext函数中,使用更快的定时器统计运行时间。

2.3 涉及的代码

        要提前配置一下

#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_TRACE_FACILITY    1
#define configUSE_STATS_FORMATTING_FUNCTIONS  1

        实现宏portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(),它用来初始化更快的定时器

        实现这两个宏之一,它们用来返回当前时钟值(更快的定时器)

                portGET_RUN_TIME_COUNTER_VALUE():直接返回时钟值

                portALT_GET_RUN_TIME_COUNTER_VALUE(Time):设置Time变量等于时钟值

        代码执行流程:

        (1)在启动调度器时,初始化更快的定时器

        (2)在任务切换时统计运行时间

        获得统计信息,可以使用下列函数:

        (1)uxTaskGetSystemState:对于每个任务它的统计信息都放在一个TaskStatus_t结构体里

        (2)vTaskList:得到的信息是可读的字符串

        (3)vTaskGetRunTimeStats:  得到的信息是可读的字符串

2.4 函数说明

        uxTaskGetSystemState:获得任务的统计信息

UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
                                        const UBaseType_t uxArraySize,
                                        uint32_t * const pulTotalRunTime );
参数描述
pxTaskStatusArray

向一个TaskStatus_t结构体数组,用来保存任务的统计信息。

有多少个任务?可以用`uxTaskGetNumberOfTasks()`来获得。

uxArraySize

数组大小、数组项个数,

必须大于或等于uxTaskGetNumberOfTasks()

pulTotalRunTime用来保存当前总的运行时间(更快的定时器),可以传入NULL
返回值

传入的pxTaskStatusArray数组,被设置了几个数组项。

注意:如果传入的uxArraySize小于uxTaskGetNumberOfTasks(),返回值就是0

        vTaskList :获得任务的统计信息,形式为可读的字符串。注意,pcWriteBuffer必须足够大。

void vTaskList( signed char *pcWriteBuffer );

        可读信息格式如下:

 

        vTaskGetRunTimeStats:获得任务的运行信息,形式为可读的字符串。注意,pcWriteBuffer必须足够大。

void vTaskGetRunTimeStats( signed char *pcWriteBuffer );

        可读信息如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/665901.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

地质灾害位移应急监测站

地质灾害位移应急监测站是一种专门用于地质灾害预警和应急响应的设施&#xff0c;它能够实时监测和分析山体、建筑物、管道等的位移变化情况。以下是关于地质灾害位移应急监测站的详细介绍&#xff1a; 主要组成部分 传感器&#xff1a;安装于需要监测的位置&#xff0c;用于…

【全开源】Java短剧系统微信小程序+H5+微信公众号+APP 源码

打造属于你的精彩短视频平台 一、引言&#xff1a;为何选择短剧系统小程序&#xff1f; 在当今数字化时代&#xff0c;短视频已经成为人们日常生活中不可或缺的一部分。而短剧系统小程序源码&#xff0c;作为构建短视频平台的强大工具&#xff0c;为广大开发者提供了快速搭建…

html+css web前端 多边形

<!DOCTYPE html><html><head><meta charset"UTF-8"><title>多边形</title><style type"text/css">#pentagon_6_1 {position: absolute;top: 0px;height: 0; width: 100; border-left: 100px solid rgb(255, 255…

机器人动力学模型与MATLAB仿真

机器人刚体动力学由以下方程控制&#xff01;&#xff01;&#xff01; startup_rvc mdl_puma560 p560.dyn 提前计算出来这些“disturbance”&#xff0c;然后在控制环路中将它“抵消”&#xff08;有时候也叫前馈控制&#xff09; 求出所需要的力矩&#xff0c;其中M项代表克服…

堆排序详细理解

目录 一、前备知识 二、建堆 2.2.1 向上调整算法建堆 2.2.2 向下调整算法建堆 三、排序 3.1 常见问题 3.2 思路 3.3 源码 一、前备知识 详细图解请点击&#xff1a;二叉树的顺序实现-堆-CSDN博客 本文只附上向上/向下调整算法的源码 //交换 void Swap(int* p, int* …

java中回调与Timer类的使用

回调&#xff1a;回调&#xff08;callback)是一种常见的程序设计模式。在这种模式中&#xff0c;可以指出某个特定事件发生时应该采取的动作。 Timer类&#xff1a;java.swing包中的Timer类&#xff0c;可以使用它在给定的时间间隔时发出通告。如程序中有一个时钟&#xff0c…

水位监测站的工作原理

TH-SW2在雨季&#xff0c;河道和湖泊的水文信息监测对于防洪减灾、水资源管理和环境保护等方面具有至关重要的意义。水文监测站作为实现这一目标的基础设施&#xff0c;发挥着关键作用。水文监测站是观测及搜集河流、湖泊、水库等水体的水文、气象资料的基层水文机构。在雨季&a…

算法与数据结构:红黑树

ACM大牛带你玩转算法与数据结构-课程资料 本笔记属于船说系列课程之一&#xff0c;课程链接&#xff1a; 哔哩哔哩_bilibilihttps://www.bilibili.com/cheese/play/ep66799?csourceprivate_space_class_null&spm_id_from333.999.0.0 你也可以选择购买『船说系列课程-年度会…

【计算机毕设】基于Spring Boot的课程作业管理系统 - 源码免费(私信领取)

免费领取源码 &#xff5c; 项目完整可运行 &#xff5c; v&#xff1a;chengn7890 诚招源码校园代理&#xff01; 1. 研究目的 课程作业管理系统旨在为教师和学生提供一个便捷的平台&#xff0c;用于发布、提交和评定课程作业。本系统旨在提高作业管理的效率&#xff0c;促进教…

NetMizer 日志管理系统前台RCE漏洞

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、产品介绍 NetMizer日志管理系统是一个与NetMizer流量管理设备配合…

nginx的安装002

之前001讲述了nginxyum安装现在讲一下nginx如何本地离线安装 操作系统&#xff1a; CentOS Stream 9 操作步骤&#xff1a; 首先访问nginx官网&#xff0c;下载。 用wget命令下载&#xff0c; [rootlocalhost ~]# wget -c https://nginx.org/download/nginx-1.26.0.tar.gz …

【网络原理】HTTP|认识请求“报头“|Host|Content-Length|Content-Type|UA|Referer|Cookie

目录 认识请求"报头"(header) Host Content-Length Content-Type User-Agent(简称UA) Referer &#x1f4a1;Cookie&#xff08;最重要的一个header&#xff0c;开发&面试高频问题&#xff09; 1.Cookie是啥&#xff1f; 2.Cookie怎么存的&#xff1f; …

在PostGIS中检查孤线(Find isolated lines in PostGIS)

场景 在PostGIS中有一张线要素表,需要检查该表中的孤线,并且进行自动纠正的计算。 其中孤线定义为两端端点都不在任何其他线的顶点上。 本文介绍在PostGIS中的线要素点,通过函数计算指定线要素表中的孤线,并计算最接近的纠偏位置。 In PostGIS, there is a table of line …

07-操作元素(键盘和鼠标事件)

在前面的文章中重点介绍了一些元素的定位方法&#xff0c;定位到元素后&#xff0c;就需要操作元素了。本篇总结了web页面常用的一些操作元素方法&#xff0c;可以统称为行为事件。 一、简单操作 点击按钮&#xff08;鼠标左键&#xff09;&#xff1a;click()清空输入框&…

git冲突

git冲突的产生&#xff1a; 首先用户A新建一个文件conflict&#xff0c;并在里面添加内容 然后通过add,commit,push将该文件上传到远端仓库 然后用户B通过pull将程序拉下来之后&#xff0c;也在这个文档里面进行编辑&#xff0c;并且内容不一样 如果这个时候其中一个人push&…

PAT-1004 成绩排名(java实现)

这一关感觉还没第三关难&#xff0c;思路很清晰 题目 1004 成绩排名 读入 n&#xff08;>0&#xff09;名学生的姓名、学号、成绩&#xff0c;分别输出成绩最高和成绩最低学生的姓名和学号。 输入格式&#xff1a; 每个测试输入包含 1 个测试用例&#xff0c;格式为 第 1 行…

加密金字塔的秘密:「高层」的回报你无法想象

原文标题&#xff1a;《The Secrets of the Crypto Pyramid!》 撰文&#xff1a;DUO NINE⚡YCC 编译&#xff1a;Chris&#xff0c;Techub News 本文来源香港Web3科技媒体&#xff1a;Techub News 意外成为一名 KOL 让我有机会深入了解这个领域的运作机制。在这个行业的幕后…

优化基础(二):线性组合、仿射组合、锥组合、凸组合、线性集合、仿射集合、锥集合、凸集合的理解

文章目录 前言组合线性组合 (linear combination)仿射组合 (affine combination)锥组合 (conic combination)凸组合 (convex combination) 集合仿射集合凸集合 练习&#xff1a;哪个图形是凸的&#xff0c;哪个是仿射的&#xff1f;参考资料 前言 组合侧重于描述由一些基点生成…

ai虚拟主播自动切换的实现

前段时间,看到b站突然冒出很多ai主播,输入数字切换小姐姐.感觉挺有趣.思考了以下决定手动实现一下. 然后就陷入长达5天的踩坑中 由于是自建的webrtc服务器,很自然的想直接收流转发,这也是最优的方案, 然而实际上遇到许多不是很友好的bug, 然后再想使用rtp转发,依然不理想. 最后…

使用香橙派 AI pro 开发板生成卡通版的东契奇

引言 AI应用如火如荼&#xff0c;而嵌入式设备与AI的结合也是不可或缺的重要场景。香橙派 AI pro 开发板正是面向嵌入式AI场景而生。 这篇文章记录了对香橙派 AI pro开发板的试用体验。介绍了开发板的基础操作&#xff0c;以及对其中一个AI应用样例的体验&#xff0c;初步感受…