ImageVerifierCode 换一换
格式:DOCX , 页数:27 ,大小:34.08KB ,
资源ID:22257293      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/22257293.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(将TIzigbee开源协议栈中的OS操作系统移植出来放在STC12C60S2中使用文档格式.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

将TIzigbee开源协议栈中的OS操作系统移植出来放在STC12C60S2中使用文档格式.docx

1、说到LTOS操作系统,不得不说说他的任务、事件和消息机制。据笔者理解,任务就是程序编写员将预实现的功能分成不同的模块,这些模块之间分工明确并且相互合作,共同完成程序员预完成的某个项目的整个功能;事件是这些任务中要处理的某个小功能的口令,比如老师说张三你站起来或坐下,张三听到站起来就站起来,听到坐下就坐下,同样道理,某个任务得到处理器后,先判断自己的事件是什么,如果是URAT_Writer则任务知道是串口写;而如果是LED_STOP,则任务知道是小灯停;消息是任务之间相互通信的方式,任务之间的数据传输一是通过消息来实现,二是通过延时设置任务来完成。任务内部消息就是一个系统事件。 在进入LTOS系

2、统前,先利用osal_init_system()等初始化程序将操作系统初始化,主要功能就是内存分配函数的初始化、定时器的初始化以及为任务的加入。任务初始化时将任务按预先设定分配了不同的优先级,LTOS系统按照赋值的优先级顺序从高到底不停的扫描这些任务,查看他们是否被设置了事件,如果该任务被设置了事件,则操作系统将马上进入这个该任务对应的pFnEventProcessor(处理任务函数)中执行该任务中的事件。 初始化和任务加入完成之后就开始进入任务调度函数osalNextActiveTask( void )。进入任务调度函数首先扫描定时器和串口,查看定时器和串口的变化,然后利用osalNextA

3、ctiveTask()函数查看任务列表中是否有被设置了事件的任务。以下是该函数的原型: osalTaskRec_t *osalNextActiveTask( void ) osalTaskRec_t *srchTask; / Start at the beginning srchTask = tasksHead; / When found or not while ( srchTask ) if (srchTask->events) /判断最高优先级中有无事件 return srchTask; srchTask = srchTask-&next; return NULL; 进入该函数后,

4、让srchTask指向任务列表的头(tasksHead),然后利用if(srch-&events)查看改任务中是否有事件,如果没有事件则srchTask指向任务链表的下一个元素,继续以上的工作,一旦查到某个任务有事件就返回任务的任务ID。然后利用retEvents = (activeTask-&pfnEventProcessor)( activeTask-&taskID, events )函数进入改任务中执行事先编写的函数。值得注意的是任务在执行完成之后一定要记得将任务的事件清空,不然返回的retEvents会跟activeTask-&events相或(activeTask-&events |

5、= retEvents),假如该任务的优先级最高,这样每当程序进入下一次的调度时总会进入该任务中(因为该任务的事件不曾清空),这样其余的任务即使有置位的事件也不会被执行。具体的分析将在下一章中利用实验详细讲解。1.2加入自己的任务 上一节中讲到了操作系统的基本运行方式,运行中涉及的任务的初始化和运行,下面主要介绍如何加入自己的任务。 在TI-MAC1.2.1中全部的任务加入是利用osalAddTasks( void )在初始化时完成的,该函数属于应用层和OS之间的接口函数,而单个的任务加入就在osalAddTasks( void )函数中利用osalTaskAdd (Task_Init,Tas

6、k_ProcessEvent, OSAL_TASK_PRIORITY)加入的,其中Task-Init(uint8 task_id)是任务的初始化函数,该函数中系统为任务分配特定的唯一的ID号;Task_ProcessEvent(uint8 task_id, uint16 events)是任务的执行函数,该函数中程序表达的就是要实现的功能;最后一个参数OSAL_TASK_PRIORITY是任务的优先级别。 下面以一个小的实验例子来说明自己的任务的加入: 该实验实现一个简单的功能LED小灯的闪烁,首先是任务的初始化函数 void LED1Init(uint8 taskId) LED1Id=task

7、Id; taskId是OS系统为该函数分配的任务ID,利用该初始化函数将taskId赋值给LED1Id。 接下来就是任务的执行函数的编写 uint16 LED2_ProcessEvent(uint8 taskId, uint16 events) if(events&MSA_SEND_EVENT) HalLedSet (HAL_LED_2, HAL_LED_MODE_ON); delay(5000); HalLedSet (HAL_LED_2, HAL_LED_MODE_OFF); osal_start_timerEx(LED1Id,MSA_SEND_EVENT,100); return

8、 (events MSA_SEND_EVENT); return 0; 最后就利用osalTaskAdd()函数将该任务加入到操作系统中去 void osalAddTasks( void ) /* HAL Drivers Task */ osalTaskAdd (Hal_Init, Hal_ProcessEvent, OSAL_TASK_PRIORITY_LOW); osalTaskAdd(LED1Init,LED1_ProcessEvent,OSAL_TASK_PRIORITY_MED );二:TI操作系统的运行方式 OS操作系统不是一个完整的操作系统,任务与任务之间也不能抢占,只是简单地利

9、用定时器管理和任务事件设置来周而复始地调用任务,与其他的操作系统一样(ucos,linux)它同样需要定时器来确定一个系统时钟tick,在cc2430中是占用一个硬件定时器来定时。每次一个任务执行完后系统都会从高优先级到低优先级扫描任务是否被设置了事件,当有任务被设置事件时,就马上进入该任务中。OS操作系统的思想是:保证高优先级的任务有事件时最先得到处理器。在任务的优先级赋值时,MAC Task一般赋最高的优先级,这样是为了使得无线电的发射和接受提高到最重要的地位。2.1一些主要的函数 OS操作系统的运行依靠许多重要的函数,下面介绍一些主要函数以及其中的参数。 1 byte osal_set_

10、event(byte task_id,uint16 event_flag) 说明:该函数与任务的运行至关重要,它是为任务设置事件的函数,该函数被利用为任务设置事件标示符。 参数:task_id:欲设置事件的这个任务ID,一旦写入,将为该任务ID的任务设置事件。 event_falg:事件标示,该事件标示占2个字节,每个位指定一个事件,只能有一个系统事件,其余的事件位在接受任务中自行定义。 2 osal_start_timer(uint16 event_id,uint16 timeout_value)该函数启动一个计时器,timeout_value单位时间后为这个函数现在所处的任务设置event

11、_id事件标示。event_id:同上。 Timeout_value:设置的时间毫秒数,当时间到是设置事件。 这个函数用的不多,为了精确地给出为哪个任务ID的任务设置事件,这个函数升级为osal_start_timerEx(byte taskID,uint16 event_id,uint16 timeout_value) 其中taskID就是所指出的预设置的事件的任务。也就是说,osal_start_timer()只能为自己所在的任务设置事件,而osal_start_timerEx()不仅可以为自己所在的任务设置事件,也可以为其余的任务设置事件。 3 byte *osal_msg_alloca

12、te( uint16 len )分配一个消息缓冲器,供任务之间利用osal_msg_send()传送消息。len:消息缓冲器的长度。 4 byte osal_msg_deallocate( byte *msg_ptr )当用消息接受完成之后,取消掉分配的消息缓冲器。*msg_ptr:指向预取消的消息缓冲器的指针。 5 byte osal_msg_send( byte destination_task, byte *msg_ptr )该函数用于源任务向目的任务发送命令,数据信息等,目的任务的标示符必须给出一个有效的系统任务ID,当消息发送成功后会给目的任务设置一个事件,该事件为系统事件SYS_E

13、VENT_MSG.destination_task:目的任务的任务标示 *msg_ptr:指向预发送的消息的指针 6 byte *osal_msg_receive( byte task_id )该函数用于一个任务去接收消息缓冲器中的消息,接收完成之后最好利用osal_msg_deallocate()取消消息缓冲器。task_id:接收者的任务标示号,这里要注意的就是task_id并不是发送消息的任务的任务ID而是接收任务的任务ID,比如说在MSA的任务标示为MSA_TaskId,在该任务中接收其余的任务发给它的消息就应该是osal_msg_receive(MSA_TaskId)。 理解了以上几

14、个函数之后,基本上就可以实现一些小的任务的加入,任务的执行和消息的发送与接收了。2.2小实验验证系统的运行方式 猜测:OS系统按照任务的优先级从高到底不停的扫描这些任务,查看他们是否被设置了事件,如果该任务被设置了事件,则操作系统将马上进入这个任务的pFnEventProcessor(处理任务函数)中执行程序员预先编制好的程序。高优先级的任务处理完成后必须取消该任务的事件,否则处理器一直进入该高优先级的任务中,不能正常执行低优先级的任务。实验目的:验证以上猜测是否正确 实验器材:zigbee实验板一套 TI-MAC程序(或者使用移植出来的LTOS以及STC12C60S2实验板)实验步骤: 1:

15、设置两个任务,TASK_LED1和TASK_LED2,TASK_LED1的优先级低,TASK_LED2的优先级高。void osalAddTasks( void ) /* HAL Drivers Task */ /* MAC Task */ osalTaskAdd( LED1Init, LED1_ProcessEvent, OSAL_TASK_PRIORITY_MED ); /* Application Task */ osalTaskAdd( LED2Init, LED2_ProcessEvent, OSAL_TASK_PRIORITY_HIGH ); 2:在任务TASK_LED1中为TAS

16、K_LED2设置开灯关灯事件,并且在TASK_LED2执行完任务后清除事件标志。在任务TASK_LED2中为TASK_LED1设置开灯关灯事件,并且TASK_LED1执行完成后清除事件标志(注意程序中标I和II的语句)。运行结果:两小灯交替闪烁。uint16 LED2_ProcessEvent(uint8 taskId, uint16 events)LED_START_EVENT) (I) uint16 LED1_ProcessEvent(uint8 taskId, uint16 events)if(events & LED_START_EVENT) HalLedSet (HAL_LED_1,

17、 HAL_LED_MODE_ON); HalLedSet (HAL_LED_1, HAL_LED_MODE_OFF); osal_start_timerEx(LED2Id,MSA_SEND_EVENT,100); (II) return 0; 3:TASK_LED1,TASK_LED2互相为对方设置开灯关灯事件,并且TASK_LED2执行完成后清除事件标志,而TASK_LED1运行完成后不清除(去掉I的语句)。 4:TASK_LED1,TASK_LED2互相为对方设置开灯关灯事件,并且TASK_LED1执行完成后清除事件标志,而TASK_LED2运行完成后不清除(去掉II的语句)。LED1和L

