- 添加通道使能开关配置,通过sys/config.h中的CONFIG_CAN_CHx_ENABLE控制各通道 - 实现isChannelEnabled()方法用于查询通道使能状态 - 修正CAN1引脚映射配置,将RX/TX引脚对调并禁用重映射 - 修正错误计数器读取逻辑,REC字段从bit24开始提取而非bit8 - 修正busOff状态判断,使用CAN_ERR_BOERR标志位 - 调整滤波器配置时机,移到所有hardReset完成后防止共享寄存器被清零 - 在发送时增加总线健康检查,避免高错误计数时继续发送导致bus off - 添加SPI Ready握手信号(PB6)控制,改善主从机通信同步 fix(spi): 实现SPI命令处理中的READY信号握手协议 - 添加SPI Ready信号控制,PB6输出指示从机就绪状态 - CS下降沿立即拉低READY信号防主机抢跑 - 命令处理完成且无待处理命令时拉高READY信号 - 忽略无效事务后恢复READY信号避免超时 - 在繁忙期间保持READY信号低电平通知主机等待
99 lines
3.3 KiB
C++
99 lines
3.3 KiB
C++
#ifndef DEVICE_APP_SPI_COMMAND_H
|
||
#define DEVICE_APP_SPI_COMMAND_H
|
||
|
||
#include <cstdint>
|
||
|
||
class ISpiCommandHandler;
|
||
|
||
/**
|
||
* @brief APP 运行期 SPI 链路与命令路由模块。
|
||
*
|
||
* 本类现在主要承担两件事:
|
||
* - 维护 SPI0 从机的硬件链路(GPIO/SPI/DMA/EXTI)
|
||
* - 将接收到的合法帧按 TYPE 注册式分发给 ISpiCommandHandler
|
||
*
|
||
* 具体命令处理逻辑不再放在这里,而是拆到 `device/spi/app_spi_cmd_*.cpp`,
|
||
* 通过 `registerHandler()` 注册进来,保持本模块可扩展。
|
||
*/
|
||
class AppSpiCommand {
|
||
public:
|
||
/** @brief 初始化 SPI0 从机命令通道并注册默认命令处理器。 */
|
||
void init();
|
||
|
||
/** @brief 主循环轮询:打印延迟日志。 */
|
||
void poll();
|
||
|
||
/** @brief 主循环调用:执行 ISR 中推迟的 SPI 命令解析(从 onCsRelease 移出)。 */
|
||
void processPendingCommand();
|
||
|
||
/** @brief SPI0 中断处理入口。 */
|
||
void onInterrupt();
|
||
|
||
/** @brief CS 边沿中断处理入口。 */
|
||
void onCsExtiInterrupt();
|
||
|
||
/**
|
||
* @brief 注册一个 SPI 命令处理器,用于 TYPE 路由。
|
||
* @param[in] handler 命令处理器指针,调用方需保证其生命周期有效。
|
||
*/
|
||
void registerHandler(ISpiCommandHandler *handler);
|
||
|
||
/** @brief 记录一条待输出日志,主循环统一打印。 */
|
||
void postLog(const char *msg);
|
||
|
||
/** @brief 记录一条带 1 字节参数的待输出日志。 */
|
||
void postLogFmt(const char *fmt, uint8_t val);
|
||
|
||
/**
|
||
* @brief 将应答帧构建到指定发送缓冲区。
|
||
* @param[out] tx_buf 发送缓冲区。
|
||
* @param[in] tx_buf_size 发送缓冲区大小。
|
||
* @param[out] tx_len 构建完成后的帧长度。
|
||
* @param[in] rsp_type 响应类型。
|
||
* @param[in] payload 响应载荷。
|
||
* @param[in] payload_len 响应载荷长度。
|
||
*/
|
||
void buildResponse(uint8_t *tx_buf, uint16_t tx_buf_size,
|
||
uint16_t *tx_len, uint8_t rsp_type,
|
||
const uint8_t *payload, uint16_t payload_len);
|
||
|
||
static constexpr uint16_t kRxBufSize = 128U;
|
||
static constexpr uint16_t kTxBufSize = 128U;
|
||
static constexpr uint16_t kLogBufSize = 256U;
|
||
|
||
private:
|
||
static constexpr uint8_t kMaxCommands = 8U;
|
||
|
||
volatile bool m_csActive = false;
|
||
volatile uint8_t m_rxLen = 0U;
|
||
uint8_t m_txLen = 0U;
|
||
volatile uint8_t m_txPos = 0U;
|
||
volatile bool m_logPending = false;
|
||
volatile bool m_cmdPending = false; /**< ISR 置位,标记有待主循环解析的 SPI 命令。 */
|
||
bool m_txActiveThisCs = false;
|
||
uint8_t m_rxBuf[kRxBufSize] = {};
|
||
uint8_t m_txBuf[kTxBufSize] = {};
|
||
char m_logBuf[kLogBufSize] = {};
|
||
uint8_t m_commandCount = 0U;
|
||
ISpiCommandHandler *m_commands[kMaxCommands] = {};
|
||
|
||
void configureGpio();
|
||
void configureSpi0();
|
||
void configureDma();
|
||
void configureExti();
|
||
void onCsAssert();
|
||
void onCsRelease();
|
||
void processCommand();
|
||
|
||
/** @brief 翻转 SPI Ready 握手引脚(PB6)电平。
|
||
* @param[in] ready true=就绪(HIGH), false=忙(LOW)。
|
||
* @note GPIO BSRR/BRR 写入原子,无需临界区;可由 ISR 与主循环共同调用。
|
||
*/
|
||
void setSpiReady(bool ready);
|
||
};
|
||
|
||
/** @brief 全局 SPI 命令总线实例。 */
|
||
extern AppSpiCommand AppSpiCommandBus;
|
||
|
||
#endif /* DEVICE_APP_SPI_COMMAND_H */
|