查看原文
其他

现成轮子OSAL操作系统抽象层的移植

菜刀和小麦 小麦大叔 2022-05-20

简单介绍一下Z-STACK中的OSAL,值得一看的现成轮子;

什么是 OSAL?

今天同学忽然问我有没有搞过OSAL,忽然间一头雾水,于是在搜索引擎上找到了答案,发现这是一个十分实用的东西。

OSAL(operating system abstraction layer),操作系统抽象层,是一种以实现多任务为核心的系统资源管理机制,实现了类似RTOS的某些功能,但并不能称之为真正意义上的RTOS,因为其本身还不支持任务的挂起,任务的抢占等等功能。

但是这种机制,实现的代码十分精简,占用资源也非常少,对于资源十分紧张的嵌入式平台,也可以完成比较复杂的逻辑功能。

TI CC2530ZIGBEE协议栈Z-STACK中可以找到OSAL的身影,可以在官网上搜索z-stack下载相关的源码,其中就包含了OSAL实现的源码;

移除掉一些无关功能的代码之后,剩下OSAL的源码总共约1100多行代码,全部由C语言实现,资源占用约为

  • RAM:512Byte
  • ROM:2KB

理论上可以移植到绝大多数的芯片平台上。

源码安装

目前官网上最新的版本,下载安装到本地;

TI官网下载的z-stack

安装完成之后,可以到安装目录下,找到相应的源码,不过这里基本上是zigbee的协议栈,所以OSAL相关的部分在下图所示的路径中;

目录结构

进入到osal路径下的文件结构如下图所示;

这个OSAL操作系统抽象层用于保护协议栈软件组件不受程序硬件细节的影响,减少程序的耦合性,提高可移植性复用性。它可以独立于程序环境,并且提供了以下功能。

  1. 任务注册、初始化、启动;
  2. 任务间的消息交换;
  3. 任务同步;
  4. 中断处理;
  5. 计时器;
  6. 内存分配;

Linux 上OSAL的移植

可以尝试把OSAL的框架移植到单片机上,进行测试,这里是GitHubfork的一个仓库OSAL ,已经具体的移植方法,可以在Linux平台上进行测试,

void osal_main(void)
{
    //系统硬件、外设等初始化

    //禁止中断
    HAL_DISABLE_INTERRUPTS();

    //osal操作系统初始化
    osal_init_system();

    //添加任务
    osal_add_Task(print_task_init, print_task_event_process, 1);
    osal_add_Task(statistics_task_init, statistics_task_event_process, 2);

    //添加的任务统一进行初始化
    osal_Task_init();

    osal_mem_kick();

    //允许中断
    HAL_ENABLE_INTERRUPTS();

    //设置初始任务事件,上电就需要自动轮询的任务事件可在此添加

    //启动osal系统,不会再返回
    osal_start_system();
}

STM32上OSAL的移植

如果直接使用ti官方的代码改动会相对比较大,这里直接在github上找到一份移植到stm32的工程,直接fork了一份改成HAL库,可以参考一下stm32-osal, 克隆代码之后,直接复制osal文件夹到CubeIDE工程目录下,然后对工程文件列表进行刷新,可以看到如下图所示;

下面是作者基于tiosal的移植说明:

  1. 完成OSAL\hal\timer.c文件,为系统提供时钟;
  2. 修改OSAL\include\type.h文件中的全局中断开关函数(可以为空),添加芯片对应的头文件,根据需要修改数据类型重定义,根据芯片字长修改halDataAlign_t类型;
  3. 根据需要修改OSAL\osal\osal_memory.h文件中的内存池大小定义,文件中osalMemHdr_t类型需要确保长度为16bit或以上,非8位单片机需要设定内存池的字节对齐;
  4. 添加任务函数中的任务优先级数值大的任务则优先级高;
  5. 根据需要修改OSAL\include\osal_memory.h文件中的OSALMEM_METRICS定义,有效则开启内存统计功能;

关键点

总体来说,因为站在巨人的肩膀上,整体的代码需要修改的部分已经很少了。首先这个机制是根据时间片轮询调度的,所以会对每个任务分配一个ID以及一个任务专属的定时器,同时,使用一个链表管理每个任务的定时器,同样的,每个定时器会更加任务ID来进行匹配,所以,需要在hal增加对定时器更新的函数;如下所示;

因为使用CubeMX修改配置,重新生成代码后会覆盖原文件stm32f1xx_it.c,所以,重新生成的时候,注意添加osal_update_timers(),如果对其他内容感兴趣的话,可以参考一下源码;

测试代码

使用串口3进行任务测试,定义了两个任务,先贴出其中的一部分,详细的可以全部的工程代码;

int osal_main(void)
{    
    HAL_DISABLE_INTERRUPTS();
    osal_init_system();
    
 osal_add_Task(Serial_Task_Init,Serial_Task_EventProcess, 1);
 osal_add_Task(Serial_Task_02_Init,Serial_Task_02_EventProcess, 2);
 osal_Task_init();
 osal_mem_kick();
 HAL_ENABLE_INTERRUPTS(); 
 //"hello task 01\r\n";
 osal_start_reload_timer( Serial_TaskID, PRINTF_STR, 100);
 //"hello task 02\r\n";
 osal_start_reload_timer( Serial_Task_02_ID, PRINTF_STR_TASK_02, 500);
 
 osal_start_system();
}

下面是运行结果:

结语

如果不使用RTOS,那么OSAL也是不错的选择,不过还需要对其源码需要进一步的理解,这样在出现问题的时候,才可以对症下药。

附件

该工程基于CubeIDE 1.3
百度网盘:https://pan.baidu.com/s/1zXkEp7jNoO-ODqMtU5YxBA)
提取码:ncry

Github:https://github.com/hotsauce1861/osal.git



长按下图二维码关注,独自前进,走得快;结伴而行,走得远;在这里除了肝出来的文章,还有一步一个脚印学习的点点滴滴;







您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存