1、OSAL解读笔记A 先粗看了一些东西如果某一个任务的event被置位了,就处理它。即 taskEventsidx!=0 而这个事件是由中断程序之类的设置的或者由某一任务设置的?只有有events事件发生的任务才去处理。没有事件发生的任务将跳过。系统信息,可能会发给本任务,这个用函数:Osal_msg_receve(simpleosal_taskID)就可以得知。猜想:当系统事件发生时,它会将一个全局变量中的事件数组的某一个与0x8000或运算,到底是哪一个就是我们的任务排列的序号来决定的,例如我们在本例子中有11个任务(后来我自已又加了一个)如果第2个任务要发系统信息运去,就将这个数组置为1。
2、程序中的这样处理的: tasksEventstask_id |= event_flag; / Stuff the event bit(s)-见osal.c中。这个信息处理函数(带任务ID参数)它就是读这个全局变量,看这个是发给谁的。所以它先看有没有系统事件是发给本任务的,uint8 *osal_msg_receive( uint8 task_id ) osal_msg_hdr_t *listHdr; /队列指针,用于搜索的 osal_msg_hdr_t *prevHdr = NULL; /前一个 osal_msg_hdr_t *foundHdr = NULL; /发现的指针处 halIntSt
3、ate_t intState; /这个不知是干什么用的 / Hold off interrupts HAL_ENTER_CRITICAL_SECTION(intState); /进入 / Point to the top of the queue listHdr = osal_qHead; /指向队列的前部 / Look through the queue for a message that belongs to the asking task while ( listHdr != NULL ) /只要队列不空,就一直往下走 if ( (listHdr - 1)-dest_id = task
4、_id ) /事件队列中的目标ID是指向本地ID否? if ( foundHdr = NULL ) /第一次发现消息是给自已的 / Save the first one foundHdr = listHdr; /发现一个消息是给自已的 else / Second msg found, stop looking 又发现一个 直接退出了 break; if ( foundHdr = NULL ) prevHdr = listHdr; /当前这个就是第一个 listHdr = OSAL_MSG_NEXT( listHdr ); /指向下一个 / Is there more than one? if
5、( listHdr != NULL ) / Yes, Signal the task that a message is waiting osal_set_event( task_id, SYS_EVENT_MSG ); else / No more 如果没有消息就告诉任务,现在没有系统消息 osal_clear_event( task_id, SYS_EVENT_MSG ); / Did we find a message? if ( foundHdr != NULL ) /将这个消息从中间抽出来让它消失掉,这时就要知道前一个 / Take out of the link list osal
6、_msg_extract( &osal_qHead, foundHdr, prevHdr ); / Release interrupts HAL_EXIT_CRITICAL_SECTION(intState); return ( (uint8*) foundHdr );B再看一下操作系统,从中断到处理的过程现在基本理清了按键消息是如何发过来的,有点绕。首先,在初始化中,允许了中断并配置了回调函数(这个函数在文件onBoard.c中InitBoard()调用了它): /* Initialize Key stuff */ OnboardKeyIntEnable = HAL_KEY_INTERRUP
7、T_ENABLE; /OnboardKeyIntEnable = HAL_KEY_INTERRUPT_DISABLE; HalKeyConfig( OnboardKeyIntEnable, OnBoard_KeyCallback);-halkey.c中定义在配置回调函数中,它初始化了两个键盘的中断允许位和上下沿等细节,将中断屏蔽位打开,且将这个中断标志位清除。注意到它将全局变量置为有效OnboardKeyIntEnable=1 而这个变量本来没什么意义的,但发现它可以用来读键盘中断位时,在区分是用中断方式来做还是用查询方式来做时用得着这个变量。中断函数的定义有点小技巧(宏),它就是将中断矢量放
8、到合适的位置,而且申明了这个函数。它既是定义,也是申明。这个在hal_mcu.h中定义了。(Keil和IAR不一样)但是这个配置程序中可能有点错,PICTL是用来控制上升沿或下降沿中断的,在多功能键初始化中,即P2.0处理中,它错误将P2IEN的D3位置为1,而不是将PICTL的D3位置1。所以这个键变成了上升沿了。当然这并不影响程序的运行。下面我们看一下是上升沿还是下降沿。先看一下电路图按下去时,它会产生一个上升沿,仿真器调一下看是否是上升沿时中断?果然,在刚按下去,还没抬起来的时候,就捕获到一个中断了。这说明这个中断是上升尚的,证明了程序的配置下降沿是没成功的,看来TI也会出点小错误。中断
9、响应程序中,最后调用了:-中断函数定义在halkey.c中.osal_start_timerEx (Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE);将生成一个按键事件。注意到这个Hal_TaskID这个是内核ID的任务。延时一下可抗抖动干扰?注意到这个函数中调用了 newTimer = osalAddTimer( taskID, event_id, timeout_value );而这个加定时器这个函数,当时只是加了一个定时器,后面的事情,就是要延时一点时间后,等时间到了后再去设置它,这个终于发现了(在定时器更新中osalTimerUpda
10、te())当定时时间一到,就将事件发送给相应的任务IDosal_set_event( freeTimer-task_id, freeTimer-event_flag );所以是它将这个按键事件是发送给内核这个任务的。注意到这里的任务ID,就是内核任务ID。而这个事件就是按键事件。注意到在中断程序中,并不确定按键是哪一个,它是在HalKeyPoll()中检测键的。而这个事件的处理在什么地方呢?它在Hal_ProcessEvent( uint8 task_id, uint16 events )中。这个是一直在调用的,它是11个运行的任务之一(事实上它是第2个任务)在这个任务中,如果发现有系统事件,
11、它会将这个事件读出来。没做什么事情,也不会有这样的系统事件(在我们这个程序中)如果是按键事件,则调用HalKeyPoll()在这个函数中将检测这个键值传送到这个回调函数中。(pHalKeyProcessFunction) (keys, HAL_KEY_STATE_NORMAL); 注意到第2个参数它=0OnBoard_KeyCallback( uint8 keys, uint8 state )注意到这个state=0.而这个shift的值为多少呢?如果不是SW6,它就是true.如果是SW6,它就是false. shift = (OnboardKeyIntEnable = HAL_KEY_IN
12、TERRUPT_ENABLE) ? false : (keys & HAL_KEY_SW_6) ? true : false); -如果是单键,它为false,为5键,它就是true. 这个回调函数,调用了OnBoard_SendKeys( keys, shift ) 在这个函数中,它调用了: osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr );这个注册的任务ID,就是我们在初始化中指定的任务(最后一个任务ID)。而这个信息就含有我们的事件名,状态,键名称。发送消息的函数调用了osal_msg_enqueue_push( destina
13、tion_task, msg_ptr, FALSE)在这个函数的开始,将消息推送到消息队列中,osal_msg_enqueue( &osal_qHead, msg_ptr ); 最后调用了osal_set_event( destination_task, SYS_EVENT_MSG );即告诉目标任务ID,你的系统事件到了。有一个问题是程序是如何按键去抖动的呢?例如由于抖动,发生了N次按键中断。难道就要加N个定时器吗?终于后来又发现了,它在osalAddTimer( uint8 task_id, uint16 event_flag, uint32 timeout )完美地解决了这个问题,这个问
14、题就在这个函数中,当增加定时器时,如果发现同样的事件,同样的任务,已经有一个定时器在运行了,则我们就不会再增加定时器了,而是将这个定时器更新一下就可以了。而如果从来没有定时器用于这个事件和这个任务(两者同时符合,则不生成一个新的定时器) newTimer = osalFindTimer( task_id, event_flag ); if ( newTimer ) /如果发现了定时器已经存在了 / Timer is found - update it. /只是将这个定时时间更新一下而已。 newTimer-timeout.time32 = timeout; return ( newTimer
15、); Else /如果没有这个定时器存在,就生成一个定时器 / New Timer newTimer = osal_mem_alloc( sizeof( osalTimerRec_t ) ); /分配一段内存。 以下设置定时器的参数真正的键的最后处理,交给应用层了。因为这个信息已经封装,发送到最未的一个任务了,消息中的事件就是KEY_CHANGE 它的状态就是true or false-这个依赖于是5键还是单个键。 它的键名就是预定义好的6个键,分别为0x01,0x02,0x04.后面还有注意到 tasksEvents = (uint16 *)osal_mem_alloc( sizeof( u
16、int16 ) * tasksCnt);分配的是一个2*事件个数的数组 例如11个任务,就分配了一个22个字节的指针处。它是一个int16的数组,每个位表示一个事件,每个任务最多有16个事件,其中的0x8000表示的是系统事件。即最高位为1的事件。我们还要看一下这个始终运行的任务 do if (tasksEventsidx) / Task is highest priority that is ready. 注意到这个数组。它代表? break; while (+idx tasksCnt);在什么地方设置这个呢?tasksEventsidxuint8 osal_set_event( uint8
17、 task_id, uint16 event_flag ) if ( task_id msg.readRsp.value0;证明这个消息中含有读的值。这个消息格式如下:typedef struct osal_event_hdr_t hdr; /! GATT_MSG_EVENT and status uint16 connHandle; /! Connection message was received on uint8 method; /! Type of message gattMsg_t msg; /! Attribute protocol/profile message gattMsg
18、Event_t;如果不是读,也不是写,而且正在忙的话,就是在做发现的事情。例如,在接到发现从机事件时,就将这个状态改变成正在发现状态:simpleBLEDiscState = BLE_DISC_STATE_SVC;此时就不是闲了。而如果有消息过来,要不就是读,要不就是写,要不就是在发现。所在在收到了系统消息后,一个看这个消息是不是按键消息,一个看消息中附加的事件是不是GATT消息,如果是GATT消息,则进一步看是读还是写还是其它。其它只有一种情况就是发现消息。而这个发现消息也是因为按了UP键引发的。最后我们还是看一下键处理,尽管这个键处理比较复杂一些。先看UP键。如果没建立连接,就调用一个函数
19、去发现从机扫描。如果正在扫描时按下UP键,就终止扫描了。不过除非你连接按两下UP,不然因为连接速度很快,不会出现终止扫描这种情况。如果已经建立连接了,按UP键的话就是一次是写,一次就是读,一直按一直这样做下去。再看一下左键处理。显示扫描到的设备号。按一下换一个,直到最多8个又回来了。再看右键 是连接更新。这个不知在做什么,因为源代码看不到在库里。再看中心键,如果选择要连接的从机是空闲状态,还没有进行连接,则进行连接,如果已经是连接状态,则断开连接。再看DOWN键,每按一次,是读取RSSI或取消读取RSSI。注意到扫描和连接是两件事情。扫描只是看下面有多少从机。而连接则是给指定的从机去连接。连的
20、是谁则通过左键去选。做试验时我们只有一个从机,只买了一个。程序还是没有看完全,还得继续努力去消化一下。只有多花时间多去看,对代码看上去就记住得差不多的时候,这个代码也就看得差不多了。这样下来速度是慢了点,但是比较深入一点。我们再一次将客户机(中心)这个程序解读一遍:先看在这个事件处理程序:它处理三种事件,第1种是系统事件,第2种是启动事件,第3种是开始发现事件。简单点的先看第3种。第3种是一个开始发现事件。我想这个开始发现事件应该是按了UP键后发出的吧。本来也没有必要搞这么一个绕来绕去的,在按键中直接调这个函数simpleBLECentralStartDiscovery( );不就行了吗?我们
21、看一下在什么地方触发了这个事件?static void simpleBLECentralEventCB( gapCentralRoleEvent_t *pEvent )中调用了这个事件。在GAP_LINK_ESTABLISHED_EVENT事件中,发调用这个osal_start_timerEx(simpleBLETaskId,START_DISCOVERY_EVT, DEFAULT_SVC_DISCOVERY_DELAY );照理,我们应该在UP键中会出现这个发现设备事件?理解错了,原来这个是发现FFF0服务?而不是发现从机。原来是与从机建立连接后,再启动这个发现从机服务的过程,而不是扫描从机。注意到这里发现FFF0服务的服务。下位机如果有N个,则怎样去发现呢?另外每个下位机它的服务都是FFF0吗?我估计下回还要看一下同时连接3个从机的例子能从中间找点线索吧。调用了这个发现从机服务后,还要做什么呢?此时应该可以与服务器的特征参数通讯了吧?只能先跟踪到这里了。过一会再来回顾这部分的处理吧。接下来我们看到第2种事件,就是启动事件,启动事件由这个任务的init()的。启动事件中,也做了不少事情的,主要有:注册了两个函数,其中一个是RSSI事件处理回调函数和一个状态处理回调函数,也就是收到一些事件后,如何处理收到的事件消息。绑定处理函数
copyright@ 2008-2023 冰点文库 网站版权所有
经营许可证编号:鄂ICP备19020893号-2