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

  1. #ifndef SENSOR_H
  2. #define SENDOR_H
  3. typedef struct sensor
  4. {
  5. int filterFrequency;
  6. int updateFrequency;
  7. int value;
  8. char whatKindOfInterface;
  9. }SENSOR;
  10. int Sensor_getFilterFrequency(const SENSOR* const me);
  11. void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency);
  12. int Sensor_getUpdateFrequency(const SENSOR* const me);
  13. void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency);
  14. int Sensor_getValue(const SENSOR* const me);
  15. //int acquireValue(SENSOR* me);
  16. SENSOR* Sensor_create(void);
  17. void Sensor_Destroy(Sensor* const me);
  18. #endif

代码 1-2 sensor.c

  1. #include "sensor.h"
  2. void Sensor_Init(SENSOR* const me){
  3. }
  4. void Sensor_Cleanup(SENSOR* const me){
  5. }
  6. int Sensor_getFilterFrequency(const SENSOR* const me){
  7. return me->filterFrequency;
  8. }
  9. void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency){
  10. me->filterFrequency=p_filterFrequency;
  11. }
  12. int Sensor_getUpdateFrequency(const SENSOR* const me){
  13. return me->updateFrequency;
  14. }
  15. void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency){
  16. me->updateFrequency=p_updateFrequency;
  17. }
  18. int Sensor_getValue(const SENSOR* const me){
  19. return me->value;
  20. }
  21. /*
  22. int acquireValue(SENSOR* me){
  23. int *r, *w;
  24. int j;
  25. switch(me->whatKindOfInterface)
  26. {
  27. case MEMPRYMAPPED:
  28. w=(int*)WRITEADDR; //Address to write to sensor
  29. *w=WRITEMASK; //sensor command to force a read
  30. for (j = 0; j < count; j++)
  31. {
  32. // wait loop
  33. }
  34. r=(int*)READADDR; //Address to returned value
  35. me->value=r;
  36. break;
  37. case PORTMAPPED:
  38. me->value=inp(SENSORPORT);
  39. //inp() is a compliler-specific port function
  40. break;
  41. }
  42. return me->value;
  43. }
  44. */
  45. SENSOR* Sensor_create(void){
  46. SENSOR* me=(SENSOR*)malloc(sizeof(SENSOR));
  47. if (me != NULL)
  48. {
  49. Sensor_Init(me);
  50. }
  51. return me;
  52. }
  53. void Sensor_Destroy(SENSOR* const me){
  54. if (me != NULL)
  55. {
  56. Sensor_Cleanup(me);
  57. }
  58. free(me);
  59. }

1.2.2 对象

对象是类的实例。

代码 1-3 main.c

  1. #include "sensor.h"
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. int main(int argc, char const *argv[])
  5. {
  6. SENSOR *p_sensor0, *p_sensor1;
  7. p_sensor0=Sensor_create();
  8. p_sensor1=Sensor_create();
  9. p_sensor0->value=99;
  10. p_sensor1->value=-1;
  11. printf("The current value from sensor0 is %d\n",
  12. Sensor_getValue(p_sensor0));
  13. printf("The current value from sensor1 is %d\n",
  14. Sensor_getValue(p_sensor1));
  15. Sensor_Destroy(p_sensor0);
  16. Sensor_Destroy(p_sensor1);
  17. return 0;
  18. }

1.2.3 多态和虚拟函数

多态允许相同函数名在一种上下文中完成一种功能,在另一种上下文中完成另一种功能。
在 C 语言中,标准的做法是使用选择语句 if 或者 switch。当出现多种上下文时,不方便;此外在最开始编写时就要知道所有可能的上下文,或者提供修改功能。

代码修改 1-1 sensor.h

  1. #ifndef SENSOR_H
  2. #define SENDOR_H
  3. typedef struct sensor
  4. {
  5. int filterFrequency;
  6. int updateFrequency;
  7. int value;
  8. char whatKindOfInterface;
  9. }SENSOR;
  10. int Sensor_getFilterFrequency(const SENSOR* const me);
  11. void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency);
  12. int Sensor_getUpdateFrequency(const SENSOR* const me);
  13. void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency);
  14. //int Sensor_getValue(const SENSOR* const me);
  15. int acquireValue(SENSOR* me);
  16. SENSOR* Sensor_create(void);
  17. void Sensor_Destroy(Sensor* const me);
  18. #endif

