《嵌入式软件的时间分析》从书中到实践-使用Tracealyzer进行RTOS任务栈分析
<div class='showpostmsg'><table cellpadding="0" cellspacing="0"><tbody>
<tr>
<td id="postmessage_3340285">
<p>书中分享了很多理论,方法和案例,</p>
<p>基于本书,本人在此基础上再分享一些更贴近实战的案例分享。</p>
<p>本人公众号 嵌入式Lee(嵌入式软硬件技术:RTOS,GUI,FS,协议栈,ARM,总线,嵌入式C,开发环境 and blablaba....多年经验分享,非硬货不发,带你扒开每一个技术背后的根本原理。)</p>
<p> </p>
<div></div>
<h1>一. <strong>前言</strong></h1>
<p>前面我们介绍完了Tracealyzer的基本原理和搭建了稳定的环境,现在开始就可以实践应用了。基于嵌入式RTOS的应用开发中到底分配多少任务栈是一个很重要的需要确定的事项,本文从任务栈监测原理,以及Tracealyzer的可视化栈监测应用等方面来介绍,Tracealyzer再RTOS任务栈分析中的应用。</p>
<h1>二. <strong>任务栈使用量监测原理</strong></h1>
<p>RTOS任务栈使用量监测原理,可以参考文章《Freertos栈检测》,<a href="https://mp.weixin.qq.com/s/3JgN6N87ww5Omw19jYldtw" target="_blank">https://mp.weixin.qq.com/s/3JgN6N87ww5Omw19jYldtw</a></p>
<p>简单的介绍下原理就是,栈初始化时全部初始化为固定值比如0xA5,运行一段时间后栈顶部分使用变为其他值。检查栈底有多少连续的初始值0xA5即可知道栈剩余多少。</p>
<p>Freertos提供接口函数uxTaskGetSystemState获取栈信息。</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p>Freertos中需要配置使能宏</p>
<p>configCHECK_FOR_STACK_OVERFLOW会自动监测,栈溢出。</p>
<p>用户实现溢出回调,vApplicationStackOverflowHook,溢出时调用该函数。</p>
<p>其他相关宏使能</p>
<p>configUSE_TRACE_FACILITY</p>
<p>INCLUDE_uxTaskGetStackHighWaterMark</p>
<p>INCLUDE_uxTaskGetStackHighWaterMark2</p>
<p>则会实现prvTaskCheckFreeStackSpace计算函数,和获取栈最小剩余的接口uxTaskGetStackHighWaterMark,uxTaskGetStackHighWaterMark2.注意Freertos中以上接口返回的数据量单位是StackType_t而不是字节。</p>
<p>宏portSTACK_GROWTH配置栈的方向。</p>
<h1>三. <strong>任务栈事件</strong></h1>
<p>TzCtrl任务中,调用xTraceStackMonitorReport();报告栈使用量事件。</p>
<p>调用</p>
<p>xTraceKernelPortGetUnusedStack,调用uxTaskGetStackHighWaterMark获取最小剩余栈大小。</p>
<p>栈事件的格式见前一篇文章”Tracealyzer事件记录格式与丢事件监测”</p>
<p>对应事件类型是PSF_EVENT_UNUSED_STACK,0xEB</p>
<p>如下是一条记录,即0x20EB高4位表示后面参数有2个WORD,类型是</p>
<p>0xEB,0x5B70是当前事件计数,0x003CABCE是时间戳,0x0810E0F8是任务地址,0x018C是最小剩余栈数,即396字节。</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<h1>四. <strong>实测</strong></h1>
<p>创建两个测试任务</p>
<section>
<pre>
<code> os_create_task_ext(test_task1, NULL, 7, 512, "test_task1");
os_create_task_ext(test_task2, NULL, 6, 512, "test_task2");</code></pre>
<div contenteditable="false" tabindex="-1"> </div>
</section>
<p>定义大的局部数据模拟栈的使用</p>
<section>
<pre>
<code>static void test_task1(void *arg)
{
(void)arg;
while(1)
{
volatile uint8_t buffer;
memset(buffer,0xAA,sizeof(buffer));
while(buffer--);
os_delay(7);
}
}
static void test_task2(void *arg)
{
(void)arg;
while(1)
{
volatile uint8_t buffer;
memset(buffer,0xAA,sizeof(buffer));
while(buffer--);
os_delay(9);
}
}</code></pre>
<div contenteditable="false" tabindex="-1"> </div>
</section>
<p>Tracealyzer上上位机抓取</p>
<p>菜单栏 views->Stack Usage点开栈可视化窗口</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p>这里可以勾选只显示关心的任务</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p>鼠标放在线上,下面会显示具体的数值,这里可以看到分别剩余276和148,</p>
<p>即相差(276-148)*4-512字节,正好是两个任务中数组的大小的差异。</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p>事件log也可以看到对应的事件</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p> </p>
<h1>五. <strong>总结</strong></h1>
<p>以上分享了使用Tracealyzer进行可视化分析的案例,实践中可能在某些时候调用某个函数时使用多个栈变多,此时曲线就可以看到明显的变化,结合事件前后事件等就可以分析出是哪个函数什么时候导致的栈使用量大。一般调试时先分配足够大的栈,发布时再根据测试覆盖率设置使用量最大的值,预留一些余量。</p>
</td>
</tr>
</tbody>
</table>
</div><script> var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;" style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
if(parseInt(discuz_uid)==0){
(function($){
var postHeight = getTextHeight(400);
$(".showpostmsg").html($(".showpostmsg").html());
$(".showpostmsg").after(loginstr);
$(".showpostmsg").css({height:postHeight,overflow:"hidden"});
})(jQuery);
} </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>
页:
[1]