UCOS-II 任务栈空间合理分配
最近利用空闲时间跑了一下正点原子的stm32f4开发板的实时操作系统demo,发现了一个比较有意思的东西,分享如下:
硬件平台:正点原子stm32f4开发板
软件开发平台:MDK uVision v5.14.0.0
代码:正点原子官方例程 实验56 UCOSII实验1-2-任务创建删除挂起恢复
需要了解的基础知识:
1、会点亮LED灯
2、会读取按键输入
3、会操作串口
4、会RTOS基本知识
官方文档描述实验现象:首先下载代码之后可以看到 LED0 和 LED1 不断闪烁,同时蜂鸣器不
断鸣叫。这个时候我们按下 KEY0 之后 led_task 任务被挂起,我们可以看到 LED 不再闪烁。接
着我们按下 KEY2, led_task 任务重新恢复,可以看到 LED 恢复闪烁。然后我们按下 KEY_UP,
任务 beep_task 被删除,所以蜂鸣器不再鸣叫。这个时候我们再按下按键 KEY_DOWN,任务
beep_task 被重新创建,所以蜂鸣器恢复鸣叫。
一切工具准备就绪,烧录代码观察现象,神奇的bug出现了
首先,确实LED0 和 LED1 不断闪烁,但是一旦按下任意一个按键直接死机。
第一想法,分析代码,打印调试信息

测试现象:果然,按下按键后,所有用户任务停止运行了,可以初步得出结论:程序跑飞了(由于本例程未初始化看门狗,所以程序跑飞,就飞不回来了)
第二想法:调试

测试方法:进入调试模式后,run代码,点击stop,程序会停在正常的代码行,如停在用户代码区、内核代码区的正常逻辑区

进入调试模式后,run代码,按下按键,点击stop,会发现程序停在stm32f4xx_it.c这个文件的HardFault_Handler函数里,这是个死循环,就是这里导致程序跑飞了
cpu进入中断后一直执行死循环,回不来了,无法再进行任务切换了!可

以在这个中断函数里追加printf("HardFault_Handler\r\n");以观察现象如下:

