1.初始化工作
(1)初始化CC2530工作时钟为32 MHz。
(2)初始化串口:配置串口0为工作串口。
(3)设置串口0的波特率为38 400。
(5)发送提示符。
(6)使能全局中断。
2.初始化操作系统
(1)操作系统初始化的主要工作是操作系统任务初始化:
(2)任务初始化分为两个步骤:
(a)将所有任务对应的事件表清空。
任务事件表保存在TaskEvents结构当中,该结构实质是一个uint16类型的数组,数组的每一个元素对应一个任务所有的事件,16位对应了16个事件,其中最高位表示是否为系统事件:最高位为1,表示系统事件;最高位为0,表示非系统事件。
(b)为每个任务分配任务ID并初始化具体任务。
任务ID决定了任务的优先级,ID越小响应的优先级越高,在任务初始化函数中,最新初始化的任务ID最小,优先级最高,依次ID递增,最小ID为0,最大ID为TaskCont-1。
3.进入操作系统轮询
操作系统轮询主要完成以下两个工作:
(1)调用OS_Scan();处理系统扫描事件,其中包含最重要的系统事件更新。
(2)按优先级从高到低的顺序查询任务事件表中是否有事件就绪,一旦有就绪事件则调用相应的任务事件处理函数进行处理。该事件响应机制保证了高优先级的任务永远是最先进行处理的,只有高优先级的任务全部处理完成后才会处理低优先级的任务。
其中两个宏需要注意:
这两个宏的功能是开关全局中断,对于一些不可中断的过程,需要进入临界代码区进行处理,就需要使用这两个宏:关中断进入临界代码区,开中断退出临界代码区。
4.事件的设置和响应
事件的设置有两种方式:
(1)直接使用osal_set_event函数来设置一个事件。
该函数包含了两个参数:任务ID和事件代码。
其函数原型如下:
显而易见,要在相应的任务层中设置一个事件,只需要在其任务事件表中增加响应的事件标识即可。(www.xing528.com)
(2)设置一个超时事件。
设置超时事件与直接设置事件的区别在于:超时事件不会再立刻将事件加入相应任务的事件列表当中,而是需要等待一定时间才会加入,这个事件通过设置函数的第三个参数决定。
该函数与osal_set_event函数相比,多了一个time_out_value参数,该参数就是用来设置超时值的。超时值的度量单位就是前面初始化timer1时设置的中断节拍。
(3)响应任务事件。
首先得到就绪任务的ID:
得到就绪任务ID后就可以通过该ID号得到相应的任务事件处理函数:
events=(TasksFn[idx])(idx,events);
其中TasksFn为任务事件处理函数表,该表中的函数与任务ID号相对应。该例程中定义了一个任务响应函数:
5.分析超时事件
(1)首先分析一个数据结构:
该结构定义了一个系统时钟资源,该数据类型是一个链表结构。其中各数据域作用如下:
next:指向下一个节点。
timer_out:超时事件中的超时值保存在这里,当该值减到0时,这会将该时钟资源记录的任务事件增加到事件列表当中。
event_flag:事件标识。
task_id:任务ID。
(2)main函数中初始化系统时钟资源:
为了简化功能来说明工作原理,该系统没有定义内存管理功能,链表结构的初始化采用一个预先定义好的数组结构,将其以链表形式逐个“串联”起来,并将链表头部指向数组的0号元素。
初始化过程除建立系统时钟资源链表外,对没使用的时钟资源都初始化为空闲可分配状态,即调用了osalDeleteTimer函数,该函数的工作实质就是将时钟资源的事件标识域清零。
(3)增加一个超时事件时,在osal_start_timerEx函数中主要调用了osalAddTimer函数,将事件加入系统时钟资源当中:
该函数首先判断所需设置的事件是否已经具有系统时钟资源,如果存在则将其超时参数更新,否则,分配一个空闲的系统时钟资源,将任务号和事件标识添加到该时钟资源当中。
(4)超时检测。
在系统轮询时,处理对任务事件进行查询,还增加了一个扫描事件查询OS_Scan:
mcuTimerCounterForOsal是一个全局变量,它在timer1的中断服务函数中进行自增运算,每次在OS_Scan中进行清零。temp则记录了mcuTimerCounterForOsal的值,也就是每次轮询花费的系统时间,关键在于osalTimerUpdate函数导致了超时,该函数原型如下:
该函数遍历系统所有的时钟资源,将设置有事件标识的时钟资源的超时值进行自减,即将运行时间在timerout中减去,一旦判断timerout值为0,就将相应的事件进行设置,并取消该超时事件记录。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。