OSAL运行、事件和消息
OSAL运行、事件和消息

主函数执行以下函数由上可以看出main()函数共做了2件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统,重点就是调用了osal_init_system()和osal_start_system()。
1.屏蔽所有中断osal_int_disable( INTS_ALL );2.初始化底板HAL_BOARD_INIT();3.电压检测 zmain_vdd_check();4.初始化IO InitBoard( OB_COLD );5.初始化硬件驱动HalDriverInit();6.初始化非易变量页面osal_nv_init( NULL );7.初始化MAC层 ZMacInit();10.中断使能osal_int_enable( INTS_ALL );11.zmain_dev_info();12.#ifdef LCD_SUPPORTEDzmain_lcd_init();13.#ifdef WDT_IN_PM1看门狗WatchDogEnable( WDTIMX );14.osal_start_system();程序最终会在系统函数中无限循环下去。
1.1osal_run_system();无限的循环,1.1.1任务轮序,跳转事件处理函数在进入无限循环之前系统定义了三个至关重要的变量,taskArr-----此数组的每一项都是const pTaskEventHandlerFn tasksArr[ ] ={- - - GenericApp_ProcessEvent }都是一个函数指针,指向具体的函数入口地址taskCnt-----保存了任务的总个数const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );taskEvent---指向事件表的首地址uint16 *tasksEvents;在任务初始化时osalInitTasks()做了这样一件事tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//将字节清零?那么关键的问题还没解决,事件到底是怎么被捕获的SYS_EVENT_MSG = 0x8000 系统事件类号case ZDO_STATE_CHANGE:不需注册网络中的设备状态发生改变时,产生的事件消息ZDO_CB_MSG 要注册 ZDO_RegisterForZdoCB( uint8 indID, pfnZdoCb pFn );AF_INOMING_MSG_CMD 消息进入好像不需要注册添加这些事件前要先调用对应的Register函数端点描述符必须要注册afRegister( &GenericApp_epDesc );ZIGBEE事件有两类,系统定义事件和用户定义事件。
OSAL你想知道的都在这里

OSAL你想知道的都在这里近日,21ic论坛TI无线连接论坛板块分享了一张OSAL调度机制的图,图片如下OSAL调度机制是何方神圣?OSAL为Operating System Abstraction Layer,即操作系统抽象层,支持多任务运行,它并不是一个传统意义上的操作系统,但是实现了部分类似操作系统的功能。
OSAL概念是由TI公司在ZIGBEE协议栈引入,他的意思是”模拟操作系统”,此OS,并非一个真正的OS,而是模拟OS的一些方法为广大编程者提供一种写MCU程序的方法.当有一个事件发生的时候,OSAL负责将此事件分配给能够处理此事件的任务,然后此任务判断事件的类型,调用相应的事件处理程序进行处理。
现有的嵌入式操作系统可以分为两类,即通用的多任务操作系统(General—purpose Multi-tasking OS)和事件驱动的操作系统(Event-driven OS)。
前者能够很好地支持多任务或者多线程,但是会随着内部任务切换频率的增加而产生很大的开销,这类操作系统有:uC /OS-II、嵌入式Linux、WinCE等。
后者支持数据流的高效并发,并且考虑了系统的低功耗要求,在功耗、运行开销等方面具有优势。
典型的代表如TinyOSl291。
目前TinyOS操作系统支持的平台有ATMEL公司的A VR系列、TI公司的MSP430系列。
由于TinyOS操作系统还没有对Chipcon公司(才知道TI把它收购了)提供CC2430开发平台提供支持,因此,要在CC2430开发平台上使用TinyOS系统来开发Zigbee协议栈软件,就必须首先对TinyOS进行移植。
因此Chipcon公司为自己设计的ZStack协议栈中提供了一个名为操作系统抽象层OSAL 的协议栈调度程序。
Osal主要提供如下功能:任务注册、任务间同步互斥、中断处理存储器分配和管理、提供定时器功能。
OSAL系统框架