代码修改 1-2 sensor.c

  1. #include "sensor.h"
  2. void Sensor_Init(SENSOR* const me){
  3. }
  4. void Sensor_Cleanup(SENSOR* const me){
  5. }
  6. int Sensor_getFilterFrequency(const SENSOR* const me){
  7. return me->filterFrequency;
  8. }
  9. void Sensor_setFilterFrequency(SENSOR* const me, int p_filterFrequency){
  10. me->filterFrequency=p_filterFrequency;
  11. }
  12. int Sensor_getUpdateFrequency(const SENSOR* const me){
  13. return me->updateFrequency;
  14. }
  15. void Sensor_setUpdateFrequency(SENSOR* const me, int p_updateFrequency){
  16. me->updateFrequency=p_updateFrequency;
  17. }
  18. /*
  19. int Sensor_getValue(const SENSOR* const me){
  20. return me->value;
  21. }
  22. */
  23. int acquireValue(SENSOR* me){
  24. int *r, *w;
  25. int j;
  26. switch(me->whatKindOfInterface)
  27. {
  28. case MEMPRYMAPPED:
  29. w=(int*)WRITEADDR; //Address to write to sensor
  30. *w=WRITEMASK; //sensor command to force a read
  31. for (j = 0; j < count; j++)
  32. {
  33. /* wait loop */
  34. }
  35. r=(int*)READADDR; //Address to returned value
  36. me->value=r;
  37. break;
  38. case PORTMAPPED:
  39. me->value=inp(SENSORPORT);
  40. //inp() is a compliler-specific port function
  41. break;
  42. }
  43. return me->value;
  44. }
  45. SENSOR* Sensor_create(void){
  46. SENSOR* me=(SENSOR*)malloc(sizeof(SENSOR));
  47. if (me != NULL)
  48. {
  49. Sensor_Init(me);
  50. }
  51. return me;
  52. }
  53. void Sensor_Destroy(SENSOR* const me){
  54. if (me != NULL)
  55. {
  56. Sensor_Cleanup(me);
  57. }
  58. free(me);
  59. }

1.2.4 子类化

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

代码 1-4 queue.h

  1. #ifndef QUEUE_H
  2. #define QUEUE_H
  3. #define QUEUE_SIZE 10
  4. typedef struct queue
  5. {
  6. int buffer[QUEUE_SIZE];
  7. int head;
  8. int size;
  9. int tail;
  10. int (*isFull)(struct queue* const me);
  11. int (*isEmpty)(struct queue* const me);
  12. int (*getSize)(struct queue* const me);
  13. void (*insert)(struct queue* const me, int k);
  14. int (*remove)(struct queue* const me);
  15. }QUEUE;
  16. void Queue_Init(QUEUE* me, int (*isFullFunction)(QUEUE* const me),
  17. int (*isEmptyFunction)(QUEUE* const me),
  18. int (*getSizeFunction)(QUEUE* const me),
  19. void (*insertFunction)(QUEUE* const me, int k),
  20. int (*removeFunction)(QUEUE* const me));
  21. void Queue_Cleanup(QUEUE* const me);
  22. int Queue_isFull(QUEUE* const me);
  23. int Queue_isEmpty(QUEUE* const me);
  24. int Queue_getSize(QUEUE* const me);
  25. void Queue_insert(QUEUE* const me, int k);
  26. int Queue_remove(QUEUE* const me);
  27. QUEUE* Queue_Create(void);
  28. void Queue_Destroy(QUEUE* const me);
  29. #endif

