1.1 嵌入式系统有何特殊之处
实时系统,” 实时” 并不意味着很快。
1.1.1 嵌入式设计的约束
减少使用硬件的需求
性能:吞吐量
可靠性:衡量系统正确完成功能的可能性
健壮性:违反先决条件下仍能提供相应服务的能力
安全性:系统的风险水平,可能会造成那些意外或者损失
1.1.2 嵌入式工具
交叉编译器:在主机上运行,开发的可执行代码在不同环境中运行
连接器
载入程序
调试器工具集
以上集成到 IDE 中
1.1.3 OS,RTOS,还是没有操作系统
1.1.4 嵌入式中间件
中间件是一种使用某种方法将软件组件连接的软件
1.1.5 与硬件协同开发
1.1.6 调试与测试
1.2 面向对象还是结构化
结构化编程:一方面,函数和过程形成基本的编程基础;另一方面是数据结构的概念。
面向对象编程:基于正交范式。面向对象编程仅有基于类概念的一个分类标准。类将数据(存储为属性)和在数据上的操作的过程(称为操作)组合到一起。对象是类的实例。
像 C 一样的结构化语言能够完成面向对象的编程么?可以。
如何实现?接着往下看。
1.2.1 类
类仅是一个 C 语言的结构体,但特殊之处是包含两种不同的特性:数据(属性)和行为(操作)。
最简单的实现类的方法是简单使用文件作为封装边界;公共变量和方法在头文件中课件,而在实现文件中包含方法体、私有变量和方法。
一个更为灵活的方式是使用文件内的结构体来表示类。类的操作用位于相同文件内的结构体的函数定义。
这允许我们拥有同一个类的多个实例,并且保证成员函数在正确的数据拷贝上工作。此外,类可以赋予 “特殊” 的操作。构造函数创建类的一个对象。初始化程序(可选择)初始化对象和它的属性。析构函数销毁类并释放已使用的内存。
代码 1-1 sensor.h
#ifndef SENSOR_H#define SENDOR_Htypedef struct sensor{int filterFrequency;int updateFrequency;int value;char whatKindOfInterface;}SENSOR;int Sensor_getFilterFrequency(const SENSOR* const me);void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency);int Sensor_getUpdateFrequency(const SENSOR* const me);void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency);int Sensor_getValue(const SENSOR* const me);//int acquireValue(SENSOR* me);SENSOR* Sensor_create(void);void Sensor_Destroy(Sensor* const me);#endif
代码 1-2 sensor.c
#include "sensor.h"void Sensor_Init(SENSOR* const me){}void Sensor_Cleanup(SENSOR* const me){}int Sensor_getFilterFrequency(const SENSOR* const me){return me->filterFrequency;}void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency){me->filterFrequency=p_filterFrequency;}int Sensor_getUpdateFrequency(const SENSOR* const me){return me->updateFrequency;}void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency){me->updateFrequency=p_updateFrequency;}int Sensor_getValue(const SENSOR* const me){return me->value;}/*int acquireValue(SENSOR* me){int *r, *w;int j;switch(me->whatKindOfInterface){case MEMPRYMAPPED:w=(int*)WRITEADDR; //Address to write to sensor*w=WRITEMASK; //sensor command to force a readfor (j = 0; j < count; j++){// wait loop}r=(int*)READADDR; //Address to returned valueme->value=r;break;case PORTMAPPED:me->value=inp(SENSORPORT);//inp() is a compliler-specific port functionbreak;}return me->value;}*/SENSOR* Sensor_create(void){SENSOR* me=(SENSOR*)malloc(sizeof(SENSOR));if (me != NULL){Sensor_Init(me);}return me;}void Sensor_Destroy(SENSOR* const me){if (me != NULL){Sensor_Cleanup(me);}free(me);}
1.2.2 对象
对象是类的实例。
代码 1-3 main.c
#include "sensor.h"#include <stdlib.h>#include <stdio.h>int main(int argc, char const *argv[]){SENSOR *p_sensor0, *p_sensor1;p_sensor0=Sensor_create();p_sensor1=Sensor_create();p_sensor0->value=99;p_sensor1->value=-1;printf("The current value from sensor0 is %d\n",Sensor_getValue(p_sensor0));printf("The current value from sensor1 is %d\n",Sensor_getValue(p_sensor1));Sensor_Destroy(p_sensor0);Sensor_Destroy(p_sensor1);return 0;}
1.2.3 多态和虚拟函数
多态允许相同函数名在一种上下文中完成一种功能,在另一种上下文中完成另一种功能。
在 C 语言中,标准的做法是使用选择语句 if 或者 switch。当出现多种上下文时,不方便;此外在最开始编写时就要知道所有可能的上下文,或者提供修改功能。
代码修改 1-1 sensor.h
#ifndef SENSOR_H#define SENDOR_Htypedef struct sensor{int filterFrequency;int updateFrequency;int value;char whatKindOfInterface;}SENSOR;int Sensor_getFilterFrequency(const SENSOR* const me);void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency);int Sensor_getUpdateFrequency(const SENSOR* const me);void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency);//int Sensor_getValue(const SENSOR* const me);int acquireValue(SENSOR* me);SENSOR* Sensor_create(void);void Sensor_Destroy(Sensor* const me);#endif
代码修改 1-2 sensor.c
#include "sensor.h"void Sensor_Init(SENSOR* const me){}void Sensor_Cleanup(SENSOR* const me){}int Sensor_getFilterFrequency(const SENSOR* const me){return me->filterFrequency;}void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency){me->filterFrequency=p_filterFrequency;}int Sensor_getUpdateFrequency(const SENSOR* const me){return me->updateFrequency;}void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency){me->updateFrequency=p_updateFrequency;}/*int Sensor_getValue(const SENSOR* const me){return me->value;}*/int acquireValue(SENSOR* me){int *r, *w;int j;switch(me->whatKindOfInterface){case MEMPRYMAPPED:w=(int*)WRITEADDR; //Address to write to sensor*w=WRITEMASK; //sensor command to force a readfor (j = 0; j < count; j++){/* wait loop */}r=(int*)READADDR; //Address to returned valueme->value=r;break;case PORTMAPPED:me->value=inp(SENSORPORT);//inp() is a compliler-specific port functionbreak;}return me->value;}SENSOR* Sensor_create(void){SENSOR* me=(SENSOR*)malloc(sizeof(SENSOR));if (me != NULL){Sensor_Init(me);}return me;}void Sensor_Destroy(SENSOR* const me){if (me != NULL){Sensor_Cleanup(me);}free(me);}
1.2.4 子类化
子类化(也被称为泛化或者继承),能够重用设计或代码。
代码 1-4 queue.h
#ifndef QUEUE_H#define QUEUE_H#define QUEUE_SIZE 10typedef struct queue{int buffer[QUEUE_SIZE];int head;int size;int tail;int (*isFull)(struct queue* const me);int (*isEmpty)(struct queue* const me);int (*getSize)(struct queue* const me);void (*insert)(struct queue* const me, int k);int (*remove)(struct queue* const me);}QUEUE;void Queue_Init(QUEUE* me, int (*isFullFunction)(QUEUE* const me),int (*isEmptyFunction)(QUEUE* const me),int (*getSizeFunction)(QUEUE* const me),void (*insertFunction)(QUEUE* const me, int k),int (*removeFunction)(QUEUE* const me));void Queue_Cleanup(QUEUE* const me);int Queue_isFull(QUEUE* const me);int Queue_isEmpty(QUEUE* const me);int Queue_getSize(QUEUE* const me);void Queue_insert(QUEUE* const me, int k);int Queue_remove(QUEUE* const me);QUEUE* Queue_Create(void);void Queue_Destroy(QUEUE* const me);#endif
代码 1-5 queue.c
#include <stdio.h>#include <stdlib.h>#include "queue.h"void Queue_Init(QUEUE* me, int (*isFullFunction)(QUEUE* const me),int (*isEmptyFunction)(QUEUE* const me),int (*getSizeFunction)(QUEUE* const me),void (*insertFunction)(QUEUE* const me, int k),int (*removeFunction)(QUEUE* const me)){me->head=0;me->tail=0;me->size=0;me->isFull=isFullFunction;me->isEmpty=isEmptyFunction;me->getSize=getSizeFunction;me->insert=insertFunction;me->remove=removeFunction;}void Queue_Cleanup(QUEUE* const me){}int Queue_isFull(QUEUE* const me){return (me->head+1)%QUEUE_SIZE==me->tail;}int Queue_isEmpty(QUEUE* const me){return me->head==me->tail;}int Queue_getSize(QUEUE* const me){return me->size;}void Queue_insert(QUEUE* const me, int k){if (!me->isFull(me)){me->buffer[me->head]=k;me->head=(me->head+1)%QUEUE_SIZE;++me->size;}}int Queue_remove(QUEUE* const me){int value=-9999;if(!me->isEmpty(me)){value=me->buffer[me->tail];me->tail=(me->tail+1)%QUEUE_SIZE;--me->size;}return value;}QUEUE* Queue_Create(void){QUEUE* me=(QUEUE*)malloc(sizeof(QUEUE));if (me!=NULL){Queue_Init(me,Queue_isFull,Queue_isEmpty,Queue_getSize,Queue_insert,Queue_remove);}return me;}void Queue_Destroy(QUEUE* const me){if (me!=NULL){Queue_Cleanup(me);}free(me);}
代码 1-6 test_queue.c
#include "queue.h"#include <stdlib.h>#include <stdio.h>int main(void){int j,k,h,t;QUEUE* myQ;myQ=Queue_Create();k=1000;for (j = 0; j<QUEUE_SIZE; j++){h=myQ->head;myQ->insert(myQ, k);printf("inserting %d at position %d, size=%d\n", k--,h,myQ->getSize(myQ));}printf("Iserted %d elements\n", myQ->getSize(myQ));for (j = 0; j<QUEUE_SIZE; j++){t=myQ->tail;k=myQ->remove(myQ);printf("Removing %d at position %d, size=%d\n", k, t, myQ->getSize(myQ));}printf("Last item removed = %d\n", k);printf("Current queue size %d\n", myQ->getSize(myQ));puts("Queue test program");return 0;}
代码 1-7 cachedqueue.h
//cached queue means the memory does not have enough space to store the whole queue//so we divide the queue into two sides://one store in memory//another store in disk#ifndef CACHEDQUEUE_H#define CACHEDQUEUE_H#include "queue.h"typedef struct cachedqueue{QUEUE* queue; //base classchar filename[80]; //new attributesint numberElementsOnDisk;QUEUE* outputQueue; //aggregation in subclass//Inherited virtual functionsint (*isFull)(struct cachedqueue* const me);int (*isEmpty)(struct cachedqueue* const me);int (*getSize)(struct cachedqueue* const me);void (*insert)(struct cachedqueue* const me, int k);int (*remove)(struct cachedqueue* const me);//new virtual functionsvoid (*flush)(struct cachedqueue* const me);void (*load)(struct cachedqueue* const me);}CACHEDQUEUE;void CachedQueue_Init(CACHEDQUEUE* const me, char* filename,int (*isFullFunction)(CACHEDQUEUE* const me),int (*isEmptyFunction)(CACHEDQUEUE* const me),int (*getSizeFunction)(CACHEDQUEUE* const me),void (*insertFunction)(CACHEDQUEUE* const me),int (*removeFunction)(CACHEDQUEUE* const me),void (*flushFunction)(CACHEDQUEUE* const me),void (*loadFunction)(CACHEDQUEUE* const me));void CachedQueue_Cleanup(CACHEDQUEUE* const me);int CachedQueue_isFull(CACHEDQUEUE* const me);int Cachedqueue_isEmpty(CACHEDQUEUE* const me);int Cachedqueue_getSize(CACHEDQUEUE* const me);void Cachedqueue_insert(CACHEDQUEUE* const me, int k);int CachedQueue_remove(CACHEDQUEUE* const me);void Cachedqueue_flush(CACHEDQUEUE* const me);void Cachedqueue_load(CACHEDQUEUE* const me);CACHEDQUEUE* CachedQueue_Create(void);void CachedQueue_Destroy(CACHEDQUEUE* const me);#endif
代码 1-8 cachedqueue.c
#include <stdio.h>#include <stdlib.h>#include <string.h>#include "cachedqueue.h"void CachedQueue_Init(CACHEDQUEUE* const me, char* filename,int (*isFullFunction)(CACHEDQUEUE* const me),int (*isEmptyFunction)(CACHEDQUEUE* const me),int (*getSizeFunction)(CACHEDQUEUE* const me),void (*insertFunction)(CACHEDQUEUE* const me),int (*removeFunction)(CACHEDQUEUE* const me),void (*flushFunction)(CACHEDQUEUE* const me),void (*loadFunction)(CACHEDQUEUE* const me)){me->queue=Queue_Create();me->numberElementsOnDisk=0;strcpy(me->filename,filename);me->outputQueue=Queue_Create();me->isFull=isFullFunction;me->isEmpty=isEmptyFunction;me->getSize=getSizeFunction;me->insert=insertFunction;me->remove=removeFunction;me->flush=flushFunction;me->load=loadFunction;}void CachedQueue_Cleanup(CACHEDQUEUE* const me){Queue_Cleanup(me->queue);}int CachedQueue_isFull(CACHEDQUEUE* const me){return me->queue->isFull(me->queue) &&me->outputQueue->isFull(me->outputQueue);}int CachedQueue_isEmpty(CACHEDQUEUE* const me){return me->queue->isEmpty(me->queue) &&me->outputQueue->isEmpty(me->outputQueue) &&(me->numberElementsOnDisk==0);}int CachedQueue_getSize(CACHEDQUEUE* const me){return me->queue->getSize(me->queue)+me->outputQueue->getSize(me->outputQueue)+me->numberElementsOnDisk;}void CachedQueue_insert(CACHEDQUEUE* const me,int k){if (me->queue->isFull(me->queue)){me->flush(me);}me->queue->insert(me->queue,k);}int CachedQueue_remove(CACHEDQUEUE* const me){if (!me->outputQueue->isEmpty(me->outputQueue)){return me->outputQueue->remove(me->outputQueue);}else if (me->numberElementsOnDisk>0){me->load(me);return me->queue->remove(me->remove);}else{return me->queue->remove(me->remove);}}void CachedQueue_flush(CACHEDQUEUE* const me){//while not queue->isEmpty()// queue->remove();// write date to disk// numberElementsOnDisk++//end while}void CachedQueue_load(CACHEDQUEUE* const me){//while (!outputQueue->isFull()&&(numberElementsOnDisk>0))// read from start of file// numberElementsOnDisk--;// outputQueue->insert();//end while}CACHEDQUEUE* CachedQueue_Create(CACHEDQUEUE* const me){CACHEDQUEUE* me=(CACHEDQUEUE*)malloc(sizeof(CACHEDQUEUE));if(me!=NULL){CachedQueue_Init(me,"C:\\queuebuffer.dat",CachedQueue_isFull,CachedQueue_isEmpty,CachedQueue_getSize,CachedQueue_insert,CachedQueue_remove,CachedQueue_flush,CachedQueue_load);}return me;}void CachedQueue_Destroy(CACHEDQUEUE* const me){if(me!=NULL){CachedQueue_Cleanup(me);}free(me);}
1.2.5 有限状态机
有限状态机(Finite State Machine,FSM)
代码 1-9 SecuritySupervisor.c
static eventStatus dispatchEvent(short id){eventStatus res=eventNotConsumed;switch (activeState){case SecuritySupervisor_Idle:{if (id==NULL_id){if(retries>=3){activeState=SecuritySupervisor_ErrorState;displayMSg("ERROR: Max retries Exceeded");res=eventConsumed;}else{++retries;activeState=SecuritySupervisor_Accepting;res=eventConsumed;}}}break;case SecuritySupervisor_Accepting:{if (id==keypress_SequritySupervisor_Event_id){if (isCANCEL(params->keys)){retries=0;displayMSg("Cancelled");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}else{if (isDigit(params->keys)){addKey(params->keys);activeState=SecuritySupervisor_Accepting;res=eventConsumed;}else{if(isEnter(params->keys)){activeState=SecuritySupervisor_CheckingLength;res=eventConsumed;}}}}}break;case SecuritySupervisor_CheckingLength:{if (id==NULL_id){if(strlen(pin)==4){activeState=SecuritySupervisor_ValidatingPIN;res=eventConsumed;}else{displayMSg("ERROR:PIN wrong length");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}}}break;case SecuritySupervisor_ValidatingPIN:{if (id==NULL_id){if (isValid(pin)){unlockDoor();displayMSg("Door unlocked");activeState=SecuritySupervisor_SecurityOpen;res=eventConsumed;}else{displayMSg("ERROR: Invalid PIN");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}}}break;case SecuritySupervisor_SecurityOpen:{if (id==keypress_SequritySupervisor_Event_id){if (isRESET(params->keys)){lockDoor();displayMSg("Door locked");activeState=SecuritySupervisor_Idle;strcpy(pin,"");res=eventConsumed;}}}break;default:break;}return res;}
1.3 小结
结构化方法将软件组织成两个并行分类,一个是数据,另一个是行为。面向对象的方法将两者结合,当低耦合时,为固有紧密耦合的元素和内容的封装提高内聚力。C 不是面向对象语言,可以用于开发基于对象或面向对象的嵌入式系统。