18、ED2各闪烁一下,不再闪烁,处理器一直进入TASK_LED2中。实验分析:在初始化时,通过osal_start_TimerEx(1, LED_START_EVENT,100)为任务TASK_LED1设置了LED_START_EVENT事件标示,于是程序扫描TASK_LED1时知道该任务中设置了事件,就进入任务TASK_LED1中,TASK_LED1为TASK_LED2设置了事件且运行完成后自己的事件标志清零了,当任务链表从头扫到尾时,扫到TASK_LED1中没事件而TASK_LED2中有事件,则进入TASK_LED2中,而TASK_LED2中为TASK_LED1设置了LED_START_EVE

19、NT事件,则TASK_LED2执行完成之后,任务链表从头扫到尾,扫到TASK_LED1中有事件,然后又进入TASK_LED1中,这样一直循环下去。 同过上面的分析不难想到第3步的实验结论是正确的,但对于第4步不好理解。其实第4步中的TASK_LED2虽然为TASK_LED1设置了事件但是自己的事件号没清除,又因为TASK_LED2的优先级高于TASK_LED1,故先扫描到TASK_LED2,于是进入TASK_LED2中,TASK_LED2执行完成之后任务链表从头扫描,先扫描到TASK_LED2中有事件又进入TASK_LED2中,这样一直在TASK_LED2中。实验结论:猜测是正确的。三:揭秘T

