2.1 轮询方式的嵌入式软件结构及实例
应该说轮询机制(Polling)最早并不是用于嵌入式软件设计,而是一种网络方面的接入方法,在其中一个主网络设备以有序的方式询问,是否二级设备有数据要发送。这个询问以信息的形式出现送给每个二级设备,其赋予二级设备传输的权利。在电信系统中,轮询机制是一种长距离载波接入方法,在其中非本地呼叫被长距离载波携带,经一个专用躯干设备进行呼叫旅程的第一或最后部分,和在载波网络进行旅程的中间部分。
就系统软件设计中的轮询机制而言,可以让处理器CPU以一定的周期按次序查询每一个外设,看它是否有数据输入或输出的要求,若有,则进行相应的输入/输出服务;若无,或I/O处理完毕,CPU就接着查询下一个外设。所需硬件为外设接口提供状态端口、数据而系统软件必须定时查询各个接口的状态端口,判断是否需要输入、输出数据,如果需要,则通过数据端口进行数据操作。CPU通过执行指令主动对外部设备进行查询,外部设备处于被动地位。
而采用这种方式的嵌入式软件结构,一般是用于等待某个标记量是否等于某个值,如果标记量变为某个特定的值后就进入轮询结构体执行相应的程序。另外,轮询程序还可以用于当中断子系统不起作用时(例如:系统崩溃或正在创建系统)对中断的模拟。轮询的软件结构通常比较简单,代码结构框架一般如下:
... /*外围程序*/ while(条件1 && 条件2 && 条件3... ) /*当条件组满足的时候判断标记是否为某个值*/ { if(Flag1) /*当Flag1满足的时候执行*/ { ... break; /*执行完后退出循环体*/ } if(Flag2) /*当Flag2满足的时候执行*/ { ... break; /*执行完后退出循环体*/ } ... } ...
举一个嵌入式软件开发中经常会用到的缓存机制(Buffer Scheme)的例子。这种机制可以采用轮询方式实现,下面的程序实现的是一个网络数据处理程序,FrameRcv函数在接收到来自网络协议栈的一个用户自定义数据帧,然后设置到一个FrameBuffer并设置FrameFlag,而FrameCpy通过轮询的方式检测到FrameFlag被设置后,才复制该帧数据,并进一步解析该数据帧(注意:定义一个完整数据帧的开头两个字节的内容均为‘x’)。
... /*先设置标记FrameFlag为0,当其为1时,表示数据FrameBuffer中已存放好一帧数据*/ unsigned char FrameFlag = 0; /*这里的FrameBuffer大小是用户自定义的76800,是满足一个320*240的LCD屏显示的*/ /*数据信息量大小。*/ unsigned char FrameBuffer[76800]; /*FrameRcv用于接受自定义数据帧*/ FrameRcv(unsigned char ch) { while(num < 76800) /*num在外程序定义,用于标记数据量大小*/ { if(num != '$') /*当num为'$'的时候,说明数据有误*/ { FrameBuffer[num] = ch; num++; } else { printf("\n Received a error char!"); errnum++; } } if(num == 76800) FrameFlag = 1; /*当FrameBuffer数据满设置标记*/ } /*FrameCpy用于接收自定义数据帧*/ FrameCpy() { while(FrameFlag) /*采用轮询方式检查FrameFlag的值*/ { printf("\n One frame have prepared!"); if(FrameBuffer[0] == 'x' && FrameBuffer[1] == 'x') AlyFrame(FrameBuffer); /*如果FrameFlag==1,开始分析该数据帧*/ } }