在嵌入式软件中发现并消除潜在的bug是一件困难的事情 。 要从观察到的崩溃、挂起或其他计划外运行时行为追溯到根本原因 , 通常需要付出巨大的努力和昂贵的工具 。 嵌入式开发工程师们常常放弃寻找罕见异常的原因——因为这些异常无法在实验室中轻易重现——而将其视为“用户错误”或“小故障” , 然而 , 机器中的这些潜在危机仍然一直存在 。
因此 , 这里有一个关于难以重现的固件错误最常见的根本原因的指南 。
1.堆碎片
嵌入式软件开发人员并未广泛使用动态内存分配——这是有充分理由的 , 其中之一是堆碎片的问题 。
通过C 的malloc() 标准库例程或C++ 的new 关键字创建的所有数据结构都存在于堆中 。 堆是RAM中预先确定的最大大小的特定区域 。 最初 , 堆中的每个分配都会将剩余的“可用”空间减少相同的字节数 。
不再需要的数据结构的存储可以通过调用free() 或使用delete关键字返回到堆中 。 从理论上讲 , 这使得该存储空间可在后续分配期间重复使用 。 但是分配和删除的顺序通常至少是伪随机的——导致堆变成一堆更小的碎片 。
2.堆栈溢出
每个程序员都知道堆栈溢出是一件非常糟糕的事情? 。 但是 , 每个堆栈溢出的影响各不相同 。 损害的性质和不当行为的时间完全取决于破坏了哪些数据或指令以及如何使用它们 。 重要的是 , 堆栈溢出与其对系统的负面影响之间的时间长度取决于使用破坏位之前的时间长度 。
不幸的是 , 在嵌入式开发中 , 堆栈溢出对嵌入式系统的影响远远超过对台式计算机的影响 。 这有几个原因 , 包括:
嵌入式系统通常只能依靠少量的RAM;
通常没有可依赖的虚拟内存(因为没有磁盘);
基于RTOS任务的固件设计利用多个堆栈(每个任务一个) , 每个堆栈的大小都必须足够大 , 以确保不会出现唯一的最坏情况堆栈深度;
中断处理程序可能会尝试使用这些相同的堆栈 。
3.缺少“volatile”关键字
【物联网|嵌入式开发:嵌入式软件错误的5大原因】未能使用C的“volatile”关键字标记某些类型的变量 , 可能会导致系统出现许多症状 , 这些症状只有在编译器的优化器设置为低级别或禁用时才能正常工作 。 volatile限定符在变量声明期间使用 , 其目的是防止优化该变量的读取和写入 。
请注意 , 除了确保对给定变量进行所有读取和写入之外 , 使用volatile还会通过添加额外的“序列点”来限制编译器 。 对多个volatile的访问必须按照它们在代码中的写入顺序执行 。
4.比赛条件
竞争条件是指两个或多个执行线程(可以是RTOS 任务或main() 加ISR)的组合结果根据每个指令交错的精确顺序而变化的任何情况 。
例如 , 假设嵌入式开发人员有两个执行线程 , 其中一个定期递增全局变量(g_counter += 1;) , 另一个偶尔重置它(g_counter =0;) 。 如果增量不能始终以原子方式执行(即 , 在单个指令周期中) , 则此处存在竞争条件 。 计数器变量的两次更新之间的冲突可能永远不会或很少发生 。 但是当它这样做时 , 计数器实际上不会在内存中重置 。 这种影响可能会对系统产生严重后果 , 尽管可能要等到实际碰撞后很长时间才会发生 。
最佳实践:可以通过围绕必须以适当的抢占限制行为对原子执行的代码的“关键部分”来防止竞争条件 。 为了防止涉及ISR的竞争条件 , 必须在其他代码的关键部分期间至少禁用一个中断信号 。 在RTOS任务之间竞争的情况下 , 最佳实践是创建特定于该共享对象的互斥锁 , 每个任务必须在进入临界区之前获取该互斥锁 。 请注意 , 依靠特定CPU的功能来确保原子性并不是一个好主意 , 因为这只会防止竞争条件 , 直到更改编译器或CPU 。
- 京东|适合过年送长辈的数码好物,好用不贵+大牌保障,最后一个太实用
- |互联网运营是什么?快来看看你是哪种类型的运营
- 物联网|据说,物联网也可以称之为“一张想想的网络”,物联网世界是梦
- 物联网|?内容创作者:要明白文章首先是写给推荐系统看的!
- 李现与eStar队员合影并晒签名队服 称“感谢冠军战队的礼物”
- 合规|上海制定反垄断、互联网营销算法、盲盒经营活动等新业态合规指引
- poizon|得物 App 线下店开通数字人民币支付
- 互联网时代|原极狐汽车总裁被挖至小米 担任小米汽车副总裁
- 阿里巴巴|社区团购是互联网巨头的宝地,美团拼多多发展强劲,阿里坐不住了
- 主席团|旷视入选全国工商联物联网委员会主席团