feat(canfd): 添加通道使能控制和SPI握手信号支持

- 添加通道使能开关配置,通过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信号低电平通知主机等待
This commit is contained in:
cbb
2026-07-06 19:13:56 +08:00
parent 6aa21a1f9d
commit b78e36ff37
6 changed files with 397 additions and 226 deletions
+30 -21
View File
@@ -152,37 +152,46 @@ void TaskRunner::taskCanRxPoll() { CanFd::poll(); }
*/
void TaskRunner::taskCanTxSend()
{
/* 启动后每 100ms 向三路 CAN 通道发送 CANFD+BRS 64 字节测试帧。
/* 启动后每 100ms 轮流发送一路 CAN 通道的 CANFD+BRS 64 字节测试帧。
* 三路通道时分复用:CH0→CH1→CH2→CH0→...,每 100ms 只发一路,
* 避免多路同时发送导致总线仲裁冲突(当多路并接到同一总线时)。
* 帧格式:扩展帧 29-bit ID,CANFD+BRS,DLC=64。
* 载荷布局:
* [0] 通道号 0/1/2
* [1] 保留
* [2..5] 发送序号(小端 uint32,每通道独立递增)
* [6..9] 系统运行秒数 g_app_uptime_sec(小端 uint32)
* [10..63] 递增填充 0x00..0x35(固定模式,便于抓包校验) */
* [10..63] 递增填充,按通道偏移便于抓包区分 */
static uint32_t seq[3] = {0U, 0U, 0U};
static uint8_t round = 0U; /* 0=CH0, 1=CH1, 2=CH2, 轮流 */
for (uint8_t ch = 0U; ch < 3U; ++ch) {
uint8_t data[64];
data[0] = ch;
data[1] = 0U;
const uint32_t s = seq[ch];
data[2] = static_cast<uint8_t>(s & 0xFFU);
data[3] = static_cast<uint8_t>((s >> 8) & 0xFFU);
data[4] = static_cast<uint8_t>((s >> 16) & 0xFFU);
data[5] = static_cast<uint8_t>((s >> 24) & 0xFFU);
data[6] = static_cast<uint8_t>(g_app_uptime_sec & 0xFFU);
data[7] = static_cast<uint8_t>((g_app_uptime_sec >> 8) & 0xFFU);
data[8] = static_cast<uint8_t>((g_app_uptime_sec >> 16) & 0xFFU);
data[9] = static_cast<uint8_t>((g_app_uptime_sec >> 24) & 0xFFU);
for (uint8_t i = 10U; i < 64U; ++i) {
data[i] = i;
}
const uint8_t ch = round;
round = (round + 1U) % 3U;
const uint32_t extId = 0x1FFFFF00U | static_cast<uint32_t>(ch);
CanFd::transmitFrame(ch, extId, data, 64U);
seq[ch]++;
/* 跳过已禁用的通道 */
if (!CanFd::isChannelEnabled(ch)) {
return;
}
uint8_t data[64];
data[0] = ch;
data[1] = 0U;
const uint32_t s = seq[ch];
data[2] = static_cast<uint8_t>(s & 0xFFU);
data[3] = static_cast<uint8_t>((s >> 8) & 0xFFU);
data[4] = static_cast<uint8_t>((s >> 16) & 0xFFU);
data[5] = static_cast<uint8_t>((s >> 24) & 0xFFU);
data[6] = static_cast<uint8_t>(g_app_uptime_sec & 0xFFU);
data[7] = static_cast<uint8_t>((g_app_uptime_sec >> 8) & 0xFFU);
data[8] = static_cast<uint8_t>((g_app_uptime_sec >> 16) & 0xFFU);
data[9] = static_cast<uint8_t>((g_app_uptime_sec >> 24) & 0xFFU);
for (uint8_t i = 10U; i < 64U; ++i) {
data[i] = static_cast<uint8_t>(i + ch * 0x40U);
}
const uint32_t extId = 0x1FFFFF00U | static_cast<uint32_t>(ch);
CanFd::transmitFrame(ch, extId, data, 64U);
seq[ch]++;
}
/**