FreeRTOS线程安全、中断安全的printf实现方式


前言

利用串口对基于FreeRTOS的多任务程序调试过程中,时常出现数据交叉打印,甚至出现乱码现象。这是因为通常情况下,串口打印函数所在任务的优先级不高,或者在程序中有多个任务均包含打印函数。此时,当发送数据时,容易被中断或者其它优先级更高的任务打断或抢占,在发送的数据量较大情况下,该现象尤为明显。

文本将介绍一种FreeRTOS的线程安全、中断安全的printf实现方式,并详细说明它是如何解决上述问题的。


一、问题描述

开发环境
平台:STM32Cube IDE,HAL库;
芯片:STM32L431CBT6;

串口设置
基于FreeRTOS的三任务程序,串口打印函数任务优先级最低,且在多个任务中均有打印函数。
串口设置如下:波特率115200;8位数据;一个停止位;一个起始位;无奇偶校验位;

输出展示
输出数据出现交叉打印现象,甚至出现乱码,如下图所示:

在这里插入图片描述

该程序下,串口的理想输出因该如下图所示:

在这里插入图片描述


二、解决方案

1. 线程安全、中断安全的printf实现方式

代码如下:

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;

/* Private function prototypes -----------------------------------------------*/
static int inHandlerMode(void);
/* 在C中,当无法列出传递函数的所有实参的类型和数目时,可以用省略号指定参数表  */
void print_usart1(char *format, ...);

/* Private function details --------------------------------------------------*/
static int inHandlerMode(void)
{
    
    
    /* 函数返回1表示正处于中断 */
	return __get_IPSR();
}

void print_usart1(char *format, ...)
{
    
    
	char buf[64];

	if (inHandlerMode() != 0)
	{
    
    
	    /* 处于中断,则关闭中断,防止中断嵌套致使线程不安全 */
		taskDISABLE_INTERRUPTS();
	}
	else
	{
    
    
	    /* 若串口正在发送数据则挂起此任务 */
		while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX)
		{
    
    
			osThreadYield();
		}
	}

	va_list ap; /* 声明字符指针ap */
	va_start(ap, format);/* 初始化变量ap,让ap指向可变参数表里面的第一个参数 */
	/* 使用参数列表发送格式化输出到字符串,如果成功,则返回写入的字符总数,否则返回一个负数。 */
	if (vsprintf(buf, format, ap) > 0)
	{
    
    
	    /* 100ms内发送 */
		HAL_UART_Transmit(&huart1, (uint8_t *)buf, strlen(buf), 100);
	}

	va_end(ap); /* 释放指针,将输入的参数 ap 置为 NULL */

	if (inHandlerMode() != 0)
	{
    
    
		taskENABLE_INTERRUPTS();
	}
}

总结

1)程序开发过程中利用串口进行调试,是不少嵌入式程序员的首选调试方式;
2)在基于FreeRTOS等实时操作系统的多任务程序调试过程中,串口时常出现数据交叉打印,甚至乱码现象;
3)串口在发送数据时,容易被中断或者其它优先级更高的任务打断或抢占;
4)文本分享了一种FreeRTOS线程安全、中断安全的printf实现方式。


参考

https://wenku.baidu.com/view/bacd8e4ea75177232f60ddccda38376bae1fe05f.html;

猜你喜欢

转载自blog.csdn.net/m0_64770246/article/details/125729121