嵌入式系统学习记录

6/6/2022 嵌入式

知识记录

嵌入式概述

刚开始认为嵌入式设备是用于控制一些比较简单的小型的系统什么电冰箱、扫地机器人之类的,上课了后才知道原来它也可以用在一些大型的复杂的系统里面,包括汽车飞机什么的。他其实是嵌入到一个机械或电子设备中的具有专用功能的计算机系统,通常具有实时计算约束,是电脑,但是把自己嵌到一个物品中,假装自己不是电脑。好像给一个物品装上了脑子一样,通过传感器接受外部的数据,执行器输出动作之类的。嵌入式是为了被嵌入的东西专门设计的,和我们平常用的通用的电脑不太一样。嵌入式系统中比较中重要的是它是实时性,它得及时处理由传感器传来的数据,并且及时的用执行器输出数据。

处理器体系结构

微控制器(MCU)是一个相对简单的中央处理器(CPU)和存储器、I/O、定时器等外围设备组成;

DSP(Digital Signal Processor)处理器,信号是对物理世界进行采样获得的结果,用一定的频率进行采样称为采样率,DSP专门处理数字信号;

“指令集”、“架构”和“CPU”,指令集(Instruction Set Architecture)位于硬件和软件的交界处。ARM(Adcanced RISC Machines)在移动端领域应用很多。处理器架构称为微架构(Microarchitecture),使用硬件电路实现指令集。

冯诺依曼体系和哈佛结构。根据指令和数据的存放位置区分,冯诺依曼体系计算机系统由一个CPU一个存储器组成,存储器存储数据和指令,更具给定的地址进行读写,程序和数据共用一个存储空间,采用单一的地址和数据总线,处理指令时要先去出指令进行解码,再取操作数执行运算。比较费时但是实现会比较简单x86就是用这种架构快速抢占市场。哈佛结构将数据存储器和指令存储器分发到两个地方使用不同的总线经行传输。

大端存储和小端存储。计算机通常采用字节作为存储单位,数据大于一个字节数,学要区分字节顺序存储。大端存储就是将字的起始对准地址的的高地址,小端存储是将字的起始对准低地址。对准的高地址或者是低地址需要是有效字节或者半字所对应的地址。对于内存的读写有对齐要求,比如uint_32 32位对齐的含义是其内存的地址的最低位是:0x0、0x4、0x8、0xC,unit16_t 16位对齐的含义是其内存的地址的最低位是:0x0、0x2、0x4、0x6、0x8、0xA、0xC、0xE;对于单字来说是没有对齐问题的(应该吧:zany_face:)。嵌入式设备中常用的ARM架构是不支持不对齐操作的,当对不对齐的地址访问时,处理器将引发异常。

总线

要实现一个高效的计算系统,总线是出于主干地位的。总线上能够挂很多设备,总用于沟通处理器,RAM,ROM等一些外设的数据传输通道。总线也分高速和低速总线,通过设置多路总线能够降低总线负载,降低成本等。数据总线是双向的,CPU和外设能够相互传输数据,地址总线是单向的,只能从CPU向外传送地址信息

计时

计算机设备里是如何提供一个精确的1秒的?如何获得一个标准的供所有设备参考的时间?

计算机里的时钟系统是由振荡器(时钟源)、定时唤醒器、分频器等电路组成的,它提供一个固定的时间作为时钟周期。振荡器(oscillator)是一种能量转换装置——将直流电能转换为具有一定频率的交流电能。常用的有晶体振荡器和RC振荡器。通过将振荡器的频率进行分频或者倍频获取应用所需要的时钟频率。

定时器,如果采用很高的频率进行计时,会需要太大的数据位表示,可以增大计时的颗粒度。每N个时钟周期,计数器的值+1。可以利用定时器产生各种时间间隔,利用这些时间间隔实现周期事件。

WDT(Watch Dog Timer),嵌入式设备通常是在一些比较恶劣环境,没人在维护的。对于程序的挂起和死锁问题,需要重新启动系统来解决这个问题(简单方法),使用看门狗,每隔一定事件需要获得狗骨头,再一定时间内需要被重新复位,不然就会重启系统。是嵌入式设备里非常有特色的硬件设备,可在windows里进入bios模式里可以设置windows的看门狗开关,看来还是很普遍的这个东西。

中断

在中断机制产生之前,CPU要知道某个设备是否就绪,只能采用轮询方式,每隔一段时间,去访问一边看看可以执行了吗。这就很浪费!加入每个一段时间都要去访问键盘的输入,间隔长一点反应就不及时,短一点又浪费CPU。而利用中断就能让CPU先专心干其他事情,等键盘有请求了再处理键盘输入。

实现中断需要满足一些要求,CPU知道事件什么是否发生?处理事件的代码指令在哪?

软中断,system call,在系统处于内核态的时候进行函数调用。调用时会查找sys_call_table索引表,获取到使用的系统调用的函数指针。