代码 1-5 queue.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include "queue.h"
  4. void Queue_Init(QUEUE* me, int (*isFullFunction)(QUEUE* const me),
  5. int (*isEmptyFunction)(QUEUE* const me),
  6. int (*getSizeFunction)(QUEUE* const me),
  7. void (*insertFunction)(QUEUE* const me, int k),
  8. int (*removeFunction)(QUEUE* const me)){
  9. me->head=0;
  10. me->tail=0;
  11. me->size=0;
  12. me->isFull=isFullFunction;
  13. me->isEmpty=isEmptyFunction;
  14. me->getSize=getSizeFunction;
  15. me->insert=insertFunction;
  16. me->remove=removeFunction;
  17. }
  18. void Queue_Cleanup(QUEUE* const me){
  19. }
  20. int Queue_isFull(QUEUE* const me){
  21. return (me->head+1)%QUEUE_SIZE==me->tail;
  22. }
  23. int Queue_isEmpty(QUEUE* const me){
  24. return me->head==me->tail;
  25. }
  26. int Queue_getSize(QUEUE* const me){
  27. return me->size;
  28. }
  29. void Queue_insert(QUEUE* const me, int k){
  30. if (!me->isFull(me))
  31. {
  32. me->buffer[me->head]=k;
  33. me->head=(me->head+1)%QUEUE_SIZE;
  34. ++me->size;
  35. }
  36. }
  37. int Queue_remove(QUEUE* const me){
  38. int value=-9999;
  39. if(!me->isEmpty(me))
  40. {
  41. value=me->buffer[me->tail];
  42. me->tail=(me->tail+1)%QUEUE_SIZE;
  43. --me->size;
  44. }
  45. return value;
  46. }
  47. QUEUE* Queue_Create(void){
  48. QUEUE* me=(QUEUE*)malloc(sizeof(QUEUE));
  49. if (me!=NULL)
  50. {
  51. Queue_Init(me,Queue_isFull,Queue_isEmpty,Queue_getSize,
  52. Queue_insert,Queue_remove);
  53. }
  54. return me;
  55. }
  56. void Queue_Destroy(QUEUE* const me){
  57. if (me!=NULL)
  58. {
  59. Queue_Cleanup(me);
  60. }
  61. free(me);
  62. }

代码 1-6 test_queue.c

  1. #include "queue.h"
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. int main(void)
  5. {
  6. int j,k,h,t;
  7. QUEUE* myQ;
  8. myQ=Queue_Create();
  9. k=1000;
  10. for (j = 0; j<QUEUE_SIZE; j++)
  11. {
  12. h=myQ->head;
  13. myQ->insert(myQ, k);
  14. printf("inserting %d at position %d, size=%d\n", k--,h,myQ->getSize(myQ));
  15. }
  16. printf("Iserted %d elements\n", myQ->getSize(myQ));
  17. for (j = 0; j<QUEUE_SIZE; j++)
  18. {
  19. t=myQ->tail;
  20. k=myQ->remove(myQ);
  21. printf("Removing %d at position %d, size=%d\n", k, t, myQ->getSize(myQ));
  22. }
  23. printf("Last item removed = %d\n", k);
  24. printf("Current queue size %d\n", myQ->getSize(myQ));
  25. puts("Queue test program");
  26. return 0;
  27. }

代码 1-7 cachedqueue.h

  1. //cached queue means the memory does not have enough space to store the whole queue
  2. //so we divide the queue into two sides:
  3. //one store in memory
  4. //another store in disk
  5. #ifndef CACHEDQUEUE_H
  6. #define CACHEDQUEUE_H
  7. #include "queue.h"
  8. typedef struct cachedqueue
  9. {
  10. QUEUE* queue; //base class
  11. char filename[80]; //new attributes
  12. int numberElementsOnDisk;
  13. QUEUE* outputQueue; //aggregation in subclass
  14. //Inherited virtual functions
  15. int (*isFull)(struct cachedqueue* const me);
  16. int (*isEmpty)(struct cachedqueue* const me);
  17. int (*getSize)(struct cachedqueue* const me);
  18. void (*insert)(struct cachedqueue* const me, int k);
  19. int (*remove)(struct cachedqueue* const me);
  20. //new virtual functions
  21. void (*flush)(struct cachedqueue* const me);
  22. void (*load)(struct cachedqueue* const me);
  23. }CACHEDQUEUE;
  24. void CachedQueue_Init(CACHEDQUEUE* const me, char* filename,
  25. int (*isFullFunction)(CACHEDQUEUE* const me),
  26. int (*isEmptyFunction)(CACHEDQUEUE* const me),
  27. int (*getSizeFunction)(CACHEDQUEUE* const me),
  28. void (*insertFunction)(CACHEDQUEUE* const me),
  29. int (*removeFunction)(CACHEDQUEUE* const me),
  30. void (*flushFunction)(CACHEDQUEUE* const me),
  31. void (*loadFunction)(CACHEDQUEUE* const me));
  32. void CachedQueue_Cleanup(CACHEDQUEUE* const me);
  33. int CachedQueue_isFull(CACHEDQUEUE* const me);
  34. int Cachedqueue_isEmpty(CACHEDQUEUE* const me);
  35. int Cachedqueue_getSize(CACHEDQUEUE* const me);
  36. void Cachedqueue_insert(CACHEDQUEUE* const me, int k);
  37. int CachedQueue_remove(CACHEDQUEUE* const me);
  38. void Cachedqueue_flush(CACHEDQUEUE* const me);
  39. void Cachedqueue_load(CACHEDQUEUE* const me);
  40. CACHEDQUEUE* CachedQueue_Create(void);
  41. void CachedQueue_Destroy(CACHEDQUEUE* const me);
  42. #endif

