feat(canfd): 添加CANFD硬件自检功能并优化初始化时序

- 新增s_channelHwOk数组跟踪各通道硬件初始化状态
- 修改CANFD初始化流程,在GPIO上电后延时200ms再进入Normal模式
- 实现selfTestL0()轻量自检函数,检查硬件初始化、退出init模式、收发器状态等
- 更新CANFD初始化逻辑,只有自检通过才标记为成功

refactor(spi): 调整SPI DMA和EXTI配置顺序避免通信失步

- 将armSpiDmasForNextCs()调用移至configureExti()之前
- 添加注释说明DMA预装和EXTI开启的时序要求
- 避免OTA跳转后ESP32立即发送HELLO导致的SPI从机失步问题

fix(app_spi): 修复HELLO_ACK响应中credit初始化问题

- 在HELLO_ACK构建前将g_localCredit设置为1
- 与requestEsp32Read()保持一致避免TX占用时credit=0的问题
- 防止主机因remoteCredit=0而拒绝发送PING帧

refactor(initial): 重构应用初始化流程添加模块状态跟踪

- 引入ModuleBit枚举和掩码机制跟踪各模块初始化状态
- 实现mark()和report()方法统一管理模块启动结果
- 按NVIC→SysTick→ESP32_EN→USART0→AppSpi→ADC→CANFD→OTA→TaskManager→Scheduler→EtherCAT→Watchdog顺序启动
- 将CANFD模块成功条件改为selfTestL0()通过才标记成功
This commit is contained in:
cbb
2026-07-17 02:03:00 +08:00
parent 52d7f9be76
commit fedd39b902
5 changed files with 223 additions and 42 deletions
+64 -2
View File
@@ -163,6 +163,7 @@ CanFd::ChannelStats CanFd::s_channelStats[3]{};
CanFd::ChannelFeedback CanFd::s_feedback[3]{};
uint32_t CanFd::s_feedbackSeq = 0U;
CanFd::IdSnapshotTable CanFd::s_idSnapshot[3]{};
bool CanFd::s_channelHwOk[3]{};
/**
* @brief 查询指定通道是否已使能。
@@ -212,6 +213,8 @@ void CanFd::initGpio()
gpio_init(ch.rxPort, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, ch.rxPin);
gpio_init(ch.txPort, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, ch.txPin);
gpio_init(ch.slpPort, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, ch.slpPin);
/* 上电先 STB=1(待机),延时后再进入 Normal */
gpio_bit_set(ch.slpPort, ch.slpPin);
}
}
@@ -326,9 +329,10 @@ void CanFd::initChannelHardware(uint8_t i)
{
const auto &ch = kChannels[i];
if (!kChannelEnabled[i]) {
printf("[CAN] CH%u DISABLED, skip init\r\n", static_cast<unsigned>(i));
s_channelHwOk[i] = false;
return;
}
s_channelHwOk[i] = false;
rcu_periph_clock_enable(ch.canRcu);
gpio_bit_reset(ch.slpPort, ch.slpPin); /* STB=0 -> Normal */
const uint8_t rxLevelBefore = (gpio_input_bit_get(ch.rxPort, ch.rxPin) != RESET) ? 1U : 0U;
@@ -412,6 +416,9 @@ void CanFd::initChannelHardware(uint8_t i)
s_rxQueues[i].head = 0U;
s_rxQueues[i].tail = 0U;
s_rxQueues[i].count = 0U;
const bool exitOk = ((CAN_STAT(ch.canPeriph) & CAN_STAT_IWS) == 0U);
s_channelHwOk[i] = (nominalOk && fdOk && exitOk);
}
/** @brief 统一配置三路滤波器(HBC1F + per-channel filter)。 */
@@ -724,7 +731,7 @@ void CanFd::dumpRegisters()
* @param[in] 无。
* @param[out] 无。
* @retval 无返回值。
* @note 初始化后默认将三路 TCAN1057A 收发器置为 Normal,并使能 FIFO0 的非空/满/overfull 中断统计。
* @note 初始化收发器 GPIO 后延时进入 Normal,并启用 FIFO0 中断统计。
*/
void CanFd::init()
{
@@ -734,6 +741,7 @@ void CanFd::init()
for (size_t i = 0; i < kChannelCount; ++i) {
s_channelStats[i] = {};
s_feedback[i] = {};
s_channelHwOk[i] = false;
}
s_feedbackSeq = 0U;
@@ -742,6 +750,10 @@ void CanFd::init()
printClockInfo();
#endif
/* 收发器待机保持后,延时再进入 Normal */
constexpr uint32_t kCanPowerOnDeferMs = 200U;
SysTickTimer::delayMs(kCanPowerOnDeferMs);
for (uint8_t i = 0; i < kChannelCount; ++i) {
initChannelHardware(i);
}
@@ -761,6 +773,56 @@ void CanFd::init()
#endif
}
/**
* @brief L0 轻量自检:无总线发帧,仅校验使能通道硬件与收发器状态。
*/
bool CanFd::selfTestL0()
{
constexpr uint32_t kTecRecLimit = 16U;
bool anyEnabled = false;
bool allOk = true;
for (uint8_t i = 0U; i < static_cast<uint8_t>(kChannelCount); ++i) {
if (!kChannelEnabled[i]) {
continue;
}
anyEnabled = true;
const auto &ch = kChannels[i];
if (!s_channelHwOk[i]) {
allOk = false;
continue;
}
/* 仍停在初始化模式 */
if ((CAN_STAT(ch.canPeriph) & CAN_STAT_IWS) != 0U) {
allOk = false;
continue;
}
/* STB=0 为 Normal;高电平视为仍待机 */
if (gpio_output_bit_get(ch.slpPort, ch.slpPin) != RESET) {
allOk = false;
continue;
}
const uint32_t errReg = CAN_ERR(ch.canPeriph);
if ((errReg & CAN_ERR_BOERR) != 0U) {
allOk = false;
continue;
}
const uint32_t tec = (errReg >> 16) & 0xFFU;
const uint32_t rec = (errReg >> 24) & 0xFFU;
if (tec > kTecRecLimit || rec > kTecRecLimit) {
allOk = false;
continue;
}
}
return anyEnabled && allOk;
}
/**
* @brief 切换 CANFD 接收过滤模式。
* @param[in] mode 目标过滤模式。