处理中断的过程,处理器在下一条指令停止,保存下一条指令地址到堆栈中,并且跳转到相应的ISR(Interrupt Service Routine)

那在执行一个指令的途中,来了一个中断请求,要不要把这个指令执行完呢?这将中断分为精确中断和非精确中断。

如果一个中断使得机器处于一种确定状态那么就是精确中断。必须满足以下状态:

  1. 程序计数器的值被保存在已知位置
  2. 程序计树器所指向的指令之前的所有指令已被执行完毕
  3. 程序计数器所指向的指令之后的所有指令不可被执行。如果中断信号到来后而转入处理前发生了任何针对寄存器/内存的更改,都必须予以还原。
  4. 程序计数器所指向的指令的执行状态已知。

中断尽管可以提高计算机处理性能,但过于密集的中断请求/响应反而回影响系统系统性能。这类情形被称为中断风暴(interrupt storm)。

专用性

嵌入式设备作为一个专用的计算机系统,有可能回在一些比较极端的环境下工作,对于功耗和稳定性的要求会比较严格。在MSP430G2553里就有五种低功耗模式。降低功耗不仅能够延长嵌入式设备的使用寿命,减少了由于发热带来的硬件不稳定性,在一定程度上有助于硬件执行效率的提升。而且还能省钱

嵌入式设备的开发对成本的要求会比较严格。硬件成本包括了电子元器件、电路板、产品外壳等。软件成本包括了研发、测试、认证等。由于它的专用性,每种设备都有不同的规格,不像PC都差不太多,在微波炉电冰箱的控制中内存可能就比较小,处理器性能比较低,而在手机里,内存和处理器的要求就会高很多。每种设备都需要在限定成本下,发挥出最大的性能,这样才能卖出更好的价钱,获取最大的利润。

如何阅读和编写嵌入式代码

在第一次实验走马灯第二次实验通过中断实现走马灯实验中主要任务是编写代码,第三次time_A定时器实现uart的实验中主要是阅读代码,再在此基础上修改代码。对于嵌入式设备的控制主要通过修改各种控制位来实现的,一看代码都是一大堆已经定义好的宏和一些位操作。一眼看上去不像以前在pc上编写的代码值观,需要不断对比头文件知道这个宏是控制哪个位,这个位又是用来控制什么操作的,当然可以看着英文猜但是如果没有对程序用处和嵌入式设备的宏观理解看起来会很吃力。

比如时钟和定时器部分,基本时钟模块有2个3个或者4个时钟源,LFXT1CLK、XT2CLK、DCOCLK和VLOCLK;时钟信号有三个ACLK、MCLK和SMCLK。基础时钟系统控制寄存器BCSCTL有三个,BCSCTL1用于控制XT2振荡器、LFXT1模式和ACLK分压器,BCSCTL2控制MCLK和SMCLK,BCSCTL3用来控制XT2频率范围,电容等。每个寄存器8位,每种控制用的位数不同,想要记下这种东西实在是太困难了,而且感觉没什么必要。

TImer_A定时器有四种模式上数、向上、连续、增加/减少,每种模式计树方式都不同。Timer_A还有两个或三个比较/捕捉模块TACCRx。捕捉模式和比较模式不同用处和用法。输出单元如何输出信号。各种功能都需要查阅说明书才能使用,每种不同的芯片都有不同的控制方式和功能。完全记下一个芯片的功能是很没有效率的事情。

通过这几次实验我觉感觉阅读嵌入式代码,如先是要理解嵌入式设备的整体架构,什么设备是用来干什么事情的,如果不知道时钟用来干什么,中断是什么这种事情那代码是怎么也看不懂的。再根据程序需要实现的功能,看程序的整体结构先不看细节,每个函数名称,执行的流程,大致推断这个函数是用来干什么的、中断是用来干什么。然后就是对着定义好的头文件和对应设备的说明书,看实现的各种细节,这个寄存器的每一位代表什么意思,组合起来是实现什么功能。看完一段陌生的代码过程感觉还是挺折磨的,可能是刚接触嵌入式比较不熟练的原因吧,但是全都看完还是会很舒服。

如何编写嵌入式代码,先是要确定好程序的功能、功耗精度要求等,决定要时钟信号使用什么时钟源,定时器使用什么时钟信号,轮询还是中断,中断用定时器的什么中断等大致要求。然后确定寄存器的各个控制位的数据,写好把注释写边上(写了感觉过一会就忘记是写来干嘛的了)。善于使用位运算,switch和?,应该会快一些提升速度。在适当的位置修改设备的低功耗模式。

感觉最重要的现有对嵌入式设备的宏观理解再熟练地阅读说明书

展望

感觉嵌入式是能够改变我们方式的一种技术,现在嵌入式什么设备以及遍布我们的生活中了,小到手机手环,大到汽车飞机火箭。在传感器,处理速度等相关技术获得突破后,可以更加精确及时监测人体健康,检查驾驶员疲劳程度,监控地震等灾害。甚至可以植入到人体中,给大脑传输只有本人能看到的数据。