您好,欢迎访问三七文档
1A先粗看了一些东西如果某一个任务的event被置位了,就处理它。即taskEvents[idx]!=0而这个事件是由中断程序之类的设置的或者由某一任务设置的?只有有events事件发生的任务才去处理。没有事件发生的任务将跳过。系统信息,可能会发给本任务,这个用函数:Osal_msg_receve(simpleosal_taskID)就可以得知。猜想:当系统事件发生时,它会将一个全局变量中的事件数组的某一个与0x8000或运算,到底是哪一个就是我们的任务排列的序号来决定的,例如我们在本例子中有11个任务(后来我自已又加了一个)如果第2个任务要发系统信息运去,就将这个数组置为1。程序中的这样处理的:tasksEvents[task_id]|=event_flag;//Stufftheeventbit(s)---见osal.c中。这个信息处理函数(带任务ID参数)它就是读这个全局变量,看这个是发给谁的。所以它先看有没有系统事件是发给本任务的,uint8*osal_msg_receive(uint8task_id){osal_msg_hdr_t*listHdr;///队列指针,用于搜索的osal_msg_hdr_t*prevHdr=NULL;///前一个osal_msg_hdr_t*foundHdr=NULL;///发现的指针处halIntState_tintState;///这个不知是干什么用的//HoldoffinterruptsHAL_ENTER_CRITICAL_SECTION(intState);////进入//PointtothetopofthequeuelistHdr=osal_qHead;////指向队列的前部//Lookthroughthequeueforamessagethatbelongstotheaskingtaskwhile(listHdr!=NULL)////只要队列不空,就一直往下走{if((listHdr-1)-dest_id==task_id)///事件队列中的目标ID是指向本地ID否?{if(foundHdr==NULL)///第一次发现消息是给自已的{//Savethefirstone2foundHdr=listHdr;////发现一个消息是给自已的}else{//Secondmsgfound,stoplooking又发现一个直接退出了break;}}if(foundHdr==NULL){prevHdr=listHdr;///当前这个就是第一个}listHdr=OSAL_MSG_NEXT(listHdr);///指向下一个}//Istheremorethanone?if(listHdr!=NULL){//Yes,Signalthetaskthatamessageiswaitingosal_set_event(task_id,SYS_EVENT_MSG);}else{//Nomore如果没有消息就告诉任务,现在没有系统消息osal_clear_event(task_id,SYS_EVENT_MSG);}//Didwefindamessage?if(foundHdr!=NULL)////将这个消息从中间抽出来让它消失掉,这时就要知道前一个{//Takeoutofthelinklistosal_msg_extract(&osal_qHead,foundHdr,prevHdr);}//ReleaseinterruptsHAL_EXIT_CRITICAL_SECTION(intState);return((uint8*)foundHdr);}B再看一下操作系统,从中断到处理的过程现在基本理清了按键消息是如何发过来的,有点绕。首先,在初始化中,允许了中断并配置了回调函数(这个函数在文件onBoard.c中InitBoard()3调用了它):/*InitializeKeystuff*/OnboardKeyIntEnable=HAL_KEY_INTERRUPT_ENABLE;//OnboardKeyIntEnable=HAL_KEY_INTERRUPT_DISABLE;HalKeyConfig(OnboardKeyIntEnable,OnBoard_KeyCallback);---halkey.c中定义在配置回调函数中,它初始化了两个键盘的中断允许位和上下沿等细节,将中断屏蔽位打开,且将这个中断标志位清除。注意到它将全局变量置为有效OnboardKeyIntEnable=1而这个变量本来没什么意义的,但发现它可以用来读键盘中断位时,在区分是用中断方式来做还是用查询方式来做时用得着这个变量。中断函数的定义有点小技巧(宏),它就是将中断矢量放到合适的位置,而且申明了这个函数。它既是定义,也是申明。这个在hal_mcu.h中定义了。(Keil和IAR不一样)但是这个配置程序中可能有点错,PICTL是用来控制上升沿或下降沿中断的,在多功能键初始化中,即P2.0处理中,它错误将P2IEN的D3位置为1,而不是将PICTL的D3位置1。所以这个键变成了上升沿了。当然这并不影响程序的运行。下面我们看一下是上升沿还是下降沿。先看一下电路图按下去时,它会产生一个上升沿,仿真器调一下看是否是上升沿时中断?果然,在刚按下去,还没抬起来的时候,就捕获到一个中断了。这说明这个中断是上升尚的,证明了程序的配置下降沿是没成功的,看来TI也会出点小错误。中断响应程序中,最后调用了:----中断函数定义在halkey.c中.osal_start_timerEx(Hal_TaskID,HAL_KEY_EVENT,HAL_KEY_DEBOUNCE_VALUE);将生成一个按键事件。注意到这个Hal_TaskID这个是内核ID的任务。延时一下可抗抖动干扰?注意到这个函数中调用了newTimer=osalAddTimer(taskID,event_id,timeout_value);而这个加定时器这个函数,当时只是加了一个定时器,后面的事情,就是要延时一点时间后,等时间到了后再去设置它,这个终于发现了(在定时器更新中osalTimerUpdate())当定时时间一到,就将事件发送给相应的任务IDosal_set_event(freeTimer-task_id,freeTimer-event_flag);所以是它将这个按键事件是发送给内核这个任务的。注意到这里的任务ID,就是内核任务ID。而这个事件就是按键事件。注意到在中断程序中,并不确定按键是哪一个,它是在HalKeyPoll()中检测键的。而这个事件的处理在什么地方呢?它在Hal_ProcessEvent(uint8task_id,uint16events)中。这个是一直在调用的,它是11个运行的任务之一(事实上它是第2个任务)在这个任务中,如果发现有系统事件,它会将这个事件读出来。没做什么事情,也不会有这样的系统事件(在我们这个程序中)如果是按键事件,则调用HalKeyPoll()在这个函数中将检测这个键值传送到这个回调函数中。(pHalKeyProcessFunction)(keys,HAL_KEY_STATE_NORMAL);注意到第2个参数它=0OnBoard_KeyCallback(uint8keys,uint8state)注意到这个state=0.而这个shift的值为多少呢?如果不是SW6,它就是true.如果是SW6,它就是false.shift=(OnboardKeyIntEnable==HAL_KEY_INTERRUPT_ENABLE)?false:((keys&HAL_KEY_SW_6)?true:false);---如果是单键,它为false,为5键,它就是true.4这个回调函数,调用了OnBoard_SendKeys(keys,shift)在这个函数中,它调用了:osal_msg_send(registeredKeysTaskID,(uint8*)msgPtr);这个注册的任务ID,就是我们在初始化中指定的任务(最后一个任务ID)。而这个信息就含有我们的事件名,状态,键名称。发送消息的函数调用了osal_msg_enqueue_push(destination_task,msg_ptr,FALSE)在这个函数的开始,将消息推送到消息队列中,osal_msg_enqueue(&osal_qHead,msg_ptr);最后调用了osal_set_event(destination_task,SYS_EVENT_MSG);即告诉目标任务ID,你的系统事件到了。有一个问题是程序是如何按键去抖动的呢?例如由于抖动,发生了N次按键中断。难道就要加N个定时器吗?终于后来又发现了,它在osalAddTimer(uint8task_id,uint16event_flag,uint32timeout)完美地解决了这个问题,这个问题就在这个函数中,当增加定时器时,如果发现同样的事件,同样的任务,已经有一个定时器在运行了,则我们就不会再增加定时器了,而是将这个定时器更新一下就可以了。而如果从来没有定时器用于这个事件和这个任务(两者同时符合,则不生成一个新的定时器)newTimer=osalFindTimer(task_id,event_flag);if(newTimer)///如果发现了定时器已经存在了{//Timerisfound-updateit.///只是将这个定时时间更新一下而已。newTimer-timeout.time32=timeout;return(newTimer);}Else///如果没有这个定时器存在,就生成一个定时器{//NewTimernewTimer=osal_mem_alloc(sizeof(osalTimerRec_t));///分配一段内存。。。。以下设置定时器的参数}真正的键的最后处理,交给应用层了。因为这个信息已经封装,发送到最未的一个任务了,消息中的事件就是KEY_CHANGE它的状态就是trueorfalse---这个依赖于是5键还是单个键。它的键名就是预定义好的6个键,分别为0x01,0x02,0x04....后面还有注意到tasksEvents=(uint16*)osal_mem_alloc(sizeof(uint16)*tasksCnt);分配的是一个2*事件个数的数组例如11个任务,就分配了一个22个字节的指针处。它是一个int16的数组,每个位表示一个事件,每个任务最多有16个事件,其中的0x8000表示的是系统事件。即最高位为1的事件。我们还要看一下这个始终运行的任务do{5if(tasksEvents[idx])//Taskishighestprioritythatisready.注意到这个数组。它代表?{break;}}while(++idxtasksCnt);在什么地方设置这个呢?tasksEvents[idx]uint8osal_set_event(uint8task_id,uint16event_flag){if(task_idtasksCnt){halIntState_tintState;HAL_ENTER_CRITICAL_SECTION(intState);//HoldoffinterruptstasksEvents[task_id]|=event_flag;//Stufftheeventbit(s)HAL_EXIT_CRITICAL_SECTION(intState);//Releaseinterruptsreturn(SUCCESS);}else{return(INVALID_TASK);}}C自已在工程中试着加任务,传事件和附加消息,还是成功了下面,我们试着在一个工程中,加一个任务,这个任务让一个LED灯闪。且时间到了,就给主任务发送一条自定义的消息,此消息含一个变量,这个变量每次都++的。通过串口打印一个时间到了XX出来。先加一个任务试试。1.首先在任务组中增加一个函数MyTestEven
本文标题:OSAL解读笔记
链接地址:https://www.777doc.com/doc-2848105 .html