请
登录
后使用快捷导航
没有帐号?
注册
首页
论坛
设计作品
全志V85x硬件设计大赛作品精选第一期
全志V85x硬件设计大赛作品精选第二期
瑞萨RA4M2物联网网关设计挑战赛作品集
国民技术N32开源移植挑战赛作品精选
2022福建省大学生人工智能创意赛作品合集
OpenHarmony开发者成长计划学生挑战赛优秀作品
精选帖子
【作品合集】龙芯2K0300蜂鸟开发板试用精选
【资源下载】英飞凌PSoC 6 RTT物联网开发板
【正点原子STM32精英V2开发板】HC-SR501红外人体感应
【沁恒CH32V208开发板试用】跳动的心脏-Systick
【鲁班猫创意氛围赛】现代化无线哨兵
【飞凌RK3588开发板试用】基于pyqt5的人脸识别
书籍评测
电子工程师必备丛书系列——电路板技能速成宝典
Proteus实战攻略:从简单电路到单片机电路的仿真
电子工程师必备丛书系列——九大系统电路识图宝典
OpenHarmony嵌入式系统原理与应用——基于RK2206芯片
深入理解微电子电路设计——数字电子技术及应用(原书第5版)
资深工程师十余年实战经验,PADS PCB设计指南
社区工程师专题
第一期:坚持兴趣成就嵌入式工程师
第二期:电子工程师需要在参赛中历练成长
第三期:创意源于生活,工具始于懒惰
第四期:工程师漫谈开发板评测的乐趣
第五期:硬件工程师的心路历程
第六期:宁精勿杂,在嵌入式领域做到优秀
版块
技术社区
FPGA开发者技术社区
RISC-V MCU技术社区
HarmonyOS技术社区
瑞芯微Rockchip开发者社区
OpenHarmony开源社区
嵌入式技术论坛
单片机及嵌入式
单片机/MCU论坛
ARM技术论坛
STM32/STM8技术论坛
RISC-V技术社区
FPGA|CPLD|ASIC论坛
DSP论坛
电源与无线技术
电源技术论坛
无线充电技术
WIFI技术
蓝牙技术
天线|RF射频|微波|雷达技术
EDA设计论坛
PCB设计论坛
DFM|可制造性设计论坛
Protel|AD|DXP论坛
PADS技术论坛
Allegro论坛
KiCad EDA 中文论坛
proteus论坛|仿真论坛
电路设计与测试
电路设计论坛
电子元器件论坛
LabVIEW论坛
Matlab论坛
传感技术
测试测量技术
DIY及创意
综合应用与活动
电机控制
发烧友官方/活动
模拟技术论坛
机器人论坛
USB论坛
音视频技术
综合技术交流
小组
厂商
龙芯技术社区
先楫半导体HPMicro
其利天下技术小组
瑞萨单片机论坛
芯海科技论坛
飞凌嵌入式论坛
国民技术论坛
飞腾派开发者社区
创龙科技论坛
米尔电子
技术
Linux论坛
单片机学习小组
嵌入式学习小组
电子行业动态
工程资源中心
电磁兼容设计与整改
物联网技术
汽车电子技术论坛
氮化镓技术社区
HiHope开发者社区
高校
东莞理工学院电子协会
西安电子科技大学西电实验室
深圳大学电子协会
桂林电子科技大学机电工程协会
湘潭大学电子科技协会
名人
张飞硬件学习小组
韦东山Linux嵌入式课程社区
黄工无刷电机学习
MILL小眼睛FPGA小组
龙哥 Labview 学习群
淘贴
开源硬件项目分享
开发板免费试用
沁恒微CH32V307试用合集
芯昇RISC-V开发板试用合集
乐鑫ESP32-C3试用合集
活动
设计大赛
瑞萨RA4M2物联网网关设计挑战赛
华秋电子x全志在线开源硬件设计大赛
RT-Thread 创新设计大赛
星核计划-高云FPGA开发者计划
OpenHarmony成长计划学生挑战赛
RT-Thread全球巡回线下培训
国民技术N32开源移植挑战赛
开发板试用
【创客营】新品Vision Board开发板免费评测
龙芯2K0300蜂鸟开发板免费试用
米尔-STM32MP135开发板-入门级MPU设计平台
风火轮YY3568开发板免费体验
【新品试用】英飞凌PSoC 6 RTT开发板试用
正点原子STM32战舰V4开发板
【有奖评测】为昕原理图设计EDA软件免费试用
社区之星
杨永胜:兴趣加努力,嵌入式工程师最好的前进之路
谢小龙:五年嵌入式开发,一个“博大”+“精深”的老鸟
罗大信:从工程师到创始人,我的20年嵌入式经验
刘建华:如果不想虚度一生,那就学习一辈子
贺婷婷:不退则进,遇到问题面对它,你会登上新台阶
罗除博士:共同携手,助力鸿蒙生态冲破牢笼
官方活动
【有奖征文】赢千元现金!发文章、上传资料送壕礼
每日打卡活动,赢取OH定制礼品
RISC-V MCU 技术社区打卡活动
【有奖打卡活动】2023年打卡计划
【书单评测】27本电子工程书籍
【书籍评测】PADS PCB设计指南
【精选集合】野火鲁班猫创意氛围赛作品
技术峰会/沙龙
2024 KiCon Asia KiCad 用户大会
2023 电子工程师大会暨第三届社区年度颁奖
开放原子开源基金会OH技术峰会
电子设计与制造技术研讨会
PCB设计与制造技术研讨会
2022 OH主题线下技术沙龙
2022开放原子全球开源峰会
专栏
技术原创
从编程到应用——从零开始学ARM
基于STM32设计的数码相册
基于DWC2的USB驱动开发-IAD描述符详解
基于CW32L083的线控器方案设计
RISC-V内核RC遥控车拆解:空心杯电机+2.4G跳频控制
最新资讯
生成式AI火爆,OpenAI获软银15亿美元新投资
“第三代家庭投影”制高点,投影光阀3LCoS有何过人之处?
ASML 2023年末爆单,中国贡献营收翻倍
光通信上车,相关方案已就位
北斗赋能开启“万亿市场”!迎北斗三代设备升级机遇
企业
推荐企业号
Aigtek安泰电子
斯丹麦德电子
张飞实战电子
芯佰微电子
其利天下技术
道生物联
扬兴科技
飞凌嵌入式
米尔电子
RA生态工作室
生态平台
OpenHarmony生态平台
RISC-V生态平台
瑞芯微Rockchip生态平台
精选内容
大咖齐聚,飞凌嵌入式技术创新日活动
米尔NXP i.MX 93开发板免费评测试用
Docker容器安装及运行测试方案详解
用时钟频率精度测量电路进行时间校验
基于Realtek的智能语音服务解决方案
问答
年度榜单
2022年度TOP榜单——模拟技术论坛问答
2021年度TOP榜单——电路设计论坛问答
2021年度TOP榜单——电源技术论坛问答
2021年度TOP榜单——电机控制技术论坛问答
高手问答
电子老顽童带你看懂电路设计
资深产品硬件研发工程师,与你讨论电路设计!
layout leader工程师任工谈PCB设计
与搞电源小哥一起揭秘电源设计那些难点
下载
电子书
电源技术知识总结
常用电源设计技巧图解
开关电源噪声-EMC(上)
开关电源噪声-EMC(下)
凡亿电路-PCB封装设计指导白皮书
精华资料
龙芯生态白皮书
中国物联网操作系统市场研究白皮书
AIGC(GPT-4)赋能通信行业应用白皮书
OPPO 《6G:极简多能 构建移动的世界》白皮书
智慧充电桩物联网技术白皮书
常用软件
Altium Designer21.9.2软件安装包下载
Cadence SPB OrCAD Allegro 17.4安装包及补丁下载
MATLAB 2020软件安装包下载
PADS 软件下载
LabVIEW 软件下载
学院
课程
直播
开发板购买
更多
电子发烧友
电子新闻
电子电路
技术文库
行业应用
电子标签
资料下载
电子元器件
技术研讨会
在线研讨会
特色服务
企业号
硬声APP
发烧友APP
产品库
积分商城
VIP会员
签到
经验
淘贴
华秋智造
PCB计价
SMT计价
元器件采购
BOM计价
Layout计价
钢网计价
PCB下单助手
工程师工具
PCB在线检查
华秋CAM
datasheet查询
替代料查询
免费样品申请
在线计算工具
工程师专区
品牌厂商查询
华秋DFM
帖子
搜索历史
清空
搜索热词
本版
帖子
用户
发 帖
提问题
发经验
发资料
发讨论
发视频
草稿箱
登录/注册
完善资料让更多小伙伴认识你,还能领取
20
积分哦,
立即完善>
3天内不再提示
每日签到
发烧友10周年庆典,全网超值优惠来袭!千元现金券,下单抽奖赶紧参与》》
电子发烧友论坛
/
嵌入式论坛
/
嵌入式论坛
电路图及DIY
电源技术论坛
综合技术与应用
无线通信论坛
EDA设计论坛
测试测量论坛
招聘/交友/外包/交易/杂谈
官方社区
ARM技术论坛
STM32/STM8技术论坛
嵌入式技术论坛
单片机/MCU论坛
RISC-V技术论坛
瑞芯微Rockchip开发者社区
FPGA|CPLD|ASIC论坛
DSP论坛
/
从项目出发,分析嵌入式编程和PC机器编程的不同 ...
【优惠升级】华秋PCB首单最高立减100元,SMT免费贴片!!!
[经验]
从项目出发,分析嵌入式编程和PC机器编程的不同
李名扬
2019-12-11 17:36:38
3874
嵌入式
编程
cpu
扫一扫,分享给好友
复制链接分享
链接复制成功,分享给好友
1
4
在中国,嵌入式编程的朋友很少是正儿八经从计算机专业毕业的,都是从自动控制啊,
电子
相关的专业毕业的。这些童鞋们,实践经验雄厚,但是理论知识缺乏;计算机专业毕业的童鞋很大一部分去弄网游、网页这些独立于操作系统的更高层的应用了。也不太愿意从事嵌入式行业,毕竟这条路不好走。他们理论知识雄厚,但缺乏
电路
等相关的知识,在嵌入式里学习需要再学习一些具体的知识,比较难走。
能从PC机器编程去看嵌入式问题,那是第一步;学会用嵌入式编程思想,那是第二步;用PC的思想和嵌入式的思想结合在一起,应用于实际的项目,那是第三步。很多朋友都是从PC编程转向嵌入式编程的。在中国,嵌入式编程的朋友很少是正儿八经从计算机专业毕业的,都是从自动控制啊,电子相关的专业毕业的。这些童鞋们,实践经验雄厚,但是理论知识缺乏;计算机专业毕业的童鞋很大一部分去弄网游、网页这些独立于操作系统的更高层的应用了。也不太愿意从事嵌入式行业,毕竟这条路不好走。他们理论知识雄厚,但缺乏电路等相关的知识,在嵌入式里学习需要再学习一些具体的知识,比较难走。
虽然没有做过产业调查,但从我所见和所招聘人员,从事嵌入式行业的工程师,要么缺乏理论知识,要么缺乏实践经验。很少两者兼备的。究其原因,还是中国的大学教育的问题。这里不探讨这个问题,避免口水战。我想列出我实践中的几个例子。引起大家在嵌入式中做项目时对一些问题的关注。
第一个问题:
同事在uC/OS-II下开发一个串口的驱动程序,驱动和接口在测试中均未发现问题。应用中开发了个通讯程序,串口驱动提供了一个查询驱动缓冲区字符的函数:GetRxBuffCharNum()。 高层需要接受一定数量的字符以后才能对包做解析。一个同事撰写的代码,用伪代码表示如下:
bExit = FALSE;
do {
if (GetRxBuffCharNum() >= 30)
bExit = ReadRxBuff(buff, GetRxBuffCharNum());
} while (!bExit);
这段代码判断当前缓冲区中超过30个字符,就将缓冲区中全部字符读到缓冲区中,直到读取成功为止。逻辑清楚,思路也清楚。但这段代码是不能正常工作。如果是在PC机上,定然是没有任何问题,工作的异常正常。但在嵌入式里真的是不得而知了。同事很郁闷,不知道为什么。来请我解决问题,当时我看到代码,就问了他,GetRxBuffCharNum()是怎么实现的?打开一看:
unsigned GetRxBuffCharNum(void)
{
cpu_register reg;
unsigned num;
reg = interrupt_disable();
num = gRxBuffCharNum;
interrupt_enable(reg);
return (num);
}
很明显,由于在循环中,interruput_disable()和interrupt_enable()之间是个全局临界区域,保证gRxBufCharNum的完整性。但是,由于在外层的do { } while() 循环中,CPU频繁的关闭中断,打开中断,这个时间非常的短。实际上CPU可能不能正常的响应UART的中断。当然这和uart的波特率、硬件缓冲区的大小还有CPU的速度都有关系。我们使用的波特率非常高,大约有3Mbps。uart起始信号和停止信号占一个比特位。一个字节需要消耗10个周期。3Mbps的波特率大约需要3.3us传输一个字节。3.3us能执行多少个CPU指令呢?100MHz的ARM,大约能执行150条指令左右。结果关闭中断的时间是多长呢?一般ARM关闭中断都需要4条以上的指令,打开又有4条以上的指令。接收uart中断的代码实际上是不止20条指令的。所以,这样下来,就有可能出现丢失
通信
数据的Bug,体现在系统层面上,就是通信不稳定。
修改这段代码其实很简单,最简单的办法是从高层修改。即:
bExit = FALSE;
do {
DelayUs(20); //延时 20us,一般采用空循环指令实现
num = GetRxBuffCharNum();
if (num >= 30)
bExit = ReadRxBuff(buff, num);
} while (!bExit);
这样,让CPU有时间去执行中断的代码,从而避免了频繁关闭中断造成的中断代码执行不及时,产生的信息丢失。在嵌入式系统里,大部分的RTOS应用都是不带串口驱动。自己设计代码时,没有充分考虑代码与内核的结合。造成代码深层次的问题。RTOS之所以称为RTOS,就是因为对事件的快速响应;事件快速的响应依赖于CPU对中断的响应速度。驱动在Linux这种系统中都是与内核高度整合,一起运行在内核态。RTOS虽然不能抄袭linux这种结构,但有一定的借鉴意义。
从上面的例子可以看清楚,嵌入式需要开发人员对代码的各个环节需要了解清楚。
第二个例子:
同时驱动一个14094串转并的芯片。串行信号是采用IO模拟的,因为没有专用的硬件。同事就随手写了个驱动,结果调试了3、4天,仍旧是有问题。我实在看不下去了,就去看了看,控制的并行信号有时候正常有时候不正常。我看了看代码,用伪代码大概是:
for (i = 0; i < 8; i++)
{
SetData((data >> i) & 0x1);
SetClockHigh();
for (j = 0; j < 5; j++);
SetClockLow();
}
将数据的8个bit在每个高电平从bit0到bit7依次发送出去。应该是正常的啊。看不出问题在哪啊?我仔细想了想,又看了14094的datasheet,明白了。原来,14094要求clock的高电平持续10个ns,低电平也要持续10个ns。这段代码只做了高电平时间的延时,没有做低电平的延时。如果中断插在低电平之间工作,那么这段代码是可以的。但是如果CPU没有中断插在低电平时执行,则是不能正常工作的。所以就时好时坏。
修改也比较简单:
for (i = 0; i < 8; i++)
{
SetData((data >> i) & 0x1);
SetClockHigh();
for (j = 0; j < 5; j++);
SetClockLow();
for (j = 0; j < 5; j++);
}
这样就完全正常了。但是这个还是不能很好移植的一个代码,因为编译器一优化,就有可能造成这两个延时循环的丢失。丢失了,就不能保证高电平低电平持续10ns的要求,也就不能正常工作了。所以,真正的可以移植的代码,应该把这个循环做成一个纳秒级的DelayNs(10);
像Linux一样,上电时,先测量一下,nop指令执行需要多长时间执行,多少个nop指令执行10ns。执行一定的nop指令就可以了。利用编译器防止优化的编译指令或者特殊的关键字,防止延时循环被编译器优化掉。如GCC中的
__vola
ti
le__ __asm__("nop;n");
从这个例子中可以清楚的看到,写好一段好代码,是需要很多知识支撑的。你说呢?
嵌入式往往没有操作系统支撑,或者因为有操作系统支撑,但因为种种的限制,操作系统提供的功能少得可怜。所以,很多代码不能像PC编程那样天马行空,任意驰骋。今天就聊聊内存分配的问题,内存碎片,可能大家都不陌生。然而在嵌入式系统里,最怕的就是内存碎片,也是系统稳定的头号杀手。我曾经做了一个项目,系统中有很多的malloc和free,尺寸不一,从60多个字节到64KB的不等。使用一款RTOS作为支撑。当时我有两个选择,一个是使用C系统库的malloc和free,另外一个是使用操作系统提供的固定内存分配。我们系统的设计要求要能稳定运行3个月以上。实际上连续运行6天左右就宕机了。各种问题都怀疑过,最后定为在内存分配上,其实就是长时间,大量的内存分配后,系统的内存变得零散而无法连续。虽有大空间,但却无法分配连续的空间。当有大空间申请时,只能是宕机完蛋。为了使系统达到原先的设计需求,我们在PC机上模拟了整个硬件,将嵌入式代码在 PC机上跑起来,并重载了malloc和free,做了个复杂的统计程序。统计系统的内存行为。运行了若干天以后,将数据提取出来分析,虽然申请的内存5花八门,还是有些规律,我们把100个字节以下的归为一类,512B的归为一类,1KB的归为一类,2KB归为一类,64KB以下归为一类。统计出每类的数量,在原先的基础上加上30%的余量。做成固定内存申请,使得系统稳定连续运行的时间大大加长。嵌入式就这样,不怕方法原始,就怕性能不达要求。
内存溢出问题,内存溢出问题嵌入式系统比PC系统更可怕! 往往是没有察觉的就溢出了。都很难想到,尤其是C/C++的初学者,对指针不熟悉,查都没法查。由于PC系统有MMU,内存发生严重的越界时,有MMU的保护,不会产生严重的灾难后果。而嵌入式往往没有MMU,差别很大,系统代码都被破坏了还能跑。只是只有上帝和那个CPU才知道跑得是什么。我们来看看这段代码:
char *strcpy(char *dest, const char * src)
{
assert(dest != NULL && src != NULL);
while (*src != '