本帖最后由 冒汗的心情 于 2016-4-15 13:43 编辑
CC2541任务,事件,消息的区别及添加自定义任务
一、简介
本篇介绍CC2541如何在SimpleBLEPeripheral工程中,添加一个自定义任务,如香瓜任务。(香瓜任务与工程原有任务相互独立,互不影响)。使用的协议栈版本:BLE-CC254x-1.4.0,编译软件:IAR 8.20.2,硬件平台:Smart RF(主芯片CC2541)。
二、基础知识
1、任务、事件、消息的区别
1)简述
1台设备中有多个任务,1个任务有16个事件,消息用于不同任务之间的传递。
2)详述
任务:SimpleBLEPeripheral工程中从底层的LL层到应用的Application层,一共分为有12个任务,每个任务会分配一个事件管理的变量,变量统一存在:
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
uint16 *tasksEvents;
其中,越底层的优先级越高,应用层的优先级是最低的,也就是此层中的事件是最后才会处理。
事件:1个任务中有16个事件,也就是上面tasksEvents的16位每一位都对应一个事件,0x0001意味着第0位的事件需要被执行。
注意,每个任务的第15位事件(0x8000)是用于不同任务之间的消息传递的,此事件不可被我们编程使用!!!!
消息:用于不同任务之间的传递。
比如,当按键按下时,HAL层检测到了按键,osal会将按键的信息打包,通过消息的形式发往应用层,最终在应用层做按键的处理。
下面举个例子,加强理解。
例如,tasksEvents[11] = 0x0002,那么就意味着,第11个任务的第1位事件需要被执行。
首先,在OSAL_SimpleBLEPeripheral.c中,可以看到第11个任务是应用层。
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
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.h文件中,发现0x0002事件是周期事件
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
// Simple BLE Peripheral Task Events
#define SBP_START_DEVICE_EVT 0x0001
#define SBP_PERIODIC_EVT 0x0002
最后,当osal层执行到应用层时,就会去执行应用层中的事件处理函数SimpleBLEPeripheral_ProcessEvent中的SBP_PERIODIC_EVT事件了。
2、是否一定需要添加自己的任务、事件、消息?
答:SimpleBLEPeripheral工程中已经给每个层分配了任务,而osal也把消息机制做好了,因此并不一定要添加自己的任务、消息。
而应用层的事件往往是需要被改动的,比如添加按键事件、通信事件、定时事件、采集事件……
当应用层的16个事件都被你使用完了,这时候才需要考虑新增一个任务,这样又多16个事件可使用。
四、修改代码
1、添加香瓜任务的初始化调用
1)调用香瓜任务的初始化函数(OSAL_SimpleBLEPeripheral.c的osalInitTasks中)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
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++ );
/* 香瓜应用 */
GUA_Init( taskID );
//香瓜
}
注意SimpleBLEPeripheral_Init任务的括号中,taskID需要增加。而香瓜任务为最后一个任务,不需要再增加。
2)注册香瓜任务的事件(OSAL_SimpleBLEPeripheral.c中)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
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
//香瓜
GUA_ProcessEvent // task 12
//香瓜
};
将香瓜任务中的事件处理函数名称,写到tasksArr中,当osal轮询到有香瓜任务的事件需要执行时,就会执行GUA_ProcessEvent函数。
3)添加香瓜任务的头文件(OSAL_SimpleBLEPeripheral.c中)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
//香瓜
#include "GUA.h"
//香瓜
2、编写并添加香瓜任务
1)写一个GUA.c(存放在“……BLE-CC254x-1.4.0ProjectsbleSimpleBLEPeripheralSourceGUA”路径下)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
//******************************************************************************
//name: GUA.c
//introduce: 香瓜任务
//author: 甜
//changetime:
//email:
//******************************************************************************
/*********************头文件************************/
#include "GUA.h"
#include "OSAL.h"
#include "ioCC2541.h"
/*********************宏定义************************/
#define VOID (void)
#define GUA_LED_TEST_EVT_PERIOD 1000
/***************内部变量声明************************/
static uint8 GUA_TaskID; // Task ID for internal task/event processing
/***************内部函数声明************************/
static void GUA_ProcessOSALMsg( osal_event_hdr_t *pMsg );
//******************************************************************************
//name: GUA_Init
//introduce: 香瓜任务的初始化
//parameter: task_id:任务的ID
//return: none
//author: 甜
//email:
//changetime: 2016.04.07
//******************************************************************************
void GUA_Init( uint8 task_id )
{
GUA_TaskID = task_id;
//执行香瓜任务的启动事件
osal_set_event( GUA_TaskID, GUA_START_DEVICE_EVT );
}
//******************************************************************************
//name: GUA_ProcessEvent
//introduce: 香瓜任务的事件处理
//parameter: task_id:任务的ID,
// events:事件
//return: 返回执行后的事件状态
//author: 甜
//email:
//changetime: 2016
//******************************************************************************
uint16 GUA_ProcessEvent( uint8 task_id, uint16 events )
{
VOID task_id;
//系统事件
if ( events & SYS_EVENT_MSG )
{
uint8 *pMsg;
if ( (pMsg = osal_msg_receive( GUA_TaskID )) != NULL )
{
GUA_ProcessOSALMsg( (osal_event_hdr_t *)pMsg );
VOID osal_msg_deallocate( pMsg );
}
return (events ^ SYS_EVENT_MSG);
}
//香瓜任务的启动事件
if ( events & GUA_START_DEVICE_EVT )
{
osal_start_timerEx( GUA_TaskID, GUA_LED_TEST_EVT, GUA_LED_TEST_EVT_PERIOD );
return ( events ^ GUA_START_DEVICE_EVT );
}
//香瓜任务的LED点灯事件
if ( events & GUA_LED_TEST_EVT )
{
//test
P1_1 = ~P1_1; //这里测试按一次长按键按键,就取反一次P1_1,方便观察P1_1对应的led
P1SEL &= ~(1 << 1); //设置为IO口
P1DIR |= (1 << 1); //设置为输出
osal_start_timerEx( GUA_TaskID, GUA_LED_TEST_EVT, GUA_LED_TEST_EVT_PERIOD );
//test
return ( events ^ GUA_LED_TEST_EVT );
}
return 0;
}
//******************************************************************************
//name: GUA_ProcessOSALMsg
//introduce: 香瓜任务的消息处理
//parameter: pMsg:消息
//return: none
//author: 甜
//email:
//changetime: 2016.04.07
//******************************************************************************
static void GUA_ProcessOSALMsg( osal_event_hdr_t *pMsg )
{
switch ( pMsg->event )
{
default:
break;
}
}
2)写一个头文件GUA.h(存放在“……BLE-CC254x-1.4.0ProjectsbleSimpleBLEPeripheralSourceGUA”路径下)
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
//******************************************************************************
//name: GUA.c
//introduce: 香瓜任务头文件
//author: 甜甜的大香瓜
//changetime: 2016.04.07
//email: 897503845@qq.com
//******************************************************************************
#ifndef GUA_H
#define GUA_H
#ifdef __cplusplus
extern "C"
{
#endif
/*********************头文件************************/
#include "bcomdef.h"
/*********************宏定义************************/
#define GUA_START_DEVICE_EVT 0x0001
#define GUA_LED_TEST_EVT 0x0002
/*******************香瓜函数************************/
extern void GUA_Init( uint8 task_id );
extern uint16 GUA_ProcessEvent( uint8 task_id, uint16 events );
#ifdef __cplusplus
}
#endif
#endif
3)工程中添加GUA.c和GUA.h
4)在IAR设置中添加香瓜任务的源文件路径
[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
$PROJ_DIR$....SimpleBLEPeripheralSourceGUA
五、实验结果
代码下进Smart RF之后,板子上P11引脚对应的LED2会一秒变换一次亮、灭状态。
这个LED2亮灭的测试代码即在香瓜任务中实现的,所以香瓜任务添加成功。
|