freertos任务级临界代码保护

freertos任务级临界代码保护

最近做项目过程中,调用播放tts语音接口播放语音时概率性出现语音播报卡顿问题,下面对此问题解决过程做个简单记录。
代码框架是一个语音播报任务,其他任务需要播报语音给此任务发送播报消息,收到播报消息后,播报对应消息的内容即可。
在这里插入图片描述

一.任务优先级

播报时卡顿,可能是因为播报过程中被其他任务打断造成的,所以从提高任务优先级方向考虑一下。
查看代码FreeRTOSConfig.h中configMAX_PRIORITIES值为任务优先级最大值(0~configMAX_PRIORITIES-1),查看其他任务的优先级别,将语音播报的优先级提高。
修改方法:
1.创建时增加其优先级
portBASE_TYPE xTaskCreate(pdTASK_CODE pvTaskCode,const portCHAR * const pcName,unsigned portSHORT usStackDepth,void *pvParameters,unsigned portBASE_TYPE uxPriority,xTaskHandle *pvCreatedTask);

参数 含义
pvTaskCode 指向任务的入口函数. 任务必须执行并且永不返回 (即:无限循环,一个句柄).
pcName 描述任务的名字。主要便于调试。最大长度由configMAX_TASK_NAME_LEN.定义
usStackDepth 指定任务堆栈的大小 ,堆栈能保护变量的数目- 不是字节数. 例如,如果堆栈为16位宽度,usStackDepth定义为 100, 200
pvParameters 指针用于作为一个参数传向创建的任务
uxPriority 任务运行时的优先级( 0 : 优先级最低)
pvCreatedTask 用于传递一个处理——引用创建的任务

2.调用函数接口修改任务优先级
void vTaskPrioritySet( TaskHandle_t pxTask, UBaseType_t uxNewPriority );

参数 含义
pxTask 任务句柄
uxNewPriority 给任务配置的新的优先级

修改任务优先级后,此问题没有根本解决。

二.freertos调度锁

增加任务优先级后,不能解决问题,现在想通过关闭freertos任务调度,尝试解决。
任务调度锁:调度锁就是 RTOS 提供的调度器开关函数,如果某个任务调用了调度锁开关函数,处于调度锁开和调度锁关之间的代码在执行期间是不会被高优先级的任务抢占的,即任务调度被禁止。这一点要跟临界段的作用区分开,调度锁只是禁止了任务调度,并没有关闭任何中断,中断还是正常执行的。而临界段进行了开关中断操作。
调度锁开启:void vTaskSuspendAll( void );
调度锁关闭:BaseType_t xTaskResumeAll(void);此函数返回 pdTRUE,否则返回 pdFALSE
强制任务切换:taskYIELD() 主动让出cpu,让同优先级的其他task获得cpu,因为没有其他优先级的task,所有调度器不会切换优先级
注意:

  1. 调度锁函数只是禁止了任务调度,并没有关闭任何中断。
  2. 调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 一定要成对使用。
  3. 切不可在调度锁开启函数 vTaskSuspendAll 和调度锁关闭函数 xTaskResumeAll 之间调用任何会引起任务切换的 API,比如 vTaskDelayUntil、 vTaskDelay、 xQueueSend 等。

代码中做如下修改:
freertos任务级临界代码保护_第1张图片
修改编译工程后,发现此方法不适用与此项目,因为此项目跑了好多定时器中断还有硬件中断,并且中断处理中会调用任务切换api,在调用这两个函数后,发现设备死机。

三.任务临界代码保护机制

临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段,比如本文中tts语音播报就是不能被打断的,否则,就会出现所谓的语音卡顿问题。
FreeRTOS 与临界段代码保护有关的函数有4 个: taskENTER_CRITICAL() 、taskEXIT_CRITICAL() 、taskENTER_CRITICAL_FROM_ISR() 和taskEXIT_CRITICAL_FROM_ISR(),这四个函数其实是宏定义,在task.h 文件中有定义。这四个函数的区别是前两个是任务级的临界段代码保护,后两个是中断级的临界段代码保护。
本文介绍下任务的临界代码保护。
taskENTER_CRITICAL()和taskEXIT_CRITICAL()是任务级的临界代码保护,一个是进入临界段,一个是退出临界段,这两个函数是成对使用的,可自行去tasks.c中查看。
使用方法很简单,在临界区代码上下直接调用即可。
在这里插入图片描述
播报语音卡顿问题就此解决。
注意:
注意临界区代码需要尽量的精简,因为进入临界区会关闭中断,这样会导致优先级低于configMAX_SYSCALL_INTERRUPT_PRIORITY 的中断得不到及时的响应。
至于configMAX_SYSCALL_INTERRUPT_PRIORITY定义在FreeRTOSConfig.h中,可自行配置,此定义应用于RTOS临界区屏蔽,逻辑优先级高于此值的中断不受RTOS影响,逻辑优先级低于此值的中断会被屏蔽。

中断级的临界段代码保护应用与中断处理函数中,使用方法相同,此处不做介绍。

你可能感兴趣的:(bug记录)