OSAL消息队列
事件是驱动任务去执行某些操作的条件,当系统中产生了一个事件,OSAL将这个事件传递给相应的任务后,任务才能执行一个相应的操作(调用事件处理函数去处理)。
通常某些事件发生时,又伴随着一些附件信息的产生,例如:从天线接收到数据后,会产生消息,但是任务的事件处理函数在处理这个事件的时候,还需要得到天线接收到的数据。
因此,这就需要将事件和数据封装成一个消息,将消息发送到消息队列,然后在事件处理函数中就可以使用osal_msg_receive,从消息队列中得到该消息。如下代码可以从消息队列中得到一个消息:
pMsg = osal_msg_receive( simpleBLEPeripheral_TaskID )
OSAL维护了一个消息队列,每一个消息都会被放到这个消息队列中去,当任务接收到事件后,可以从消息队列中获取属于自己的消息,然后调用消息处理函数进行相应的处理。
OSAL中消息队列如下所示:
每个消息都包含一个消息头osal_msg_hdr_t和自定义的消息,osal_msg_hdr_t结构体的定义为:
typedef struct
{
void *next;
uint16 len;
uint8 dest_id;
} osal_msg_hdr_t;
OSAL添加新任务
我们结合示例工程“simpleBLEPeripheral”来讲解,打开“Projects\ble\SimpleBLEPeripheral\Source”目录下的“OSAL_SimpleBLEPeripheral.c”文件可以找到数组“tasksArr[]”和初始化函数“osalInitTasks()”:
1.“tasksArr[]”数组里存放了所有任务的事件处理函数的地址。
2.“osalInitTasks()”函数是OSAL的任务初始化函数,所有任务的初始化工作都在这里完成,并且自动给每个任务分配一个任务ID。
因此,要添加新任务,我们只需要编写两个函数:
1.新任务的初始化函数。
2.新任务的事件处理函数。
将新任务的初始化函数添加在“osalInitTasks()”函数的最后,如下代码所示:
void osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
/* LL Task */
LL_Init( taskID++ );
/* Hal Task */
Hal_Init( taskID++ );
/* HCI Task */
HCI_Init( taskID++ );
#if defined ( OSAL_CBTIMER_NUM_TASKS )
/* Callback Timer Tasks */
osal_CbTimerInit( taskID );
taskID += OSAL_CBTIMER_NUM_TASKS;
#endif
/* L2CAP Task */
L2CAP_Init( taskID++ );
/* GAP Task */
GAP_Init( taskID++ );
/* GATT Task */
GATT_Init( taskID++ );
/* SM Task */
SM_Init( taskID++ );
/* Profiles */
GAPRole_Init( taskID++ );
GAPBondMgr_Init( taskID++ );
GATTServApp_Init( taskID++ );
/* Application */
SimpleBLEPeripheral_Init( taskID );
}
将新任务的事件处理函数的地址加入“tasksArr[]”数组的最后,如下所示:
const pTaskEventHandlerFn tasksArr[] =
{
LL_ProcessEvent, // task 0
Hal_ProcessEvent, // task 1
HCI_ProcessEvent, // task 2
#if defined ( OSAL_CBTIMER_NUM_TASKS )
OSAL_CBTIMER_PROCESS_EVENT( osal_CbTimerProcessEvent ), // task 3
#endif
L2CAP_ProcessEvent, // task 4
GAP_ProcessEvent, // task 5
GATT_ProcessEvent, // task 6
SM_ProcessEvent, // task 7
GAPRole_ProcessEvent, // task 8
GAPBondMgr_ProcessEvent, // task 9
GATTServApp_ProcessEvent, // task 10
SimpleBLEPeripheral_ProcessEvent // task 11
};
在此例中,将“SimpleBLEPeripheral_ProcessEvent”函数添加到了“tasksArr[]”数组的末尾,将“SimpleBLEPeripheral_Init( taskID );”函数也添加到了“osalInitTasks()”任务初始化函数的末尾了。
所以,需要注意一下两点:
1.“tasksArr[]”数组里各事件处理函数的排列顺序要与“osalInitTasks()”函数中调用各任务初始化函数的顺序保持一致,只有这样才能够保证每个任务的事件处理函数能够接收到正确的任务ID(在“osalInitTasks()”函数中分配的)
2.为了保证“osalInitTasks()”函数所分配的任务ID,需要给每一个任务定义一个全局变量来保存这个ID,在“Projects\ble\SimpleBLEPeripheral\Source”目录下的“simpleBLEPeripheral.c”文件中定义了一个全局变量“simpleBLEPeripheral_TaskID”,并且在“SimpleBLEPeripheral_Init()”初始化函数中对其赋值,所赋的值就是“osalInitTasks()”函数中调用“SimpleBLEPeripheral_Init()”初始化函数时传入的值。