0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

用实例引起大家在嵌入式中做项目时对一些问题的关注

m3eY_edn_china 2018-01-05 11:31 次阅读

在中国,嵌入式编程的朋友很少是正儿八经从计算机专业毕业的,都是从自动控制啊,电子相关的专业毕业的。这些童鞋们,实践经验雄厚,但是理论知识缺乏;计算机专业毕业的童鞋很大一部分去弄网游、网页这些独立于操作系统的更高层的应用了。也不太愿意从事嵌入式行业,毕竟这条路不好走。他们理论知识雄厚,但缺乏电路等相关的知识,在嵌入式里学习需要再学习一些具体的知识,比较难走。

能从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中的

__volatile__ __asm__("nop;\n");

从这个例子中可以清楚的看到,写好一段好代码,是需要很多知识支撑的。你说呢?

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 嵌入式
    +关注

    关注

    5056

    文章

    18950

    浏览量

    301495
  • PC
    PC
    +关注

    关注

    9

    文章

    2053

    浏览量

    153890

原文标题:高手闲谈嵌入式编程和PC编程的区别,实例分析一波...

文章出处:【微信号:edn-china,微信公众号:EDN电子技术设计】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    关于嵌入式培训的一些看法

    标榜自己是真正的嵌入式培训学校。有各种的认证体系。对于这个问题和学校的老师做了一些讨论。现给大家一些建议:首先,要看看他的课程体系。因为嵌入式
    发表于 02-02 15:08

    求教嵌入式和ARM的一些问题

    搞定了51单片机,学校的其他专业课程又没什么兴趣,嵌入式系统下学期才有课,本来想深入学习一些别的单片机比如AVR什么的,但是后来想想还是想学嵌入式先。本人对编程还是很有信心的,但是嵌入式
    发表于 11-08 21:20

    对于嵌入式一些认识

    本来学嵌入式就不简单,所以大家都会去找一些学习嵌入式的方法或步骤什么的,如果是你去学嵌入式的话,肯定也不会例外,下面可以
    发表于 05-25 17:40

    嵌入式开发一些硬件相关的概念有哪些

    嵌入式系统开发,经常要接触硬件。嵌入式开发对数字电路和模拟电路要有定的了解。这样才能深入的研究下去。下面我们简单的介绍
    发表于 02-24 08:56

    时钟设计应该注意的一些问题

    1. 前言时钟是嵌入式系统中非常重要,但又常常被忽视的地方。它的成本只占整个系统的个零头,但由于时钟的停振,或其它异常最终导致厂商付出高昂代价的案例却并不少见。下面我们看一下在时钟设计
    发表于 07-21 09:01

    学习嵌入式linux上的一些问题分享

    不知不觉,博客似乎也成为了自己记录学习道路上的一些迷茫的个小日记。可能也是自己疫情期间在家呆了4个月的时间,也可能是最近课程压力比较大,或者是最近和导师聊了下之后的想法,还有最近自己学习嵌入式
    发表于 11-04 06:50

    梳理嵌入式Linux的一些知识

    前言这篇文章简单我们来起梳理嵌入式Linux的一些知识,方便于一些想跟我样想要由单片机进阶到嵌入式
    发表于 11-04 07:33

    如何解决Linux嵌入式开发中断按键实验碰到的一些问题

    如何解决Linux嵌入式开发中断按键实验碰到的一些问题
    发表于 11-30 06:51

    嵌入式项目中一些常用知识及技巧是什么

    大家好,我是ZhengN。本次给大家分享一些C语言、嵌入式项目中的常用知识。1、使用宏给结构体初始化 如果频繁使用
    发表于 12-15 07:10

    嵌入式一些日常小技巧分享

    杂记–算法学习日志+关于实验室部门架构的思考+嵌入式一些日常小技巧分享算法学习日志因为从初中到现在直是学习嵌入式程序的开发和研究,并没有
    发表于 12-21 08:07

    cadence画板遇到的一些问题

    cadence画板遇到的一些问题,在这里分享给大家,多多指教
    发表于 02-25 16:01 0次下载

    解析嵌入式开发一些硬件相关概念

    嵌入式系统开发,经常要接触硬件。嵌入式开发对数字电路和模拟电路要有定的了解。这样才能深入的研究下去。下面我们简单的介绍
    发表于 06-06 16:35 893次阅读
    解析<b class='flag-5'>嵌入式</b>开发<b class='flag-5'>中</b>的<b class='flag-5'>一些</b>硬件相关概念

    嵌入式系统的一些基础知识

    本文主要介绍嵌入式系统的一些基础知识,希望对各位有帮助。
    的头像 发表于 02-18 10:44 2235次阅读

    DSP嵌入式系统的应用实例

    DSP嵌入式系统的应用实例(嵌入式开发工具软件)-该文档为DSP
    发表于 07-30 13:09 22次下载
    DSP<b class='flag-5'>在</b><b class='flag-5'>嵌入式</b>系统<b class='flag-5'>中</b>的应用<b class='flag-5'>实例</b>

    嵌入式一些概念

    嵌入式一些概念嵌入式系统的概念什么是MCU、CPU、MPU、DSPMCUMPUDSP几大MCU公司瑞萨电子(Renesas)恩智浦(NXP)+飞思卡尔(Freescale)(后者被
    发表于 10-19 18:33 8次下载
    <b class='flag-5'>嵌入式</b><b class='flag-5'>中</b>的<b class='flag-5'>一些</b>概念