本帖最后由 1079236915 于 2024-12-2 21:38 编辑
什么是OSAL
OSAL(operating system abstraction layer),操作系统抽象层,是一种以实现多任务为核心的系统资源管理机制,实现了类似RTOS的某些功能,但并不能称之为真正意义上的RTOS,因为其本身还不支持任务的挂起,任务的抢占等等功能,但是这种机制,实现的代码十分精简,占用资源也非常少,对于资源十分紧张的嵌入式平台,也可以完成比较复杂的逻辑功能。
osal头文件框架
osal头文件
接下来看一下main函数里如何对osal进行初始化的
- <div><font size="3">int app_main(void)</font>
- <font size="3">{</font>
- <font size="3"> <font color="#00ff00"> </font><font color="#9acd32">/*初始化操作系统*/</font></font>
- <font size="3"> osal_init_system();</font>
- <font size="3"> <font color="#9acd32">/*</font></font><font color="#9acd32">选择允许HAL睡眠管理器进入LITE睡眠状态或深度睡眠状态<span style="font-size: medium;">*/</span></font>
- <font size="3"> osal_pwrmgr_device( PWRMGR_BATTERY );//此处可以选择</font><span style="font-size: medium;">PWRMGR_ALWAYS_ON选项,不节省电力</span>
- <font size="3"> <font color="#9acd32">/* 启动OSAL */</font></font>
- <font size="3"> osal_start_system(); </font>
- <font size="3"> return 0;</font>
- <font size="3">}</font></div>
复制代码 如何使用osal创建任务
在OSAL里有着不同类型的任务,分别对应着zigbee协议栈各层的任务处理函数,们有着不同的优先级,优先级高(数值小)的任务会先进行调度处理
每一个任务都会有一个任务号task_id。
static uint8 xx_TaskID;
tasksArr是一个函数指针数组,用于存放不同任务的处理函数(数组下标就是任务号)。
我们可以在例程xx_osal.c文件里找到任务表(tasksArr[])
const pTaskEventHandlerFn tasksArr[] =
{
LL_ProcessEvent,
xx_ProcessEvent,
...
}
OSAL 为每个任务函数分配了一个 16 位的事件变量,每一位代表一个事件,最高位 0x8000 保留为系统事件 SYS_EVENT_MSG。其余的 15 位留给用户自定义需要的事件。
tasksEvents是一个指向数组的指针,此数组保存了当前任务的状态
uint16 *tasksEvents;
两秒后我要点亮LED1,这就需要发送一个点亮 LED1 的事件,然后等待,在任务回调函数里判断对应的事件是否发生
if (events & xx_Task_EVT)
默认情况下,OSAL最大任务数为9,最大事件数为16
任务数量 由tasksArr 长度决定const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
事件数量 16位2进制uint16 *tasksEvents;
初始化任务
该函数为每个任务调用初始化函数.
为了方便用户开发程序,每个任务要以一个 Task 单独存在,
Task 的唯一标准用其 ID 组成,像下面这个的写法。
void osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16*)osal_mem_alloc( sizeof( uint16 ) * tasksCnt); //根据任务数量来分配空间,任务数量由tasksArr长度决定
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
LL_Init( taskID++);
/*
Application
*/
LED1_Init(taskID++);
LED2_Init(taskID++);
}
创建事件
创建OSAL事件的方法有2种:①定时器,②消息传递
本贴只使用定时器创建任务
定时器有两个API函数,
uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value ); 一次性定时器,在一次事件结束时需要再次调用
uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint32 timeout_value ); 重复定时器,无需重复调用
参数 taskID:任务ID event_id:任务状态 timeout_value :定时时间
接下来实现两个LED闪烁
OSAL_XX.c文件
const pTaskEventHandlerFn tasksArr[] =
{
LL_ProcessEvent,
LED1_ProcessEvent,
LED2_ProcessEvent
};
const uint8 tasksCnt = sizeof( tasksArr ) / sizeof( tasksArr[0] );
uint16* tasksEvents;
void osalInitTasks( void )
{
uint8 taskID = 0;
tasksEvents = (uint16*)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);
osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));
LL_Init( taskID++);
/*
Application
*/
LED1_Init(taskID++);
LED2_Init(taskID++);
}
gpio.c文件
void LED_Toggle(gpio_pin_e pin);
static uint8 Demo_TaskID1;
#define LED1_Task_EVT 0x0001
static uint8 Demo_TaskID2;
#define LED2_Task_EVT 0x0002
void LED_Toggle(gpio_pin_e pin)
{
if(hal_gpio_read(pin))
{
gpio_write(pin,0);
}
else
{
gpio_write(pin,1);
}
}
void LED1_Init(uint8 task_id)
{
Demo_TaskID1 = task_id;
LOG("%d\n",task_id);
gpio_pin_e pin = P34;
LOG("TASK1INIT\n");
hal_gpio_pin_init(pin,GPIO_OUTPUT);
osal_start_reload_timer(Demo_TaskID1, LED1_Task_EVT, 2000);
}
void LED2_Init(uint8 task_id)
{
Demo_TaskID2 = task_id;
LOG("task2id=%d\n",task_id);
gpio_pin_e pin = P0;
LOG("TASK2INIT\n");
hal_gpio_pin_init(pin,GPIO_OUTPUT);
osal_start_reload_timer(Demo_TaskID2, LED2_Task_EVT, 1000);
}
uint16 LED1_ProcessEvent( uint8 task_id, uint16 events )
{
//判断是否这个任务ID
if (task_id != Demo_TaskID1)
{
return 0;
}
//判断所在的ID是否一致
if (events & LED1_Task_EVT)
{
// LED 转换
LOG("TASK1\n");
LOG("%d\n",task_id);
hal_gpio_fast_write(P34,1);
WaitMs(300);
hal_gpio_fast_write(P34,0);
WaitMs(300);
return (events ^ LED1_Task_EVT);
}
return 0;
}
uint16 LED2_ProcessEvent( uint8 task_id, uint16 events )
{
//判断是否这个任务ID
if (task_id != Demo_TaskID2)
{
LOG("TASK2err\n");
return 0;
}
//判断所在的ID是否一致
if (events & LED2_Task_EVT)
{
LOG("TASK2\n");
hal_gpio_write(P0,1);
WaitMs(500);
hal_gpio_write(P0,0);
WaitMs(500);
return (events ^ LED2_Task_EVT);
}
LOG("TASK2err\n");
return 0;
}
|