代码 1-8 cachedqueue.c

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include "cachedqueue.h"
  5. void CachedQueue_Init(CACHEDQUEUE* const me, char* filename,
  6. int (*isFullFunction)(CACHEDQUEUE* const me),
  7. int (*isEmptyFunction)(CACHEDQUEUE* const me),
  8. int (*getSizeFunction)(CACHEDQUEUE* const me),
  9. void (*insertFunction)(CACHEDQUEUE* const me),
  10. int (*removeFunction)(CACHEDQUEUE* const me),
  11. void (*flushFunction)(CACHEDQUEUE* const me),
  12. void (*loadFunction)(CACHEDQUEUE* const me)){
  13. me->queue=Queue_Create();
  14. me->numberElementsOnDisk=0;
  15. strcpy(me->filename,filename);
  16. me->outputQueue=Queue_Create();
  17. me->isFull=isFullFunction;
  18. me->isEmpty=isEmptyFunction;
  19. me->getSize=getSizeFunction;
  20. me->insert=insertFunction;
  21. me->remove=removeFunction;
  22. me->flush=flushFunction;
  23. me->load=loadFunction;
  24. }
  25. void CachedQueue_Cleanup(CACHEDQUEUE* const me){
  26. Queue_Cleanup(me->queue);
  27. }
  28. int CachedQueue_isFull(CACHEDQUEUE* const me){
  29. return me->queue->isFull(me->queue) &&
  30. me->outputQueue->isFull(me->outputQueue);
  31. }
  32. int CachedQueue_isEmpty(CACHEDQUEUE* const me){
  33. return me->queue->isEmpty(me->queue) &&
  34. me->outputQueue->isEmpty(me->outputQueue) &&
  35. (me->numberElementsOnDisk==0);
  36. }
  37. int CachedQueue_getSize(CACHEDQUEUE* const me){
  38. return me->queue->getSize(me->queue)+
  39. me->outputQueue->getSize(me->outputQueue)+
  40. me->numberElementsOnDisk;
  41. }
  42. void CachedQueue_insert(CACHEDQUEUE* const me,int k){
  43. if (me->queue->isFull(me->queue))
  44. {
  45. me->flush(me);
  46. }
  47. me->queue->insert(me->queue,k);
  48. }
  49. int CachedQueue_remove(CACHEDQUEUE* const me){
  50. if (!me->outputQueue->isEmpty(me->outputQueue))
  51. {
  52. return me->outputQueue->remove(me->outputQueue);
  53. }
  54. else if (me->numberElementsOnDisk>0)
  55. {
  56. me->load(me);
  57. return me->queue->remove(me->remove);
  58. }
  59. else
  60. {
  61. return me->queue->remove(me->remove);
  62. }
  63. }
  64. void CachedQueue_flush(CACHEDQUEUE* const me){
  65. //while not queue->isEmpty()
  66. // queue->remove();
  67. // write date to disk
  68. // numberElementsOnDisk++
  69. //end while
  70. }
  71. void CachedQueue_load(CACHEDQUEUE* const me){
  72. //while (!outputQueue->isFull()&&(numberElementsOnDisk>0))
  73. // read from start of file
  74. // numberElementsOnDisk--;
  75. // outputQueue->insert();
  76. //end while
  77. }
  78. CACHEDQUEUE* CachedQueue_Create(CACHEDQUEUE* const me){
  79. CACHEDQUEUE* me=(CACHEDQUEUE*)malloc(sizeof(CACHEDQUEUE));
  80. if(me!=NULL)
  81. {
  82. CachedQueue_Init(me,"C:\\queuebuffer.dat",
  83. CachedQueue_isFull,CachedQueue_isEmpty,
  84. CachedQueue_getSize,CachedQueue_insert,
  85. CachedQueue_remove,CachedQueue_flush,CachedQueue_load);
  86. }
  87. return me;
  88. }
  89. void CachedQueue_Destroy(CACHEDQUEUE* const me){
  90. if(me!=NULL)
  91. {
  92. CachedQueue_Cleanup(me);
  93. }
  94. free(me);
  95. }

