最近利用空闲时间跑了一下正点原子的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 任务栈空间合理分配的更多相关文章

  1. Linux学习笔记4——函数调用栈空间的分配与释放

    一.函数执行时使用栈空间作为自己的临时栈,3种方式决定编译器清空栈的方式:__stdcall. __fastcall.__cdecl 1.__stdcall表示每个调用者负责清空自己调用的函数的临时栈 ...

  2. java虚拟机 jvm 出入java栈 栈空间内存分配

    java栈空间是一块线程私有的内存空间,java堆和程序数据密切相关,那么java栈就是和线程执行密切相关.线程最基本的执行行为就是函数的调用.每次函数调用其实是通过java栈传递数据的. 数据结构中 ...

  3. 更改Linux默认栈空间的大小

    有时候在Linux写C++程序处理大量的数据,程序内部需要分配很大的数组来存放一些数据,但有时候分配的数组太大的话运行时会出现段错误.这种情况可能是分配的数组大小超过了Linux系统的默认栈空间的大小 ...

  4. DE1-SOC开发板上搭建NIOS II处理器运行UCOS II

    DE1-SOC开发板上搭建NIOS II处理器运行UCOS II   今天在DE1-SOC的开发板上搭建NIOS II软核运行了UCOS II,整个开发过程比较繁琐,稍微有一步做的不对,就会导致整个过 ...

  5. (转)在.NET程序运行过程中,什么是堆,什么是栈?什么情况下会在堆(栈)上分配数据?它们有性能上的区别吗?“结构”对象可能分配在堆上吗?什么情况下会发生,有什么需要注意的吗?

    转自:http://www.cnblogs.com/xiaoyao2011/archive/2011/09/09/2172427.html 在.NET程序运行过程中,什么是堆,什么是栈? 堆也就是托管 ...

  6. [转帖] Linux 下面栈空间大小的实验

    比如局部变量是保存在栈空间中的,今天突然在想栈的上限是多大呢,什么时候才会栈溢出? ulimit 命令 linux下使用ulimit 命令可以查看系统的很多上限值. ulimit -a 查看所有 ul ...

  7. C语言中函数调用过程(如何管理栈空间)

    ps:先做草稿,以后有时间再整理并贴图,:) 主要是利用栈底寄存器(ebp).栈顶寄存器(esp)跟eax寄存器(存储返回值)来实现. 假设P调用Q: P() { Q(1,2); } (跟实际情况可能 ...

  8. 0xC0000005;Access Violation(栈区空间很宝贵, linux上栈区空间默认为8M,vc6下默认栈空间大小为1M)

    写C/C++程序最怕出现这样的提示了,还好是在调试环境下显示出来的,在非调试状态就直接崩溃退出. 从上述汇编代码发现在取内存地址 eax+38h 的值时出错, 那说明这个地址非法呗, 不能访问, 一般 ...

  9. 堆、栈、内存分配、==、equals、hashcode详解(转载)

    问题的引入: 问题一:String str1 = "abc";String str2 = "abc";System.out.println(str1==str2 ...

  10. 《浏览器工作原理与实践》 <12>栈空间和堆空间:数据是如何存储的?

    对于前端开发者来说,JavaScript 的内存机制是一个不被经常提及的概念 ,因此很容易被忽视.特别是一些非计算机专业的同学,对内存机制可能没有非常清晰的认识,甚至有些同学根本就不知道 JavaSc ...

随机推荐

  1. k8s容器互联-flannel host-gw原理篇

    k8s容器互联-flannel host-gw原理篇 容器系列文章 容器系列视频 简析host-gw 前面分析了flannel vxlan模式进行容器跨主机通信的原理,但是vxlan模式需要对数据包进 ...

  2. Trie(字典)树模板

    模板 int son[N][26], cnt[N], idx; // 0号点既是根节点,又是空节点 // son[][]存储树中每个节点的子节点 // cnt[]存储以每个节点结尾的单词数量 // 插 ...

  3. 机器学习算法(八):基于BP神经网络的乳腺癌的分类预测

    机器学习算法(八):基于BP神经网络的乳腺癌的分类预测 1.算法简介和应用 1.1 算法简介 BP(Back Propagation)网络是1986年由Rumelhart和McCelland为首的科学 ...

  4. SwitchHosts operation not permitted 解决方案--亲测有效

    SwitchHost!是帮助我们管理Hosts的工具,可以帮助我们做域名解析, 弥补了如果要修改域名还要改计算机C:\Windows\System32\drivers\etc位置下的hosts文件的弊 ...

  5. smtp.office365.com 无法从传输连接中读取数据: net_io_connectionclosed

    这几天发送邮件时突然会报一个错 无法从传输连接中读取数据:net_io_connectionclosed. 因使用的是 smtp.office365.com 经过查询,发现了这个 Recently, ...

  6. .NET CORE 部署到IIS上,HTTP 错误 500.19 - Internal Server Error

    经排查,是因为项目中web.config的rewrite节点不支持,注释掉此节点即可,或者尝试下载相关依赖以支持此节点

  7. 随手记:Redis 部署到linux上面后,本地无法连接

    修改redis的配置文件 redis.conf 1. bind 设置为 0.0.0.0 2. protected-mode 设置为no   (也就是关闭保护模式) 3.    daemonize 设置 ...

  8. CentOS 6.8 安装 node 后报错,显示 gcc 版本过低

    因为测试服务器要部署一个 vue 的环境,安装了 node 和 npm 后,却由于 gcc 动态库版本过低,导致报错如下 node: /usr/lib64/libstdc++.so.6: versio ...

  9. FreeSWITCH添加iLBC编码及转码

    操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 一.安装ilbc库 从第三方库里下载指定版本: git clone https://freeswitch.org/s ...

  10. STM32下载ELF文件、最小可执行bin文件测试

    1.STM32能下载ELF格式的文件吗? 答:可以.因为所谓的bin文件就是ELF文件的.text代码段. 当然前提是下载工具能识别ELF文件格式,STM32下载ELF文件并不意味着STM32可以把E ...