taskID 这个 task,设置一个 event_id,让这个事件在后面的主循环中运行到。
下面我们通过一个图表来解释下这种机制:
8
这个表就是 osalTimerUpdate 函数的“任务表”,上面讲过这个函数给应用程序提供 了“软计时”,就是体现在这里:osal_start_timerEx 通过 osalAddTimer 向链表里添加了 “定时任务”,由 osalTimerUpdate 来以 ms 为单位对这些“软定时器”减计数,溢出时, 即调用 osal_set_event,实现主循环里对任务事件的调用。
二、通过消息机制调用事件
这是另外一种设置事件(Set Event)的重要方式,下面我们以 ZStack 协议栈的基础 例程-GenericApp 来看一下按键是如何产生的,及如何调用相应的接口程序。
前文讲过,按键的相关处理都安排在了 HAL 的 task 当中,在 HAL 的核心处理函数 Hal_ProcessEvent 中,有个 HalKeyPoll 的处理函数,在 HalKeyPoll 函数中,无论按键是 ADC 方式,或者是扫描 IO 口的方式,最后都会生成一个键值 key,然后通过下面的语句来 调用按键服务程序:
1.2 任务(task)的概念 在 OSAL 中,所有的“事件”会被安排到不同的“任务”里进行执行,比如按键、串口、 LCD 等外设均被安排在 Hal 任务中,而无线数据的底层收发则放在 mac 任务中等等。 以一个简单的 OSAL 项目为例:
macTaskInit( taskID++ ); nwk_init( taskID++ ); Hal_Init( taskID++ ); MT_TaskInit( taskID++ ); APS_Init( taskID++ ); APSF_Init( taskID++ ); ZDApp_Init( taskID++ ); ZDNwkMgr_Init( taskID++ ); SampleApp_Init( taskID );
OSAL调度机制

