添加了CAN FD收发器静默模式功能,允许通过硬件引脚控制发送使能: - 新增setTxSilent/isTxSilent接口控制TCAN1057收发器Silent模式 - 静默时驱动器关断但接收机继续工作,支持只听不发场景 - 添加SPI命令0xC8用于ESP32远程控制静默模式切换 - 在总线状态位图中增加bit5表示静默状态 - 新增canBusyWaitUs函数用于ISR安全的微秒延时 fix(esc_lan9252): 改进warm jump后LAN9252探测逻辑 修复warm jump导致的LAN9252初始化问题: - 识别warm jump后芯片非POR状态(idx0!=0x1234)的情况 - 自动补发硬件复位对齐到POR状态后再进行正常探测 - 改进调试信息输出,区分POR状态和warm jump残值情况 - 修正失败路径的复位标志初始化逻辑 refactor(spi): 整理SPI命令文件结构 调整SPI命令相关文件的组织结构: - 移动诊断相关文件到更合适的位置 - 重新整理SPI命令处理文件的分组
123 lines
6.1 KiB
C++
123 lines
6.1 KiB
C++
#ifndef DEVICE_APP_SPI_DIAG_H
|
|
#define DEVICE_APP_SPI_DIAG_H
|
|
|
|
#include <cstdint>
|
|
#include <cstddef>
|
|
#include "sys/config.h"
|
|
|
|
/**
|
|
* @file app_spi_diag.h
|
|
* @brief SPI 链路全量硬件与协议诊断模块声明。
|
|
*
|
|
* 用于快速量化与定位 SPI 通信故障根因:
|
|
* - 物理/时序层:CS 边沿跳变、丢失下降沿、0 字节事务(SCK未走/DMA落后)、短包(<20B)、全FF/全00
|
|
* - 硬件状态:SPI0 RXORERR (接收FIFO溢出)、FERR (格式错误)、SPI_STAT 寄存器值
|
|
* - 协议/帧层:SOF丢失、相位偏移(SOF drift)、版本错误、超长/截断、CRC32位跳变(附带期望值与计算值)
|
|
* - 状态机/会话:Session ID脱节、序号跳变(丢包)、序号重复(重发)、未处理命令TYPE、空响应
|
|
* - 握手/流控:PB6 DATA_READY 引脚电平、PA15 CS 引脚电平、主动按铃超时、按铃竞争碰撞
|
|
* - 现场快照:记录最近一次异常发生时刻、实际接收长度、前导原始字节及 CRC 对比
|
|
*/
|
|
|
|
/**
|
|
* @brief SPI 帧解析失败原因细分
|
|
*/
|
|
enum SpiParseResult : uint8_t {
|
|
SPI_PARSE_OK = 0U, ///< 成功解析合法 v2 帧
|
|
SPI_PARSE_ERR_TOO_SHORT = 1U, ///< 事务长度小于 v2 最小帧头 (rxLen < 20)
|
|
SPI_PARSE_ERR_ALL_FF = 2U, ///< 接收数据全为 0xFF (从机浮空/DMA未就绪/MISO未连接)
|
|
SPI_PARSE_ERR_ALL_00 = 3U, ///< 接收数据全为 0x00 (地电平短路或总线死锁)
|
|
SPI_PARSE_ERR_NO_SOF = 4U, ///< 未扫描到 SOF 同步字 (0xA5 0x5A)
|
|
SPI_PARSE_ERR_BAD_VERSION = 5U, ///< 找到 SOF,但 VERSION != 0x02
|
|
SPI_PARSE_ERR_BAD_LEN = 6U, ///< 长度异常 (payload_len > 236 或帧总长超出实际收到的 rxLen)
|
|
SPI_PARSE_ERR_CRC_MISMATCH = 7U, ///< CRC32 校验失败 (物理信号干扰/位跳变)
|
|
};
|
|
|
|
/**
|
|
* @brief SPI 链路全量诊断计数器与状态快照
|
|
*/
|
|
struct SpiDiagStats {
|
|
/* 1. CS 边沿与事务统计 */
|
|
uint32_t total_cs_assert; ///< CS 下降沿次数
|
|
uint32_t total_cs_release; ///< CS 上升沿次数
|
|
uint32_t missed_cs_assert; ///< 丢失 CS 下降沿异常次数
|
|
uint32_t zero_rx_len_count; ///< RX 收到 0 字节 (SCK 未时钟化或 DMA 启动严重落后)
|
|
uint32_t short_rx_len_count; ///< RX 收到 1~19 字节 (<20B 残包)
|
|
uint32_t all_ff_count; ///< 全 0xFF 事务数
|
|
uint32_t all_00_count; ///< 全 0x00 事务数
|
|
|
|
/* 2. 硬件外设与状态 */
|
|
uint32_t rx_overrun_count; ///< SPI0 RXORERR (接收 FIFO 溢出)
|
|
uint32_t format_error_count; ///< SPI0 FERR (帧格式错误)
|
|
uint16_t last_spi_stat; ///< 最近一笔事务结束时的 SPI_STAT 寄存器值
|
|
|
|
/* 3. 帧解析统计 */
|
|
uint32_t valid_v2_frames; ///< 成功解析的合法 v2 帧总数
|
|
uint32_t parse_fail_count; ///< 帧解析失败总数
|
|
uint32_t err_no_sof; ///< 未找到 SOF0(0xA5)+SOF1(0x5A)
|
|
uint32_t err_sof_drift; ///< SOF 偏移不在索引 0 (前导毛刺或字节时序偏移)
|
|
uint32_t err_bad_version; ///< 版本不匹配
|
|
uint32_t err_bad_len; ///< 长度字段错误或事务截断
|
|
uint32_t err_crc_mismatch; ///< CRC32 校验失败
|
|
|
|
/* 4. 会话与序号流控 */
|
|
uint32_t hello_count; ///< 收到 LINK_HELLO 次数
|
|
uint32_t session_mismatch; ///< Session ID 不匹配 (对端重置或会话脱节)
|
|
uint32_t seq_ok_count; ///< 序号严格递增正常次数
|
|
uint32_t seq_jump_count; ///< 序号跳变 (丢帧)
|
|
uint32_t seq_dup_count; ///< 序号重复 (重发包)
|
|
uint16_t last_rx_len; ///< 最近收到的 rx_len (字节数)
|
|
uint8_t last_rx_seq; ///< 最近收到的 rx_seq
|
|
uint8_t expected_rx_seq; ///< 当前期望的 rx_seq
|
|
uint8_t last_tx_seq; ///< 最近发送的 tx_seq
|
|
|
|
/* 5. 命令路由与处理 */
|
|
uint8_t last_rx_type; ///< 最近收到的命令 TYPE
|
|
uint8_t last_tx_type; ///< 最近构建的响应 TYPE
|
|
uint32_t unknown_type_count; ///< 未知命令 TYPE (无 handler 注册)
|
|
uint8_t last_unknown_type; ///< 最近未知的 TYPE 值
|
|
uint32_t handler_empty_count; ///< Handler 执行但返回 tx_len == 0
|
|
uint8_t last_empty_type; ///< 最近产出 0 字节的 TYPE 值
|
|
uint32_t error_rsp_count; ///< GD32 主动返回 0x82 ERROR 响应次数
|
|
uint8_t last_error_code; ///< 最近一次返回 0x82 的错误码 (0xE8/0xE9/0xEA/V2_ERR_*)
|
|
|
|
/* 6. 握手引脚与流控 */
|
|
uint32_t ring_request_count; ///< 主动按铃请求次数
|
|
uint32_t ring_timeout_count; ///< 按铃超时 (ESP32 未在期限内读走)
|
|
uint32_t ring_collision_count; ///< 按铃与 ESP32 主动发帧竞争碰撞次数
|
|
uint8_t current_local_credit; ///< 当前 local credit (0 或 1)
|
|
|
|
/* 7. 最近异常快照 (用于定位具体错误现场) */
|
|
uint32_t last_error_uptime_ms; ///< 异常发生时刻 SysTick 毫秒数
|
|
uint16_t last_error_rx_len; ///< 异常事务收到的字节数
|
|
uint8_t last_error_bytes[8]; ///< 异常事务前 8 字节原始数据
|
|
uint32_t last_error_calc_crc; ///< CRC 错误时: 计算出的 CRC
|
|
uint32_t last_error_expected_crc;///< CRC 错误时: 帧内携带的 CRC
|
|
uint8_t last_error_sof_offset; ///< SOF 所在的偏移位置 (255 表示未找到)
|
|
uint8_t last_error_reason; ///< SpiParseResult 错误原因枚举
|
|
};
|
|
|
|
#if (CONFIG_SPI_DIAG_ENABLE != 0)
|
|
/** @brief 获取当前全局 SPI 诊断统计快照引用 */
|
|
const SpiDiagStats& getSpiDiagStats();
|
|
|
|
/** @brief 复位清零所有 SPI 诊断统计计数器 */
|
|
void resetSpiDiagStats();
|
|
|
|
/** @brief 将解析结果枚举转换为可读字符串 */
|
|
const char* spiParseResultToString(SpiParseResult res);
|
|
|
|
/** @brief 打印完整 SPI 链路诊断报告到串口 (ASCII 表格) */
|
|
void dumpSpiDiag();
|
|
#else
|
|
inline const SpiDiagStats& getSpiDiagStats()
|
|
{
|
|
static const SpiDiagStats s_empty{};
|
|
return s_empty;
|
|
}
|
|
inline void resetSpiDiagStats() {}
|
|
inline const char* spiParseResultToString(SpiParseResult /*res*/) { return "DISABLED"; }
|
|
inline void dumpSpiDiag() {}
|
|
#endif
|
|
|
|
#endif /* DEVICE_APP_SPI_DIAG_H */
|