Files
DCU_APP/GD32E508_DCU_APP/device/usart0.h
T
cbb 44d407390b fix(esc_lan9252): 修复LAN9252 HBI访问模型和IRQ输出使能问题
- 修正HBI访问模型:将ESC核心CSR(0x0000-0x0FFF)改为通过ECAT_CSR_CMD/DATA
  间接端口访问,解决此前直接寻址导致核心寄存器恒读0/写丢弃的问题

- 新增csrRead/csrWrite/pramRead/pramWrite接口,正确实现LAN9252访问端口操作

- 添加PDI就绪检测:等待DL_STATUS bit0置位确认EEPROM加载完成和EtherCAT核心使能

- 实现IRQ引脚输出使能:配置IRQ_CFG和INT_EN寄存器,使EtherCAT事件能到达PB1,
  解决PDI_Isr未触发导致SAFEOP->OP无限挂起的问题

- 为ESC_EXMC硬件诊断添加CONFIG_ESC_EXMC_DIAG门控,默认关闭避免影响正常运行

- 修正system_gd32e50x.c中HXTAL故障诊断的寄存器偏移和位设置错
2026-09-02 02:38:35 +08:00

107 lines
3.8 KiB
C++

#ifndef DEVICE_USART0_H
#define DEVICE_USART0_H
#include <stdint.h>
#include <stdio.h>
/**
* @brief USART0 串口模块。
* @note 负责 GPIO 初始化、外设配置、TX 环形缓冲与中断驱动发送。
*/
class Usart0 {
public:
/**
* @brief 配置 USART0 的 GPIO 引脚。
* @param[in] 无。
* @param[out] 无。
* @retval 无返回值。
* @note 当前配置为:PA9=TX(AF_PP)、PA10=RX(IN_FLOATING)。
*/
static void configurePins();
/** init 故障码(0=成功;经 0xA3 INIT_STATUS fault_codes[] 上报) */
enum InitFault : uint8_t {
kFaultOk = 0U, /**< 成功 */
kFaultNotEnabled = 1U, /**< CTL0.UEN 回读未置位(使能未生效) */
};
/**
* @brief 初始化 USART0 外设与 NVIC。
* @param[in] 无。
* @param[out] 无。
* @retval uint8_t InitFault 故障码(0=USART 已使能,CTL0.UEN 回读置位)。
* @note 使用 8N1 格式,收发使能,同步配置 NVIC 以便 TXE 中断驱动发送。
*/
static uint8_t init();
/**
* @brief 将字符写入 USART0 发送环形缓冲。
* @param[in] ch 待发送字符。
* @param[in] f 标准流指针,实际未使用。
* @param[out] 无。
* @retval int 返回已写入缓冲的字符值。
* @note 新字符写入后自动启动 TXE 中断来推动实际硬件发送。
*/
static int putChar(int ch, FILE *f);
/**
* @brief USART0 中断处理入口。
* @param[in] 无。
* @param[out] 无。
* @retval 无返回值。
* @note 在 TXE 产生时从环形缓冲取下一字节发送;缓冲空后关闭 TXE 中断。
*/
static void onInterrupt();
private:
/**
* @brief 获取环形缓冲下一索引。
* @param[in] idx 当前索引。
* @param[out] 无。
* @retval uint16_t 下一索引值。
*/
static uint16_t nextIndex(uint16_t idx);
/**
* @brief 判断环形发送缓冲是否为空。
* @param[in] 无。
* @param[out] 无。
* @retval bool true 表示空,false 表示仍有待发送数据。
*/
static bool isBufferEmpty();
static bool putCharNonBlocking(int ch);
/**
* @brief 在临界区内直接轮询 TBE 并发出一个字节,腾出一个缓冲槽位。
* @param[in] 无。
* @param[out] 无。
* @retval bool true 表示成功发出一字节(tail 已前进),false 表示等待 TBE 超时。
* @note 调用者必须已持有临界区(USART0 中断 preempt=3 被 BASEPRI 屏蔽),
* 因此这里独占 s_txTail,不会与 onInterrupt() 争用同一字节。
* 不依赖中断投递,故在任意上下文(含 ISR 内 printf)均可安全使用。
*/
static bool drainOneByteLocked();
/** @brief 3M 波特率下 init 阶段诊断是突发写入,1024 字节会溢出致日志掉字。 */
static constexpr uint16_t kTxBufSize = 4096U;
/** @brief 等待 TBE 的自旋上限:3M 下单字节约 3.3us,此值远大于之,仅防 USART 失效死等。 */
static constexpr uint32_t kTbeSpinMax = 200000U;
static uint8_t s_txBuf[kTxBufSize];
static volatile uint16_t s_txHead;
static volatile uint16_t s_txTail;
static volatile uint32_t s_txDropped;
public:
/**
* @brief 读取因发送缓冲溢出而被丢弃的字节数。
* @param[in] 无。
* @param[out] 无。
* @retval uint32_t 累计丢弃字节数(0 表示日志完整可信)。
* @note 非 0 说明串口日志有掉字,诊断结论不可全信——历史上掉字日志曾导致
* LAN9252 故障两次误定性,故显式暴露该计数供 init 报告核对。
*/
static uint32_t droppedBytes() { return s_txDropped; }
};
#endif /* DEVICE_USART0_H */