《C嵌入式编程设计模式》 Bruce Powel Douglass著 刘旭东译
标签: 读书笔记 嵌入式开发
C嵌入式编程设计模式 1 嵌入式系统有何特殊之处 11 嵌入式设计的约束12 嵌入式工具13 OSRTOS还是没有操作系统14 嵌入式中间件15 与硬件协同开发16 调试与测试 2 面向对象还是结构化 21 类22 对象23 多态和虚拟函数24 子类化25 有限状态机 3 小结实时系统,”实时”并不意味着很快。
减少使用硬件的需求 性能:吞吐量 可靠性:衡量系统正确完成功能的可能性 健壮性:违反先决条件下仍能提供相应服务的能力 安全性:系统的风险水平,可能会造成那些意外或者损失
交叉编译器:在主机上运行,开发的可执行代码在不同环境中运行 连接器 载入程序 调试器工具集 以上集成到IDE中
中间件是一种使用某种方法将软件组件连接的软件
结构化编程:一方面,函数和过程形成基本的编程基础;另一方面是数据结构的概念。 面向对象编程:基于正交范式。面向对象编程仅有基于类概念的一个分类标准。类将数据(存储为属性)和在数据上的操作的过程(称为操作)组合到一起。对象是类的实例。 像C一样的结构化语言能够完成面向对象的编程么?可以。 如何实现?接着往下看。
类仅是一个C语言的结构体,但特殊之处是包含两种不同的特性:数据(属性)和行为(操作)。 最简单的实现类的方法是简单使用文件作为封装边界;公共变量和方法在头文件中课件,而在实现文件中包含方法体、私有变量和方法。 一个更为灵活的方式是使用文件内的结构体来表示类。类的操作用位于相同文件内的结构体的函数定义。 这允许我们拥有同一个类的多个实例,并且保证成员函数在正确的数据拷贝上工作。此外,类可以赋予“特殊”的操作。构造函数创建类的一个对象。初始化程序(可选择)初始化对象和它的属性。析构函数销毁类并释放已使用的内存。
代码1-1 sensor.h
#ifndef SENSOR_H #define SENDOR_H typedef 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 read for (j = 0; j < count; j++) { // wait loop } r=(int*)READADDR; //Address to returned value me->value=r; break; case PORTMAPPED: me->value=inp(SENSORPORT); //inp() is a compliler-specific port function break; } 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-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; }多态允许相同函数名在一种上下文中完成一种功能,在另一种上下文中完成另一种功能。 在C语言中,标准的做法是使用选择语句if或者switch。当出现多种上下文时,不方便;此外在最开始编写时就要知道所有可能的上下文,或者提供修改功能。
代码修改 1-1 sensor.h
#ifndef SENSOR_H #define SENDOR_H typedef 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 read for (j = 0; j < count; j++) { /* wait loop */ } r=(int*)READADDR; //Address to returned value me->value=r; break; case PORTMAPPED: me->value=inp(SENSORPORT); //inp() is a compliler-specific port function break; } 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-4 queue.h
#ifndef QUEUE_H #define QUEUE_H #define QUEUE_SIZE 10 typedef 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 class char filename[80]; //new attributes int numberElementsOnDisk; QUEUE* outputQueue; //aggregation in subclass //Inherited virtual functions int (*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 functions void (*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); }有限状态机(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; }结构化方法将软件组织成两个并行分类,一个是数据,另一个是行为。面向对象的方法将两者结合,当低耦合时,为固有紧密耦合的元素和内容的封装提高内聚力。C不是面向对象语言,可以用于开发基于对象或面向对象的嵌入式系统。