20、I操作系统:3.1:调度,非抢占,不需重入 调度是内核的主要职责之一,就是要决定该轮到哪个任务运行了。多数实时内核是基于优先级调度法的。每个任务根据其重要程度的不同被赋予一定的优先级。基于优先级的调度法指,CPU 总是让处在就绪态的优先级最高的任务先运行。然而,究竟何时让高优先级任务掌握CPU 的使用权,有两种不同的情况,这要看用的是什么类型的内核,是非抢占型的还是可抢占型内核。3.1.1 非抢占型内核 (Non-Preemptive Kernel)非抢占型内核也叫做不可剥夺型内核,不可剥夺型内核要求每个任务自我放弃CPU 的所有权。不可剥夺型调度法也称作合作型多任务,各个任务彼此合作共享一个

21、CPU。异步事件还是由中断服务来处理。中断服务可以使一个高优先级的任务由挂起状态变为就绪状态。但中断服务以后控制权还是回到原来被中断了的那个任务,直到该任务主动放弃CPU 的使用权时,那个高优先级的任务才能获得CPU的使用权。不可剥夺型内核的一个优点是响应中断快。在任务级,不可剥夺型内核允许使用不可重入函数。每个任务都可以调用不可重入性函数,而不必担心其它任务可能正在使用该函数从而造成数据的破坏。因为每个任务要运行到完成时才释放CPU 的控制权。 使用不可剥夺型内核时,任务级响应时间比前后台系统快得多。此时的任务级响应时间取决于最长的任务执行时间。不可剥夺型内核的另一个优点是,几乎不需要使用信

