如何统计RTOS用了多少RAM资源
Posted 嵌入式软件实战派
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何统计RTOS用了多少RAM资源相关的知识,希望对你有一定的参考价值。
好久没写我和妹子的故事了,甚至都有人问怎么不更新了,最近怎样了。
主要原因是“懒”。
至于近况,我还是原来的我,而妹子是是聪明的妹子,最近进步不少,很多技术问题都已经搞定了,问我的比较少。
而今天,妹子突然问了我一个RTOS资源的问题,细细了解了下,原来她被人“将军”了,也就是她被人怼了。
岂有此理,欺负妹子不就是欺负我吗!
就在上周,她去参加了一个项目的启动会议,谈到MCU选型和内存预估的问题,妹子就将以往的一个类似的项目的数据搬过来用,偏偏遇到了个较真的项目经理。
项目经理问为什么要用这么多内存,能不能再少30%,好换个低一档资源的MCU(主要是为了节省成本)。
妹子说,这项目跟以往的比较接近,这些都是经验值,没办法再优化了,等等。
项目经理,对这话不满意,觉得小丫头忽悠他,让她拿出评估数据。
妹子一时半会弄不出来,就说下周给。
会后,妹子觉得委屈了,然而也觉得自己做得不够,此时也明白,要镇住这项目经理,是要靠数据的。
于是她,左思右想,还翻了一堆代码,也不好做这个数据。但是她最终看到了不是很明确的一大块数据使用,有30多KB,想了好久,不知怎么评估。
于是,今天早上,她就找我了。
看着她委屈楚楚可怜的样子,我微微笑了下,说,“放心,哥今天帮你搞定”。
“授人以鱼不如授人以渔”,我决定今天手把手教会妹子分析RTOS内存消耗情况。
首先,查看了下,FreeRTOS config.h文件里面的配置,确实用了32KB。
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024U ) )
为什么用了这么多呢?
搜索这个“configTOTAL_HEAP_SIZE”,能找到
PRIVILEGED_DATA static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
那么怎么统计ucHeap的使用情况呢?
接着,我们找到这个pvPortMalloc函数
void * pvPortMalloc( size_t xWantedSize )
// ... ...
traceMALLOC( pvReturn, xWantedSize );
// ... ...
里面有个traceMALLOC,通过这个函数,我们不是可以统计每次申请的内存了?
而traceMALLOC是啥呢?
在FreeRTOS.h
#ifndef traceMALLOC
#define traceMALLOC( pvAddress, uiSize )
#endif
原来,这是要自定义的……
一顿操作猛如虎,妹子觉得我威武。
#define traceMALLOC traceMALLOCFun
// ... ...
typedef struct
void* ret;
size_t size;
AllockInfoType;
AllockInfoType FreeRTOSAllocInfo[1024] = .ret=(void*)0;
int AllocCounter = 0;
void traceMALLOCFun(void* ret, size_t size)
FreeRTOSAllocInfo[AllocCounter].ret = ret;
FreeRTOSAllocInfo[AllocCounter].size = size;
AllocCounter++;
然后,我们统计FreeRTOSAllocInfo里面的数据就可以了
通过查看内存,得到的数据是
204088B0 00 00 00 00 00 00 00 00 C0 08 40 20 08 04 00 00
204088C0 C8 0C 40 20 78 00 00 00 40 0D 40 20 08 04 00 00
204088D0 48 11 40 20 78 00 00 00 C0 11 40 20 A8 00 00 00
204088E0 68 12 40 20 08 08 00 00 70 1A 40 20 78 00 00 00
204088F0 E8 1A 40 20 D8 00 00 00 C0 1B 40 20 E8 02 00 00
20408900 A8 1E 40 20 58 00 00 00 00 1F 40 20 58 00 00 00
20408910 58 1F 40 20 58 00 00 00 B0 1F 40 20 58 00 00 00
20408920 08 20 40 20 58 00 00 00 60 20 40 20 D8 00 00 00
20408930 38 21 40 20 58 00 00 00 90 21 40 20 58 00 00 00
20408940 E8 21 40 20 08 10 00 00 F0 31 40 20 78 00 00 00
20408950 68 32 40 20 58 00 00 00 C0 32 40 20 58 00 00 00
20408960 18 33 40 20 08 08 00 00 20 3B 40 20 78 00 00 00
20408970 98 3B 40 20 08 10 00 00 A0 4B 40 20 78 00 00 00
20408980 18 4C 40 20 08 10 00 00 20 5C 40 20 78 00 00 00
20408990 98 5C 40 20 58 00 00 00 F0 5C 40 20 08 04 00 00
204089A0 F8 60 40 20 78 00 00 00 70 61 40 20 08 20 00 00
204089B0 78 81 40 20 78 00 00 00 F0 81 40 20 58 00 00 00
204089C0 48 82 40 20 D8 00 00 00 00 00 00 00 00 00 00 00
204089D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
204089E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
204089F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20408A00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20408A10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
妹子在旁边低声说,“这还真是原生数据啊,咋看呢?”
“淡定,慢慢来……”我一边说一边操作。
于是,我把左边的地址信息删了,然后通过正则表达式格式化得到
Address Size
204008C0 00000408
20400CC8 00000078
20400D40 00000408
20401148 00000078
204011C0 000000A8
20401268 00000808
20401A70 00000078
20401AE8 000000D8
20401BC0 000002E8
20401EA8 00000058
20401F00 00000058
20401F58 00000058
20401FB0 00000058
20402008 00000058
20402060 000000D8
20402138 00000058
20402190 00000058
204021E8 00001008
204031F0 00000078
20403268 00000058
204032C0 00000058
20403318 00000808
20403B20 00000078
20403B98 00001008
20404BA0 00000078
20404C18 00001008
20405C20 00000078
20405C98 00000058
20405CF0 00000408
204060F8 00000078
20406170 00002008
20408178 00000078
204081F0 00000058
20408248 000000D8
00000000 00000000
00000000 00000000
00000000 00000000
00000000 00000000
妹子顿时惊叹,原来还可以这么做。
我顺势说,“有空,我教你正则表达式啊”。
她笑了,我也笑了。
再通过Excel生成个图
“哇”,在看到图片后,她信心满满的,觉得胸有成竹可以回怼项目经理了。
这就是RTOS运行一会后的Heap申请情况。
经过以上的统计,这个Heap已经被使用超过90%了。
妹子是很好学的,她问:
“但是,怎么知道那些资源各占多少呢?”
“这有点麻烦琐碎……”
我找了个task试试教给她看
仿真进入create task函数
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
TCB_t * pxNewTCB;
BaseType_t xReturn;
// ...
/* Allocate space for the stack used by the task being created. */
pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) );
if( pxStack != NULL )
/* Allocate space for the TCB. */
pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
这里有两个信息要注意:
-
xTaskCreate传进来的usStackDepth并非是task stack的实际大小,这里还要乘以sizeof( StackType_t ),一般是4倍
-
还要为TCB分配空间,即pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
这样,我们就知道一个task需要占用多少资源了。
另外,趁热打铁,再找个mailbox的看看,其实际调用的是xQueueGenericCreate
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType )
Queue_t * pxNewQueue;
size_t xQueueSizeInBytes;
uint8_t * pucQueueStorage;
// ...
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) + xQueueSizeInBytes );
方法以此类推,等等
又一顿操作后,我们算出了很多数据,妹子雪亮的眼睛发现:
“为什么测试得出的数据跟配置的数据还差一截?”
她并非怀疑我的操作,而是有些疑惑。
“实际上,FreeRTOS还默认创建了IDLE Task和Tmr Svc Task。”
如vTaskStartScheduler调用了xTimerCreateTimerTask
void vTaskStartScheduler( void )
// ...
#if ( configUSE_TIMERS == 1 )
if( xReturn == pdPASS )
xReturn = xTimerCreateTimerTask();
else
mtCOVERAGE_TEST_MARKER();
#endif /* configUSE_TIMERS */
而xTimerCreateTimerTask如下
BaseType_t xTimerCreateTimerTask( void )
BaseType_t xReturn = pdFAIL;
// ...
xReturn = xTaskCreate( prvTimerTask,
configTIMER_SERVICE_TASK_NAME,
configTIMER_TASK_STACK_DEPTH,
NULL,
( ( UBaseType_t ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT,
&xTimerTaskHandle );
以上是原生态的分析RTOS的资源分配分析方式。
妹子对我的技术佩服又进了一步……
(以下内容,我是没有给妹子讲的,免得她说搞了半天,原来是有现成工具可以做的。这意义是不一样的啊,不是么?)
其实,目前市面上很多IDE已经支持Free RTOS的资源分配情况,如
另外,还有个问题,如何统计Task的Stack使用情况,如何定义合理的Task Stack,老是说这是“经验值”,没有数据支持,也会被怼的。
实际上FreeRTOS提供了这样的函数uxTaskGetStackHighWaterMark,来检测Stack的使用情况。
很多IDE也支持在debug情况下获得Task的运行情况
关键的问题点是,如何检测好Stack使用的worst case。
引申出另一个问题:如何测试MCU的CPU占用率?
这个问题,我觉得妹子还是会问我的,因为这个项目的客户有关注这个问题点,迟早要做报告……
好了,以上内容,妹子说她都掌握了,剩下的她可以自己做了。
我看了下手机上的时间,快下班了。
手机上还明显提示,今天是“情人节”……
静默几秒钟……
我知道她常常加班,应该是没男朋友的,我厚着脸皮问了一句妹子,“要下班了,你今晚要回去过节吧?”
“过啥节!”她笑了下,说:“师兄你要下班了吧”。
“呃……哦,呵呵,想下班了呢。”
“剩下的,我自己可以搞定了,谢谢师兄!”
静默几秒钟……
“要……要不……我们……一起,呃,一起整完它吧,今晚就不要加班了……”
脑子有点不好使了,原是想,是不是叫她一起去吃饭来着,突然想着,这个日子有点特殊,这不是太明显了……后来想着叫她不要加班了,但是我又蹦出了个“一起”……
差点就尴尬了……
关注公众号“嵌入式软件实战派”,获得更多我和妹子的故事。
以上是关于如何统计RTOS用了多少RAM资源的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法测量应用程序/程序占用多少系统资源(例如RAM)[重复]