精华内容
下载资源
问答
  • 每当面对这个问题的时候,其实我也是一脸懵逼状态的,这些问题真心很不好回答,说少了,有敷衍的嫌疑,说多了,又是长篇大论,于是为了解答这个问题我决定写下这篇文章,暂定的名字叫《嵌入式系统架构师之道》。...

    第一,道可道,非恒道

    有许多朋友都曾跟我聊过类似这样的问题——想要从事嵌入式行业都需要学习哪些知识?

    每当面对这个问题的时候,其实我也是一脸懵逼状态的,这些问题真心很不好回答,说少了,有敷衍的嫌疑,说多了,又是长篇大论,于是为了解答这个问题我决定写下这篇文章,暂定的名字叫《嵌入式系统架构师之道》。

    虽然我自己也还在这条道上“上下而求索”,但毕竟是在嵌入式行当里摸爬滚打将近十年了,午夜梦回也会抓起床头的小本子记录一下零星的感悟,时间久了总算是找到了一条我认为能够在嵌入式领域登堂入室的大道。

    这是一条我自己的道,所以,正在阅读这篇文字的亲们:

    如果您是前辈,还请不吝指教;

    如果你是道友,我们不妨相互印证一下彼此的心得、彼此的道;

    如果你是正准备踏上这条道的菜鸟,真心希望我总结的道能让你少走一些弯道。

    第二,名可名,非恒名

    何谓嵌入式系统?

    对于嵌入式系统的定义,最权威的莫过于IEEE给出的定义:“Devices used to control, monitor, or assist operation of equipment, machinery or plants.”

    可是这个定义实在是太宽泛了,宽到跟没说一样。

    所以我个人还是比较倾向于咱们国家计算机技术与软件专业技术资格(水平)考试指定的那本《嵌入式系统设计师教程》(后文简称为教材)中的给出的一句解释:“嵌入式系统是一种专用的计算机系统,作为装置和设备的一部分。……”

    诚如教材中的解释所说,在早期的工程应用中,嵌入式系统就是一种专用的计算机系统。

    由于使用通用的计算机系统成本太高,为了降低成本,于是针对某个领域内的具体应用,重新设计软、硬件结构,优化掉无用的部分,一方面降低了系统的成本,另一方面也有针对性地提升了系统的性能。

    但,一开始的嵌入式系统远没有现在这么丰富多彩。近些年来半导体技术的爆发式增长,Soc也越发的变得复杂,与此同时,通信技术的发展也极大地推动了嵌入式系统的繁荣。

    随着微处理器成本越来越低、性能越来越好,成本的因素在嵌入式系统中的约束已经越来越弱化,如果当前的发展趋势可以保持下去的话,在可预见的将来,嵌入式系统的设计与研发也许将会向着集成化、通用化、模块化的方向发展。

    不过咱们话说回来,无论是IEEE、还是教材中的解释都明确指出,嵌入式系统一定是包含软件和硬件两个部分的。

    近些年来,我面试别人的时候常常遇见一些有志于嵌入式行业的青年,只学习了一写嵌入式Linux的剪裁和移植,和基于Linux的程序开发就来面试嵌入式的岗位。

    每到这个时候,我的内心都是很困惑的,不知道从什么时候开始,嵌入式的培训变成了Linux培训,会在Linux系统上用QT写扫雷真的不能叫懂得嵌入式。

    记得大学的时候刷侯捷老师的《深入浅出MFC》这本书的时候,印象最深的就是郑重写在章节前面的一句话“勿在浮沙筑高台”,在我之后的技术生涯中,这句话一直被我奉为座右铭。

    那么当前的嵌入式系统知识体系中都包含哪些内容呢?

    嵌入式行业发展到今天这个地步,我个人认为,如果想从事嵌入式这个行业,并且想要有所成就,至少如下六块技术都要有所涉猎:

    硬件技术,主要包括:数字电路、MCU、常用电子元器件、传感器、原理图以及PCB制版,等;

    驱动技术,主要包括:常用数字量和模拟量IO、时钟、总线(SPI、I2C、USB等)、存储,等;

    通信技术,主要包括:通信原理、以太网、Wi-Fi、蓝牙、射频,加密解密、网络安全等;

    操作系统,主要包括:操作系统原理、常用嵌入式操作系统、BSP、Boot-loader,等;

    开发工具,主要包括:硬件分析与调试工具、网络工具、交叉编译工具链、版本管理、仿真仪器,等;

    开发语言,主要包括:汇编语言、C/C++、QT界面、脚本语言、Linux Shell开发,等;

    除此之外,想成为嵌入式系统架构师以上这些知识也还是不太够看,至少还需要在加上两大部分:

    其一,对所在行业的理解。

    做系统设计,尤其是嵌入式系统的设计,绝大多数时候是与行业密切相关的,很多时候即使是同样的功能需求,在不同的行业应用中也会导致完全不同的系统设计。例如,同样是温湿度的采集,对于野外的气象数据收集模块通常的要求是防尘、防水以及低功耗,对数据的实时性要求不高,而放在工业领域上则更侧重的是测量精度与实时性要求,但放在民用领域则更看重的是低功耗与有好的人机交互,对精度和实时性反而没什么要求。一个嵌入式系统最终成败,很大程度上取决于设计者对目标行业的理解程度,不仅包含输入的需求文档还有最终用户的使用习惯、目标行业的工艺流程甚至操作人员的教育程度等等。

    其二,项目管理相关知识。

    关于系统架构师是否要懂得项目管理这个话题就不在这里争论了。在我看来,一个工程从需求导入、到系统设计、再到系统实现、实施乃至最后的交付,整个过程中,无论是资源申请、成本估算,还是风险评估、进度跟踪,都与架构师的工作密不可分。很难想象在一个项目中,架构师只管将设计抛给项目经理,之后就对项目不理不睬,这应该就是一场灾难。

    这也正是我心中的嵌入式系统与嵌入式系统架构师。

    所以我坚信,只有像这样一步一步踏踏实实走出来的道,才是真正通往嵌入式系统架构师的康庄大道。

    最后,献上一幅嵌入式架构师知识地图,与诸位道友共勉!

    1a4b343913402f5e7c1a5a8b57d16907.png

    展开全文
  • 比较针对嵌入式系统,单片机,程序已C语言为主,尽管是面向过程,但不妨碍我们使用面向对象的思维来开发。 1. 访问硬件的设计模式 嵌入式系统,特别单片机最明显的是对硬件的直接访问。基础硬件不仅有CPU,内存,...

    关注、星标公众号,直达精彩内容

    来源:网络素材 | ZeroMing222

    这系列开始谈软件上面的设计,对设计模式在面向对象里面应该各位都知道,或许你在实际开发当中用到,也或许你见过别人的代码中用到。当你程序的代码足够庞大的时候,你会发现维护寸步难行,牵一发而动全身,这个时候你就能够理解在开发初期对程序架构的搭建重要性。而架构最基本熟知的其中就是设计模式,使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。尝试去研究优秀的开源代码,你会惊叹别人对程序的掌控,这时你会稍稍明白架构的目的所在。

    文章基于《C嵌入式编程设计模式》这本书,英文是Design Patterns for Embedded Systems in C。主要是做个笔记,并添加一点个人的理解,分享出来与各位探讨。比较针对嵌入式系统,单片机,程序已C语言为主,尽管是面向过程,但不妨碍我们使用面向对象的思维来开发。


    1. 访问硬件的设计模式

    嵌入式系统,特别单片机最明显的是对硬件的直接访问。基础硬件不仅有CPU,内存,键盘,传感器,通讯RS232等这样的设备。做单片机的不得不对硬件进行控制,读,写操作,而这篇文章已解决管理和操作这些硬件通常的一个模式。或许对你来说并不陌生,但是是否能够系统的,详细的表达出来这就不仅仅只是了解就能达到的。

    下面讨论的设计模式已经在操作硬件上得到证明是可靠有效的。简单总结说,硬件代理模式是以封装详细信息为目的的硬件抽象的一个原型模式,它有可能改变提供给硬件或来自硬件的信息处理方法。硬件适配器模式扩展硬件代理模式,以提供支持不同硬件接口的能力。中介者支持多种硬件设备的协调,实现系统级行为。观察者模式是发布遥感数据到需要的软件元素的方法。去抖动模式和中断模式是硬件设备接口简单重用的方法。定时器模式扩展中断定时器为嵌入式系统提供精确时序。

    1.1 硬件代理模式

    硬件代理模式概念是对访问硬件接口的封装,限制客户直接访问硬件造成问题。

    1.1.1 模式结构

    模式结构非常简单,可能客户会有多个,但是每个硬件设备仅有一个硬件代理,客户只能访问代理接口,无法直接访问硬件就是这个模式的目的。

    1.1.2 角色

    1.1.2.1 硬件设备(HardwareDevice)

    硬件设备可以是各种,内存,传感器等,包含了端口地址,内存地址,寄存器地址等等元素。与硬件代理的关联是通过软件寻址方式,对硬件的读写操作。

    1.1.2.2 硬件代理(HardwareProxy)

    这个是系统中的主功能。给上层应用提供的硬件访问接口,上层应用无须详细关心硬件的具体实现。基本上通常每个代理都有initialize()、configure()和disable()函数。大部分还会有对设备的值读取访问,或者写访问接口。但是一般不能随意读写,会详细到读取到最终的值。

    函数包括:

    access():从设备返回一个特殊值。大多数情况下,代理会对每个来自设备单独的信息提供单独的函数。例如返回传感器的温度,湿度值。

    configure():提供硬件配置的方法。一般会有参数列表,通过传入参数来配置正确的工作状态。

    disable()、enable():提供设备的安全禁用或开启的方法。

    initialize():用于第一次启动时候的初始化硬件。

    mutate():用于向设备写入数据,通常总是有一个或更多的输入参数。

    marshal()、unmarshal():这两个为私有函数,用于把客户数据格式转为硬件所需格式,后者相反,把硬件原始数据格式转换为客户格式。常用于加密解密,压缩解压缩等。

    deviceAddr:是一个私有变量,提供底层直接访问硬件的地址。必须隐藏在代理中,不能给客户访问的机会,所以特别注意到一些接口,是否会通过了指针把该变量暴露出去。

    1.1.2.3 代理客户(ProxyClient)

    客户代码调用硬件代理服务来访问硬件设备。

    1.1.3 效果

    该模式非常普遍并且具有封装硬件接口以及编码系统的所有优点。这为不对客户端进行任何改变而从根本上改变实际硬件接口提供了灵活性。基本上所有的硬件设备都能用此模式搭建,注意的是不能暴露细节,只能返回一个最后的结果,特别在读写操作,否则就不具备有封装性了。

    1.1.4 实现

    可以有很多不同方法用C语言实现,最常见的是如linux驱动,使用结构体里的函数指针统一硬件的接口。然后在具体的硬件设备上实现。

     

    1.2 适配器模式

    硬件适配器模式提供一种方法,使已经存在硬件接口能适用应用期望。可以说是在硬件代理模式基础上,为了能够适应底层不同的硬件设备,在中间增加一层适配器。比如在通讯上面在硬件上都存在RS232,RS485,程序需要在不同情况下使用232通讯或485通讯,而适配器可以提供统一的接口给客户层,通过指针指向所需通讯,则可以实现。最大的特点是在运行中选择,相比使用宏定义需要生成不同执行程序,可以在程序中实现自适应的功能。

    1.2.1 模式结构

     

    1.2.2 角色

    1.2.2.1 硬件适配器(HardwareAdapter)

    硬件适配器在客户和硬件代理之间执行匹配。客户告知适配器所需的硬件设备,适配器执行客户的请求。

    1.2.2.2 客户硬件接口(HardwareInterfaceToClient)

    客户的硬件接口表示客户期望硬件代理提供的一组服务和参数列表。仅仅作为接口,并没有实现,是通过适配器提供硬件实现。

    1.2.2.3 硬件设备(HardwareDevice)

    与硬件代理模式中描述一致。

    1.2.2.4 硬件代理(HardwareProxy)

    与硬件代理模式中描述一致。

    1.2.3 效果

    该模式允许使用各种硬件代理,并且在不同的应用中使用与它们相关的硬件设备,同时亦有的应用使用不同的硬件设备时不需要做改变。我个人理解有点类似是面向对象语言中的多态概念。

    1.2.4 实现

    同样如linux系统驱动,创建一个结构体的接口代理,硬件设备使用这些接口具体实现,然后使用一个指向结构体接口的指针,把需要使用的硬件设备注册到指针上,客户代码只需调用这个指针,即可操作具体的硬件设备,而且可以动态的修改指针的指向,从而实现动态的加载切换。

     

    1.3 中介者模式

    中介者模式提供的是为一组硬件设备复杂交互协调的一个方法。

    1.3.1 模式结构

     中介者模式使用一个中介类来协调各个设备集合的行为,来达到整理的一个效果。这里举一个具体的例子,比如一台车有4个轮子,也就4个电机设备,当向前行驶的时候四个轮子都是向前前进,这时候中介者就承担了控制4个轮子的责任。所以说中介者其实就是一个中央控制。

    1.3.2 角色

    1.3.2.1 合作者接口(CollaboaratorInterface)

    是被中介者调用的接口,对于硬件通常是initaialize(),enable(),reset()等这类函数,但是具体的是在具体合作者实现。

    1.3.2.2 中介者(Mediator)

    在模式中协调所有的具体合作者。中介者对于每个具体合作者都有一个链接,以便他能给具体合作者发送信息。此外,当有事情发生时,每个具体合作者必须能给中介者发送消息。中介者提供协调的逻辑。

    1.3.2.3 具体合作者(SpecificCollaborator)

    表示一个硬件设备。可以从中介者获取命令,也可以发送信息给中介者。

    1.3.3 效果

    该模式创建中介者来协调合作具体硬件,但是对客户来说又不需要直接耦合硬件设备,极大的简化了整理的设计。很多嵌入式系统必须高精度时间相应,动作的延时可能造成不可估计的影响,中介者能够在这些规定时间反应很重要。

    1.3.4 实现

    中介者的实现可以通过指针数组,链表等,能够连接到每个具体的合作者。另外统一接口能够给中介者代码上带来很多便利。

     

    1.4 观察者模式

    观察者模式非常的普遍,你可以在任何地方看到它的身影。这模式提供一个方法来“监听”所感兴趣的消息,而不需要修改数据服务器,这意味着传感器数据很容易分享给所需的客户。

    1.4.1 模式结构

     观察者模式,另外一个名字是“发布-订阅模式”。首先模式下数据服务器不需要清楚客户,相反是由客户通知数据服务器,也就是订阅。订阅意思是允许数据服务器在通知列表中添加(和删除)自身。最常见的通知策略是当新数据到达服务器时,服务器发送数据。但是客户也能定期更新,向服务器获取数据,以减小服务器的计算负担,确保客户具有实时数据。另外更复杂的模式是在数据服务器和客户中间添加一层中央控制器,用于连接服务器与客户的通讯,这样服务器就完全不需要与客户直接联系。如果有大量使用消息使用观察者模式,添加中央不失为一种好方法。

    1.4.2 角色

    1.4.2.1 抽象客户接口(AbstratClient)

    它包含了accept(Datum)函数,当AbstratClient订阅时或者AbstratSubject认为有适合发送数据去调用它。AbstratClient是抽象的,不提供任何具体实现。

    1.4.2.2 抽象发布接口(AbstratSubject)

    在模式中AbstratSubject是数据服务器。在提供模式相关的3个函数。subscribe(acceptPtr)服务添加指向接收函数通知列表的指针。unsubscribe(acceptPtr)函数从通知列表中删除接收功能。最后,notify()函数遍历通知列表通知订阅的客户。

    1.4.2.3 具体客户(concreteClient)

    concreteClient是AbstratClient接口的具体实现。

    1.4.2.4 具体发布(concreteSubject)

    concreteSubject是AbstratSubject接口的具体实现。不仅提供函数的实现,而且提供获取和管理它发布数据的方法。扮演concreteSubject也可以是硬件设备,传感器等。

    1.4.2.5 数据(Datum)

    该元素是实际的数据包,可以是int,更多的是复杂的结构体。

    1.4.2.6 回调接口(NotificationHandle)

    NotificationHandle是调用客户的accept方法的代表。最常见的实现方式是函数指针。

    1.4.3 效果

    观察者模式是在服务器分配数据的过程,并且在运行时可以动态地管理客户列表。实际一个例子,读取硬件的值,通常我们可能是使用轮询的方式读取,轮询的弊端是响应不及时,读取间隔时间很难去固定和评估。另一种方法是定时中断读取,但是定时读取未必每次都会有数据产生。还有是触发中断的方法,如果在中断读取数据后,需要计算,在中断里进行可能不太好,原则是尽量不要中断占用太多的CPU。这个时候观察者模式的好处体现出来了,首先能够保证响应及时,因为使用的回调方式,第二能一个硬件发布,多个接收客户,一对多的模式,第三能够确保每次执行客户回调都能有数据产生。其实观察者模式随处可见,ROS系统的节点通讯就是基于这个策略。该模式明显的缺点是实现较复杂,而且当然也不是所有情况都适应,希望各位能够详细分析后,选择合适的方法。

    1.4.4 实现

    该模式复杂的方面在通知句柄的实现,以及通知句柄列表的管理。通知句柄通常是一个回调函数指针。通知列表最简单的方式是定义足够大的数组来包含所有潜在用户,但是实际占用空间大浪费内存,所以并不常用。另一个常见的是使用链表管理,也就是给每个通知句柄添加在链表上,这样只要遍历链表即可通知所有客户,强烈推荐使用链表形式。

     

    1.5 去抖动模式

    这个模式用于消除来自硬件金属表面间歇性连接引起的多个假时间。

    1.5.1 模式结构

     解决的方案是接受第一次发生的事件,等待抖动减弱,然后再对读取它的状态。

    1.5.2 角色

    1.5.2.1 应用客户(ApplicationClient)

    该元素是去抖动最后的接受者。当在抖动消除后,使用deviceEventReceive()接收最后读取到的值。

    1.5.2.2 具体硬件(BouncingDevice)

    代表了硬件设备。这个设备绝大部分都是全硬件,机械特性的,所以才会引起抖动的现象。sendEvent()用于发送事件,激活中断接收到首次的响应。getState()操作时通过读取内存或IO端口显示,读取具体的硬件值。deviceState通常是二值属性,即ON或OFF。

    1.5.2.3 硬件客户(DeviceClient)

    是用于处理进入事件的中断,去除抖动,并读取确保代表实际设备状态。它的eventRecevie()函数通过BouncingDevice的sendEvent()函数激活。同时,它需要设置延时定时器,去抖动事件过后,如果状态与第一次读取的一致,证明值是真实的。这样它就发送相应的信息给ApplicationClient。旧状态保存在变量oldState中,每当状态发生改变的时候更新这个变量。

    1.5.2.4 定时器(DebouncingTimer)

    这个定时器可以通过delay()服务来提供空闲等待。可以使用while()等待,或者硬件定时器实现。

    1.5.3 效果

    通常去抖动的任务是由软件来承担,这是一个简单的去抖动,应用程序只需要关心硬件状态产生的真实值才接收。

    1.5.4 实现

    硬件客户通常使用中断来通知应用客户。或者使用观察者模式混合也可以给等个客户提供信号。在RTOS系统去抖动必须注意时间单位的延时时间,比如如果想要45毫秒的延时,那么必须使用大于等于期望时间最接近时间精度。如果在等待去抖动时,你不介意完全占用CPU,那么这就很简单,使用while(loop--)循环就好了。

     

    1.6 中断模式

    在嵌入式系统,硬件设备很多时候都是自主发生,如果你不加以注意,这些事件就会丢失。当一个你感兴趣的事件发生时,使用中断来通知是非常有效的方法。基本上芯片都支持外部硬件中断的方式。中断能保证响应的及时,但是中断会抢占CPU的控制,所以中断里面不适合处理算法等这种耗时长的任务。这个模式下可以是纯软件的中断模式。

    1.6.1 模式结构

     确保中断函数一般是没有入参,和返回值的。

    1.6.2 角色

    1.6.2.1 中断响应(InterruptHandler)

    是中断模式里面唯一有具体行为的元素。它能够安装和卸载中断向量的功能。install()函数运行时,拷贝传入的中断句柄到向量表中,使用合适的中断服务程序地址。deinstall()函数相反,用于卸载回复原本的向量表。

    每个handleInterrupt_x()函数处理指定的中断。

    1.6.2.2 中断向量表(InterruptVectorTable)

    就是中断服务程序的地址数组。它依赖在指定的内存位置上。当中断号x出现时,CPU挂起当前进程,调用这个数组中相应的第x个索引地址。

    1.6.2.3 向量指针(VectorPtr)

    VectorPtr是数据类型,具体是一个没有参数和返回值的函数指针。

    1.6.3 效果

    该模式最大的优势是可以高响应处理感兴趣的事件。通常情况下,当中断服务程序执行时,关闭中断,这意味着中断服务程序必须快速执行以确保不会丢失其他中断。

    使用中断有点特别注意是资源的保护。当有可能会在中断和普通程序中处理了同一个元素,设想当普通程序读取数据中途发生了中断,而中断会导致普通程序暂停,然后在中断里面修改了数据返回。普通函数将会读取损坏的数据,即部分是新数据,部分是旧数据。解决方法有1.在普通函数读取数据时禁止中断,访问完成后恢复中断。2.使用互斥信号量。

    1.6.4 实现

    中断函数执行之前必须保存现场,在执行完成需要恢复现场。事实上每个中断服务程序必须:

    1. 保存CPU寄存器,包括CPU指令指针和任何处理器标志,如进位,奇偶校验。

    2. 清除终端位。

    3. 执行适当处理。

    4. 恢复CPU寄存器。

    5. 返回。

     

    1.7 轮询模式

    另一种从硬件获取数据常用的模式是定期检查,称为轮询过程。当数据或信号不是很紧急,或者当数据可用时,硬件没有能力产生中断,又或者硬件本身能保留数据到下次读取情况,这是轮询就非常好用。

    1.7.1 模式结构

     轮询模式是读取硬件上数据最简单的方法。轮询能够定期或不定期进行,可以是定时器读取,也可以当系统需要时读取。

    1.7.2 角色

    1.7.2.1 应用过程(ApplicationProcessingElement)

    这个元素用于循环调用poll()操作。这个也可以是定时器中断里面。

    1.7.2.2 硬件(Device)

    Device通过可访问的函数提供数据或设备状态信息。这个类上面实例了两个方法,getData()用来获取数据,getState()用来获取数据状态。MAX_POLL_DEVICE连接到所有的硬件设备,以便poll()函数全部能够扫描并通知给客户。

    1.7.2.3 轮询者(OpportunisticPoller)

    具有poll()函数,用于扫描连接的设备以读取数据和状态,并把数据转发给客户。这个元素可以添加定时器操作,实现定期读取数据的功能。

    1.7.2.4 客户(PollDataClient)

    该元素来自一个或多个设备数据和状态信息的客户。

    1.7.3 效果

    轮询比使用中断服务简单的多,能够同时检测多种不同的设备,但是基本上没有中断响应那样及时,所以使用轮询最好确保最长的读取间隔时间,确保在一个时间内至少读取一次数据,否则数据将会丢失,但有时候这不是一个问题,所以具体情况就具体分析。

    1.7.4 实现

    最简单的显示方法是在系统操作的主进程循环中插入硬件检查,这叫做“对称机会轮询”,因为它总是以同样的方式操作,即使处理循环事件长度可能变化。非对称机会轮询是在整个进程中方便时候读取新数据(对称是固定位置读取数据,非对称是在需要的时候再读取),这种方式具有更好的响应,但是对主流程有更大影响,而且难以维护。

    ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

    推荐阅读:

    嵌入式编程专辑Linux 学习专辑C/C++编程专辑
    Qt进阶学习专辑
    

     关注公众号『技术让梦想更伟大』,后台回复关键字:『Qt』『C语言基础』『C语言难点』『C++』『Linux』『freertos』『指针』『数据结构与算法』『经验技巧篇』『疑问篇』『基础理论篇』『实战篇』『架构篇』『模块化编程』『状态机』『实用工具』『心声社区』『期刊』『视频』······等,查看更多精选内容。 


    关注我的微信公众号,回复“加群”按规则加入技术交流群。


    这是我另一个技术号,程序员的编程学习基地,注重编程思想,欢迎关注!


    点击“阅读原文”查看更多分享。

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

    2021-04-12 21:17:36
    嵌入式软件架构师 Base上海/深圳 岗位职责: 1.收集并分析市场和产品需求,完成架构设计; 2.制定相关技术演进的roadmap,以及实施计划; 3.带领团队设计并开发复杂异构的操作系统以及多媒体系统解决方案,满足不同...

    嵌入式软件架构师
    Base上海/深圳
    岗位职责:
    1.收集并分析市场和产品需求,完成架构设计;
    2.制定相关技术演进的roadmap,以及实施计划;
    3.带领团队设计并开发复杂异构的操作系统以及多媒体系统解决方案,满足不同应用场景的需求;
    4.深入理解产品,参与产品的整个生命周期的开发过程,包括需求定义、设计、实现、测试、生产、售后等;
    5.制定和改善软件的开发流程;
    6.跟踪嵌入式领域最新的技术发展,对团队进行技术指导。
    任职要求:
    1.至少是EE,CE,CS或同等专业的硕士,至少6年以上的开发经验,以及1年以上架构师经验;
    2.深度参与至少1款产品的架构设计,对于设计简单、高复用、高扩展、高可靠、高性能、低功耗的架构有深入理解和体会;
    3.丰富的嵌入式软件开发经验,如:操作系统(RTOS、Linux、Android)、安全、媒体链路、GPU等;
    4.深入理解SoC架构,以及系统优化方法,如NEON、DSP、GPU等;
    5.具备较强的开发和编程实践能力,以及良好的质量意识;
    6.至少参与过一款产品的敏捷开发实践,如:Scrum、Kanban等;
    7.良好的沟通协调能力,以及较好的驱动力;
    8.良好的学习能力及团队领导力,喜欢挑战。

    展开全文
  • 嵌入并发,意味着多...声明:文章基于《C嵌入式编程设计模式》这本书,英文是DesignPatternsforEmbeddedSystems in C。主要是做个笔记,并添加一点个人的理解,分享出来与各位探讨。 1.嵌入并发和资源管理的设计...

    嵌入并发,意味着多线程或者多任务,基本上都是使用了系统,linux系统或RTOS系统之类的实现。RTOS系统里任务的调度主要有抢占式和时间片调度两种,具体的区别这里就不详细说明了。此篇章包含了并发的一些术语,如并发性,临界性,资源,死锁等的概念。最好是详细阅读RTOS系统的书籍。

    声明:文章基于《C嵌入式编程设计模式》这本书,英文是Design Patterns for Embedded Systems in C。主要是做个笔记,并添加一点个人的理解,分享出来与各位探讨。


    1. 嵌入并发和资源管理的设计模式

    总共有8个模式,前两个循环执行模式和静态优先级模式,提供了两个不同的方法来调度任务或县城。接下来3个模式临界区模式,守卫调用模式和队列模式,为了使解决在多任务环境下串行访问资源的问题。汇合模式讲的是多任务以不同的方式进行同步。最后两个模式是关注预防死锁问题。希望下面的模式能够各位一点启发。

    1.1 循环执行模式

    循环模式有非常简单的方式调用多个任务的特点,允许所有的任务有同等机会运行,但是不能及时响应紧急事件。一般在资源少的系统里面使用,避免了RTOS的开销,也不需要复杂的任务调度。简单就是最大的优点。

    1.1.1 模式结构

     CyclicExecutive有一个controlLoop()函数,可以反复调用每个任务的run操作。也需要等待任务的结束再调用下一个任务。

    1.1.2 角色

    1.1.2.1 抽象任务(AbstractCEThread)

    通过声明run()函数为线程提供接口。它是用来循环执行的任务函数。

    1.1.2.2 循环控制(CyclicExecutive)

    这个类用于循环执行每个任务。此外也有全局栈和任务本身需要的静态数据。模式的一个变体是时间触发循环执行,在这个变体中,CyclicExecutive设置使用CycleTimer来开启每个周期。也就是使用这个变体可以在周期类执行每个函数。

    1.1.2.3 循环定时器(CycleTimer)

    图中有表示带有“0,1”,这个定时器是可选的。当定时器时间到时,可以调用中断或者返回TRUE给hasElapsed()函数。CyclicExecutive讲调用start()为下一个周期开始计时。

    1.1.2.4 具体任务实现(ConcreteCEThread)

    每个ConcreteCEThread都有自己的run()函数,用于具体的任务实现。

    1.1.3 效果

    如前所述,该模式优点在于简单,一方面很难导致调度程序错误,另一方面对紧急事件响应不足,使得仅使用在内存小的设备。还有缺点是,任务间的通讯会值得考虑,比如一个任务需要另一个任务的数据,那么数据只能保存在全局的内存或共享资源中。我们尽量不要定义太多的全局变量,否则会难以管理维护,和造成内存的浪费。

    1.1.4 实现

    该模式的实现非常简单。在大多数情况下,循环执行可能仅是应用的main()函数中调用。

     

    1.2 静态优先级模式

    大多数的实时操作系统都是静态优先级模式。所以想要使用这个模式直接移植RTOS系统就好了。这里的模式复杂度和完整度是无法比得上RTOS系统的,不过阅读这里也可以使你对RTOS的任务调度有所了解,因为这是基于这个框架的。静态优先级模式能够为任务划分优先级,能够更好响应高优先级时间。

    1.2.1 模式结构

    除了右下角AbstraceStaticThread,SharedResource,ConcreteStaticThread这三个类,其他一般是由RTOS实现。

    1.2.2 角色

    1.2.2.1 抽象线程(AbstraceStaticThread)

    是一个抽象类,提供run()函数给调度器运行。

    1.2.2.2 具体线程(ConcreteStaticThread)

    ConcreteThread作为AbstraceStaticThread具体实现run()函数。

    1.2.2.3 互斥锁(Mutex)

    是一个互斥的信号量类,用来串行访问SharedResource。当一个任务调用了互斥量的lock()函数,其他任务尝试锁定的同一个互斥量时候,会被阻塞,直到互斥量的解锁或超时退出。

    1.2.2.4 队列(PriorityQueue)

    PriorityQueue是根据优先级,对指向StaticTaskControlBlock的指针进行排序,也就是说队列里存储的其实每个线程的排队。一般在RTOS系统里,存在不止一个队列,有就绪队列,阻塞队列等,调度器会从就绪队列取出第一个执行。

    1.2.2.5 资源(SharedResource)

    该资源可能在一个或多个线程里共享,需要保证资源的正常,在下面模式会说明资源共享的问题。

    1.2.2.6 栈(Stack)

    每个AbstraceStaticThread都有一个栈用于返回地址和传递参数。

    1.2.2.7 调度器(StaticPriorityScheduler)

    最简单的法则:总是运行最高优先级的准备线程。RTOS系统里,任务创建,任务切换等都需要经过调度器。任务创建成功后,会把任务按优先级加入到就绪列表中,任务挂起就会加入到挂起列表。系统有个滴答时钟中断或其他能够进行任务切换,查找下一个运行的任务可以有通用方法,就是从就绪列表取。另一种是硬件方法,使用处理器自带的硬件指令来实现,需要硬件本身支持。

    1.2.2.8 程序控制块(StaticTaskControlBlock)

    包含了它相应的AbstraceStaticThread对象的调度信息。有线程的优先级,默认开始地址,目前地址,只要线程还在没被销毁,这个块就会伴随着存在。

    1.2.3 效果

    静态优先级模式能够对事件提供及时响应,可以对CPU大程序优化,避免单线程因等待时占用CPU这种浪费。因RTOS系统的支持,线程间通讯也有很多保证,邮箱,信号量机制,避免了过多的全局变量。

    1.1.4 实现

    最好的方式是直接移植成熟的RTOS系统来实现。使用这种模式,需要对前期开发有个设计,对内存分配,优先级分配等因素,需要在程序开发前有个规划,否则可能会造成后面存在各种问题。复杂度比单线程的高,所以需要你有个深入的理解,才能对RTOS系统运用掌握,但是也不用害怕,RTOS始终还是中小的系统,有时间可以研究源码,RTOS对指针,数据结构的运用非常的成熟高效。

     

    1.3 临界区模式

    临界区模式是任务协调最简单的方式。它直接禁止了任务的切换,在临界区内安全访问之后,再退出临界区。

    1.3.1 模式结构

    模式结构非常简单,在进入临界区后才访问资源。调度程序不参与临界区的开启和结束过程,知识提供服务禁止和重启任务切换。如果调度系统不提供,则临界区能够在硬件级别使用C的asm直接开关中断处理。

    1.3.2 角色

    1.3.2.1 临界区(CRShaaredResource)

    使用这个元素来禁止任务切换,以防止任务同时访问资源。这个例子里,受保护资源是Value属性,相关的服务都必须使用临界区来保护,setValue()和getValue()函数必须独立实现临界区。

    1.3.2.2 任务集合(TaskWithSharedResource)

    这个元素代表所有想要访问共享资源的任务集。这些任务并不知道保护资源的方法,因为它被封装在共享资源内。

    1.3.3 效果

    模式特点就是禁止调度任务的切换,更严格的,禁止所有的中断。注意的是,一旦元素离开了临界区,将重启任务切换,另外使用了临界区,就注定会影响到其他任务的时序,所以尽量保证临界区的时间不要长。

    1.3.4 实现

    绝大多数的RTOS系统直接提供函数,调用即可。

     

    1.4 守卫调用模式

    守卫调用模式提供了锁定的机制串行访问,可以阻止当锁定后来自其他线程的调用资源。在RTOS系统里,直白的说就是信号量。使用这个模式可能会导致优先级导致,或死锁的问题发生。

    1.4.1 模式结构

    在模式下,多个PreemptiveTasks通过他们的函数访问GuardeResource。当一个线程调用一个正在锁定的信号量时,调度服务会把该线程加入到阻塞队列中,等待当那个信号量释放或超时时,解除阻塞。调度服务必须作为临界区实现信号量的lock()功能,以防止可能的竞争条件。

    1.4.2 角色

    1.4.2.1 共享资源(GuardedResource)

    在这个类中使用互斥信号量来互斥访问。在访问资源之前,执行与Semaphore实例关联的lock()函数。如果Semaphore是在非锁定状态,则变为锁定;如果在锁定状态,则Semaphore会调度复位发信号阻塞这个任务。

    1.4.2.2 任务(PreemptiveTask)

    访问共享资源的任务。

    1.4.2.3 互斥信号量(Semaphore)

    它串行访问GuardedResource。lock()函数是用于访问资源之前,release()函数是访问资源后,调用释放信号量。

    1.4.3 效果

    该模式提供及时访问资源,并同时阻止多个能够导致数据损坏和系统错误行为的同时访问。如果资源没有上锁,那么访问资源并不会遭受到延迟。

    1.4.4 实现

    通过使用RTOS提供的信号量函数。一般都会提供创建信号量,摧毁信号量,上锁,解锁的接口。

     

    1.5 队列模式

    队列模式是任务异步通讯常见的实现。它提供了在任务间的通讯方式。发送者将消息队列Cyrus队列中,一段时间过后,接受者从队列取出消息。它也可以实现了串行访问共享资源,把访问消息排队,并且在稍后处理,这避免了共享资源同时访问的问题。

    1.5.1 模式结构

     QUEUE_SIZE声明决定队列能容纳最大的元素数目。必须足够大来处理最差的情况,也不要太大以免内存的浪费。

    1.5.2 角色

    1.5.2.1 消息(Message)

    它可以任何东西,是简单的数据值,或发送消息的详细数据报结构。

    1.5.2.2 消息队列(MessageQueue)

    MessageQueue是QTasks间交换的信息存储。提供了getNextIndex()函数来运行计算下一个有效的索引值。insert()函数在头部位置将Message插入到队列中并更新头索引。remove()函数可以用于删除最旧的消息。iFull(),isEmpty()两个用来检测队列是否已满,是否为空。

    1.5.2.3 互斥信号量(Mutex)

    是互斥信号量,如静态优先级模式中的描述类似。

    1.5.2.4 任务(QTask)

    QTask是MessageQueue的客户,要么调用insert()插入新消息,要么调用remove()访问最早的数据。

    1.5.3 效果

    当数据在任务间传递,队列模式十分好用。互斥量可以确保队列本身不会由于同时访问造成损坏。相比守卫调用模式,队列模式接收数据不是很及时。

    1.5.4 实现

    队列的最简单实现是消息元素数组。有简单的优点,也会有灵活性不足,占用空间固定等缺陷。更多是使用链表的方式来实现队列。MessageQueue还可以添加多个缓冲区,每个优先级一个队列,这样实现优先级策略,或者基于消息优先级,通过插入元素队列中实现。在复杂的系统中,预测最佳队列大小是不可行的,如果使用数组实现队列的方式,会存在超出容量的问题。在这种情况下,可以额外使用一个缓冲队列在作为临时存储。

     

    1.6 汇合模式

    任务必须以不同的方式同步。发生同步可能是共享单一资源,或者等待信号量等造成,这些队列模式和守卫调用模式都能够实现。但是如果同步需要的条件更加复杂呢?汇合模式就是解决这个问题。当所有的任务都满足同步条件时,才能继续运行。

    1.6.1 模式结构

    需要同步的线程至少2个,同时拥有唯一的Rendezvous。

    1.6.2 角色

    1.6.2.1 聚合(Rendezvous)

    用于管理同步。它通过两个方式:reset()函数重置同步标准为初始条件。synchronize()函数,当任务想要同步时调用这个方法。如果不满足标准,则任务阻塞。这个通常可以使用观察者模式或守卫调用模式实现。

    1.6.2.2 计数信号量(Semaphore)

    这个通常是计数信号量,有创建,摧毁,上锁和释放标准锁的接口函数。用于存储当前所有任务满足同步条件的数量。当等于预设值时,同步条件满足。

    1.6.2.3 线程(SynchronizingThread)

    代表使用Rendezvous同步的每个线程。

    1.6.3 效果

    在这个模式中,两个或更多的任务都同时满足某个条件时,才能继续运行或调用回调函数。

    1.6.4 实现

    该模式可以通过前面的观察者模式,或者守卫调用模式实现。如果使用的是观察者模式,则任务必须使用函数的地址注册,当满足同步条件时调用。如果使用的是守卫调用模式,则每个Rendezvous对象拥有唯一的信号量,任务想同步时调用synchronize()函数告知给Rendezvous,当Rendezvous满足同步条件时,释放信号量,并且任务随后根据通常的调度策略全部释放运行。

     

    1.7 同时锁定模式

    首先不考虑软件自身导致的错误,发生死锁需要满足4个条件:

    1. 互斥锁资源。
    2. 当请求其他资源时,一些资源已经锁定。
    3. 当资源锁定是允许抢断。
    4. 存在循环等待条件。

    死锁能够通过打破这4个条件的任意一个避免。使用临界区模式打破的是条件1和条件3。队列模式避免了条件1的发生。

    同时锁定模式是通过破坏条件2达到避免死锁的目的。模式以全或无的形式工作。要么所有需要的资源一次都锁定,要么都没有锁定。简单来说在线程需要某个资源的时候,只有把所有的资源都一起上锁成功,才能成功往下执行,这样就避免了两个线程都在请求对方的资源造成的死锁。

    1.7.1 模式结构

     一般来说,MultimasteredResource是不同资源集合的任意数目的一部分,其中ResourceMaster的单独实例管理一个这样的集合。

    1.7.2 角色

    1.7.2.1 资源管理(MultimateredResource)

    这个元素通过多个ResourceMasters管理,然后他有自己的互斥信号量来避免同时申请锁。使用QueryMutex必须通过tryLock()函数,以便能够通过ResourceMasters决定所有的尝试锁定将会是成功或者失败。

    1.7.2.2 互斥量(QueryMutex)

    这个算数是一个正常的互斥信号量,与之前的不用,它提供了tryLock()函数。这个函数和lock()函数目的是一样的,都是为了上锁,只是tryLock()函数除此之外,如果锁失败,他将会返回一个错误代码,而不是阻塞当前的线程。

    1.7.2.3 客户(ResourceClient)

    这个元素是一个客户,想要一次访问所有资源集合来避免死锁。它直接访问MultimateredResource,直到成功接收到ResourceMaster上的锁。在使用完资源后释放。

    1.7.2.4 控制锁(ResourceMaster)

    ResourceMaster控制整个资源合集的锁。

    1.7.3 效果

    同时锁定模式通过消除必要条件2,通过一次锁定所有需要的资源或一个都不锁防止死锁。但是这样会增加了其他任务执行的延时,而且很可能发生在甚至没有实际资源的冲突下。在资源更多,更广泛时出现这种情况更明显。此外,模式不能解决优先级倒置问题,事实上可能更严重。

    1.7.4 实现

    需要保证tryLock()函数错做之前确保成功锁定MultimasteredResource。

     

    1.8 排序锁定

    排序锁定是另一种确保死锁不会发生的方法,这次是用过防止条件4发生。通过对资源排序,并且需要客户总是按照那个指定的顺序锁定资源,这样就不可能形成循环等待条件。

    1.8.1 模式结构

    1.8.2 角色

    1.8.2.1 锁(Mutex)

    与上面的模式一样,提供两个基本的函数lock()和release()。

    1.8.2.2 资源管理(OrderedResource)

    这个是模式的核心。它有resourceID属性,是一个唯一的与每个资源关联的ID,并且与ResourceList关联。这个类执行的排序锁定规则永远是:如果资源的resourceID大于任意已锁定资源最大的resourceID,则资源仅能被锁定。ResourceClient首先需要调用lockDyadic(),然后添加到资源列表中,在对资源操作完成之后,调用releaseDyadic()函数。书上把这种访问称作为二元的,与二元不一样的一元,差异在一元是在内部完成上锁,使用资源,解锁。而二元是可以保持在锁的状态,等到资源使用完之后在释放。

    1.8.2.3 客户(ResourceClient)

    代表了想要调用OrderedResource服务的元素集合。对于客户,不需要知道关于resourceID本身的任何东西。

    1.8.2.4 资源列表(ResourceList)

    在这个元素里,如果传递的resourceID大于已锁定资源的最大一个,则addLock()返回成功。否则返回失败。

    1.8.2.5 已使用资源(ResourceReference)

    这仅是一个在有序列表中包含的resourceID数组。只是保存一个最大值是不够的,因为很多资源可能在任何时候锁定。

    1.8.3 效果

    模式通过确保所有的客户按相同的顺序锁定资源来消除死锁。这个模式需要在设计时做好分析来规划好资源的排序。例如现在有两个线程,都需要用到资源A,B,C,如果线程1按A,B,C的顺序锁定,线程2按C,B,A的顺序锁定,就有可能发生死锁。因此该模式就是为了让资源都按照规定的序列来锁定。

    1.8.4 实现

    模式的实现需要给每个OrderedResource增加额外的resourceID,并且在ResourceList的逻辑中确保每个OrderedResource的resourceID大于任意当前所的resourceID。还有,已经上锁的resourceID的列表必须维护,当OrderedResource释放时,可以适当地锁定其他。

    ResourceList最常见的实现是一个按照锁定顺序表示的resourceID整形数组。

     

    展开全文
  • 基于此,提到简单嵌入式系统的软件架构,我脑海中立马浮现这样的画面: 看到这张图,不同的人,可能会有不同的感受:有的高手能一眼看破,能马上进行万千补充、引申;有的会心领神会,从而期待后面的内容;而有的,...
  • 软件架构对于系统整体的稳定性和可靠性是非常重要的,一个合适的软件架构不仅结构清晰,并且便于开发。 我相信在嵌入式或单片机软件开发的初期大多数开发者采用的都是简单的前后台顺序执行架构(我就是这样的)。在...
  • 搞了近十年嵌入式嵌入式应用开发,嵌入式在我的工作经历里大部分是应用层的设备功能、设备通信开发。较为复杂有趣的是对结合硬件可定制化部分的研究+软件上的修改实现+结合实际调试演示产品功能。较为费时且全程...
  • 远程教学录播系统得到了广泛的应用,但是不同厂家产品不一定能兼容...在选购的过程中又如何区别PC架构上与嵌入式架构呢?下面跟随捷视飞通小编一起来了解下。PC架构的录播主机也叫做工控式录播主机。这种PC架构录播...
  • 导语内容提要本书首先介绍微型计算机的相关概念及嵌入式系统的应用,接着介绍Cortex M3微处理器架构及开发方法,介绍汇编语言及其程序设计。在开发应用方面,以STM32F103VET6为背景,介绍常见接口的原理及应用。根据...
  • 点击上方“小麦大叔”,选择“置顶/星标公众号”福利干货,第一时间送达前言在嵌入式软件开发,包括单片机开发中,软件架构对于开发人员是一个必须认真考虑的问题。软件架构对于系统整体的稳定性和可靠...
  • 存储系统 寄存器 中央处理器CPU:处理程序指令控制器。 指令寄存器IR:存储当前正在执行的指令 程序计数器PC(指令计数器):存储将要执行的下一条指令的地址 程序状态寄存器PSW:存放条件码标志、控住标志和...
  • 嵌入式系统是一种以应用为中心,以计算机技术为基础,可以适应不同应用对功能、可靠性、成本、体积、功耗等方面的要求,集可配置,可裁减的软、硬件于一体的专用计算机系统。它具有很强的灵活性,主要由嵌入式硬件...
  • 系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录系列文章目录前言一、开发平台二、传感器系统1.无人驾驶车传感器配置2....通讯架构架构1:有M
  • 关注+星标公众号,不错过精彩内容素材来源 |apriorit编排 | strongerHuang以前的嵌入式系统对安全问题相对不那么重视,但随着时间的推移,你会发现很多嵌入式设备都在做各...
  • 中断服务程序中断是嵌入式系统中重要的组成部分,但是在标准C中不包含中断。许多编译开发商在标准C上增加了对中断的支持,提供新的关键字用于标示中断服务程序(ISR),类似于__interrupt、#program interrupt等。当一...
  • 嵌入式是软件设计领域的一个分支,它自身的诸多特点决定了系统架构师的选择,同时它的一些问题又具有相当的通用性,可以推广到其他的领域。 提起嵌入式软件设计,传统的印象是单片机,汇编,高度依赖硬件。传统的...
  • 嵌入式开源RTOS架构

    2021-05-03 22:22:01
    RT-Thread 架构图: RT-Thread开发指南 开源地址 内核层:RT-Thread 内核,是 RT-Thread 的核心部分,包括了内核系统中对象的实现,例如多线程及其调度、信号量、邮箱、消息队列、内存管理、定时器等;libcpu/BSP...
  • 在工作中经过摸索实验,总结出单片机大致应用程序的架构有四种: 1. 简单的前后台顺序执行程序,这类写法是大多数人使用的方法,不需用思考程序的具体架构,直接通过执行顺序编写应用程序即可。 2.状态机 3. 时间...
  • 19.1 嵌入式系统 1. 什么是嵌入式系统? 一种以应用为中心、以计算机技术为基础,可以适应不同应用对功能、可靠性、成本、体积、功耗等方面的要求,集可配置,可裁剪的软硬件于一体的专用计算机系统。 2. 嵌入式...
  • 嵌入式系统的硬件架构嵌入式系统硬件模型结构,此系统主要由微处理器MPU、外围电路,以及外设组成,微处理器为ARM嵌入式处理芯片,如ARM7TMDI系列及ARM9系列微处理器,MPU为整个嵌入式系统硬件的核心,决定了整个...
  • 嵌入式系统开发

    千次阅读 2021-08-12 15:27:07
    嵌入式系统概论 嵌入式系统的特点: 专用性:与具体应用紧密结合,具有很强的专用性 隐蔽性:嵌入式系统是被包装在内部 资源受限:要求小型化、轻型化、低功耗及低成本,因此软硬件资源受到限制 高可靠性:任何误...
  • 嵌入式系统试卷

    2020-12-21 10:06:34
    嵌入式系统试卷一(选择题1.下面那个系统属于嵌入式系统(,)a、“天河一号”计算机系统b、联想t400笔记本计算机c、联想s10上网本d、联想ophone手机2(软硬件协同设计方法与传统设计方法的最大不同之处在于(,)a、软硬件...
  • 在底层代码编写中,初始的框架设计总会面临选择,针对实际的硬件使用环境,大家对于使用的软件框架有很多选择,今天我简单描述一些比较常用的架构,让大家能够理解并选择合适的架构。 总述 1.简单的顺序执行程序...
  • 关注、星标公众号,直达精彩内容来源:嵌入式云IOT技术圈| veryarm1. 前言嵌入式是软件设计领域的一个分支,它自身的诸多特点决定了系统架构师的选择,同时它的一些问题又具有相当的通...
  • 嵌入式系统与物联网的关系

    千次阅读 2021-03-28 11:38:43
    嵌入式系统与物联网的关系一、物联网与嵌入式的基本概念物联网定义定义 1定义 2定义 3定义 4嵌入式定义IEEE 的定义嵌入式与物联网的区别和联系二、从构成模型看物联网与嵌入式三、物联网时代嵌入式系统的华丽转身从...
  • 软件架构,就是软件的结构,包含软件元素...嵌入式系统软件与硬件联系紧密。首先想到要将硬件的驱动程序和功能应用的程序分开,且相对独立,做到高内聚、低耦合。最常用的方法就是模块化设计,就是将驱动程序、...
  • 一、填空题:1、试列举三种主流的嵌入式处理器:( ARM )、( MIPS )、(PowerPC)。2、ARM处理器共有(37)个寄存器,其中包括(31个通用寄存器)和(6个状态寄存器)。3、寄存器R13在ARM指令中(堆栈指针SP )。R14也称(程序...
  • 嵌入式开发中的三种程序构架

    千次阅读 2020-12-30 11:54:18
    关注、星标公众号,直达精彩内容0、前言在嵌入式软件开发,包括单片机开发中,软件架构对于开发人员是一个必须认真考虑的问题。软件架构对于系统整体的稳定性和可靠性是非常重要的,一个合适的软件架...
  • 1.与个人计算机(PC)相比,嵌入式系统具有许多不同的特点。下面不属于嵌入式系统特点的是( )。 A) 嵌入式系统与具体应用紧密结合,具有很强的专用性 B) 嵌入式系统通常包含在非计算机设备(系统)中,具有隐蔽性 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 99,072
精华内容 39,628
关键字:

嵌入式系统架构