【PB-03F-kit】初识OSAL操作系统

[复制链接]
查看172 | 回复2 | 前天 19:49 | 显示全部楼层 |阅读模式
本帖最后由 1079236915 于 2024-12-2 21:38 编辑

什么是OSAL
OSAL(operating system abstraction layer),操作系统抽象层,是一种以实现多任务为核心的系统资源管理机制,实现了类似RTOS的某些功能,但并不能称之为真正意义上的RTOS,因为其本身还不支持任务的挂起,任务的抢占等等功能,但是这种机制,实现的代码十分精简,占用资源也非常少,对于资源十分紧张的嵌入式平台,也可以完成比较复杂的逻辑功能。
osal头文件框架

osal头文件

osal头文件

接下来看一下main函数里如何对osal进行初始化的

  1. <div><font size="3">int app_main(void)</font>
  2. <font size="3">{</font>
  3. <font size="3">   <font color="#00ff00"> </font><font color="#9acd32">/*初始化操作系统*/</font></font>
  4. <font size="3">    osal_init_system();</font>
  5. <font size="3">    <font color="#9acd32">/*</font></font><font color="#9acd32">选择允许HAL睡眠管理器进入LITE睡眠状态或深度睡眠状态<span style="font-size: medium;">*/</span></font>
  6. <font size="3">    osal_pwrmgr_device( PWRMGR_BATTERY );//此处可以选择</font><span style="font-size: medium;">PWRMGR_ALWAYS_ON选项,不节省电力</span>
  7. <font size="3">    <font color="#9acd32">/* 启动OSAL */</font></font>
  8. <font size="3">    osal_start_system(); </font>
  9. <font size="3">    return 0;</font>
  10. <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;
}







回复

使用道具 举报

爱笑 | 昨天 08:36 | 显示全部楼层
用心做好保姆工作
回复

使用道具 举报

1055173307 | 昨天 09:15 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则