1.2.5 有限状态机

有限状态机(Finite State Machine,FSM)

代码 1-9 SecuritySupervisor.c

  1. static eventStatus dispatchEvent(short id){
  2. eventStatus res=eventNotConsumed;
  3. switch (activeState)
  4. {
  5. case SecuritySupervisor_Idle:
  6. {
  7. if (id==NULL_id)
  8. {
  9. if(retries>=3)
  10. {
  11. activeState=SecuritySupervisor_ErrorState;
  12. displayMSg("ERROR: Max retries Exceeded");
  13. res=eventConsumed;
  14. }
  15. else
  16. {
  17. ++retries;
  18. activeState=SecuritySupervisor_Accepting;
  19. res=eventConsumed;
  20. }
  21. }
  22. }
  23. break;
  24. case SecuritySupervisor_Accepting:
  25. {
  26. if (id==keypress_SequritySupervisor_Event_id)
  27. {
  28. if (isCANCEL(params->keys))
  29. {
  30. retries=0;
  31. displayMSg("Cancelled");
  32. activeState=SecuritySupervisor_Idle;
  33. strcpy(pin,"");
  34. res=eventConsumed;
  35. }
  36. else
  37. {
  38. if (isDigit(params->keys))
  39. {
  40. addKey(params->keys);
  41. activeState=SecuritySupervisor_Accepting;
  42. res=eventConsumed;
  43. }
  44. else
  45. {
  46. if(isEnter(params->keys))
  47. {
  48. activeState=SecuritySupervisor_CheckingLength;
  49. res=eventConsumed;
  50. }
  51. }
  52. }
  53. }
  54. }
  55. break;
  56. case SecuritySupervisor_CheckingLength:
  57. {
  58. if (id==NULL_id)
  59. {
  60. if(strlen(pin)==4)
  61. {
  62. activeState=SecuritySupervisor_ValidatingPIN;
  63. res=eventConsumed;
  64. }
  65. else
  66. {
  67. displayMSg("ERROR:PIN wrong length");
  68. activeState=SecuritySupervisor_Idle;
  69. strcpy(pin,"");
  70. res=eventConsumed;
  71. }
  72. }
  73. }
  74. break;
  75. case SecuritySupervisor_ValidatingPIN:
  76. {
  77. if (id==NULL_id)
  78. {
  79. if (isValid(pin))
  80. {
  81. unlockDoor();
  82. displayMSg("Door unlocked");
  83. activeState=SecuritySupervisor_SecurityOpen;
  84. res=eventConsumed;
  85. }
  86. else
  87. {
  88. displayMSg("ERROR: Invalid PIN");
  89. activeState=SecuritySupervisor_Idle;
  90. strcpy(pin,"");
  91. res=eventConsumed;
  92. }
  93. }
  94. }
  95. break;
  96. case SecuritySupervisor_SecurityOpen:
  97. {
  98. if (id==keypress_SequritySupervisor_Event_id)
  99. {
  100. if (isRESET(params->keys))
  101. {
  102. lockDoor();
  103. displayMSg("Door locked");
  104. activeState=SecuritySupervisor_Idle;
  105. strcpy(pin,"");
  106. res=eventConsumed;
  107. }
  108. }
  109. }
  110. break;
  111. default:
  112. break;
  113. }
  114. return res;
  115. }

1.3 小结

结构化方法将软件组织成两个并行分类,一个是数据,另一个是行为。面向对象的方法将两者结合,当低耦合时,为固有紧密耦合的元素和内容的封装提高内聚力。C 不是面向对象语言,可以用于开发基于对象或面向对象的嵌入式系统。