在许多蓝牙SDK中通常会使用RTOS,而ST的蓝牙解决方案则采用了Sequencer。Sequencer并非真正的实时操作系统,而是专为较简单的应用场景设计的RTOS替代方案。不过,它并不涵盖操作系统提供的所有功能。

一、序列器如何处理应用程序的执行流程

任务创建:用于初始化任务,使其可被序列器内部调度器调用。
任务启用:通过任务或中断触发,使任务处于可执行状态,从而被调度器执行。
任务暂停/恢复:从调度器角度控制任务的执行状态(暂停或恢复),该操作与任务是否启用无关。
空闲任务:当调度器无任务可执行时,将调用可选钩子函数以管理空闲模式进入。
任务执行:调用与任务关联的函数,调度器在该函数返回前将保持锁定状态。
序列器:内置任务调度器,负责管理任务执行顺序,并允许任务在等待事件期间暂停运行。

二、需要了解

序列器并非操作系统
其目标并非与标准操作系统竞争,而是旨在优化标准的裸机实现方案
它是对传统裸机"while循环"实现方式的优化封装
有助于避免裸机实现中常见的竞态条件,尤其是在实现低功耗模式时
此外,了解序列器提供的功能特性至关重要:
最多可注册32个任务
支持任务执行请求
提供任务暂停与恢复功能
可等待特定事件(支持非阻塞模式)
支持任务优先级设定
允许管理空闲任务
三、Sequencer例子
1、首先建立一个基于NUCLEO-WBA65RI 开发板的空模板

只配置了bsp外设

2、工程中加入Sequencer源文件

3、加入include路径

4、程序

main.h
加入头文件,定义task

复制

 
  1. /* Private includes ----------------------------------------------------------*/
  2. /* USER CODE BEGIN includes */
  3. /* sequencer include */
  4. #include "stm32_seq.h"
  5. /* USER CODE END includes */
  6. /* Exported constants --------------------------------------------------------*/
  7. /* USER CODE BEGIN EC */
  8. /* Task ID definition */
  9. #define TASK0    1 << 0
  10. /* USER CODE END EC */



main.c
 

复制

 
  1. /* USER CODE BEGIN PFP */
  2. /* task function prototype */
  3. void function_Task0( void );
  4. /* USER CODE END PFP */

初始化Sequencer,注册task,while(1)中加入Sequencer守护

复制

 
  1. /* USER CODE BEGIN WHILE */
  2.   /* sequencer initialization */
  3.   UTIL_SEQ_Init();
  4.   /* sequencer task registration */
  5.   UTIL_SEQ_RegTask(TASK0, 0, function_Task0);
  6.   while (1)
  7.   {
  8.     /* USER CODE END WHILE */
  9.     /* USER CODE BEGIN 3 */
  10.         /* run the sequencer */  
  11.         UTIL_SEQ_Run(~0);  
  12.   }
  13.    /* USER CODE END 3 */
  14. }
在task函数中反转LED
复制

 
  1. /* USER CODE BEGIN 4 */
  2. /* task definition */
  3. void function_Task0( void )
  4. {
  5.         BSP_LED_Toggle(LED_GREEN);
  6. }
  7. /* USER CODE END 4 */


stm32xxxx_it.c
中断回调函数中,设置每400ms触发一次task0

复制

 
  1. void SysTick_Handler(void)
  2. {
  3.   /* USER CODE BEGIN SysTick_IRQn 0 */
  4.   /* USER CODE END SysTick_IRQn 0 */
  5.   HAL_IncTick();
  6.   /* USER CODE BEGIN SysTick_IRQn 1 */
  7.   /* each 400 ms set task 0 to be run */
  8.   if ((HAL_GetTick() % 400) == 0)
  9.   {
  10.           UTIL_SEQ_SetTask(TASK0, 0);
  11.   }
  12.   /* USER CODE END SysTick_IRQn 1 */
  13. }


 

首先进行序列器初始化:
UTIL_SEQ_init 初始化序列器运行环境
UTIL_SEQ_RegTask 注册TASK0并关联待执行函数
第二部分是在UTIL_SEQ_Run函数上运行的无限循环
SysTick中断处理程序指示序列器每400毫秒执行一次TASK0
当序列器检测到TASK0执行请求时,将调用其关联函数


---------------------
作者:sujingliang
链接:https://bbs.21ic.com/icview-3498990-1-1.html?_dsign=fb498385
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