22、号量保护共享数据。运行着的任务占有CPU,而不必担心被别的任务抢占。但这也不是绝对的,在某种情况下,信号量还是用得着的。处理共享I/O 设备时仍需要使用互斥型信号量。例如,在打印机的使用上,仍需要满足互斥条件。图2 示意不可剥夺型内核的运行情况,任务在运行过程之中,2(1)中断来了,如果此时中断是开着的,CPU 由中断向量2(2)进入中断服务子程序,中断服务子程序做事件处理2(3),使一个有更高级的任务进入就绪态。中断服务完成以后,中断返回指令2(4), 使CPU 回到原来被中断的任务,接着执行该任务的代码2(5)直到该任务完成,调用一个内核服务函数以释放CPU 控制权,由内核将控制权交给那个

23、优先级更高的、并已进入就绪态的任务2(6),这个优先级更高的任务才开始处理中断服务程序标识的事件2(7)。图片2.jpg) 不可剥夺型内核的最大缺陷在于其响应时间。高优先级的任务已经进入就绪态,但还不能运行,要等,也许要等很长时间,直到当前运行着的任务释放CPU。3.1.2 可剥夺型内核当系统响应时间很重要时,要使用可剥夺型内核。最高优先级的任务一旦就绪,总能得到CPU 的控制权。当一个运行着的任务使一个比它优先级高的任务进入了就绪态,当前任务的CPU 使用权就被剥夺了,或者说被挂起了,那个高优先级的任务立刻得到了CPU 的控制权。如果是中断服务子程序使一个高优先级的任务进入就绪态,中断完成时

24、,中断了的任务被挂起,优先级高的那个任务开始运行。如图3 所示。图片3.jpg) 使用可剥夺型内核,最高优先级的任务什么时候可以执行,可以得到CPU 的控制权是可知的。 3.1.3 LTOS的调度分析 LTOS属于非抢占型操作系统,所以不必担心函数重入的问题,也不必担心临界区的保护问题,对于没有任何操作系统使用经验的人来说,学习并且分析LTOS操作系统,将使你在最短的时间里对操作系统有一个整体的理解。LTOS中调度函数 osal_start_system( void ) 函数分析 void osal_start_system( void ) UINT16 events; UINT16 retE

25、vents; halIntState_t intState; / Forever Loop while(1) /* This replaces MT_SerialPoll() and osal_check_timer() */ TaskActive = osalNextActiveTask(); TaskActive是一个全局变量,总是记录着此刻处于就绪态的任务,在LTOS中,所谓就绪态就是有事件等待处理的任务。osalNextActiveTask()该函数是用来寻找此刻有事件并且处于最高优先级的任务,该函数返回一个指针,指针指向最高优先级有事件任务。 if ( TaskActive ) 如果

26、TaskActive非空,即某个任务有事件,则进入处理函数中 HAL_ENTER_CRITICAL_SECTION(intState);宏,保存此时的EA寄存器值,然后关闭中断 events = TaskActive-&events;取得TaskActive中的事件。 / Clear the Events for this task TaskActive-&events = 0;清除TaskActive中的事件,为下一次的调度作准备。 HAL_EXIT_CRITICAL_SECTION(intState);宏,还原中断值 if ( events != 0 )此处,不少读者可能认为该判断可以不要。但是TI程序员写程序非常的谨慎,为了避免任何一个不可预知的错误,他们总是很小心。 / Call the task to process the event(s) if ( TaskActive-&pfnEventProcessor )如果Tas

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1