2026-06-03 03:13:49 +08:00
|
|
|
|
#ifndef DEVICE_APP_SPI_COMMAND_H
|
2026-05-30 00:24:31 +08:00
|
|
|
|
#define DEVICE_APP_SPI_COMMAND_H
|
|
|
|
|
|
|
2026-06-23 01:49:33 +08:00
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
|
|
|
|
class ISpiCommandHandler;
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2026-06-23 01:49:33 +08:00
|
|
|
|
* @brief APP 运行期 SPI 链路与命令路由模块。
|
2026-05-30 00:24:31 +08:00
|
|
|
|
*
|
2026-06-23 01:49:33 +08:00
|
|
|
|
* 本类现在主要承担两件事:
|
|
|
|
|
|
* - 维护 SPI0 从机的硬件链路(GPIO/SPI/DMA/EXTI)
|
|
|
|
|
|
* - 将接收到的合法帧按 TYPE 注册式分发给 ISpiCommandHandler
|
2026-05-30 00:24:31 +08:00
|
|
|
|
*
|
2026-06-23 01:49:33 +08:00
|
|
|
|
* 具体命令处理逻辑不再放在这里,而是拆到 `device/app_spi_cmd_*.cpp`,
|
|
|
|
|
|
* 通过 `registerHandler()` 注册进来,保持本模块可扩展。
|
2026-05-30 00:24:31 +08:00
|
|
|
|
*/
|
|
|
|
|
|
class AppSpiCommand {
|
|
|
|
|
|
public:
|
2026-06-23 01:49:33 +08:00
|
|
|
|
/** @brief 初始化 SPI0 从机命令通道并注册默认命令处理器。 */
|
|
|
|
|
|
void init();
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
/** @brief 主循环轮询:打印延迟日志。 */
|
2026-06-23 01:49:33 +08:00
|
|
|
|
void poll();
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
/** @brief SPI0 中断处理入口。 */
|
2026-06-23 01:49:33 +08:00
|
|
|
|
void onInterrupt();
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
/** @brief CS 边沿中断处理入口。 */
|
2026-06-23 01:49:33 +08:00
|
|
|
|
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);
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
|
|
|
|
|
static constexpr uint16_t kRxBufSize = 128U;
|
|
|
|
|
|
static constexpr uint16_t kTxBufSize = 64U;
|
2026-06-25 01:11:31 +08:00
|
|
|
|
static constexpr uint16_t kLogBufSize = 256U;
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
2026-06-23 01:49:33 +08:00
|
|
|
|
private:
|
|
|
|
|
|
static constexpr uint8_t kMaxCommands = 8U;
|
2026-05-30 00:24:31 +08:00
|
|
|
|
|
2026-06-23 01:49:33 +08:00
|
|
|
|
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;
|
|
|
|
|
|
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();
|
2026-05-30 00:24:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-06-23 01:49:33 +08:00
|
|
|
|
/** @brief 全局 SPI 命令总线实例。 */
|
|
|
|
|
|
extern AppSpiCommand AppSpiCommandBus;
|
|
|
|
|
|
|
2026-05-30 20:03:31 +08:00
|
|
|
|
#endif /* DEVICE_APP_SPI_COMMAND_H */
|