现成轮子OSAL操作系统抽象层的移植
简单介绍一下Z-STACK中的OSAL,值得一看的现成轮子;
什么是 OSAL?
今天同学忽然问我有没有搞过OSAL
,忽然间一头雾水,于是在搜索引擎上找到了答案,发现这是一个十分实用的东西。
OSAL(operating system abstraction layer
),操作系统抽象层,是一种以实现多任务为核心的系统资源管理机制,实现了类似RTOS
的某些功能,但并不能称之为真正意义上的RTOS
,因为其本身还不支持任务的挂起,任务的抢占等等功能。
但是这种机制,实现的代码十分精简,占用资源也非常少,对于资源十分紧张的嵌入式平台,也可以完成比较复杂的逻辑功能。
在TI CC2530
的ZIGBEE
协议栈Z-STACK
中可以找到OSAL的身影,可以在官网上搜索z-stack
下载相关的源码,其中就包含了OSAL
实现的源码;
移除掉一些无关功能的代码之后,剩下OSAL的源码总共约1100多行代码,全部由C语言实现,资源占用约为
RAM:512Byte ROM:2KB
理论上可以移植到绝大多数的芯片平台上。
源码安装
目前官网上最新的版本,下载安装到本地;
安装完成之后,可以到安装目录下,找到相应的源码,不过这里基本上是zigbee
的协议栈,所以OSAL
相关的部分在下图所示的路径中;
进入到osal
路径下的文件结构如下图所示;
这个OSAL
操作系统抽象层用于保护协议栈软件组件不受程序硬件细节的影响,减少程序的耦合性,提高可移植性和复用性。它可以独立于程序环境,并且提供了以下功能。
任务注册、初始化、启动; 任务间的消息交换; 任务同步; 中断处理; 计时器; 内存分配;
Linux 上OSAL的移植
可以尝试把OSAL
的框架移植到单片机上,进行测试,这里是GitHub
上fork
的一个仓库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
工程目录下,然后对工程文件列表进行刷新,可以看到如下图所示;
下面是作者基于ti
的osal
的移植说明:
完成 OSAL\hal\timer.c
文件,为系统提供时钟;修改 OSAL\include\type.h
文件中的全局中断开关函数(可以为空),添加芯片对应的头文件,根据需要修改数据类型重定义,根据芯片字长修改halDataAlign_t类型;根据需要修改 OSAL\osal\osal_memory.h
文件中的内存池大小定义,文件中osalMemHdr_t类型需要确保长度为16bit或以上,非8位单片机需要设定内存池的字节对齐;添加任务函数中的任务优先级数值大的任务则优先级高; 根据需要修改 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
长按下图二维码关注,独自前进,走得快;结伴而行,走得远;在这里除了肝出来的文章,还有一步一个脚印学习的点点滴滴;