typedef void (*pTaskInitFn)(unsigned char task_id) ; //指向任务初始化函数 typedef void (*pTaskEventHandlerFn)(usigned char task_id unsigned short event_flag); //指向事件处理函数
三部分:1、任务调度
2、时间管理
3、原语通信
(一)任务调度
//每层任务=对应事件处理函数
//任务链表,任务按优先级插入 ZigBee 协议栈中的每一层都有很多原语操作要执行,因此对于整个协议栈来说,就会有很多并发操作要执行。协议栈 的每一层都设计了一个事件处理函数,用来处理与这一层操作相关的各种事件。这些事件处理函数可以看成是与协议栈 每一层相对应的任务,由 ZigBee 协议栈中调度程序 OSAL 来进行管理。这样,对于协议栈来说,无论何时发生了何种事 件,我们都可以通过调度协议栈相应层的任务,即事件处理函数来进行处理。这样,整个协议栈便会按照时间顺序有条
typedef struct osalTaskRec { struct osalTaskRec *next; //指向链表中下一个结构体 pTaskInitFn pfnInit; //指向相关层任务初始化函数 pTaskEventHandlerFn pfnEventProcessor; //指向相关层事件处理函数 byte taskID; //对应当前任务 ID byte taskPriority; //当前任务优先级 uint16 events; //需要被处理的事件,0 表示没有要被处理事件 } osalTaskRec_t; //链表中的每一项数据结构
3、原语通信:请求响应原语操作:一旦调用了下层相关函数后,就立即返回。下层处理函数在操作结束后,将结果以 消息的形式发送到上层并产生一个系统事件,调度程序发现这个事件后就会调用相应的事件处理函数对它进行处理。两 个相关函数:向目标任务发送消息的函数;消息提取函数。
OSAL

OSAL一、概述OSAL(Operating System Abstraction Layer),翻译为“操作系统抽象层”,OSAL 就是以实现多任务为核心的系统资源管理机制。
所以OSAL与标准的操作系统还是有很大的区别的。
简单而言,OSAL实现了类似操作系统的某些功能,但并不能称之为真正意义上的操作系统。
二、OSAL系统的初始化首先在main()中调用OSAL初始化函数Init_Osal(),在Init_Osal()中通过调用osal_init_system()来进行初始化OSAL,在调用osal_init_system()过程中关闭所有中断。
在osal_init_system()中包括了内存、定时器、任务初始化、添加任务和初始化添加的任务等。
(分别为函数osal_mem_init();osalTimerInit();osalTaskInit(); osalAddTasks();osalInitTasks();osal_mem_kick();)现在我们先进行OSAL系统任务是如何运行的进行分析。
关于任务初始化中主要用到osalTaskInit(); osalAddTasks();osalInitTasks();这三个函数。
osalTaskInit()函数的功能是将任务头指针tasksHead置零,有效任务指针activeTask置零,并且初始化任务ID变量taskIDs为零。
osalAddTasks()函数的功能是添加所有的任务,所谓的添加任务就是在系统内存空间(此部分关于内存的操作将放到最后进行说明)中申请一段空间用于存储任务的结构变量osalTaskRec,按照链表的形式存储所有的任务结构变量,此结构变量中将存储所有任务所需要的信息。
通过调用osalTaskAdd()依次添加每个任务。
添加任务有三个作用的参数,他们分别是:pfnInit、pfnEventProcessor和taskPriority(任务初始化函数地址、任务处理函数地址和任务的优先级)而taskID参数则是系统通过osalAddTasks()函数随机给分配的。
OSAL概述

OSAL概述OSAL概述OSAL为Operating System Abstraction Layer,即操作系统抽象层,⽀持多任务运⾏,其中BLE协议栈、配置⽂件以及所有的应⽤程序(app)都在其上运⾏,它并不是⼀个传统意义上的操作系统,但是实现了部分类似操作系统的功能,为了⽅便,下⾯简称OSAL系统。
1、OSAL简要流程初始化完成后,在app的init最后⼀般会启动⼀个定时器或者直接set⼀个任务事件START_DEVICE_EVT,超时后进⼊app回调函数START_DEVICE_EVT事件分⽀处理,在该分⽀中启动具体的信息采集、数据处理、数据显⽰或发送等定时任务。
OSAL系统⼯作,判断当前是否存在待处理的任务事件,有,则调⽤对应的回调函数进⾏处理,并在结束后重新设定定时器等待超时,若没有任务事件,则进⼊休眠状态,等待唤醒。
2、OSAL的main函数任何⼀个程序都由main函数起,单⽚机程序中,⼀般顺序为:时钟初始化——>相应外设初始化——>系统关键参数初始化——>进⼊死循环处理;在OSAL的main函数中,同样也是这些流程:123/**************************************************************************************************45 * @fn main67 *89 * @brief Start of application.1011 *1213 * @param none1415 *1617 * @return none1819 **************************************************************************************************2021*/2223int main(void)2425 {2627/* Initialize hardware */28 HAL_BOARD_INIT();2930// Initialize board I/O31 InitBoard( OB_COLD );3233/* Initialze the HAL driver */34 HalDriverInit();3536/* Initialize NV system */37 osal_snv_init();3839/* Initialize LL */4041/* Initialize the operating system */42 osal_init_system();4344/* Enable interrupts */45 HAL_ENABLE_INTERRUPTS();4647// Final board initialization48 InitBoard( OB_READY );4950#if defined ( POWER_SAVING )5152 osal_pwrmgr_device( PWRMGR_BATTERY );5354#endif5556/* Start OSAL */57 osal_start_system(); // No Return from here5859return0;6061 }62636465解析:HAL_BOARD_INIT(); //初始化晶振及预读取程序InitBoard( OB_COLD ); //在main函数中有两处InitBoard();此为第⼀次初始化,此时OSAL 还未启动,初始化IO及⼀些系统级寄存器,类似电脑上的BIOS 为系统的启动做准备,个⼈认识,欢迎指正。
OSAL(Operating System Abstraction Layer),“操作系统抽象层”
OSAL一、概述OSAL(Operating System Abstraction Layer),翻译为“操作系统抽象层”,OSAL就是以实现多任务为核心的系统资源管理机制。
所以OSAL与标准的操作系统还是有很大的区别的。
简单而言,OSAL实现了类似操作系统的某些功能,但并不能称之为真正意义上的操作系统。
二、OSAL系统的初始化首先在main()中调用OSAL初始化函数Init_Osal(),在Init_Osal()中通过调用osal_init_system()来进行初始化OSAL,在调用osal_init_system()过程中关闭所有中断。
在osal_init_system()中包括了内存、定时器、任务初始化、添加任务和初始化添加的任务等。
(分别为函数osal_mem_init();osalTimerInit();osalTaskInit();osalAddTasks();osalInitTasks();osal_mem_kick();)现在我们先进行OSAL系统任务是如何运行的进行分析。
关于任务初始化中主要用到 osalTaskInit(); osalAddTasks();osalInitTasks();这三个函数。
osalTaskInit()函数的功能是将任务头指针tasksHead置零,有效任务指针activeTask置零,并且初始化任务ID变量taskIDs 为零。
osalAddTasks()函数的功能是添加所有的任务,所谓的添加任务就是在系统内存空间(此部分关于内存的操作将放到最后进行说明)中申请一段空间用于存储任务的结构变量osalTaskRec,按照链表的形式存储所有的任务结构变量,此结构变量中将存储所有任务所需要的信息。
通过调用osalTaskAdd()依次添加每个任务。
添加任务有三个作用的参数,他们分别是:pfnInit、pfnEventProcessor和taskPriority(任务初始化函数地址、任务处理函数地址和任务的优先级)而 taskID参数则是系统通过osalAddTasks()函数随机给分配的。
osal原理
OSAL原理详解1. OSAL概述OSAL(Operating System Abstraction Layer)是一种操作系统抽象层,它的目的是提供一套统一的接口,使得应用程序可以在不同的操作系统上运行而无需修改代码。
OSAL可以隐藏不同操作系统之间的差异,使得应用程序可以更加方便地移植和跨平台。
OSAL通常包含以下几个方面的功能:•线程管理:提供创建、销毁、调度和同步线程的接口。
•任务管理:提供创建、销毁和调度任务的接口。
•内存管理:提供内存分配和释放的接口。
•时钟管理:提供获取系统时间和延时的接口。
•事件管理:提供事件的创建、销毁和等待的接口。
在下面的内容中,我们将详细解释OSAL的基本原理和实现方式。
2. OSAL的基本原理OSAL的基本原理是通过封装操作系统的底层接口,提供一套统一的高层接口给应用程序使用。
这样,应用程序可以使用OSAL提供的接口来完成操作系统相关的功能,而无需关心具体的操作系统实现细节。
下面我们将分别介绍OSAL的几个基本功能的实现原理。
2.1 线程管理线程管理是OSAL的一个重要功能,它负责创建、销毁、调度和同步线程。
为了实现线程管理功能,OSAL通常会提供以下几个接口:•创建线程:OSAL提供一个函数用于创建新的线程。
该函数接受一个函数指针作为参数,表示新线程的入口函数。
在函数内部,OSAL会调用操作系统的底层接口来创建一个新的线程,并执行指定的入口函数。
•销毁线程:OSAL提供一个函数用于销毁指定的线程。
该函数接受一个线程句柄作为参数,表示待销毁的线程。
在函数内部,OSAL会调用操作系统的底层接口来销毁指定的线程。
•线程调度:OSAL提供一个函数用于调度线程。
该函数会根据一定的调度算法从就绪队列中选择一个线程,并将其设置为运行状态。
在函数内部,OSAL 会调用操作系统的底层接口来实现线程调度功能。
•线程同步:OSAL提供一些函数用于线程同步操作,如互斥锁、信号量、条件变量等。
WSN知识点(复习资料)
WSN知识点(复习资料)⼀、填空题1、WSN的全称是Wireless Sensor Networks2、⽆线传感器⽹络通常包括传感器节点、汇聚节点、⽹关节点和基站3、⽆线传感器节点随机或有规律地部署在监测区域内部或附近,通过⽆线多跳⾃组织⽅式构成⽹络。
4、⽆线传感器节点的硬件部分⼀般由传感器模块、处理器模块、⽆线通信模块和能量供应模块4部分组成5、对⽆线传感器⽹络来说,协议栈包括物理层、数据链路层、⽹络层、传输层和应⽤层,与互联⽹协议的五层相对应。
6、对⽆线传感器⽹络来说,协议栈包括能量管理平台、移动管理平台和任务管理平台。
7、低成本、低功能和对等通信,是短距离⽆线通信技术的三个重要特征和优势。
8、Bluetooth⼯作在全球开放的2.4GHzISM频段9、Wi-Fi使⽤的是2.4GHz附近的频段10、RFID由标签(Tag)、解读器(Reader)和天线(Antenna)三个基本要素组成11、ZigBee技术基于IEE802.15.4⽆线标准研制开发的12、ZigBee的基本速率是250kb/s,可与254个节点联⽹13、ZigBee使⽤的频段分别为2.4GHz、868MHz(欧洲)915MHz(美国),均为免执照频段14、在⽆线传感器⽹络中,物理层是数据传输的最底层,向下直接与传输介质相连,物理层协议是各种⽹络设备进⾏互联时必须遵循的底层协议。
15、频率的选择直接决定⽆线传感器⽹络节点的⽆线尺⼨、电感的集成度以及节点功耗16、动态变化的拓扑结构是⽆线传感器⽹络最⼤特点之⼀17、⽆线传感器⽹络的定位是指⾃组织的⽹络通过特定⽅法提供节点位置信息。
18、ZigBee⽀持星型拓扑、⽹状拓扑和混合型拓扑3种⽆线⽹络拓扑结构19、拓扑控制研究已经形成功率控制和睡眠调度两个主流研究⽅向。
20、功率控制,就是为传感器节点选择合适的发射功率;睡眠调度,就是控制传感器节点在⼯作状态和睡眠状态之间的转换。
21、区域覆盖研究对⽬标区域的覆盖(监测)问题;点覆盖研究对⼀些离散的⽬标点的覆盖问题;栅栏覆盖研究运动物体穿越⽹络部署区域被发现的概率问题。
osal操作系统函数使用
Zigbee协议栈OSAL层API函数(译)收藏3.信息管理API3.1 概述这部分API提供了任务或处理单元与不同的处理环境之间的数据交换。
这部分API函数能够为任务分配和收回消息缓冲区,发送命令消息给以外一个任务并且接收应答。
3.2 osal_msg_allocate ( )概述:当一个任务调用这个函数时,将为消息分配缓冲区,函数会将消息加入缓冲区,并调用osal_msg_send()将消息发送到另一个任务。
原型:byte *osal_msg_allocate( uint16 len )参数:len :消息的长度返回值:指向消息缓冲区的指针,当分配失败时返回NULL3.3 osal_msg_deallocate( )概述:用于收回缓冲区原型:byte osal_msg_deallocate( byte *msg_ptr )参数:Msg_ptr : 指向将要收回的缓冲区的指针返回值:RETURN V ALUE DESCRIPTIONZSUCCESS 回收成功INV ALID_MSG_POINTER 错误的指针MSG_BUFFER_NOT_A V AIL 缓冲区在队列中3.4 osal_msg_send( )概述:任务调用这个函数以实现发送指令或数据给另一个任务或处理单元。
目标任务的标识必须是一个有效的系统任务,当调用osal_create_task ( )启动一个任务时,将会分配任务标识。
osal_msg_send()也将在目标任务的事件列表中设置SYS_EVENT_MSG原型:byte osal_msg_send( byte destination_task, byte *msg_ptr )参数:destination_task :目标任务的标识msg_ptr :指向消息缓冲区的指针返回值:ZSUCCESS 消息发送成功INV ALID_MSG_POINTER 无效指针INV ALID_TASK 目标任务无效3.5 osal_msg_receive( )概述:任务调用这个函数来接收消息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
主函数执行以下函数由上可以看出main()函数共做了2件事:一是系统初始化,另外一件是开始执行轮转查询式操作系统,重点就是调用了osal_init_system()和osal_start_system()。
1.屏蔽所有中断osal_int_disable( INTS_ALL );2.初始化底板HAL_BOARD_INIT();3.电压检测 zmain_vdd_check();4.初始化IO InitBoard( OB_COLD );5.初始化硬件驱动HalDriverInit();6.初始化非易变量页面osal_nv_init( NULL );7.初始化MAC层 ZMacInit();10.中断使能osal_int_enable( INTS_ALL );11.zmain_dev_info();12.#ifdef LCD_SUPPORTEDzmain_lcd_init();13.#ifdef WDT_IN_PM1看门狗WatchDogEnable( WDTIMX );14.osal_start_system();程序最终会在系统函数中无限循环下去。
1.1osal_run_system();无限的循环,1.1.1任务轮序,跳转事件处理函数在进入无限循环之前系统定义了三个至关重要的变量,taskArr-----此数组的每一项都是const pTaskEventHandlerFn tasksArr[ ] ={- - - GenericApp_ProcessEvent }都是一个函数指针,指向具体的函数入口地址taskCnt-----保存了任务的总个数const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );taskEvent---指向事件表的首地址uint16 *tasksEvents;在任务初始化时osalInitTasks()做了这样一件事tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));//将字节清零?那么关键的问题还没解决,事件到底是怎么被捕获的SYS_EVENT_MSG = 0x8000 系统事件类号case ZDO_STATE_CHANGE:不需注册网络中的设备状态发生改变时,产生的事件消息ZDO_CB_MSG 要注册 ZDO_RegisterForZdoCB( uint8 indID, pfnZdoCb pFn );AF_INOMING_MSG_CMD 消息进入好像不需要注册添加这些事件前要先调用对应的Register函数端点描述符必须要注册afRegister( &GenericApp_epDesc );ZIGBEE事件有两类,系统定义事件和用户定义事件。
系统类事件是协议栈已定义好的,用户类事件是我们用户层面来定义的。
事件类号采用一个16bit的常量,使用独热码编码,独热码是只有一个bit为1,其他全为0的一种码制,采用独热码的优点是操作方便,可以使用简单的位操作指令实现,如:提取系统类事件用events & SYS_EVENT_MSG,清除系统类事件用events ^ SYS_EVENT_MSG;由于事件类号是16bit,也就是说zigbee事件类只有16个,系统类事件SYS_EVENT_MSG使用0x8000,故自定义事件类只有15个,可采用0x4000至0x0001。
实际上在协议栈里发现其中有几个已经用过了。
#define HAL_KEY_EVENT 0x0001#define HAL_LED_BLINK_EVENT 0x0002#define HAL_SLEEP_TIMER_EVENT 0x0004#define PERIOD_RSSI_RESET_EVT 0x0008系统类事件SYS_EVENT_MSG是协议栈里已经定义好的事件,它是一个事件集合,以下的几个事件都属于系统类事件,这些事件都是8位的二进制数,从0x00~0xcf:①AF_INCOMINGMSG_CMD表示收到一个新的无线数据。
②ZDO_STATE_CHANGE当网络状态发生变化时,会产生该事件,如终端节点加入网络时,就可以通过判断该事件来决定何时向协调器发送数据包。
③ZDO_CB_MSG指示每一个注册的ZDO响应消息④AF_DATA_CONFIRM_CMD调用AF_DataRequest()发送数据时,有时需要确认信息。
⑤AF_INCOMING_KVP_CMD:Incoming KVP type message收到键值对类型的消息。
⑥AF_INCOMING_GRP_KVP_CMD:Incoming Group KVP type message收到群键值对类型的消息。
⑦KEY_CHANGE:Key Events按键触发事件。
⑧ZDO_NEW_DSTADDR:ZDO has received a new DstAddr for this app ZDO终端获得新地址;匹配描述符请求(Match Descriptor Request)响应指示(例如:自动匹配);如A设备加入绑定后,A 设备触发ZDO_NEW_DSTADDR事件。
⑨ZDO_MATCH_DESC_RSP_SENT:ZDO match descriptor response was sent ZDO描述符匹配响应发送;A设备发送ZDP_MatchDescReq函数请求描述符匹配绑定,B设备收到后发送ZDP_MatchDescRsp函数响应,B设备发送响应函数后触发ZDO_MATCH_DESC_RSP_SENT事件。
⑩用户可以定义的事件类号还有15个从0x4000至0x0001,各个事件类下用户可定义的事件号29个从0xE0~0xFC. 事件处理函数为:app_ProcessEvent( byte task_id, UINT16 events ),可见调用此函数将传递两个参数,task_id任务号和events事件类号;事件处理函数首先根据事件类号来判断是何种类型事件,然后根据任务号得到消息指针pMsg,最后根据消息指针结构里的事件号pMsg->event 来具体处理事件,event为8bit的常量,系统event在ZComDef.h里定义。
event是如何被改变从而触发事件处理函数的呢?通过osal_set_event()这个函数。
当然一般都是通过osal_start_timerEx(),osal_msg_send() 来触发,这俩个函数都调用了osal_set_event()脑子不够用了,速度做个总结,以后有时间会仔细的把每个函数都分析一遍。
首先,OSAL专门建立了一个任务来对硬件资源进行管理,这个任务的事件处理函数是Hal_ProcessEvent。
在这个函数中通过调用osal_start_timerEx( Hal_TaskID, HAL_KEY_EVENT, 100);这个函数使得每隔100毫秒就会执行一次HalKeyPoll()函数。
HalKeyPoll()获取当前按键的状态,并且通过调用OnBoard_KeyCallback函数向GenericApp任务发送一个按键消息,并且设置tasksEvents中GenericApp所对应的值为非零。
在osal_set_event这个函数中,有这样一个语句:tasksEvents[task_id]|=event_flag;}下面以一个例子说明事件到底是怎样被捕获的:#define AT_COMMEND 0x01osal_set_event( GenericApp_TaskID, AT_COMMEND);设置了自己的事件下面来看一下这个函数是怎样设置事件的。
uint8 osal_set_event( uint8 task_id, uint16 event_flag ) 函数原型{if ( task_id < tasksCnt ){halIntState_t intState;HAL_ENTER_CRITICAL_SECTION(intState); // Hold off interruptstasksEvents[task_id] |= event_flag; // Stuff the event bit(s)只将某一位置1传到此函数的任务号就是GenericApp_TaskID用户任务号,事件就是自己定义的事件号0x01(不管是8位还是16位最好选择独热码,因为tasksEvents是双字节的数组所以如果定义的是8位事件那么高8位就会补0)。
这样tasksEvents[task_id]里面16位的某一位就会置1,这个1就是自己定义的事件。
这个事件一般只会被执行一次,在系统轮询下某个层如果有事件发生时,系统会这样处理事件1、events= tasksEvents[task_id];取出事件号2、tasksEvents[task_id]=0;当前任务下的事件清03、events=tasksArr[task_id](idx,events);处理事件所以在下次任务轮询时如果此事件没有被再设置的话,它就不会再被执行。
HAL_EXIT_CRITICAL_SECTION(intState); // Release interruptsreturn ( SUCCESS );}else{return ( INVALID_TASK );}}1.3下面是系统消息(事件)其余的是用户可以自己定义的消息。
可以称之为消息事件,用户通过定义一个消息事件然后调用函数1.2下面是事件EVENT。