关注+星标公众号,不错过精彩内容
杰理蓝牙针对不同系列芯片,搭载的嵌入式操作系统可能存在差异。杰理在进行SDK设计时,专门设置了一个OS API抽象层,其对所使用的操作系统进行了封装,即使底层使用不同的嵌入式操作系统,能向上层应用提供统一的API接口。杰理系统层OS支持任务管理、信号量、互斥量、队列、延时等系统级的基础功能。本篇文章对杰理系统层OS API相关代码进行简单分析与介绍。
说到操作系统,那首先不得不提到“任务”,通常也称之为线程 ,是操作系统调度的最小单位,一般操作系统任务状态流转如下图。

任务的使用主要包括任务创建、调度、状态管理等操作。以下以杰理JL701N-SDK为例展开:
任务设置
在app_main.c文件中的task_info_table[]中填入任务的基本设置,包括任务名、优先级、任务栈内存大小等设置,具体配置例如下:

任务启动运行
这里以最常用的“app_core”任务为例,这可以认为是杰理SDK的主任务,在开机启动的时候便会调用OS API中的创建任务函数task_create()来创建“app_core”任务,如下图

在系统运行os_start之后,可以将app_core任务看成一个“长期存在”的执行实体,此时的任务会进入运行app_task_loop()函数,此时app_core任务会进入任务循环中持续运行,如下图app_task_loop函数的处理,任务相关初始化app_task_init()完成之后会循环while(1),没有消息时一直处于阻塞状态等待各模式的消息处理。

信号量
信号量(Semaphore)是操作系统中用于实现进程/线程间同步的核心原语,其本质上可以理解成是一个变量。一般用来解决进程间的同步逻辑问题,比如需要某个进程完成某一动作后,另外一个进程再进行某些动作,信号量(Semaphore)便可以作为同步信号完成上述进程的同步逻辑。
如下为杰理SDK一个的应用举例:app_core任务中led驱动初始化时使用了信号量,使用OS API提供的信号量创建函数os_sem_create()创建了一个led_driver_ready_sem的信号量。

在调用task_creat()创建了“led_driver”任务之后便停会在这里一直等待led_driver_ready_sem的信号量os_sem_pend(led_driver_ready_sem, 0);而当“led_driver”任务启动之后,进入任务循环led_driver_task()函数,这时调用os_sem_post()发送led_driver_ready_sem信号量。“app_core”任务在接收到“led_driver”任务发来的信号量之后继续进行接下来的初始化以及后续的代码流程,实现了进程间的同步。

互斥量
互斥量(Mutex) 是操作系统中核心的互斥原语,是一种特殊的信号量,本质上是一把独占锁,核心目的是保证在同一时间,只能有一个线程能访问共享资源(临界区),杜绝多任务并发操作带来的竞态条件。
互斥量在杰理SDK中的应用举例:如下图,在时钟管理分配函数入口处加入了互斥量操作,使用os_mutex_pend()函数加互斥锁保护临界区,避免在一个任务中申请时钟操作的时候,另一个任务同时修改操作了临界区中的时钟链表,保障整个时钟分配操作的安全。

消息队列(Queue)是操作系统中的一种先进先出的数据结构,是进程间的一种通信机制。简单来说,消息队列就像内核为任务(或进程)搭建的一个公共信箱:进程A把要传递的信息(消息)按规则放进信箱,进程B在需要时从信箱中取出消息,二者不用同时在线,也不用直接交互,由内核负责消息的存储、管理和转发。

“app_core”任务在跑起来之后便会进入各模式的消息处理函数,如上为BT模式消息处理,BT模式会一直处于一个while循环下,一直等待处理消息的状态,app_get_message()实际调用的就是OS API中的os_taskq_pend()函数,任务在阻塞态等待消息。

在其他任务下给“app_core”任务发送消息,即可让“app_core”任务进入就绪等待系统调度运行。比如可以在其他线程调用OS API封装的os_taskq_post_type()函数发送Q_CALLBACK的消息可以在“app_core”任务上执行指定的函数和传递指定的参数。

以上便是杰理操作系统代码使用简单说明,祝小伙伴们开发顺利。
欢迎加入蓝牙音频领域的技术交流群,这是一个致力于为行业技术爱好者、工程师及专业人士搭建技术研讨平台和资源共享互助空间。如需加入,可添加我微信(有时是助理),备注 “蓝牙音频入群” ,助理将尽快邀您进群,期待与您共同探讨技术!
------------ END-----------