最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

《C/C++嵌入式系统编程》读书笔记总结

XAMPP教程 admin 800浏览 0评论

第五章与第六章属于硬件工作机制与存储器测试的介绍,由于不作深入了解,个人选择跳过该章节。但下图比较清晰的显示通信过程,因此贴在下面。

ew45

第七章主要介绍 1、控制与状态寄存器  2、设备驱动原理  3、时钟驱动  4、修改后的闪烁程序

1、控制与状态寄存器

外围设备有两种,一是与处理器包含在同一芯片称为内部外围设备,在芯片外部的为外部外围设备。在嵌入式系统中,这两种外围设备又可被称作存储映像外设以及输入输出外设。外围设备与芯片之间的最基本的接口是一组控制和状态寄存器。存储映像的控制与状态寄存器可以看做普通变量,需要声明一个指向寄存器的指针,并且显示设置指针值。例如:

volatile unsigned * pP2LTCH = (unsigned short *) 0x7200005E 

其中 volatile 关键字,旨在在编译器中不要优化改变量。则程序变为

volatile unsigned * pP2LTCH = (unsigned short *) 0x7200005E 

void 
toggleLed(void)
{
  *pP2LTCH ^= LED_GREEN;//  x ^= y 等于 x = x^y
}

I/O映像寄存器主要问题在于C/C++没有标准的方法访问,只有特殊的机器指令,而指令无法支持C语言。只能用汇编或库例程读写。

 

2、设备驱动原理

设备驱动应该完全隐藏硬件,通常有5要素。

1、覆盖设备的存储映像控制以及状态存储器的数据结构

创建一个结构体struct  存放寄存器以及其偏移地址的表,从最低偏移处开始填充表,如果有位置没有用,则需要填充哑元变量。

2、跟踪目前硬件和设备状态的一组变量

3、一个把硬件初始化到已知状态的例程

4、合起来为设备驱动的用户提供API的一组例程

5、中断服务例程

 

3、时钟驱动 (80188EB处理器时钟为例) 

C++类允许我们更好地隐藏硬件接口,防止应用程序意外地从程序其他部分读写设备寄存器。 Timer 类定义如下

enum TimerState{};
enum TimerState{};

class Timer
{
  public:
    Timer();
    ~Timer();

    int start(unsigned int nMilliseconds,TimeType = OneShot);
    int waitfor();
    int cancel();

    volatile TimerState state();   //Active、Idle、Done 防止编译优化
    TimeType type();      // OneShot、Periodic
    unsigned int length();
    unsigned int count(); //记录剩余节拍数信息
    Timer * pNext();      //指向下一个最先溢出的软件时钟

private:
    static void interrupt Interrupt();// 中断服务例程

}

初始化

#include "i8018xEB.h"
#include "timer.h"

#define CYCLES_PER_TICK (25000/4) //80188EB为25MHz处理器
Timer::Timer(void){
  static int bInitialized = 0;//初始指示标志

  state = Idle;
  type = OneShot;
  length = 0;
  count = 0;
  pNext = NULL;

  if (!bInitialized)
  {
     gProcessoer.installHAndler(); //把中断服务例程插入中断向量表中
     gProcessoer.pPCB->inControl.timerControl &=      ~(Timer_MASK|Timer_PRIORITY);     gProcessoer.pPCB->timer[2].count = 0;     gProcessoer.pPCB->timer[2].maxCountA = CYCLES_PER_TICK;
     //maxCountA表示1ms内输入到时钟的时钟周期数     gProcessoer.pPCB->timer[2].control = 
     Timer_ENABLE|Timer_INTERRUPT|Timer_PERIODIC;     bInitialized = 1;
  }
}

全局对象 gProcessoer 在头文件  i8018xEB.h 中声明。全局数据结构PCB 覆盖了外设控制的存储映像寄存器,与时钟单元2相关的三个寄存器为这个256字节数据结构的一部分,为了美观,实现成一组嵌套式结构。可以通过gProcessoer.pPCB->timer[2].control  这种方式进行访问控制寄存器

类公共函数 start

int Timer::start(unsigned int nMilliseconds, TimerType timeType)
{
  if (state != Idle)
  {
     return (-1);
  }
  state = Active;
  type = timerType;
  length = nMIlliseconds / MS_PER_STICK;

  timerList.insert(this);
  return (0);
}

类公共函数 interrrupt

void interrrupt
Timer::Interuppt()
{
  timerList.tick();  //tick方法为列表最顶端时钟count减1直至为0后改变state为done然后删除

  gProcessoer.intControl.eoi = EOI_NONSPECIFIC;

  gProcessoer.pPCB->inControl.timerControl &= ~TIMER_MAXCOUNT;
}

类公共函数 waitfor  会检查软件时钟是否到期

int Timer::waitfor()
{
  if (state != Active)
  {
     return (-1);
  }
  while(state != Done);
  if(type == Periodic)
  {
    state = Active;
    timerList.insert(this);
  }
  else
  {
    state = Idle;
  }  
  return (0);
}

类公共函数 cancel  删除时钟

void Timer::cancel(void )
{
  if (state == Active)
  {
     timerList.remove(this);
  }  
  state = Idle;
}

Timer 类还有其他一些函数,查看时钟是否活动,例如poll 它会返回 state == Done 的当前值。还有一特性称为callback ,

4、修改后的闪烁程序

当初实现计时是依靠估计nCycles– 的处理器速度,现在可以依靠时钟来精准定时。

#include "led.h"
#include "timer.h"
void main()
{
  Timer timer;

  time.start(500,Periodic)
  while(1)
  {
    toggleLed(LED_GREEN);
    timer.waitfor();
  }
}

有必要在这里提到看门狗(watchdog )程序,它是一个恢复系统异常的普遍方法,与这里点亮LED很相似,如果没有给watchdog 相应,该程序即会判断出异常,重启系统。

ew000000046

《C/C++嵌入式系统编程》书籍下载链接

转载请注明:XAMPP中文组官网 » 《C/C++嵌入式系统编程》读书笔记总结

您必须 登录 才能发表评论!