C嵌入式编程设计模式

《C嵌入式编程设计模式》
Bruce Powel Douglass著
刘旭东译

C嵌入式编程设计模式

标签: 读书笔记 嵌入式开发

  • C嵌入式编程设计模式
    • 1 嵌入式系统有何特殊之处
      • 11 嵌入式设计的约束
      • 12 嵌入式工具
      • 13 OSRTOS还是没有操作系统
      • 14 嵌入式中间件
      • 15 与硬件协同开发
      • 16 调试与测试
    • 2 面向对象还是结构化
      • 21 类
      • 22 对象
      • 23 多态和虚拟函数
      • 24 子类化
      • 25 有限状态机
    • 3 小结

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_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.2.2 对象

对象是类的实例。

代码1-3 main.c

#include "sensor.h"
#include 
#include 

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_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.2.4 子类化

子类化(也被称为泛化或者继承),能够重用设计或代码。

代码 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 
#include 
#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 
#include 

int main(void)
{
    int j,k,h,t;

    QUEUE* myQ;
    myQ=Queue_Create();
    k=1000;

    for (j = 0; jhead;
        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; jtail;
        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 
#include 
#include 
#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不是面向对象语言,可以用于开发基于对象或面向对象的嵌入式系统。

你可能感兴趣的:(嵌入式开发,读书笔记)