| 本帖最后由 1079236915 于 2024-12-2 21:38 编辑 
 什么是OSAL
 OSAL(operating system abstraction layer),操作系统抽象层,是一种以实现多任务为核心的系统资源管理机制,实现了类似RTOS的某些功能,但并不能称之为真正意义上的RTOS,因为其本身还不支持任务的挂起,任务的抢占等等功能,但是这种机制,实现的代码十分精简,占用资源也非常少,对于资源十分紧张的嵌入式平台,也可以完成比较复杂的逻辑功能。
 osal头文件框架
 
 osal头文件   接下来看一下main函数里如何对osal进行初始化的
 
 如何使用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里有着不同类型的任务,分别对应着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;
 }
 
 
 
 
 
 
 
 
 |