串口助手打印的信息刚好验证了上述结论
整理思路如下:运行ucos ii 应用程序,按下按键后程序发生硬件错误,一般发生硬件错误,很可能就是跟内存有关,最典型的就是栈溢出了,
分析到这里,基本上排查bug就很easy了,检查代码各个任务栈大小发现:三个任务都是设置64字节,经过多次实验,发现只需把KEY_STK_SIZE设置
为大于64时,实验现象就正常了,说明再执行按键任务时,此任务堆栈大小超过64字节了。
#define KEY_TASK_PRIO 3
#define KEY_STK_SIZE 64
OS_STK KEY_TASK_STK[KEY_STK_SIZE];
void key_task(void *pdata);
那么当我们在编写任务函数时,到底栈大小设置多少合适呢?我怎么知道新建的任务运行起来用了多少栈空间呢?
若栈空间设置过大,无疑会导致空间的浪费,这在嵌入式产品中简直就是极其浪费
若栈空间过小,那真运行起来,搞不好某个时间点,栈空间就溢出了,这个时间点可能是一触即发,可能会一年后,甚至10年后
经过一顿百度操作,发现ucosii 系统早都给你设计好了,通过下面的函数即可统计指定任务运行时用了多少栈空间,还剩多少栈空间
OSTaskCreateExt(key_task,(void *)0,(OS_STK *)&KEY_TASK_STK[KEY_STK_SIZE-1],KEY_TASK_PRIO, KEY_TASK_PRIO, KEY_TASK_STK, KEY_STK_SIZE, (void*)0,OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSTaskStkChk(KEY_TASK_PRIO, &StackBytes);
printf("%d\r\n", StackBytes.OSUsed);
这也只是一种估测栈空间使用量,测试时,得模拟各种极端条件,尽量让最大使用量测出来
最后,一般堆栈大小设置为任务实际使用量的1.5-2倍即可
具体原理,大家可自行百度理解,也可以自己尝试手撕一波栈空间检测算法(栈基地址----栈顶地址)
UCOS-II 任务栈空间合理分配的更多相关文章
- Linux学习笔记4——函数调用栈空间的分配与释放
一.函数执行时使用栈空间作为自己的临时栈,3种方式决定编译器清空栈的方式:__stdcall. __fastcall.__cdecl 1.__stdcall表示每个调用者负责清空自己调用的函数的临时栈 ...
- java虚拟机 jvm 出入java栈 栈空间内存分配
java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调用其实是通过java栈传递数据的. 数据结构中 ...
- 更改Linux默认栈空间的大小
有时候在Linux写C++程序处理大量的数据,程序内部需要分配很大的数组来存放一些数据,但有时候分配的数组太大的话运行时会出现段错误.这种情况可能是分配的数组大小超过了Linux系统的默认栈空间的大小 ...
- DE1-SOC开发板上搭建NIOS II处理器运行UCOS II
DE1-SOC开发板上搭建NIOS II处理器运行UCOS II 今天在DE1-SOC的开发板上搭建NIOS II软核运行了UCOS II,整个开发过程比较繁琐,稍微有一步做的不对,就会导致整个过 ...
- (转)在.NET程序运行过程中,什么是堆,什么是栈?什么情况下会在堆(栈)上分配数据?它们有性能上的区别吗?“结构”对象可能分配在堆上吗?什么情况下会发生,有什么需要注意的吗?
转自:http://www.cnblogs.com/xiaoyao2011/archive/2011/09/09/2172427.html 在.NET程序运行过程中,什么是堆,什么是栈? 堆也就是托管 ...
- [转帖] Linux 下面栈空间大小的实验
比如局部变量是保存在栈空间中的,今天突然在想栈的上限是多大呢,什么时候才会栈溢出? ulimit 命令 linux下使用ulimit 命令可以查看系统的很多上限值. ulimit -a 查看所有 ul ...
- C语言中函数调用过程(如何管理栈空间)
ps:先做草稿,以后有时间再整理并贴图,:) 主要是利用栈底寄存器(ebp).栈顶寄存器(esp)跟eax寄存器(存储返回值)来实现. 假设P调用Q: P() { Q(1,2); } (跟实际情况可能 ...
- 0xC0000005;Access Violation(栈区空间很宝贵, linux上栈区空间默认为8M,vc6下默认栈空间大小为1M)
写C/C++程序最怕出现这样的提示了,还好是在调试环境下显示出来的,在非调试状态就直接崩溃退出. 从上述汇编代码发现在取内存地址 eax+38h 的值时出错, 那说明这个地址非法呗, 不能访问, 一般 ...
- 堆、栈、内存分配、==、equals、hashcode详解(转载)
问题的引入: 问题一:String str1 = "abc";String str2 = "abc";System.out.println(str1==str2 ...
- 《浏览器工作原理与实践》 <12>栈空间和堆空间:数据是如何存储的?
对于前端开发者来说,JavaScript 的内存机制是一个不被经常提及的概念 ,因此很容易被忽视.特别是一些非计算机专业的同学,对内存机制可能没有非常清晰的认识,甚至有些同学根本就不知道 JavaSc ...
随机推荐
- 使用ELRepo升级CentOS内核
在腾讯云中部署了一些服务器,操作系统使用的是CentOS 7.6,但是其默认内核版本较低,现使用ELRepo对CentOS的内核进行升级. 操作环境 服务器:腾讯云轻量应用服务器 操作系统:CentO ...
- Redis使用ZSET实现消息队列使用总结一
转载请注明出处: 目录 1.zset为什么可以做消息队列 2.zset实现消息队列的步骤 3.使用jedis实现消息队列示例 4.+inf与-inf 5.redis使用list与zset做消息队列有什 ...
- Day05笔记
01.数组类(了解) 1.目的:设计一个类,该类有数组的功能,可以存储数据,可以删除修改数据 2.设计核心数据 1.属性:指针(指向堆区空间),数组实际存储的元素个数,数组容量 2.方法:构造(开辟堆 ...
- 页面录制服务上线:RESTful API 调用实现,所见所录即所得
我们为很多实时互动场景提供了服务.在一些场景中,用户不仅需要实时互动,还需要把互动的过程录下来.那么一个好的录制解决方案究竟需要具备哪些特征呢? 在回答这个问题之前,先聊一下客户使用录制的原因.一般来 ...
- SpringBoot——自定义start
更多内容,前往 IT-BLOG 一.Mybatis 实现 start 的原理 首先在写一个自定义的 start 之前,我们先参考下 Mybatis 是如何整合 SpringBoot:mybatis-s ...
- 在Android应用中通过Chaquopy使用Python
在Android应用中通过Chaquopy使用Python [译] 通过Python脚本和包为Android应用带来更多的功能 翻译自https://proandroiddev.com/chaquop ...
- SpringBoot2 简明教程
1.环境配置: ●Java 8 & 兼容java14 .●Maven 3.3+●idea 2019.1.2 maven的settings.xml配置 <mirrors> <m ...
- 使用CURL调用接口[*示例*]
<?php header("content-type:text/html;charset=utf-8"); /* 这是 使用CURL调用接口 */ $ch = curl_in ...
- 【Spring注解驱动】(三)Servlet 3.0
前言 今天是7.21日,终于是看完了..暑假在家学习是真的差点意思 1 Servlet 3.0简介 Servlet 2.0是在web.xml中配置servlet filter.listener.Dis ...
- 如何确定 this 指向?改变 this 指向的方式有哪些?
this 指向: 1. 全局上下文(函数外) 无论是否为严格模式,均指向全局对象.注意:严格模式下全局对象为undifined 2. 函数上下文(函数内) 默认的,指向函数的调用对象,且是最直接的调用 ...