Files
STM32F4-Base/Src/usart.c
T

699 lines
21 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file usart.c
* @brief This file provides code for the configuration
* of the USART instances.
******************************************************************************
* @attention
*
* Copyright (c) 2026 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "usart.h"
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart1_tx;
DMA_HandleTypeDef hdma_usart1_rx;
/* UART4 init function */
void MX_UART4_Init(void)
{
/* USER CODE BEGIN UART4_Init 0 */
/* USER CODE END UART4_Init 0 */
/* USER CODE BEGIN UART4_Init 1 */
/* USER CODE END UART4_Init 1 */
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART4_Init 2 */
/* USER CODE END UART4_Init 2 */
}
/* UART5 init function */
void MX_UART5_Init(void)
{
/* USER CODE BEGIN UART5_Init 0 */
/* USER CODE END UART5_Init 0 */
/* USER CODE BEGIN UART5_Init 1 */
/* USER CODE END UART5_Init 1 */
huart5.Instance = UART5;
huart5.Init.BaudRate = 115200;
huart5.Init.WordLength = UART_WORDLENGTH_8B;
huart5.Init.StopBits = UART_STOPBITS_1;
huart5.Init.Parity = UART_PARITY_NONE;
huart5.Init.Mode = UART_MODE_TX_RX;
huart5.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart5.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart5) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART5_Init 2 */
/* USER CODE END UART5_Init 2 */
}
/* USART1 init function */
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/* USART3 init function */
void MX_USART3_UART_Init(void)
{
/* USER CODE BEGIN USART3_Init 0 */
/* USER CODE END USART3_Init 0 */
/* USER CODE BEGIN USART3_Init 1 */
/* USER CODE END USART3_Init 1 */
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART3_Init 2 */
/* USER CODE END USART3_Init 2 */
}
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspInit 0 */
/* USER CODE END UART4_MspInit 0 */
/* UART4 clock enable */
__HAL_RCC_UART4_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**UART4 GPIO Configuration
PC10 ------> UART4_TX
PC11 ------> UART4_RX
*/
GPIO_InitStruct.Pin = ST_TX4_Pin|ST_RX4_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART4;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
/* UART4 interrupt Init */
HAL_NVIC_SetPriority(UART4_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspInit 1 */
/* USER CODE END UART4_MspInit 1 */
}
else if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspInit 0 */
/* USER CODE END UART5_MspInit 0 */
/* UART5 clock enable */
__HAL_RCC_UART5_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**UART5 GPIO Configuration
PC12 ------> UART5_TX
PD2 ------> UART5_RX
*/
GPIO_InitStruct.Pin = ST_TX1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
HAL_GPIO_Init(ST_TX1_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = ST_RX1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF8_UART5;
HAL_GPIO_Init(ST_RX1_GPIO_Port, &GPIO_InitStruct);
/* UART5 interrupt Init */
HAL_NVIC_SetPriority(UART5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(UART5_IRQn);
/* USER CODE BEGIN UART5_MspInit 1 */
/* USER CODE END UART5_MspInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* USART1 clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 DMA Init */
/* USART1_TX Init */
hdma_usart1_tx.Instance = DMA2_Stream7;
hdma_usart1_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_tx.Init.Mode = DMA_NORMAL;
hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart1_tx);
/* USART1_RX Init */
hdma_usart1_rx.Instance = DMA2_Stream2;
hdma_usart1_rx.Init.Channel = DMA_CHANNEL_4;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart1_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart1_rx);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* USART2 clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
GPIO_InitStruct.Pin = ST_TX3_Pin|ST_RX3_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE END USART2_MspInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* USART3 clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = ST_TX2_Pin|ST_RX2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
void HAL_UART_MspDeInit(UART_HandleTypeDef* uartHandle)
{
if(uartHandle->Instance==UART4)
{
/* USER CODE BEGIN UART4_MspDeInit 0 */
/* USER CODE END UART4_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART4_CLK_DISABLE();
/**UART4 GPIO Configuration
PC10 ------> UART4_TX
PC11 ------> UART4_RX
*/
HAL_GPIO_DeInit(GPIOC, ST_TX4_Pin|ST_RX4_Pin);
/* UART4 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART4_IRQn);
/* USER CODE BEGIN UART4_MspDeInit 1 */
/* USER CODE END UART4_MspDeInit 1 */
}
else if(uartHandle->Instance==UART5)
{
/* USER CODE BEGIN UART5_MspDeInit 0 */
/* USER CODE END UART5_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_UART5_CLK_DISABLE();
/**UART5 GPIO Configuration
PC12 ------> UART5_TX
PD2 ------> UART5_RX
*/
HAL_GPIO_DeInit(ST_TX1_GPIO_Port, ST_TX1_Pin);
HAL_GPIO_DeInit(ST_RX1_GPIO_Port, ST_RX1_Pin);
/* UART5 interrupt Deinit */
HAL_NVIC_DisableIRQ(UART5_IRQn);
/* USER CODE BEGIN UART5_MspDeInit 1 */
/* USER CODE END UART5_MspDeInit 1 */
}
else if(uartHandle->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 DMA DeInit */
HAL_DMA_DeInit(uartHandle->hdmatx);
HAL_DMA_DeInit(uartHandle->hdmarx);
/* USART1 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
else if(uartHandle->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOD, ST_TX3_Pin|ST_RX3_Pin);
/* USART2 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
}
else if(uartHandle->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PB10 ------> USART3_TX
PB11 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOB, ST_TX2_Pin|ST_RX2_Pin);
/* USART3 interrupt Deinit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "cmsis_os.h"
#include "sys_events.h"
/* ===== 控制台单写者日志(2026-09-24 加固,HardFault 定位结论驱动)=====
* 背景:旧路径 DBG_* → printf → fputc **每字符一次** HAL_UART_Transmit。HAL 的锁只保证
* "单字节"原子,任务切换发生在字符之间 → 两行日志逐字符交错(2026-09-24 崩溃前
* 实测:"[2026-[2026-0909-24 15:2-24 15:27:37:39]…");更严重的是字符串指针一旦
* 被破坏,脏指针会直接进入 UART 缓冲遍历(同日 HardFault:BFAR=0x10010000 恰为
* CCM 末尾+1,PC 落在 HAL_UART_Transmit 的缓冲读取处)。
* 架构:**defaultTask 是唯一串口发送者**;其余任务/上下文只把文本写入环形缓冲。
* ① 行级原子:整行在一次临界区内拷入环形缓冲,写者按块一次 HAL_UART_Transmit
* 发出 → 行与行不可能再交错(UART 只有这一个调用点);
* ② 指针可控:进 UART 的缓冲恒为本文件的环形缓冲,调用方脏指针再也到不了 UART;
* ③ 写者未注册(内核启动早期/裸机)或中断上下文:回退直接阻塞发送(无并发或必须裸发)。
* 约束:不新增任务、不动态分配;环形缓冲为 BSS(SRAM1,非 CCM),无 DMA 可达性冲突。
*/
#define DBG_CON_LINE_MAX 192U /* 单行文本上限(含结尾 '\0',超出截断) */
#define DBG_CON_RING_SIZE 4096U /* 环形缓冲字节数(必须为 2 的幂) */
#define DBG_CON_CHUNK_MAX 256U /* 写者单次 HAL_UART_Transmit 字节上限 */
#define DBG_CON_WAIT_MS 200U /* 缓冲满时生产者最长等待(ms),仍满则丢弃并计数 */
static uint8_t s_con_ring[DBG_CON_RING_SIZE];
static volatile uint16_t s_con_head; /* 生产者写入位置 */
static volatile uint16_t s_con_tail; /* 写者读取位置 */
static volatile uint32_t s_con_drop; /* 因缓冲满丢弃的行数 */
static volatile uint8_t s_con_writer_up; /* 1 = 写者已注册(此后走环形缓冲) */
static TaskHandle_t s_con_writer_task; /* 写者任务句柄(自等保护用) */
void dbg_console_write_raw(const char *buf, unsigned len);
void dbg_console_writer_attach(void);
void dbg_console_drain(void);
int dbg_console_write_line(const char *line, unsigned len);
uint32_t dbg_console_dropped(void);
static uint16_t con_used(void)
{
return (uint16_t)((uint16_t)(s_con_head - s_con_tail) & (DBG_CON_RING_SIZE - 1U));
}
/*
* 函数功能:控制台裸发送(异常/早期路径专用:有界、单次、不加锁)
* 入口参数:buf - 文本缓冲;len - 字节数(超上限截断)
* 限定条件:串口已初始化;仅用于写者未注册、中断/异常上下文、崩溃上报
*/
void dbg_console_write_raw(const char *buf, unsigned len)
{
if ((buf == NULL) || (len == 0U)) {
return;
}
if (len > DBG_CON_CHUNK_MAX) {
len = DBG_CON_CHUNK_MAX;
}
(void)HAL_UART_Transmit(&huart1, (uint8_t *)buf, (uint16_t)len, 0xFFFFu);
}
/*
* 函数功能:注册控制台写者(defaultTask 在进入主循环前调用一次)
* 函数说明:注册后生产者改走环形缓冲;未注册时直接阻塞发送(内核启动早期)
*/
void dbg_console_writer_attach(void)
{
s_con_writer_task = xTaskGetCurrentTaskHandle();
s_con_writer_up = 1U;
}
/*
* 函数功能:排空环形缓冲(仅写者任务调用)
* 函数说明:按块一次 HAL_UART_Transmit 发出;每块完成后再推进读指针(临界区保护)
*/
void dbg_console_drain(void)
{
uint16_t used;
if (s_con_writer_up == 0U) {
return;
}
while ((used = con_used()) != 0U) {
uint16_t tail = s_con_tail;
uint16_t contig = (uint16_t)(DBG_CON_RING_SIZE - tail); /* 到环尾的连续段 */
uint16_t n = (used < contig) ? used : contig;
if (n > DBG_CON_CHUNK_MAX) {
n = DBG_CON_CHUNK_MAX;
}
(void)HAL_UART_Transmit(&huart1, &s_con_ring[tail], n, 0xFFFFu);
taskENTER_CRITICAL();
s_con_tail = (uint16_t)((uint16_t)(s_con_tail + n) & (DBG_CON_RING_SIZE - 1U));
taskEXIT_CRITICAL();
}
/* 丢弃可观测性:缓冲满丢行必须显式可见(否则会掩盖开机自检/测试标记的丢失) */
if (s_con_drop != 0U) {
char note[64];
uint32_t d = s_con_drop;
int n;
s_con_drop = 0U;
n = snprintf(note, sizeof(note), "\r\n[ERR] CONSOLE dropped %lu lines\r\n",
(unsigned long)d);
if (n > 0) {
if (n > (int)sizeof(note) - 1) {
n = (int)sizeof(note) - 1;
}
dbg_console_write_raw(note, (unsigned)n);
}
}
}
/*
* 函数功能:把一段文本放入控制台(写者已注册)/直接发出(未注册或中断上下文)
* 返回值:0 - 已入缓冲或已直发;-1 - 缓冲满丢弃(计入 dbg_console_dropped)
* 函数说明:生产者不持锁等待过久:最多 DBG_CON_WAIT_MS,仍满则丢弃该行;
* 写者自身记录日志时先排空缓冲,避免自等。
*/
static int con_append(const char *buf, uint16_t len)
{
uint32_t waited = 0U;
if ((buf == NULL) || (len == 0U)) {
return -1;
}
if ((s_con_writer_up == 0U) || (__get_IPSR() != 0U)) {
dbg_console_write_raw(buf, len);
return 0;
}
if (len > (DBG_CON_RING_SIZE / 2U)) {
len = (uint16_t)(DBG_CON_RING_SIZE / 2U); /* 超长保护(正常路径不会触发) */
}
if (xTaskGetCurrentTaskHandle() == s_con_writer_task) {
dbg_console_drain(); /* 写者自己记录:先腾空,避免自等 */
}
for (;;) {
uint16_t used = con_used();
uint16_t free_space = (uint16_t)((DBG_CON_RING_SIZE - 1U) - used);
if (free_space >= len) {
break;
}
if (waited >= DBG_CON_WAIT_MS) {
s_con_drop++;
return -1;
}
vTaskDelay(1);
waited++;
}
taskENTER_CRITICAL();
{
uint16_t head = s_con_head;
uint16_t first = (uint16_t)(DBG_CON_RING_SIZE - head);
uint16_t i;
if (first > len) {
first = len;
}
for (i = 0U; i < first; i++) {
s_con_ring[head + i] = (uint8_t)buf[i];
}
for (i = first; i < len; i++) {
s_con_ring[(uint16_t)((uint16_t)(head + i) & (DBG_CON_RING_SIZE - 1U))] =
(uint8_t)buf[i];
}
s_con_head = (uint16_t)((uint16_t)(head + len) & (DBG_CON_RING_SIZE - 1U));
}
taskEXIT_CRITICAL();
if (sys_evtHandle != NULL) {
(void)osEventFlagsSet(sys_evtHandle, SYS_EVT_CONSOLE_TX); /* 唤醒写者 */
}
return 0;
}
/*
* 函数功能:把一行已格式化的文本交给单写者控制台(生产者入口,**非可变参数**)
* 入口参数:line - 整行文本(含结尾换行);len - 字节数
* 返回值:写入字节数;-1 - 参数非法或被丢弃
* 函数说明:整行一次入环形缓冲 → 行级原子(不会与他行交错);调用方缓冲随即可复用。
* 刻意不用自研可变参数函数(规范 S12 7.6);格式化由 DBG_PRINT 宏内
* 库 snprintf 在调用点完成。
*/
int dbg_console_write_line(const char *line, unsigned len)
{
if ((line == NULL) || (len == 0U)) {
return -1;
}
if (len > DBG_CON_LINE_MAX) {
len = DBG_CON_LINE_MAX; /* 截断(丢尾,保开头的标记信息) */
}
if (con_append(line, (uint16_t)len) != 0) {
return -1;
}
return (int)len;
}
/*
* 函数功能:已丢弃的日志行数(诊断用)
*/
uint32_t dbg_console_dropped(void)
{
return s_con_drop;
}
/*
* 函数功能:MicroLIB printf 底层重定向(库内部/遗留 printf 调用)
* 函数说明:同样只把字节交给单写者路径;未注册写者时直发(与旧行为一致)
*/
int fputc(int ch, FILE *f)
{
uint8_t b = (uint8_t)ch;
(void)f;
(void)con_append((const char *)&b, 1U);
return ch;
}
/* USER CODE END 1 */