Zigbee协议栈内核分析 - 按键分析
来源:互联网 发布:主升浪选股软件 编辑:程序博客网 时间:2024/05/16 09:11
Zigbee协议栈内核分析 - 按键分析
Jesse
协议栈按键代码分析 - 思维导图(放大可看)
一、综述
上图从协议栈的 main() 函数开始分析,罗列出了 main() 函数里调用的函数。接下来我们将会对函数一个一个的分析,有关于 key 的函数我将会用黄色方框表示。
二、协议栈代码分析(按照上图逐步分析)
******************************************************** 轮询 ********************************************************
1、osal_int_disable( INTS_ALL ); //关闭总中断
2、HalDriverInit();
调用 HalKeyInit(); //按键初始化函数
HalKeyInit(){ ...... /*Initialize callback function */ pHalKeyProcessFunction = NULL; //初始化按键回调函数为NULL /*Start with key is not configured */ HalKeyConfigured = FALSE; }
3、osal_init_system(); //系统初始化函数
osal_init_system(); 里调用 osalInitTasks(); 初始化任务;
osalInitTasks(){ ...... SampleApp_Init( taskID ); //用户在 应用层 自定义的任务初始化。}SampleApp_Init( taskID ){ ...... RegisterForKeys( SampleApp_TaskID ); ......}
在自定义的任务初始化里面调用了 RegisterForKeys(SampleApp_TaskID ); ,里面的 registeredKeysTaskID = task_id; ,这个很关键,它将用户自定义的 SampleApp_Task 任务注册为按键任务。
4、osal_int_enable( INTS_ALL ); //使能了总中断
5、InitBoard( OB_READY );
调用了 HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE,OnBoard_KeyCallback); 来配置按键。
HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE,OnBoard_KeyCallback){ ... ... (void)osal_set_event(Hal_TaskID, HAL_KEY_EVENT); //用 tasksEvents[task_id] |= event_flag; 来通知Hal_Task任务有消息,使Hal_Task任务进入就绪态 ... ... pHalKeyProcessFunction = cback; //将 OnBoard_KeyCallback 函数赋值给按键回调函数指针}
6、最后就是进入我们的 osal_start_system(); 操作系统,无限循环啦。
首先是先执行:
do{ if (tasksEvents[idx]) // Task is highest priority that is ready. { break; } }while (++idx < tasksCnt);
来查询是否有任务进入了就绪状态。我们回去看看第 5 步,在第 5 步的时候有调用到 osal_set_event(Hal_TaskID,HAL_KEY_EVENT); 设置了一个消息给 Hal_Task 任务使Hal_Task任务进入了就绪态。
所以接下来协议栈要执行:
if(idx < tasksCnt) //如果任务是有登记的 { uint16 events; halIntState_t intState; HAL_ENTER_CRITICAL_SECTION(intState); events = tasksEvents[idx]; tasksEvents[idx] = 0; // Clearthe Events for this task. HAL_EXIT_CRITICAL_SECTION(intState); activeTaskID = idx; events = (tasksArr[idx])( idx, events ); //这一句调用了按键的处理函数 activeTaskID = TASK_NO_TASK; HAL_ENTER_CRITICAL_SECTION(intState); tasksEvents[idx] |= events; //Add back unprocessed events to the current task. HAL_EXIT_CRITICAL_SECTION(intState); }
events = (tasksArr[idx])( idx, events ); 这一句调用了Hal_Task的处理函数。让我们进入 tasksArr[idx] 看看,有了,Hal_Task任务对应的Hal_ProcessEvent 硬件抽象层的事件处理函数,我们进去看看。
uint16 Hal_ProcessEvent( uint8 task_id,uint16 events ){ ... ... #if (defined HAL_KEY) && (HAL_KEY == TRUE) /* Check for keys */ HalKeyPoll(); /* if interrupt disabled, do next polling */ if (!Hal_KeyIntEnable) { osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100); } #endif // HAL_KEY ... ...}
我们先看一下 HalKeyPoll();函数:
HalKeyPoll(){ ...... if(newKeys && pHalKeyProcessFunction) { (pHalKeyProcessFunction)(newKeys, HAL_KEY_STATE_NORMAL); //调用了按键处理回调函数 } ......}
按键轮询函数里调用了 (pHalKeyProcessFunction)(newKeys,HAL_KEY_STATE_NORMAL); 按键处理回调函数来处理按键事件,那么这个函数指针到底指向哪呢?让我们回去看看上面,有两个地方出现了回调函数指针的赋值。
(1)在第 2 步的时候 pHalKeyProcessFunction = NULL; 初始化按键回调函数指针为NULL;
(2)在第 5 步的时候调用了 HalKeyConfig(HAL_KEY_INTERRUPT_DISABLE, OnBoard_KeyCallback); 函数将 OnBoard_KeyCallback函数赋值给按键回调函数指针。
所以现在我们就去找 OnBoard_KeyCallback()看看它是怎么处理按键事件的吧。
OnBoard_KeyCallback(){ ... ... if ( OnBoard_SendKeys( keys, shift ) != ZSuccess ) ... ...}
OnBoard_SendKeys() 函数将发送一个消息给 registeredKeysTask 任务。
OnBoard_SendKeys(){ ...... if( registeredKeysTaskID != NO_TASK_ID ) { // Send the address to the task msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) ); if ( msgPtr ) { msgPtr->hdr.event = KEY_CHANGE; //将消息打包 msgPtr->state = state; msgPtr->keys = keys; //将消息发送给按键任务 osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr ); } return ( ZSuccess ); } ......}
看上面的代码,协议栈首先将消息打包,然后通过 osal_msg_send() 函数将消息发送给 registeredKeysTask 任务(也就是用户自定义的SampleApp_Task任务)。
我们进去 osal_msg_send()函数 里看看它是怎么发送消息的吧。
osal_msg_send(){ ...... //queue message osal_msg_enqueue(&osal_qHead, msg_ptr ); //Signal the task that a message is waiting osal_set_event( destination_task, SYS_EVENT_MSG ); ......}
看看上面的代码,我把最重要的两句列了出来:
首先是osal_msg_enqueue( &osal_qHead, msg_ptr ); ,将消息放入消息队列中;
最后果然还是要用到我们的 osal_set_event( destination_task, SYS_EVENT_MSG ); 函数来通知任务有消息发过来了!那这次是通知那个任务呢,让我们回去看看destination_task指的是什么任务吧。原来是第 6 步的按键回调函数里一直往里面看可以看到osal_msg_send(registeredKeysTaskID, (uint8 *)msgPtr );,所以通知的是registeredKeysTask任务,也就是用户自定义的SampleApp_Task任务。
然后 osal_run_system()又进入
do{ if (tasksEvents[idx]) // Task ishighest priority that is ready. { break; } }while (++idx < tasksCnt);
此时,托osal_msg_send( registeredKeysTaskID, (uint8 *)msgPtr);的福,我们的SampleApp_Task终于进入了就绪态。
那么接下来的 events = (tasksArr[idx])( idx, events );,我们进入的是我们用户自定义的 SampleApp_ProcessEvent 处理函数。
SampleApp_ProcessEvent(){ if ( events & SYS_EVENT_MSG ) { MSGpkt = (afIncomingMSGPacket_t*)osal_msg_receive( SampleApp_TaskID ); while ( MSGpkt ) { switch ( MSGpkt->hdr.event ) { // Received when a key is pressed case KEY_CHANGE: SampleApp_HandleKeys( ((keyChange_t*)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys ); break; … …}
然后就进入了SampleApp_HandleKeys按键处理函数了!
就这样,按键从协议栈系统一开始,到执行了一次用户自定义的按键处理函数的过程就全部结束啦!
然后是不是按键就这样结束了呢,那怎么叫轮询呢?!!!!
让我们看回到第 6 步的 Hal_ProcessEvent处理函数里面吧,它除了调用了按键轮询函数外,还调用了osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);,这个函数的作用是 100ms 后再次让Hal_TaskID任务进入准备态,此时就会无限循环的重复第 6 步,从而达到轮询的功能!
******************************************************** 中断 ********************************************************
void HalKeyConfig(bool interruptEnable, halKeyCBack_t cback){ if ((Hal_KeyIntEnable = interruptEnable)) { HAL_KEY_CLR_INT(); // Clear spurious ints. PICTL |= 0x01; // P1ICONL: Falling edge ints on pins 0-3. P1IEN |= PUSH1_BV | PUSH2_BV; // Enable specific P1 bits for ints by bit mask. IEN2 |= 0x10; // Enable general P1 interrupts. } else { (void)osal_set_event(Hal_TaskID, HAL_KEY_EVENT); } pHalKeyProcessFunction = cback;}如果参数为 HAL_KEY_INTERRUPT_ENABLE,将执行 if 里面的语句初始化按键中断模式。也就是没有执行 osal_set_event(Hal_TaskID, HAL_KEY_EVENT); 了,也就不会进行按键轮询了,那么当我们按下按键的时候,协议栈又是怎么进行终端处理的呢?
HAL_ISR_FUNCTION( halKeyPort0Isr, P0INT_VECTOR ){ HAL_ENTER_ISR(); if (HAL_KEY_SW_6_PXIFG & HAL_KEY_SW_6_BIT) { halProcessKeyInterrupt(); } /* Clear the CPU interrupt flag for Port_0 PxIFG has to be cleared before PxIF */ HAL_KEY_SW_6_PXIFG = 0; HAL_KEY_CPU_PORT_0_IF = 0; CLEAR_SLEEP_MODE(); HAL_EXIT_ISR();}当有按键按下的时候,则会进入这个外部中断服务函数,调用 halProcessKeyInterrupt(); 来处理按键事件。
void halProcessKeyInterrupt(void){... ... if (valid) { osal_start_timerEx(Hal_TaskID, HAL_KEY_EVENT, HAL_KEY_DEBOUNCE_VALUE); }... ...}在这个按键中断处理函数里面我们又见到了非常熟悉的 osal_start_timerEx() 函数了,这个函数在这起什么作用呢?
- Zigbee协议栈内核分析 - 按键分析
- CC2530按键流程分析相当于zigbee协议栈分析
- Zigbee协议栈内核分析 – 串口分析
- zigbee按键分析
- ZigBee协议分析
- ZigBee路由协议分析
- zigbee 协议栈 按键驱动
- ZigBee协议栈TI Z-Stack分析
- ZigBee协议栈TI Z-Stack分析
- TI BLE协议栈 按键流程分析
- zigbee协议栈之按键处理流程
- ZIGBEE:协议栈工作流程简要分析与学习方法记录
- ZigBee ZStack 协议栈学习--架构分析篇
- ZigBee协议分析仪Smart PacketSniffer
- Zigbee协议按键触发流程
- Linux内核网络协议栈代码分析
- Linux内核网络协议栈代码分析
- Linux内核网络协议栈代码分析
- Android之将ListView嵌套到ScrollView中只显示一行的问题
- fatal error LNK1123: failure during conversion to COFF: file invalid or corrupt
- 混杂设备驱动模型
- 懒人必备之Android效率开发框架(伪原创)
- 谈谈spring中的拦截器interceptor
- Zigbee协议栈内核分析 - 按键分析
- DEV-C++
- UITabBarItem 只有图片,没有文字,图片居中
- 基于Java自带同步机制实现生产者-消费者模式
- CentOS:yum安装MySQL5.6并更改其默认路径
- awr中"PHYSICAL_MEMORY_BYTES"显示的内存是当前可用的物理内存
- 内部类精讲
- 【C/C++】运算符问题
- 作业《IOS_C语言》结构体、结构体数组