嵌入式系统是将一个电子系统嵌入到一个物理系统中,连接起物理系统和电子信息系统,从而实现信息系统对物理系统观察和控制。
一个嵌入式系统的设计,可以从总则上分三大步骤:建模 –> 设计 -> 分析。这里所说的设计,是理论的设计,图纸的设计,而不涉及到系统的实施。
Ø 建模:根据系统的物理特性、行为逻辑、业务逻辑等,建立系统的数学据模型。对于不同类型的系统,有不同的描述方式,比如对于人人机交互可以用状态机模型,对于一个控制系统可以用状态空间方程或者传递函数,对于一个交易系统可以用流程图。对于一个大系统,也可以分解成多个子系统,子系统建立不同的数学模型,这个大系统是不同数学模型的组合。
Ø 设计:根据系统的数学模型,创建实现系统模型的结构,指定系统如何实现功能,这包括硬件系统、软件系统的设计、软硬件结合的设计。
Ø 分析:说明设计的系统为什么能完成它的设计目标,这个设计目标包括功能、性能等指标。
对于一个系统,大致可以分为四大功能组件:输入,处理,控制,输出。
而软件运行的载体,就是硬件。比如信号的输入就是各种传感器,输出就是各种执行部分,处理、控制算法,则需要运行在MCU、CPU、FPGA上,运行的数据需要存储在RAM、Flash上。
对于PC机、手机、服务器等编程,已经有多种实践模型,基础的如面向对象思想,基于组件的思想,面向接口编程,函数式编程。在应用层有MVC,23种设计模式,领域驱动等。但在嵌入式编程上,由于受到硬件资源和实时性要求的限制,过于重的设计实践和编程语言,在嵌入式系统上根本无法实现。结合自己的实际编程经验和自己的思考,建立起自己的嵌入式编程模型。
嵌入式软件一般由芯片驱动、板级驱动、操作系统、文件系统、通讯协议、UI等组成,其中包括信号处理代码、控制算法代码,也是嵌入式软件的一部分,对于这些功能组件,如何将它们按照一个有效方式,组合起来以实现系统功能要求,这种组合方式,就是嵌入式编程模式。
系统的运行过程,是个动态连续的过程,相同的连续过程,可以认为系统处于一个状态,状态与状态之间,通过事件触发转移。系统中的相关元素集合,可以抽象为对象,对象是变量和方法的集合。
Ø 对象描述
对象是软件的基本操作单元,对象由变量进行描述,对象的方法是对对象变量的操作。
Ø 状态空间
状态空间是系统所有状态的合集,各状态之间可以相互转换,某状态可以是另一状态的子状态。各状态间的转移是通过事件触发的。
Ø 事件驱动
通过事件,来实现任务间的同步。一个事件,可能会触发一个动作,也可能触发一次状态转移。
以最简单的交通灯控制为例
对象描述:
typedef struct { Color_t color; //交通灯颜色 int hold_time; //交通灯的保持时间} Ligght_t;
typedef struct { Color_t (* Turn)(Color_t color)} Light_Op_t;
交通灯控制系统的状态空间
typedef enum { STOP, WAIT, THROUGH}
三个状态对应的led对象为
stop -- red -- 15秒;wait -- yellow -- 3秒;through -- green -- 45秒。
事件触发:
事件由于定时器产生,定时器在15秒,3秒,45秒之间循环,每次计时完成,则发出一个信号,同时进行另一个计时。主任务接收到信号后,进行状态切换,同时输出根据状态,控制对应的交通灯的颜色。
伪代码:main(){ while(1){ switch(state){ case STOP: Light.Turn(red); state ++; break; case STOP_HOLD: Wait_TimeOUt(15); //15秒后,状态切换 state ++; break; case WAIT: Light.Turn(yellow); state ++; break; case WAIT_HOLD: Wait_TimeOUt(3); //3秒后,状态切换 state ++; break; case THROUGH: Light.Turn(green); state ++; break; case THROUGH_HOLD: Wait_TimeOUt(45); //45秒后,状态切换 state = STOP; break; } } }
对于同一个系统,也可以从不同的角度定义状态空间和状态转移过程,但是他们在逻辑上是等效的。
在一些系统中,如protothread、STC51的任务调度系统,均是采用类似的方案。