feat(ethercat): LAN9252 bring-up完成,EEPROM烧录改主站侧并增强DC/AL可观测性
- 新增ESC硬件复位序列(1.5.25):PB10驱动LAN9252 RST#,拉低30ms+释放后300ms轮询HBI就绪, 满足tpurstd/trstia时序;此前RST#仅靠R44上拉自然释放 - 修正EXMC 16-bit地址左移(1.5.27):HBI DATA偏移0x20000/0x30000→0x40000/0x60000; ADDSET 2→4 HCLK;片选更名NE1→NE0(LQFP100仅Region0) - 按LAN9252手册/AN1907修正EEPROM镜像(1.5.28):word1高字节0x00→0xCC(SYNC0/1 Map+Output, 否则SYNC0留LATCH态DC过程数据死)、word2=5000(脉宽50µs)、尾部补真实0xFF; gen_eeprom.py按ETG.1000.6重写;DCU_ESI.xml PDI 0x05→0x8D、RxPdo/TxPdo互换改4×64bit对齐 - 删除GD32侧EEPROM烧录路径(1.5.29):移除EscEeprom/esc_eeprom、eeprom_image.h及主循环 烧录块,ESI镜像改由主站ecat_flash_eeprom.py经ESC 0x0500刷写(162字全校验通过); HBI互斥补屏蔽EXTI2(SYNC1),防Sync1_Isr两步事务打断主循环HBI访问致错址 - DC SYNC0通路可观测(1.5.30/31):EthercatSync新增sync0/sync1/escirq三个volatile计数器, task_runner 5s按增量打印速率;SSC OD新增只读0x2000 SYNC Diag,主站SDO轮询网页显示 - AL通路诊断(1.5.32):ECAT_Main/SetALStatus打印主站AL请求与写回状态+错误码, task_runner新增5s [ECAT][HB]心跳(仅同步ISR激活时);dc_app.c导出EcatDbg_ReadAlDiag - 删除死代码EthercatSlave::periodicIsr三缓冲PDO桥,PDO交换由SSC完成(4×64bit=32B); EthercatSlave::init()恢复调用并以isBusReady()(BYTE_TEST)门控 - CANFD修复同通道突发只发3帧:transmitFrame新增allow_abort区分突发/软件队列路径, 邮箱满落入软件TX队列(深度13)由TX完成中断drainTxQueueIsr回灌;BRS重新启用(0→1) - motor_state新增CONFIG帧缓存(0x00000101, DLC 24)记录目标值回报,条目44B→76B、每页5→3 - SPI 0xA2诊断扩展action 20~24(ECAT_NRST拉低/拉高/浮空/回读);新增ESP32 EN自检打印 - 版本号更新至1.5.32
This commit is contained in:
@@ -52,7 +52,7 @@ constexpr uint16_t CONFIG_MOTOR_OFFLINE_MS = 3000U;
|
||||
/** @brief CAN-FD BRS 使能(canfd.cpp #if)。
|
||||
* 关闭 BRS: 数据段用仲裁段同速率,牢牢性更高。
|
||||
* 电机 BOOT 无法正确接收 BRS 高速段→nonce(16B FD+BRS)被拒绝→握手失败。 */
|
||||
#define CONFIG_CAN_FD_BRS_ENABLE 0U
|
||||
#define CONFIG_CAN_FD_BRS_ENABLE 1U
|
||||
/** @brief 启动时总线探测帧;正常固件关。 */
|
||||
#define CONFIG_CAN_STARTUP_BUS_TEST_ENABLE 0
|
||||
/** @brief 启动时内部回环自检;正常固件关。 */
|
||||
@@ -115,7 +115,7 @@ constexpr bool CONFIG_CAN_CH2_ENABLE = true;
|
||||
* ============================================================ */
|
||||
constexpr uint32_t APP_FW_VERSION_MAJOR = 1U;
|
||||
constexpr uint32_t APP_FW_VERSION_MINOR = 5U;
|
||||
constexpr uint32_t APP_FW_VERSION_PATCH = 15U; /* 1.5.15:EXMC 通断测试新增 MODE0/MODE1 strap 驱动测试(action 0x0A-0x0D, PB8/PB9) */
|
||||
constexpr uint32_t APP_FW_VERSION_PATCH = 32U; /* 1.5.32:AL 通路诊断打印(排查主站连接后 AL 卡 INIT)——ECAT_Main 收到主站 AL 控制请求打 [ECAT][AL] evt/req、SetALStatus 写回打 [ECAT][AL] -> 状态+错误码、task_runner 5s 心跳 [ECAT][HB] al/code/evt(仅同步 ISR 激活时,心跳停=主循环卡死);dc_app.c 导出 EcatDbg_ReadAlDiag(0x0130+0x0220 快照)。1.5.31:DC 通路观测同步到网页——SSC OD 新增只读记录 0x2000 SYNC Diag(sub1=sync0/sub2=sync1/sub3=escirq/sub4=uptime 秒,UINT32),APPL_InputMapping 每 PDO 周期从 EthercatSync 拉取快照(ethercat_sync.cpp 导出 EcatDbg_Get* extern C);配套 tools/ecat:/api/sync_diag 经 SDO 读 0x2000 并以主站时间戳算 sync0 速率,ecat.html 运行期 2s 轮询显示,串口 5s 低频打印保留为旁证。1.5.30:DC SYNC0 通路可观测性——EthercatSync 增加 s_sync0Count/s_sync1Count/s_escIrqCount 三个 volatile 计数器(ISR 内自增,SYNC0 路径实测仅 LDR/ADDS/STR 三条指令,仍在 .ramfunc);task_runner 新增 ethercatSyncCounterPrint(),5s 诊断按增量打印 sync0 速率(主站设 1ms 周期时应 ≈1000/s),无脉冲时静默。配套 tools/ecat 支持分布时钟:ecat_tool.py send/monitor 新增 --dc-cycle-us/--dc-shift-us(0=free-run 默认),enter_op() 在 config_map 后、进 SAFEOP 前调 config_dc()+dc_sync();ecat_server.py /api/op/start 接受 dc_cycle_us/dc_shift_us;ecat.html 加 DC SYNC0 周期下拉。此前工具从不调用 config_dc,PDO 恒为 free-run,SYNC0 引脚无脉冲、Sync0_Isr 从未触发,1.5.28 配的 word1=0xCC/word2=5000 一直未被实测覆盖。1.5.29:删除 GD32 侧 EEPROM 烧录路径(EscEeprom/esc_eeprom.h/.cpp、eeprom_image.h 及 task_runner 主循环烧录块)——ESI 镜像改由 EtherCAT 主站侧刷写(tools/ecat/ecat_flash_eeprom.py 经 ESC 0x0500 EEPROM 接口,2026-08-31 实测 162 字全校验通过),固件不再负责烧录;gen_eeprom.py 生成器保留。HBI 复查修复:maskEnter/Exit 补屏蔽 EXTI2(SYNC1)——Sync1_Isr 的 PDO_InputMapping→HW_EscWriteIsr 两步事务(preempt=1)可打断主循环 HW_EscRead/Write 致错址;通断测试模式进入/退出改经 maskEnter/Exit 屏蔽三类 EXTI,防测试期 ISR 访问 GPIO 态总线读垃圾。1.5.28:对照 LAN9252 数据手册/AN1907/官方 EVB XML 修正——EEPROM word1 高字节 0x00→0xCC(Sync/Latch 0151h:SYNC0/1 Map+Output、推挽低有效配 EXTI 下降沿;原 0x00 时 SYNC0 引脚留在 LATCH 输入态,DC 模式过程数据死);word2 0→5000(Sync 脉宽 0982h,x10ns=50us,0=确认模式不可用);eeprom_image.h 尾部补真实 0xFF 字节(原注释行致 C 零填充,烧写全阵列);EXMC ADDSET 2→4 HCLK(DS 表9-4 trdrd/twrwr/twrrd≥13ns);XML ConfigData 扩到 14B 并加 CycleTimeSync1。1.5.27:LAN9252 使用修正——EXMC 16-bit 地址左移 1 位(HBI DATA 偏移 0x20000/0x30000→0x40000/0x60000);gen_eeprom.py 按 ETG.1000.6 重写(CRC-8/word7、身份字 word8-15、CoE=0x0004、分类区 byte128);DCU_ESI.xml ConfigData PDI 0x05→0x8D、RxPdo/TxPdo 互换并改 4×64bit 对齐 dc_app.c;HBI 两步事务互斥守卫(主循环 mask EXTI0/1 + PDI/Sync1 ISR 屏蔽 EXTI0);删除死代码 EthercatSlave::periodicIsr 三缓冲;20s HBI 诊断在同步 ISR 激活后自动停跑 */
|
||||
constexpr uint32_t APP_FW_VERSION_BUILD = 0U;
|
||||
|
||||
|
||||
@@ -178,7 +178,8 @@ constexpr uint8_t CONFIG_CANFD_ID_SNAPSHOT_MAX = 16U;
|
||||
/** @brief 快照条目最大数据字节数(CAN FD DLC 上限)。 */
|
||||
constexpr uint8_t CONFIG_CANFD_ID_SNAPSHOT_DATA_MAX = 64U;
|
||||
|
||||
/** @brief ESP32 硬件复位控制端口(PC9 接 ESP32 EN/RESET)。 */
|
||||
/** @brief ESP32 硬件复位控制端口(PC9 接 ESP32 EN/RESET,对应原理图 WLESS_EN)。
|
||||
* @note 复位后 PC9 浮空,ESP_CHIP_EN 会被 C41/U11 拉低;BOOT 也必须主动拉高。 */
|
||||
constexpr uint32_t CONFIG_ESP32_RESET_PORT = GPIOC;
|
||||
/** @brief ESP32 硬件复位控制引脚。 */
|
||||
constexpr uint32_t CONFIG_ESP32_RESET_PIN = GPIO_PIN_9;
|
||||
@@ -296,11 +297,9 @@ constexpr uint32_t CONFIG_IRQ_PREEMPT_SPI_USART = 3U;
|
||||
/* ============================================================
|
||||
* EtherCAT LAN9252 配置(开关见顶部 CONFIG_MAIN_LOOP_WFI / ETHERCAT_SYNC_MODE)
|
||||
* ============================================================ */
|
||||
constexpr uint32_t CONFIG_ETHERCAT_ISR_MAX_US_THRESHOLD = 5U;
|
||||
constexpr uint32_t CONFIG_ESC_PDI_INPUT_OFFSET = 0x1000U;
|
||||
constexpr uint32_t CONFIG_ESC_PDI_OUTPUT_OFFSET = 0x1200U;
|
||||
/** @brief 默认 PDO 缓冲大小(字节),应用/ISR 三缓冲共用。 */
|
||||
constexpr size_t CONFIG_ETHERCAT_PDO_SIZE = 32U;
|
||||
/* 1.5.27:CONFIG_ETHERCAT_ISR_MAX_US_THRESHOLD / CONFIG_ESC_PDI_INPUT_OFFSET /
|
||||
* CONFIG_ESC_PDI_OUTPUT_OFFSET / CONFIG_ETHERCAT_PDO_SIZE 随死代码 EthercatSlave::
|
||||
* periodicIsr 三缓冲一并删除;PDO 交换由 SSC(dc_app.c APPL_*, 4×64bit=32B) 完成。 */
|
||||
|
||||
/* ---------- EXMC 引脚配置(GD32E508 EXMC 标准映射) ---------- */
|
||||
constexpr uint32_t CONFIG_ESC_EXMC_BASE_ADDR = 0x60000000U;
|
||||
@@ -337,6 +336,17 @@ constexpr IRQn_Type CONFIG_ESC_SYNC1_IRQn = EXTI2_IRQn;
|
||||
constexpr uint32_t CONFIG_ESC_SYNC1_EXTI_SOURCE_PORT = GPIO_PORT_SOURCE_GPIOB;
|
||||
constexpr uint32_t CONFIG_ESC_SYNC1_EXTI_SOURCE_PIN = GPIO_PIN_SOURCE_2;
|
||||
|
||||
/* ---------- ESC 硬件复位(PB10 → LAN9252 Pin11 RST#,SCH 第1页 Pin47) ---------- */
|
||||
/** @note 2026-08-22(1.5.25) 前固件从未初始化 PB10,RST# 仅靠 R44 10k 上拉自然释放,
|
||||
* 不满足 LAN9252 手册 18.6.3 tpurstd(电源稳定→RST#释放)≥25ms、trstia(低脉宽)≥200µs。
|
||||
* 由 EscLan9252::hardwareReset() 执行受控复位序列;释放后保持推挽输出高,
|
||||
* GD32 自身复位期间引脚回浮空,由 R44 上拉维持高,不会误复位 ESC。 */
|
||||
constexpr uint32_t CONFIG_ESC_NRST_PORT = GPIOB;
|
||||
constexpr uint32_t CONFIG_ESC_NRST_PIN = GPIO_PIN_10;
|
||||
constexpr uint32_t CONFIG_ESC_NRST_ASSERT_MS = 30U; /* 低脉宽,同时覆盖 tpurstd 25ms 与 trstia 200µs */
|
||||
constexpr uint32_t CONFIG_ESC_HBI_POLL_TIMEOUT_MS = 300U; /* RST# 释放后等待 ESC 启动/EEPROM 加载 */
|
||||
constexpr uint32_t CONFIG_ESC_HBI_POLL_STEP_MS = 5U;
|
||||
|
||||
/* ---------- EXMC 数据/控制线引脚(GD32E508 标准映射) ---------- */
|
||||
constexpr uint32_t CONFIG_EXMC_D0_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D0_PIN = GPIO_PIN_14;
|
||||
constexpr uint32_t CONFIG_EXMC_D1_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D1_PIN = GPIO_PIN_15;
|
||||
@@ -357,10 +367,13 @@ constexpr uint32_t CONFIG_EXMC_D15_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC
|
||||
constexpr uint32_t CONFIG_EXMC_A16_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_A16_PIN = GPIO_PIN_11;
|
||||
/* A17 (PD12) 用于 HBI Indexed Mode 访问 HBI_DATA_0 寄存器,已将 LAN9252 A2 (Pin 29) 接到 PD12。
|
||||
* 注意 LAN9252 引脚顺序:Pin25=A1, Pin26=A3, Pin27=A4, Pin28=CS, Pin29=A2。
|
||||
* A2 是 IDX/DATA 选择位,必须接到 PD12 才能访问 DATA 寄存器,EEPROM 烧录功能可用。 */
|
||||
* A2 是 IDX/DATA 选择位,必须接到 PD12 才能访问 DATA 寄存器,EEPROM 烧录功能可用。
|
||||
* 注意 EXMC 16-bit 模式地址左移 1 位(用户手册 p869):A16(PD11)=CPU 偏移 0x20000、
|
||||
* A17(PD12)=CPU 偏移 0x40000,HBI_DATA_0 访问偏移见 esc_lan9252.cpp。 */
|
||||
constexpr uint32_t CONFIG_EXMC_A17_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_A17_PIN = GPIO_PIN_12;
|
||||
constexpr uint32_t CONFIG_EXMC_NOE_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_NOE_PIN = GPIO_PIN_4;
|
||||
constexpr uint32_t CONFIG_EXMC_NWE_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_NWE_PIN = GPIO_PIN_5;
|
||||
constexpr uint32_t CONFIG_EXMC_NE1_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_NE1_PIN = GPIO_PIN_7;
|
||||
/* LQFP100 只有 NE0(PD7) 一个 NOR/SRAM 片选,归 Region0(0x60000000);命名沿用硬件真值 NE0。 */
|
||||
constexpr uint32_t CONFIG_EXMC_NE0_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_NE0_PIN = GPIO_PIN_7;
|
||||
|
||||
#endif /* SYS_CONFIG_H */
|
||||
|
||||
@@ -116,6 +116,9 @@ void AppInitializer::init()
|
||||
gpio_bit_set(CONFIG_ESP32_RESET_PORT, CONFIG_ESP32_RESET_PIN);
|
||||
gpio_init(CONFIG_ESP32_RESET_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, CONFIG_ESP32_RESET_PIN);
|
||||
mark(kEsp32Hold);
|
||||
/* ESP32 EN 自检:日志里能直接看出是上电即拉高,还是被外部钳住 */
|
||||
APP_LOGI("[APP] ESP32_EN PC9=%d (1=released)\r\n",
|
||||
(int)gpio_input_bit_get(CONFIG_ESP32_RESET_PORT, CONFIG_ESP32_RESET_PIN));
|
||||
|
||||
Usart0::configurePins();
|
||||
Usart0::init();
|
||||
@@ -144,8 +147,13 @@ void AppInitializer::init()
|
||||
mark(kScheduler);
|
||||
|
||||
/* ---- EtherCAT: EXMC 总线探活 → SSC 协议栈初始化 → SYNC0/IRQ 中断使能 ----
|
||||
* 1.5.27:改经 EthercatSlave::init()(内部调用 EscLan9252::init 并记录
|
||||
* chipId/AL 状态诊断,此前该函数无调用点、s_escReady 恒为 false)。
|
||||
* 门控用 EscLan9252::isBusReady()(BYTE_TEST 通过)而非 isEscReady():
|
||||
* 冷启动时 AL=INIT,SSC 必须照常启动并等待主站配置。
|
||||
* EEPROM 校验/烧录延迟到主循环执行,避免阻塞 init(烧录需 ~20s)。 */
|
||||
if (EscLan9252::init()) {
|
||||
EthercatSlave::init();
|
||||
if (EscLan9252::isBusReady()) {
|
||||
const uint16_t sscResult = MainInit();
|
||||
if (sscResult == 0U) {
|
||||
mark(kEthercat);
|
||||
|
||||
@@ -16,9 +16,8 @@
|
||||
#include "sys/task_manager.h"
|
||||
#include "sys/task_runner.h"
|
||||
#include "comm/ethercat_slave.h"
|
||||
#include "comm/esc_eeprom.h"
|
||||
#include "comm/ethercat_sync.h"
|
||||
#include "comm/esc_exmc_bus.h"
|
||||
#include "comm/ssc/port/eeprom_image.h"
|
||||
|
||||
extern "C" {
|
||||
void MainLoop(void);
|
||||
@@ -272,6 +271,68 @@ bool TaskRunner::copyAdcSample(Adc::Sample *out)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* SSC 侧 AL 诊断快照(dc_app.c): [19:16]=AL 状态 [31:24]=AL 错误码 [15:0]=AL 事件寄存器 */
|
||||
extern "C" uint32_t EcatDbg_ReadAlDiag(void);
|
||||
|
||||
/**
|
||||
* @brief 1.5.32 ECAT 心跳:主循环存活证明 + ESC AL 状态/事件寄存器快照。
|
||||
* @note 仅在同步 ISR 激活(SSC 在跑)时打印。心跳停 = 主循环卡死;
|
||||
* al=0x1 且 evt bit0 长期置位 = SSC 没处理 AL 请求;
|
||||
* al 与主站读到的不一致 = ESC 写回路径问题。
|
||||
*/
|
||||
static void ethercatAlHeartbeat()
|
||||
{
|
||||
if (!EthercatSync::isActive()) {
|
||||
return;
|
||||
}
|
||||
const uint32_t alDiag = EcatDbg_ReadAlDiag();
|
||||
printf("[ECAT][HB] al=0x%lX code=0x%02lX evt=0x%04lX (uptime=%lus)\r\n",
|
||||
(unsigned long)((alDiag >> 16) & 0x0FU),
|
||||
(unsigned long)((alDiag >> 24) & 0xFFU),
|
||||
(unsigned long)(alDiag & 0xFFFFU),
|
||||
(unsigned long)g_app_uptime_sec);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印 EtherCAT 同步中断计数与速率(DC 通路验证)。
|
||||
* @note 主站启用 DC(SYNC0 周期 T)后,sync0 速率应稳定 ≈ 1e6/T_us 次/秒;
|
||||
* free-run 模式下 SYNC0 引脚无脉冲,三个计数器恒为 0(本函数不打印)。
|
||||
* 仅在有增量时输出,避免未接主站时刷屏。
|
||||
*/
|
||||
static void ethercatSyncCounterPrint()
|
||||
{
|
||||
static uint32_t s_prevSync0 = 0U;
|
||||
static uint32_t s_prevSync1 = 0U;
|
||||
static uint32_t s_prevEscIrq = 0U;
|
||||
static uint32_t s_prevSec = 0U;
|
||||
|
||||
const uint32_t sync0 = EthercatSync::getSync0Count();
|
||||
const uint32_t sync1 = EthercatSync::getSync1Count();
|
||||
const uint32_t escIrq = EthercatSync::getEscIrqCount();
|
||||
|
||||
const uint32_t d0 = sync0 - s_prevSync0; /* 无符号回绕自然成立 */
|
||||
const uint32_t d1 = sync1 - s_prevSync1;
|
||||
const uint32_t di = escIrq - s_prevEscIrq;
|
||||
|
||||
const uint32_t now = g_app_uptime_sec;
|
||||
const uint32_t elapsed = (now > s_prevSec) ? (now - s_prevSec) : 1U;
|
||||
|
||||
s_prevSync0 = sync0;
|
||||
s_prevSync1 = sync1;
|
||||
s_prevEscIrq = escIrq;
|
||||
s_prevSec = now;
|
||||
|
||||
if (d0 == 0U && d1 == 0U && di == 0U) {
|
||||
return; /* 未接主站或 free-run:无脉冲,静默 */
|
||||
}
|
||||
|
||||
printf("[ECAT][SYNC] sync0=%lu(+%lu, %lu/s) sync1=%lu(+%lu) escirq=%lu(+%lu) dt=%lus\r\n",
|
||||
(unsigned long)sync0, (unsigned long)d0, (unsigned long)(d0 / elapsed),
|
||||
(unsigned long)sync1, (unsigned long)d1,
|
||||
(unsigned long)escIrq, (unsigned long)di,
|
||||
(unsigned long)elapsed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 5s 诊断任务:默认仅状态变化/错误增量;可选全量 UART 摘要。
|
||||
* @note CONFIG_UART_TEMP_PERIODIC_PRINT=1 时打印 ADC/CAN/ECAT 全量行(调试用)。
|
||||
@@ -326,19 +387,16 @@ void TaskRunner::taskDiagnosticPrint()
|
||||
#endif
|
||||
|
||||
if (EthercatSlave::isEscReady()) {
|
||||
uint32_t maxCyc = 0U, avgCyc = 0U, cnt = 0U;
|
||||
EthercatSlave::getIsrStats(&maxCyc, &avgCyc, &cnt);
|
||||
/* 180MHz: cycles / 180 = µs;用 *1000/180 获得亚微秒精度避免浮点 */
|
||||
const uint32_t maxUs_x1000 = maxCyc * 1000U / 180U;
|
||||
const uint32_t avgUs_x1000 = avgCyc * 1000U / 180U;
|
||||
printf("[ECAT] periodicIsr cnt=%lu max=%lu.%03luus avg=%lu.%03luus\r\n",
|
||||
(unsigned long)cnt,
|
||||
(unsigned long)(maxUs_x1000 / 1000U), (unsigned long)(maxUs_x1000 % 1000U),
|
||||
(unsigned long)(avgUs_x1000 / 1000U), (unsigned long)(avgUs_x1000 % 1000U));
|
||||
/* 1.5.27:periodicIsr 已删除(死代码,无调用点),PDO 交换由 SSC
|
||||
* Sync0_Isr → ECAT_Application → dc_app.c APPL_* 完成。 */
|
||||
printf("[ECAT] ESC ready (chip id=0x%08lX), PDO via SSC Sync0_Isr\r\n",
|
||||
(unsigned long)EthercatSlave::getChipId());
|
||||
} else {
|
||||
printf("[ECAT] ESC not detected (chip id=0x%08lX), EtherCAT disabled\r\n",
|
||||
(unsigned long)EthercatSlave::getChipId());
|
||||
}
|
||||
ethercatSyncCounterPrint();
|
||||
ethercatAlHeartbeat();
|
||||
}
|
||||
#else
|
||||
/* ---- 默认静默路径:仅错误增量 / 状态变化,无 uptime 心跳 ---- */
|
||||
@@ -351,7 +409,6 @@ void TaskRunner::taskDiagnosticPrint()
|
||||
static uint8_t s_prev_adc_valid = 0xFFU; /* 0xFF=尚未采样 */
|
||||
static bool s_prev_esc_ready = false;
|
||||
static bool s_esc_ready_inited = false;
|
||||
static uint32_t s_prev_ecat_max_cyc = 0U;
|
||||
|
||||
const uint32_t rx_drop = diag->rx_drop_count;
|
||||
const uint32_t rx_full = diag->rx_fifo_full_count;
|
||||
@@ -403,39 +460,14 @@ void TaskRunner::taskDiagnosticPrint()
|
||||
(unsigned long)g_app_uptime_sec);
|
||||
s_prev_esc_ready = esc_ready;
|
||||
}
|
||||
|
||||
if (esc_ready) {
|
||||
uint32_t maxCyc = 0U, avgCyc = 0U, cnt = 0U;
|
||||
EthercatSlave::getIsrStats(&maxCyc, &avgCyc, &cnt);
|
||||
/* 阈值单位 µs → CPU 周期(180 MHz) */
|
||||
const uint32_t threshCyc = CONFIG_ETHERCAT_ISR_MAX_US_THRESHOLD * 180U;
|
||||
if (maxCyc > threshCyc && maxCyc > s_prev_ecat_max_cyc) {
|
||||
const uint32_t maxUs_x1000 = maxCyc * 1000U / 180U;
|
||||
printf("[ECAT] ISR max over threshold: max=%lu.%03luus thr=%luus cnt=%lu (uptime=%lus)\r\n",
|
||||
(unsigned long)(maxUs_x1000 / 1000U),
|
||||
(unsigned long)(maxUs_x1000 % 1000U),
|
||||
(unsigned long)CONFIG_ETHERCAT_ISR_MAX_US_THRESHOLD,
|
||||
(unsigned long)cnt,
|
||||
(unsigned long)g_app_uptime_sec);
|
||||
s_prev_ecat_max_cyc = maxCyc;
|
||||
}
|
||||
}
|
||||
/* 1.5.27:periodicIsr ISR 统计随死代码一并删除 */
|
||||
/* DC SYNC0 通路验证:仅在有脉冲增量时打印(未接主站时静默)。 */
|
||||
ethercatSyncCounterPrint();
|
||||
ethercatAlHeartbeat();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行 EtherCAT 周期/事件处理(非实时应用层 PDO 映射)。
|
||||
* @param[in] 无。
|
||||
* @param[out] 无。
|
||||
* @retval 无返回值。
|
||||
* @note 由周期 ISR(EXTI0 SYNC0)或 ESC 事件 ISR(EXTI1 IRQ)置位 TASK_ETHERCAT_PROCESS。
|
||||
*/
|
||||
void TaskRunner::taskEthercatProcess()
|
||||
{
|
||||
EthercatSlave::process();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化任务执行器运行时上下文。
|
||||
* @param[in] 无。
|
||||
@@ -468,41 +500,21 @@ void TaskRunner::runPending()
|
||||
{
|
||||
Watchdog::feed();
|
||||
|
||||
/* === HBI 周期诊断:每 20 秒重新跑一次 EXMC/HBI 探活,方便热插拔/焊接后观察 === */
|
||||
/* === HBI 周期诊断:每 20 秒重新跑一次 EXMC/HBI 探活,方便热插拔/焊接后观察 ===
|
||||
* 1.5.27:EtherCAT 同步 ISR 激活后停止(diagDump 会把 EXMC 引脚切成 GPIO,
|
||||
* 拆毁运行中的总线;诊断的 bit-bang 也与 HBI 事务互斥冲突)。 */
|
||||
static uint32_t s_lastDiagSec = 0xFFFFFFFFU;
|
||||
if (g_app_uptime_sec >= s_lastDiagSec + 20U || s_lastDiagSec == 0xFFFFFFFFU) {
|
||||
if (!EthercatSync::isActive()
|
||||
&& (g_app_uptime_sec >= s_lastDiagSec + 20U || s_lastDiagSec == 0xFFFFFFFFU)) {
|
||||
s_lastDiagSec = g_app_uptime_sec;
|
||||
printf("[ECAT][DIAG] === 20s periodic HBI probe (uptime=%lus) ===\r\n",
|
||||
(unsigned long)g_app_uptime_sec);
|
||||
EscExmcBus::diagDump();
|
||||
}
|
||||
|
||||
/* 延迟 EEPROM 烧录:init 不阻塞,主循环第一轮执行一次。
|
||||
* 校验编译期镜像与 AT24C32 内容,不匹配则全量烧录(~20s,期间看门狗正常喂)。 */
|
||||
static bool s_eepromDone = false;
|
||||
if (!s_eepromDone) {
|
||||
s_eepromDone = true;
|
||||
if (EscEeprom::init()) {
|
||||
if (EscEeprom::verifyEsi(ESI_EEPROM_IMAGE, ESI_EEPROM_SIZE)) {
|
||||
printf("[ECAT][EEPROM] content OK, skip burn\r\n");
|
||||
} else {
|
||||
printf("[ECAT][EEPROM] content mismatch, burning ESI (%u bytes)...\r\n",
|
||||
(unsigned)ESI_EEPROM_SIZE);
|
||||
if (EscEeprom::writeEsi(ESI_EEPROM_IMAGE, ESI_EEPROM_SIZE)) {
|
||||
if (EscEeprom::verifyEsi(ESI_EEPROM_IMAGE, ESI_EEPROM_SIZE)) {
|
||||
EscEeprom::reload();
|
||||
printf("[ECAT][EEPROM] burn+verify OK, reload issued\r\n");
|
||||
} else {
|
||||
printf("[ECAT][EEPROM] post-burn verify FAIL\r\n");
|
||||
}
|
||||
} else {
|
||||
printf("[ECAT][EEPROM] burn FAIL\r\n");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("[ECAT][EEPROM] init FAIL (PDI control not acquired)\r\n");
|
||||
}
|
||||
}
|
||||
/* 延迟 EEPROM 烧录已删除(1.5.29):ESI 镜像改由 EtherCAT 主站侧刷写
|
||||
* (tools/ecat/ecat_flash_eeprom.py 经 ESC 0x0500 EEPROM 接口),
|
||||
* 固件不再承担烧录/校验职责。 */
|
||||
|
||||
/* poll() 含按铃超时看门狗(cancelRing),必须每轮无条件执行。
|
||||
* 主动推送已随 2026-08 请求驱动改造移除,此处仅需消费请求响应的按铃。 */
|
||||
|
||||
@@ -52,8 +52,6 @@ private:
|
||||
static void taskHeartbeat();
|
||||
/** @brief 诊断打印任务。 */
|
||||
static void taskDiagnosticPrint();
|
||||
/** @brief EtherCAT 周期/事件处理(非实时应用层 PDO 映射)。 */
|
||||
static void taskEthercatProcess();
|
||||
};
|
||||
|
||||
#endif /* SYS_TASK_RUNNER_H */
|
||||
|
||||
Reference in New Issue
Block a user