嵌入式软件 订阅
嵌入式软件就是嵌入在硬件中的操作系统和开发工具软件,它在产业中的关联关系体现为:芯片设计制造→嵌入式系统软件→嵌入式电子设备开发、制造 [1]  。 展开全文
嵌入式软件就是嵌入在硬件中的操作系统和开发工具软件,它在产业中的关联关系体现为:芯片设计制造→嵌入式系统软件→嵌入式电子设备开发、制造 [1]  。
信息
应    用
嵌入式开发 [1]
外文名
Embedded software [1]
领    域
软件工程 [1]
含    义
嵌入在硬件中的操作系统和开发工具软件 [1]
中文名
嵌入式软件 [1]
产业关联
芯片设计制造 [2]
嵌入式软件定义
嵌入式软件与嵌入式系统是密不可分的,嵌入式系统一般由嵌入式微处理器、外围硬件设备、嵌入式操作系统以及用户的应用程序4个部分组成,用于实现对其他设备的控制、监视或管理等功能。嵌入式软件就是基于嵌入式系统设计的软件,它也是计算机软件的一种,同样由程序及其文档组成,是嵌入式系统的重要组成部分 [2]  。
收起全文
精华内容
参与话题
问答
  • 嵌入式软件

    2020-06-15 10:22:52
    嵌入式跟其他纯软件开发不一样,嵌入式软件的基础是要懂硬件原理,要会看懂硬件电路图,所以要有数电和模电基础。 哪些知识是嵌入式软件开发工程师必备的?有哪些要注意的问题? 嵌入式软件开发涉及的知识点很多,...

    嵌入式跟其他纯软件开发不一样,嵌入式软件的基础是要懂硬件原理,要会看懂硬件电路图,所以要有数电和模电基础。

    哪些知识是嵌入式软件开发工程师必备的?有哪些要注意的问题?

    嵌入式软件开发涉及的知识点很多,我仅简单说一下:

    1、具备简单的硬件电路设计能力,包括数字电路和模拟电路;做嵌入式软件对硬件一样要有一定的基础;

    2、MCU设计与应用,从单片机到ARM到DSP等要具备根据客户要求设计产品的能力;外围端口和设备的设计使用以及驱动程序的编写能力,包括ADC、FLASH、EEPROM、RTC、Timer、GPIO、CAN、UART、I2C、SPI、以太网、液晶显示器等等;

    3、操作系统方面至少要精通一种嵌入式操作系统,比如uCOSIII、freeRTOS 、Vxworks等,并且一定要学嵌入式linux ,搞明白多任务调度、信号量、邮箱等的原理和使用;在实际的项目中使用这些操作系统并逐渐掌握它们;

    4、能编写常见的linux平台下的外围设备驱动,包括但不限于ADC、GPIO、UART、I2C、摄像头、SD卡、网卡、SPI等等,搞明白字符设备、块设备以及网络设备的常用设备驱动程序架构;

    5、具备GUI设计能力,可以学习Qt,它的跨平台特性使得一套设计可以应用于不同的平台包括windows以及linux;

    6、具备多线程编程能力,弄懂线程池的原理并应用到实际工作中;

    7、具备高并发网络通信编程能力,epoll以及libevent 的使用和设计;

    8、精通C/C++,并涉猎其他编程语言比如python

    9、具备至少一种数据库编程能力,嵌入式可以学习SQLite ;

    10、掌握常用数据结构及算法的原理以及编程实现,包括链表、队列、二叉树等,掌握常用排序、查找等算法的实现;多关注一些开源项目,从中学习编程能力,提高自己;

    掌握这些已经基本具备嵌入式系统开发能力,一定要保持时刻学习的能力,接下来就是多做项目,多解决客户问题,在实际工作中历练自己提高自己。

    嵌入式开发项目中,首先需要做需求分析,然后根据需求分析进行综合考虑,这里给出几个特别要注意的问题。

    1.MCU的选择

    选择 MCU 时要考虑 MCU 所能够完成的功能、MCU 的价格、功耗、供电电压、I/O 口电平、管脚数目以及 MCU 的封装等因素。MCU 的功耗可以从其电气性能参数中查到。供电电压有 5V、3.3V 以及 1.8V 超低电压供电模式。为了能合理分配 MCU 的I/O资源,在 MCU 选型时可绘制一张引脚分配表,供以后的设计使用。

    2.电源

    (1)考虑系统对电源的需求,例如系统需要几种电源,如24V、12V、5V或者3.3V等,估计各需要多少功率或最大电流(mA)。在计算电源总功率时要考虑一定的余量,可按公式“电源总功率=2×器件总功率”来计算。

    (2)考虑芯片与器件对电源波动性的需求。一般允许电源波动幅度在 ±5% 以内。对于A/D转换芯片的参考电压一般要求 ±1% 以内。

    (3)考虑工作电源是使用电源模块还是使用外接电源。

    3.普通I/O口

    (1)上拉、下拉电阻:考虑用内部或者外部上/下拉电阻,内部上/下拉阻值一般在 700Ω 左右,低功耗模式不宜使用。外部上/下拉电阻根据需要可选 10KΩ~1MΩ 之间。

    (2)开关量输入:一定要保证高低电压分明。理想情况下高电平就是电源电压,低电平就是地的电平。如果外部电路无法正确区分高低电平,但高低仍有较大压差,可考虑用 A/D 采集的方式设计处理。对分压方式中的采样点,要考虑分压电阻的选择,使该点通过采样端口的电流不小于采样最小输入电流,否则无法进行采样。

    (3)开关量输出:基本原则是保证输出高电平接近电源电压,低电平接近地电平。I/O 口的吸纳电流一般大于放出电流。对小功率元器件控制最好是采用低电平控制的方式。一般情况下,若负载要求小于10mA,则可用芯片引脚直接控制;电流在 10~100mA 时可用三极管控制,在 100mA~1A 时用 IC 控制;更大的电流则适合用继电器控制,同时建议使用光电隔离芯片。

    4.A/D电路与D/A电路

    (1)A/D电路:要清楚前端采样基本原理,对电阻型、电流型和电压型传感器采用不同的采集电路。如果采集的信号微弱,还要考虑如何进行信号放大。

    (2)D/A电路:考虑 MCU 的引脚通过何种输出电路控制实际对象。

    5.控制电路

    对外控制电路要注意设计的冗余与反测,要有合适的信号隔离措施等。在评估设计的布板时,一定要在构件的输入输出端引出检测孔,以方便排查错误时测量。

    6. 考虑低功耗

    低功耗设计并不仅仅是为了省电,更多的好处在于降低了电源模块及散热系统的成本。由于电流的减小也减少了电磁辐射和热噪声的干扰。随着设备温度的降低,器件寿命则相应延长,要做到低功耗一般需要注意以下几点:

    (1)并不是所有的总线信号都要上拉。上下拉电阻也有功耗问题需要考虑。上下拉电阻拉一个单纯的输入信号,电流也就几十微安以下。但拉一个被驱动了的信号,其电流将达毫安级。所以需要考虑上下拉电阻对系统总功耗的影响。

    (2)不用的I/O口不要悬空,如果悬空的话,受外界的一点点干扰就可能成为反复振荡的输入信号,而MOS器件的功耗基本取决于门电路的翻转次数。

    (3)对一些外围小芯片的功耗也需要考虑。对于内部不太复杂的芯片功耗是很难确定的,它主要由引脚上的电流确定。例如有的芯片引脚在没有负载时,耗电大概不到1毫安,但负载增大以后,可能功耗很大。

    7.考虑低成本

    (1)正确选择电阻值与电容值。比如一个上拉电阻,可以使用4.5K-5.3K的电阻,你觉得就选个整数5K,事实上市场上不存在5K的阻值,最接近的是4.99K(精度1%),其次是5.1K(精度5%),其成本分别比精度为20%的4.7K高4倍和2倍。20%精度的电阻阻值只有1、1.5、2.2、3.3、4.7、6.8几个类别(含10的整数倍);类似地,20%精度的电容也只有以上几种值,如果选了其它的值就必须使用更高的精度,成本就翻了几倍,却不能带来任何好处。

    (2)指示灯的选择。面板上的指示灯选什么颜色呢?有些人按颜色选,比如自己喜欢蓝色就选蓝色。但是其它红绿黄橙等颜色的不管大小(5mm以下)封装如何,都已成熟了几十年,价格一般都在5毛钱以下,而蓝色却是近三四年才发明的,技术成熟度和供货稳定度都较差,价格却要贵四五倍。

    (3)不要什么都选最好的。在一个高速系统中并不是每一部分都工作在高速状态,而器件速度每提高一个等级,价格差不多要翻倍,另外还给信号完整性问题带来极大的负面影响。



    作者:亓霂_宣萧
    链接:https://www.jianshu.com/p/bfac3e5fc8fc
    来源:简书

    展开全文
  • 嵌入式软件面试经历分享(海康威视&涂鸦智能)

    千次阅读 多人点赞 2019-03-19 19:21:54
    本人一个垃圾大学学渣,毕业就一直干着嵌入式软件开发,这次换工作也是深思熟虑后的一个选择。面试了两家公司都拿到了Offer,还是极大增强了我的信心。同时,在面临抉择的时候也是一个艰难的过程。 海康威视面试: ...

         本人一个垃圾大学学渣,毕业就一直干着嵌入式软件开发,这次换工作也是深思熟虑后的一个选择。面试了两家公司都拿到了Offer,还是极大增强了我的信心。同时,在面临抉择的时候也是一个艰难的过程。

     海康威视面试:

         其实我自己认为我们这种不好的大学毕业,这样的企业应该是不会考虑我们的,当时想去面试就当是一次经历吧,大公司是怎样的也该去看看,就当开开眼界。想到这次面试是一个机会,自己还是准备了一下,对应面试上的职能要求,详细的看了相关部分的内容,面试的时候好几个都问到啦(哈哈)。

          我也属于社招啦,海康威视那边流程还是蛮规范的,比较清楚。都是流程性的,第一个当然是签到啊,填个人信息啊啥的,然后就等待面试,那天周五下午面试,人巨多,有java有嵌入式,只有一个小姐姐在那里弄,忙的要死。那时候心里就想,我怕是凉了,打个酱油吧。一共面了三轮,技术面,HR面,总监面。

          技术面主要是介绍一下自己,然后就开始直接问项目啦,把自己的项目简述一下,必要的时候可以自己带几张白纸,可以方便画出项目构架图啦,说的可能会清楚一点,然后会通过项目问一下相对应的知识,没有问到很复杂的问题,都是比较基础的吧。比如你项目用到了TCP,TIME_WAIT,CLOSE_WAIT怎么产生的,如何解决过多TIME_WAIT状态。对于字节对齐的理解,32位机器上的代码移到64位机器上代码,有哪些注意的,需要修改的。还主要问了一些问题,让你给出思路,解决方法,类似于一些文件的操作也会问到。整个技术面大概面了40分钟左右,接下来就是HR面了,这个基本上表现的正常一些,积极一些,不要问一些太傻的问题基本没有大的问题,补充一下,最好面试公司,先去要面试的公司官网看看,企业理念啊,具体产品啊啥的,很有帮助,不然到时候问你对公司有啥了解,基本就懵逼了。和技术面试让你问问题就问技术相关的,别问待遇五险一金那些乱七八糟的,那个留给问HR.最后总监开会,等开完然后又去面试了一轮,基本10分钟就结束了,也没问啥,比较直接,估计就是认识一下的感觉,也没问啥技术,总监还蛮帅的,哈哈(我是Boy,纯粹觉得)!

         最后说一周内给通知,我周五面的,周二给我发了Offer,电话沟通详细的一些待遇问题,收到Offer当时还蛮激动的,哈哈。

    涂鸦智能面试:

         这也是一家我蛮看好的一家公司,主要发展AI+IOT,不过加班还蛮严重的,听说9点下班是正常时间,面试的人也很多,应该属于扩张期招聘职位还满多的。

          我面试的无线嵌入式软件开发工程师,主要对TCP,HTTP,NBIOT这类相关通信要求比较多。不过个人感觉还是有点忙乱,人来人往。面试流程四轮,笔试,技术面,技术总监面,HR面,给我弄了4小时,中间等总监等了一小时。笔试的话其实还好,基本也是一些比较基础的问题,直接把笔试题贴出来的话也不太好,所以我大致说下知识点吧,后面我会将我总结的知识点再记录一份博客和大家分享。

        笔试知识点:

         1,大端小端字节序

          2,malloc使用的一些事项,free后指针要指向空类似问题

          3,结构体字节对齐,形参,实参的区别,数据溢出

          4,位操作,函数指针,排序,链表操作

         接下来就是技术面试,基本就是根据笔试题进行一些解答,问了相关HTTP,TCP,NBIOT相关内容,还好我都整理并看了,回答的都还不是太差,准备还是很有必要的。在后面就是总监面试,问的问题不多,进程线程的区别等等比较经典的问题,介绍项目,带张白纸很有必要。最后HR就是聊聊薪资待遇,也没有太多,后面的话就是等通知,周六面试到周一给我通知,然后要体检OK才会给Offer,当然最后也是成功拿到了Offer.

    对于面试,准备是非常重要的,我后面会说说我自己的准备工作,希望能有一些参考价值,祝大家都找到满意的工作!

    自己的准备工作分享:嵌入式软件面试准备与知识点总结

    展开全文
  • 从CSDN各个博客上摘选的一些容易做错的嵌入式软件的笔试题,做一下记录,让自己记住。 文章转自:嵌入式经典面试题。 1、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) 解答:这一...

    从CSDN各个博客上摘选的一些容易做错的嵌入式软件的笔试题,做一下记录,让自己记住。

    文章转自:嵌入式经典面试题

     

    1、用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

    解答:这一题主要容易错的地方就是:意识到这个表达式将使一个16位机的整型数溢出,因此要用到长整型符号L,告诉编译器这个常数是的长整型数。

     #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL

    2、写一个"标准"宏MIN,这个宏输入两个参数并返回较小的一个。

    解答:这一题主要容易错的地方就是:懂得在宏中小心地把参数用括号括起来。

    #define MIN(A,B) ((A)<=(B)?(A):(B)) 

    当然,使用宏也是有副作用的。就拿这一个例子来说:该宏定义对MIN(*p++, b)的作用结果是:((*p++) <= (b) ? (*p++) : (b)) 这个表达式会产生副作用,指针p会作两次++自增操作。

    3、用变量a给出下面的定义:一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数。

    解答:这一道题主要容易错的地方就是:函数指针、指针数组。

    int (*a[10])(int);

    4、关键字static的作用是什么?

    解答:在C语言中,关键字static有三个明显的作用:

    • 在函数体中,一个被声明为静态的变量在这一函数被调用过程中只会被分配一次内存,且整个运行期间不会重新分配;
    • 在函数体外、某个源文件内,一个被声明为静态的变量只可被该源文件内的所有函数访问,但不能被其他源文件的函数访问。它是一个本地的全局变量;
    • 在某个源文件内,一个被声明为静态的函数仅仅只可以被这个源文件的其它函数调用。也就是说,这个函数被限制在声明它的源文件的本地范围之内使用。

    5、关键字const的作用是什么?

    解答:简单地说,const意味着常数。

    • const定义的变量,它的值不能被改变,在整个作用域中都保持固定;
    • 同宏定义一样,可以避免意义模糊的数字出现,同样可以很方便地进行参数的调整和修改;
    • 可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。const是通过编译器在编译的时候执行检查来确保实现的。

    const与指针

    下面的声明都是什么意思:

    const int a;
    int const a;
    const int *a;
    int * const a;
    const int * const a;
    int const * const a;
    • 前两个的作用是一样,a是一个常整型数;
    • 第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以);
    • 第四个意思a是一个指向整型 数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的);
    • 最后两个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数 是不可修改的,同时指针也是不可修改的)。

    const与函数

    • const 通常用在函数形参中,如果形参是一个指针,为了防止在函数内部修改指针指向的数据,就可以用 const 来限制。比如在String的程序中有很多const修饰形参的情况:
    void StringCopy(char* strDestination, const char *strSource);
    • const还可以表示该函数返回一个常量,放在函数的返回值的位置。比如:
    const char * GetString(void);
    • 在类成员函数的声明和定义中,const放在函数的参数表之后,函数体之前,表示该函数的this指针是一个常量,不能修改该对象的数据成员。比如:
    void getId() const;

    6、关键字volatile有什么含意?并给出三个不同的例子。

    解答:一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子:

    • 存储器映射的硬件寄存器通常也要加voliate,因为每次对它的读写都可能有不同意义;
    • 在中断函数中的交互变量,一定要加上volatile关键字修饰,这样每次读取非自动存储类型的值(全局变量,静态变量)都是在其内存地址中读取的,确保是我们想要的数据;
    • 多任务环境下各任务间共享的标志应该加volatile。

    一个参数既可以是const还可以是volatile吗?

    可以的,例如只读的状态寄存器。它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。软件不能改变,并不意味着我硬件不能改变你的值,这就是单片机中的应用。

    参考文章:C语言中的volatile——让我保持原样

    一个指针可以是volatile 吗?

    可以。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

    下面的函数有什么错误:

    int square(volatile int *ptr)
    {
            return *ptr * *ptr;
    }

    这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

    int square(volatile int *ptr) 
    {
        int a,b;
        a = *ptr;
        b = *ptr;
        return a * b;
    }

    由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。结果,这段代码可能返不是你所期望的平方值!正确的代码如下:

    long square(volatile int *ptr) 
    {
        int a;
        a = *ptr;
        return a * a;
    }

    7、给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。

    解答:这道题清除a的bit3,使用“&=~”的方法。

    #define BIT3 (0x1 << 3)
    static int a;
    
    void set_bit3(void) 
    {
        a |= BIT3;
    }
    void clear_bit3(void) 
    {
        a &= ~BIT3;
    }

    8、嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa66。

    解答:这一问题测试你是否知道为了访问一绝对地址,把一个整型数(绝对地址)强制转换为一指针是合法的。

    int *ptr;
    ptr = (int *)0x67a9;
    *ptr = 0xaa55;

    9、中断是嵌入式系统中重要的组成部分,这导致了很多编译开发商提供一种扩展——让标准C支持中断。具代表事实是,产生了一个新的关键字 __interrupt。下面的代码就使用了__interrupt关键字去定义了一个中断服务子程序(ISR),请评论一下这段代码的。

    __interrupt double compute_area (double radius) 
    {
        double area = PI * radius * radius;
        printf("/nArea = %f", area);
        return area;
    }

    解答:这个函数有太多的错误了,以至让人不知从何说起了:

    • ISR 不能传递参数,不能返回一个值;
    • 在许多的处理器/编译器中,浮点一般都是不可重入的。有些处理器/编译器需要让额处的寄存器入栈,有些处理器/编译器就是不允许在ISR中做浮点运算。此外,ISR应该是短而有效率的,在ISR中做浮点运算是不明智的;
    • printf(char * lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用。

    关于这些要求的解释:

    a.为什么不能有返回值?

    中断服务函数的调用是硬件级别的,当中断产生,pc指针强制跳转到对应的中断服务函数入口,进入中断具有随机性,并不是某段代码对其进行调用,那么如果有返回值它的返回值返回给谁?显然这个返回值毫无意义,如果有返回值,它必定需要进行压栈操作,这样一来何时出栈怎么出栈将变得无法解决。

    b.不能向ISR传递参数?

    同理,也是由于这样会破坏栈的原因,因为函数传递参数必定会要求压栈出栈操作,由于进入中断服务函数的随机行,谁给它传递参数都成问题。

    c.ISR应尽可能的短小精悍?

    如果某个中断频繁产生,而它对应的ISR相当的耗时,那么对中断的响应就会无限的延迟,会丢掉很多的中断请求。

    d.printf(char * lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用。

    这就涉及到一个中断嵌套问题,由于printf之类的glibc函数采用的是缓冲机制,这个缓冲区是共享的,相当于一个全局变量,第一层中断来时,它向缓冲里面写入一些部分内容,恰好这时来了个优先级更高的中断,它同样调用了printf,也向缓冲里面写入一些内容,这样缓冲区的内容就错乱了。

    可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数执行的任何时刻中断它,转入OS调度下去执行另外一段代码,而返回控制时不会出现什么错误;而不可重入的函数由于使用了一些系统资源,比如全局变量区,中断向量表等,所以它如果被中断的话,可能会出现问题,这类函数是不能运行在多任务环境下的。

    中断服务函数与函数调用的联系与区别:

    联系:两者都需要保护断点(即下一条指令地址)、跳至子程序或中断服务程序、保护现场、子程序或中断处理、恢复现场、恢复断点(即返回主程序)。两者都可实现嵌套,即正在执行的子程序再调另一子程序或正在处理的中断程序又被另一新中断请求所中断,嵌套可为多级。

    区别:两者的根本区别主要表现在服务时间与服务对象不一样上。首先,调用子程序过程发生的时间是已知和固定的,即在主程序中的调用指令(CALL)执行时发生主程序调用子程序,调用指令所在位置是已知和固定的。而中断过程发生的时间一般的随机的,CPU在执行某一主程序时收到中断源提出的中断申请时,就发生中断过程,而中断申请一般由硬件电路产生,申请提出时间是随机的(软中断发生时间是固定的),也可以说,调用子程序是程序设计者事先安排的,而执行中断服务程序是由系统工作环境随机决定的;

    其次,子程序完全为主程序服务的,两者属于主从关系,主程序需要子程序时就去调用子程序,并把调用结果带回主程序继续执行。而中断服务程序与主程序两者一般是无关的,不存在谁为谁服务的问题,两者是平行关系;

    第三,主程序调用子程序过程完全属于软件处理过程,不需要专门的硬件电路,而中断处理系统是一个软、硬件结合系统,需要专门的硬件电路才能完成中断处理的过程;

    第四,子程序嵌套可实现若干级,嵌套的最多级数由计算机内存开辟的堆栈大小限制,而中断嵌套级数主要由中断优先级数来决定,一般优先级数不会很大。

    10、下面的代码输出是什么,为什么?

    void foo(void)
    {
        unsigned int a = 6;
        int b = -20;
        (a+b > 6) ? puts("> 6") : puts("<= 6");
    }

    解答:这个问题测试你是否懂得C语言中的整数自动转换原则,我发现有些开发者懂得极少这些东西。不管如何,这无符号整型问题的答案是输出是 ">6"。原因是当表达式中存在有符号类型和无符号类型时所有的操作数都自动转换为无符号类型。因此-20变成了一个非常大的正整数,所以该表达式 计算出的结果大于6。

    还有一个重要的知识点:

    通常情况下,在对int类型的数值作运算时,CPU的运算速度是最快的。在x86上,32位算术运算的速度比16位算术运算的速度快一倍。C语言是一个注重效率的语言,所以它会作整型提升,使得程序的运行速度尽可能地快。因此,你必须记住整型提升规则,以免发生一些整型溢出的问题。

    整型提升是C程序设计语言中的一项规定,在表达式计算时(包括比较运算、算术运算、赋值运算等),比int类型小的类型(char, signed char, unsigned char, short, unsigned short等)首先要提升为int类型,然后再执行表达式的运算。

    至于提升的方法,是根据原始类型进行位扩展(如果原始类型为unsigned char,进行零扩展,如果原始类型为signed char,进行符号位扩展)到32位。也就是说:

    • 对于unsigned char,进行零扩展,即在左边的高位用 0 填充至32位;
    • 对于signed char,进行符号位扩展。如果其符号位为0,则左边的高位用 0 填充至32位;如果其符号位为1,则左边的高位用 1 填充至32位。

    11、评价下面的代码片断:

    unsigned int compzero = 0xFFFF;

    解答:对于一个int型不是16位的处理器为说,上面的代码是不正确的。应编写如下:

    unsigned int compzero = ~0;

    12、 尽管不像非嵌入式计算机那么常见,嵌入式系统还是有从堆(heap)中动态分配内存的过程的。那么嵌入式系统中,动态分配内存可能发生的问题是什么?

    解答:动态分配将不可避免会产生问题:

    • 内存泄露:内存泄露通常是程序自身编码缺陷造成,常见的 malloc内存后没有free等类似的操作, 系统在运行过程当中反复的malloc,吃掉系统内存,造成内核OOM,将某个进程需要申请内存的杀死而退出。
    • 内存碎片:内存碎片是一个系统问题,反复的malloc和 free,而free后的内存又不能马上被系统回收利用。这个是因为负责动态分配内存的分配算法使得这些空闲的内存无法使用,这一问题的发生,原因在于这些空闲内存以小且不连续方式出现在不同的位置。

    下面的代码片段的输出是什么,为什么?

    char *ptr;
    if ((ptr = (char *)malloc(0)) == NULL) 
        puts("Got a null pointer");
    else
        puts("Got a valid pointer");

    函数malloc()的参数是可以时0的。

    13、Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理器做类似的事。例如,思考一下下面的例子:

    #define dPS struct s *
    typedef struct s * tPS;

    以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢?

    解答:typedef更好。思考下面的例子:

    dPS p1,p2;
    tPS p3,p4;

    如果是第一个define的扩展:

    struct s * p1, p2;

    p1为指针,p2为结构体。很明显,不是我们想要的答案。

     

    展开全文
  • 如何学习嵌入式软件

    万次阅读 多人点赞 2016-02-03 16:35:46
    什么是嵌入式嵌入式分为广义和狭义两种。广义的嵌入式就是片上系统(system on a chip),包括单片机、PSOC、NIOS、Microblaze等。而狭义的嵌入式就是ARM9、cortex A8等特定的跑操作系统的芯片。这里主要介绍狭义...

    什么是嵌入式?

            嵌入式分为广义和狭义两种。广义的嵌入式就是片上系统(system on a chip),包括单片机、PSOC、NIOS、Microblaze等。而狭义的嵌入式就是ARM9、cortex A8等特定的跑操作系统的芯片。这里主要介绍狭义嵌入式的学习路线。

            还是主流的方法,先学会使用它,再深入研究底层。

            常用的嵌入式操作系统有Linux、WIN CE、安卓、Vxworks、QNX、OSE等,目前资料最多的是linux,所以下面以linux为例。

    一、安装虚拟机和Linux系统。

            一般人用的电脑都会装Windows系统,要想在Windows上跑其它系统,得安装虚拟机。而目前主流的虚拟机有vmware、VirtualBox、hyperV等,你可以随便选一个安装。然后去官网下载个人版的Linux镜像(.iso文件)并把它安装在虚拟机里面即可,这里给出主流Linux系统的官网链接:ubuntufedoracentosdebiansuse。如果你没有用过linux的话,推荐使用ubuntu。因为RedHat要收费,并改名为RHEL,所以这里不作介绍。

             先下载一本《鸟哥私房菜》。然后进入第二、三、四阶段(前期的学习不需要开发板)。

    二、学会使用Linux常用命令。

             这里,必须改改在Windows下点鼠标的习惯,在linux下做事得用命令行。此外,在Linux下载软件,不需要在百度下载,而是用linux自带的软件包管理工具(如:apt-get、dnf、rpm等)。如果你用ubuntu的话,得修改软件源(下载软件的网址),因为国外的源比较慢,百度上有详细说明。接下来,得学会最基本的命令,如:ls、cd、find、grep、ps、diff、fdisk、ifconfig等。跟着教材多操作几遍就会了,没有很深的理论知识,不需要掌握所有的命令,也不需要记住所有命令的选项,用到的时候会查就可以了。有空的话可以上ubuntu社区或者linux公社

    三、学会使用Linux常用工具。

    1、编辑器(写代码必备的)。有gedit,vim,emacs,sublime等,推荐学vim

    2、gcc和gdb。gcc是编译器,gdb就是代码调试器。

    3、makefile、autoconf、automake。这里可不像VC++6.0这种工具,点个鼠标就给你编译好。在Linux下,你得用makefile和make工具,来编译代码。其中autoconf和automake可以自动生成makefile。

    4、ssh、tftp。如果你在ARM开发板上弄了个Web服务器,那么,你就可以用这些工具去访问它。其中,ssh工具建议用SecureCRT或者MobaXterm

    5、samba。要想用Linux跟windows交换数据,还可以搭建samba服务器。

    6、版本控制器。有svn,cvs,git等,推荐学git。有了git,你就不必手动备份代码了。

    7、串口调试助手。推荐serials。其它的,比如:minicom,cutecom,picocom都不好用。

    四、学会编写shell脚本。

             在实际工作中,复杂的系统管理操作,不会一行一行地敲命令,而是用脚本(命令是基础)。脚本也是一种编程语言,只不过是解释型语言。相比C/C++、C#、JAVA这类高级语言,脚本要易学很多(因为增加了语法糖)。在Linux下,shell也有很多种,如:bsh、bash、csh、tcsh、ksh、zsh等,一般是学bash,其它的遇到再学也不迟,因为都是大同小异的。此外,bash语法比较奇特,很多符号(如:$#,$0,$?等)比较难记,不过也没必要特意去死记它,有个印象就可以了,用到的话再查手册,这里重点掌握正则表达式。如果有时间的话,建议再学python脚本,python的语法要容易很多,用途也比bash广很多。推荐《Shell脚本编程诀窍》。

    五、学会Linux下C编程。

             尽管学会bash已经能做很多事情了,但是驱动和内核开发还是用C语言,因为那时候系统还没起来,bash是用不了的。此外,C语言的执行效率比bash要高,网络编程的Socket也常常用C语言开发。在这里,得掌握基本的文件操作、进程/线程控制、Socket等。推荐《Linux环境C程序设计》、《UNIX环境高级编程》、《UNIX网络编程 卷1》、《UNIX网络编程 卷2》,或许这些教材有点难,但是,请不要钻牛角尖,不懂的暂时跳过,在学完下一阶段的理论之后,再来看,之前不懂的东西就变得容易。

    六、增强理论知识。

            因为有的人打着嵌入式硬件工程师的名号装逼,其实嵌入式硬件就是普通硬件工程师做的工作。我们这里都是讨论软件方面的内容,而且嵌入式是以软件为主导的(工资上有较大差距)。如果对硬件感兴趣的,可以参考本博客《如何学习硬件设计——理论篇》和《如何学习硬件设计——实践篇》,这里不要求掌握硬件,有一定程度的了解即可。

    1、单片机。具体的学习路线请参考本博客的《如何学习单片机》。不想学单片机的话,可以学计算机组成原理。

    2、数据结构。主要掌握表和树,其中链表会在操作系统的调度算法中用到。

    3、操作系统。全部都是重点,必须深入研究,才会对Linux有个较全面的认识。

    4、编译原理。有时间的话,最好多看看,没空的话,也得了解一下。对于提高编程能力,有一定的帮助。

    5、数据库。除了基本的数据库理论之外,还得掌握SQLite或者Oracle。

    6、ARM体系结构。介绍ARM的架构和指令集,在移植uboot和驱动中会用到,不做这两项工作的话,可以不学。

    7、计算机网络基础。开发中用到的tcp、udp、ssh、tftp、http、rtp就会涉及到网络相关的知识,也就是socket套接字编程。

    8、接口应用。如:串口、zmodem、IIC、SPI、1-wire、USB、HDMI、CAN、IIS、PCIE、蓝牙、陀螺仪等。

               学完上面这些理论之后,得再复习一下linux下C编程,你会有更大的收获。

               先下载一本韦东山的《嵌入式Linux应用开发完全手册》,还要买一块2440的开发板(虽然s3c2440已经停产,但是这芯片依照是资料最多的一块),然后进入七、八、九、十阶段。其中第七、八、九阶段,使用开发板自带的bootloader即可,暂时不必研究它。

    七、文件系统。

           在学习操作系统原理的时候,已经有介绍文件系统了,而且不需要深入研究文件系统的具体算法,只需要了解其特性再学会使用它就可以了。如:NFS、FAT32、NTFS、yaffs2、ext4、ZFS等。

    八、内核裁剪。

            一般初学,可以先掌握内核剪裁(具体工作就是填写若干个选项)。剪裁只是去掉内核部分不需要的功能,以减少代码体积。这里只要求你对内核的各个功能选项都很熟悉就可以了。如果剪裁还不能满足要求的话,得阅读内核源码,修改内核了。推荐《Understanding the Linux Kernel》和《Linux Kernel Development》。阅读内核源码,推荐windows下的source insight或者eclipse。

    九、驱动开发。

            由于系统还没起来,所以驱动能用到的API(内核的部分API,如:kprintk、kmalloc等)并不多,很多函数还是得自己写的,其中,会经常访问临界资源,所以得掌握自旋锁、睡眠锁。此外,驱动程序出问题的话,整个系统就挂掉了,所以还要掌握各种调试驱动的方法,如:goto语句、日志系统、KDB等。接下来就要熟悉掌握字符设备和块设备的驱动程序了。推荐《小白的博客》和《Linux Device Drivers》(不建议看中文版)。

    十、移植bootloader。

            单片机也有bootloader,在keil C下的startup.a51,主要是做一些初始化工作。那么,在ARM上面的bootloader也是一样的功能,同样,也没有那么重要所以把它排在后面。常用的bootloader有vivi和uboot,一般学习uboot,主要掌握uboot的启动流程和移植。在经过前面的学习,那么uboot对你来说已经非常容易的了,一般只需要学会使用uboot或者用已经移植好的uboot,不需要深入研究它。推荐看uboot自带的帮助文档以及《深入理解BootLoader》。阅读uboot源码,推荐windows下的source insight或者eclipse。

    十一、图形界面开发。

            常用的GUI图形库有:GTK++、QT、JAVA、安卓等。有C++基础的,建议学习QT,不会C++的,建议学JAVA。在前期的GUI开发,可以不需要使用开发板,而2440下适合跑QT,如果要跑JAVA、安卓的话,建议换一块开发板,可以考虑Exynos4412开发板。此外,你还可以用python自带的TKinter来开发图形界面。推荐《QT5编程入门》、《疯狂JAVA讲义》、《疯狂Android讲义》、《python编程入门》。

             因为安卓系统是在Linux的基础上封装了一层API,所以,如果做安卓驱动,就得掌握Linux(上面前十个阶段)。如果只做安卓app,你只需要使用android studio或者eclipse配合安卓模拟器(最好用安卓手机),就可以了,不需要学习Linux,也不需要开发板。

              在你做过几个GUI项目之后,再学习UML设计模式这会大大增强你的代码架构能力。

    十二、Web开发。

             有的时候得在ARM板上搭个Web服务器,这里,得学习HTML、CSS、Javascript、XML、Ajax、PHP等。看起来内容很多,但其实并不多,因为这些语言都很容易上手。初学可以使用Adobe的Dreamweaver做开发,上手之后一个sublime text配合firefox浏览器就可以了(还要学习MVC模式)。此外,还得会用bash或者python编写CGI程序,这样才可以在网页上调用到底层的C语言接口。推荐《疯狂HTML 5/CSS3/JavaScript讲义》。

    十三、杂谈。

              本文没有涉及流程图绘制软件文档生成工具等(这两个东西在工作中会经常用到)。

              由上文可知,嵌入式软件涉及很多计算机相关的知识,这对于电子专业的学生来说,无疑相当于跨专业那么大难度。此外,就算你掌握了上面所提及的知识,那也只是打开一扇小小的窗户而已,还有很多事情做不了的。比如:二维码识别、视频采集卡等。

    BTW,嵌入式的工作也分成几个岗位,分别是系统工程师、驱动工程师、软件工程师(负责网页或GUI开发)、UI工程师(又称美工)。

    系统工程师:熟悉操作系统的内核原理、熟读内核源码。主要职责为系统打补丁或者添加新功能,如:热升级、提高系统的容错性等。一般的公司是不做这种开发的。

    驱动工程师:熟悉各种外设的驱动开发,为内核和GUI提供接口。由于很多IC厂商提供了相关芯片的驱动程序,而导致很多驱动工程师下岗(需求量减少)。

    软件工程师:熟悉各种编程语言和GUI图形库、框架(不是会查文档就可以的,而是要求非常熟悉框架)。由于项目需求经常变更,开发效率跟不上变化,所以软件工程师的需求量大大增加。

    UI工程师:主要负责美化界面。美术特长生更适合这类工作。

    展开全文
  • 嵌入式软件架构设计

    万次阅读 2018-08-31 11:49:26
    在开发中一直觉得好的软件架构可以做到事半功倍,而且可以做到代码复用和移植。 但是如果没有架构或者说架构很差,那么移植将是很痛苦的事,特别是对不熟悉改功能的人来讲还不如自己写呢,移植不对那将是很头疼的事...
  • 什么是嵌入式以及嵌入式软件和非嵌入式软件的区别 嵌入式:在已有的硬件上移植(需要修改操作系统源码,安装不需要)操作系统解决软硬件耦合导致的问题 嵌入式软件和非嵌入式软件的区别(即传统开发和嵌入式开发的优...
  • 嵌入式软件是怎么分类的?

    千次阅读 2019-04-04 16:47:15
    随着嵌入式系统应用的逐渐普及,为保证嵌入式系统的顺利运行,嵌入式软件得到了快速发展,成为软件业的一股新生力量。粤嵌在这里介绍下嵌入式软件是什么,以及它是如何分类的。 嵌入式软件与嵌入式系统是密不可分的...
  • 2017嵌入式软件行业现状及概述

    万次阅读 多人点赞 2017-11-05 16:41:38
    本文章介绍了截止2017年为止的嵌入式软件行业现状,包括就业方向,行业产品类型,待遇等等。另外还简单概述了下嵌入式软件所需的知识技能以及未来可能的技能发展走向。本文章远不如专业的行业报告一般精准、专业,...
  • 10种受欢迎的嵌入式软件开发工具

    千次阅读 2019-10-18 18:44:01
    驱动设备的引擎是嵌入式软件,它是快速发展的IoT生态系统中不可或缺的一部分。 本篇博客主要谈嵌入式软件开发工具。解释什么是嵌入式系统以及需要什么工具能够构建出来一个。你将了解到现在IT市场上最受欢迎的、...
  • 本阶段对大家重要还有个更主要原因就是:本课程中讲的东西都是各种嵌入式软件开发岗位技术面试笔试中常遇到的。所以如果是希望通过学习搞定面试找到工作,那本阶段的课程就要作为重点学(尤其是C语言专题)。 第2...
  • 嵌入式软件架构的设计

    千次阅读 2019-02-18 22:00:35
    嵌入式软件架构的设计 大多数嵌入式程序员学习编程,都是从开发板的附带例程开始。之后工作也会继续参考那些例程,很多编程习惯、方式也会受之影响。 其实开发板式的编程方式与工作中实际需求的并不完全一致。 ...
  • 嵌入式软件工程师自学之路

    万次阅读 多人点赞 2018-11-20 17:13:14
    目标是成为嵌入式软件工程师。 当时误打误撞的选择了这个专业,在学校也没有充分认识到未来的方向,所以浪费了 大学宝贵的学习时间及其丰富的学习资源。毕业后接触到现实的社会,总感觉未来很茫然, 想着还是利用...
  • 海康威视嵌入式软件工程师的题目只包含两个部分选择题和简答题,也就是说,没有编程题! 照样是C语言基础的题量最多了,又因为是BSP方向,所以关于Linux操作系统和驱动方面的题目可能页会比较多一点,但是就题目的...
  • 嵌入式软件工程师薪资多少呢?这想必是所有想要学习或者接触嵌入式软件工程师的人儿都想要了解的。首先我们跟着华清远见的老师嵌入式软件工程师发展前景分析来看:嵌入式领域较新,目前发展非常快,很多软硬件技术...
  • 嵌入式软件测试参考书籍

    千次阅读 2019-06-17 19:18:32
    嵌入式软件测试的几本参考书籍: 1、《嵌入式软件测试》; 2、《嵌入式软件测试 方法、案例与模板详解》; 3、《嵌入式软件测试实用技术》; 4、《嵌入式系统软件测试》 1、《嵌入式软件测试》 《嵌入式...
  • 嵌入式软件开发流程

    万次阅读 2018-05-06 20:16:33
    图1:嵌入式软件开发流程 (1)创建工程项目:在配置硬件设备和安装软件开发工具后,就可以开始创建工程项目,通常需要选择项目文件的存储位置及目标处理器。 (2)添加项目文件:开发人员需要创建源程序文件,...
  • 从CSDN各个博客上摘选的一些容易做错的嵌入式软件的笔试题,做一下记录,让自己记住。 文章转自:嵌入式软件开发:笔试总结。 编程语言的基础考察 1、以下代码运行结果为: #include <iostream> using ...
  • 本系列课程针对有意向学习嵌入式软件开发的童鞋,从零开始、深入浅出,内容涵盖:linux系统基础、shell、linux C编程、linux系统编程、网络编程、ARM体系结构及汇编语言、ARM裸机编程、linux系统移植、linux驱动开发...
  • 嵌入式软件评审规范:软件评审规程-交付物审计检查表;软件评审规程-内部审计进程表单;软件质量系统管理评审规程。。。 嵌入式软件评审要素:单板软件详细设计评审要素表(硬件);单板软件详细设计评审要素表...
  • 嵌入式软件测试

    千次阅读 2019-06-22 00:20:24
    嵌入式软件开发过程中,一般来说,花在测试和花在编码的时间比为3:1(实际上可能更多)。这个比例随着你的编程和测试水平的提高而不断下降,但不论怎样,软件测试对一般人来讲很重要。很多年前,一位开发人员为了在...

空空如也

1 2 3 4 5 ... 20
收藏数 176,848
精华内容 70,739
关键字:

嵌入式软件