注册机制在嵌入式编程中很少提到,但回调函数大家经常接触,以软件定时器为例:
软件定时器设备通过函数Start把FunctionCallback作为参数传入定时器设备中保存,之后开启定时器,延时1000ms之后,定时器就会直接调用FunctionCallback,所以这个FunctionCallback就叫做回调函数。类似处理器的中断一样。
注册机制类似回调函数性质,只是把概念扩展到变量,上层应用通过注册函数地址或者变量地址到设备中保存,当设备中这个地址对应的函数被激活或者变量值有改变,就调用这个函数或者更改这个变量值,以此达到底层对上层的信息传递。
以ADC设备为例,我们看一下注册机制的应用。首先在ADC设备device_adc.c中定义一个用于注册变量地址的指针数组RegisterPointerBlock,初始值必须要指向一个空变量,否则若指向了一些有用的地址而导致这个地址对应的数据改变,会引起不可预测问题。
在设备中引入注册机制,应用层只需要把变量的地址注册到设备中,设备自己可以通过这个地址修改数据,这样解放了应用层,让应用层不需要关心如何获取数据。但是,注册机制也存在一些缺陷,那就是操作的数据,必须要原子操作,否则会导致两个应用层与设备同时修改一个数据的异常存在,出现数据错误,这个是需要避免的。
相对注册机制,消息机制是大家所熟悉的一种底层向上层传递的方式,msOS采用uC/OS-II,标配为业务逻辑与菜单界面两个任务,业务逻辑为高优先级,支持消息队列,设备发送的消息,都在业务逻辑中处理。
需要注意的是,msOS是采用的是uC/OS-II,它属于RTOS,业务逻辑与菜单界面虽然是两个独立的任务,但并不是同时运行的,一个时刻只能运行一个任务,业务逻辑的任务优先级高于菜单界面,所以在没有消息的时候,业务逻辑任务(LogicTask)在PendMessageQueue函数中挂起等待消息到来,这个时候退到菜单界面任务(MenuTask)执行,一旦按键设备检测到按键并通过PostMessageToLogicTask发送消息,就会激活业务逻辑任务,让业务逻辑任务抢占菜单界面任务运行。按键设备的运行是基于系统节拍的,它是在中断中运行,优先级比任务高,不会被任务抢占。
飞言走笔 2014-7-22 10:22
用户1646637 2014-2-14 16:26