- 修正HBI访问模型:将ESC核心CSR(0x0000-0x0FFF)改为通过ECAT_CSR_CMD/DATA 间接端口访问,解决此前直接寻址导致核心寄存器恒读0/写丢弃的问题 - 新增csrRead/csrWrite/pramRead/pramWrite接口,正确实现LAN9252访问端口操作 - 添加PDI就绪检测:等待DL_STATUS bit0置位确认EEPROM加载完成和EtherCAT核心使能 - 实现IRQ引脚输出使能:配置IRQ_CFG和INT_EN寄存器,使EtherCAT事件能到达PB1, 解决PDI_Isr未触发导致SAFEOP->OP无限挂起的问题 - 为ESC_EXMC硬件诊断添加CONFIG_ESC_EXMC_DIAG门控,默认关闭避免影响正常运行 - 修正system_gd32e50x.c中HXTAL故障诊断的寄存器偏移和位设置错
385 lines
40 KiB
C++
385 lines
40 KiB
C++
/**
|
||
* @file config.h
|
||
* @brief 应用级集中配置项定义。
|
||
* @note 用于统一管理当前项目中可调的外设、时序、通信与算法常量。
|
||
*/
|
||
#ifndef SYS_CONFIG_H
|
||
#define SYS_CONFIG_H
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
#include "gd32e50x.h"
|
||
|
||
/* ============================================================
|
||
* 功能开关(调试/特性总闸 — 改这里即可开关,改完重编)
|
||
* 0/false=关,1/true=开。需要 #if 的保留 #define。
|
||
* ============================================================ */
|
||
/**
|
||
* @brief 5s 诊断任务是否输出全量 UART 摘要(task_runner)。
|
||
* @note 任务本身始终 5s 调度:0=默认仅状态变化/错误增量;1=周期打印 ADC/CAN/ECAT 全量行。
|
||
* 现场抓吞吐/温度时改回 1 后重编即可。
|
||
*/
|
||
#define CONFIG_UART_TEMP_PERIODIC_PRINT 0
|
||
/**
|
||
* @brief 全量摘要详细级别(仅 PERIODIC_PRINT=1 时生效;0=ADC 精简 1=含 CAN 统计)。
|
||
* @note 默认 0;需要 can_tx/rx/drop 等列时与 PERIODIC_PRINT 一并打开。
|
||
*/
|
||
#define CONFIG_UART_DIAG_LEVEL 0
|
||
/**
|
||
* @brief SPI 调试反馈 0xC4:GD32 ADC 温度/VDDA/VIN 1Hz 主动推送。
|
||
* @note 调试用;0=不注册 handler、不推送。与 ESP32 GD32_ADC_FEEDBACK_ENABLE 配对。
|
||
*/
|
||
#define CONFIG_SPI_ADC_FEEDBACK_ENABLE 1
|
||
/**
|
||
* @brief 多电机状态表 0xC5:CAN STATUS 帧缓存 + 250ms 主动推送。
|
||
* @note 0=不注册 handler、不推送、不解析 STATUS 帧。与 ESP32 端 motor_state_task 配对。
|
||
*/
|
||
#define CONFIG_MOTOR_STATE_ENABLE 1
|
||
/**
|
||
* @brief 多电机版本 0xC6:CAN 版本应答帧(0x00FF)缓存 + 事件驱动推送。
|
||
* @note 0=不识别版本帧、不推送。与 ESP32 端 motor_version 缓存配对。
|
||
* 版本为按需查询的低频数据,独立于 0xC5 周期推送。
|
||
*/
|
||
#define CONFIG_MOTOR_VERSION_ENABLE 1
|
||
/** @brief 最大电机节点数 (node ID 1-9)。 */
|
||
constexpr uint8_t CONFIG_MOTOR_MAX_NODES = 9U;
|
||
/** @brief 电机离线判定超时 (ms)。超过此时间未收到 STATUS 帧则标记 offline。 */
|
||
constexpr uint16_t CONFIG_MOTOR_OFFLINE_MS = 3000U;
|
||
/** @brief SPI 命令逐帧日志(#if)。 */
|
||
#define CONFIG_SPI_APP_LOG_ENABLE 0
|
||
/** @brief CAN_SEND 成功帧详细日志(#if)。 */
|
||
#define CONFIG_SPI_CAN_SEND_VERBOSE_LOG 0
|
||
/** @brief CAN-FD BRS 使能(canfd.cpp #if)。
|
||
* 关闭 BRS: 数据段用仲裁段同速率,牢牢性更高。
|
||
* 电机 BOOT 无法正确接收 BRS 高速段→nonce(16B FD+BRS)被拒绝→握手失败。 */
|
||
#define CONFIG_CAN_FD_BRS_ENABLE 1U
|
||
/** @brief 启动时总线探测帧;正常固件关。 */
|
||
#define CONFIG_CAN_STARTUP_BUS_TEST_ENABLE 0
|
||
/** @brief 启动时内部回环自检;正常固件关。 */
|
||
#define CONFIG_CAN_STARTUP_LOOPBACK_TEST_ENABLE 0
|
||
/** @brief CAN 启动详细诊断 dump;默认关。 */
|
||
#define CONFIG_CAN_STARTUP_DIAG_VERBOSE 0
|
||
/**
|
||
* @brief 周期测试发送任务(taskCanTxSend,发 0x18FF5000 64B FD 帧)。
|
||
* @note 调试用:该 PGN 无业务接收节点 ACK。auto_retrans=ENABLE 时无 ACK 被
|
||
* 无限重发吞进 TEC(TEC 一直涨);DISABLE 时单发失败即 MTEn→error_count++。
|
||
* 电机拓扑下无对端应答,默认关以消除持续错误帧。需要回放测试波形时打开。
|
||
*/
|
||
#define CONFIG_CAN_PERIODIC_TEST_TX_ENABLE 0
|
||
/** @brief CAN0/1/2 通道使能。CH1/CH2 未接设备,关闭避免持续 CAN 错误 + 占 SPI 带宽。 */
|
||
constexpr bool CONFIG_CAN_CH0_ENABLE = true;
|
||
constexpr bool CONFIG_CAN_CH1_ENABLE = true;
|
||
constexpr bool CONFIG_CAN_CH2_ENABLE = true;
|
||
/** @brief 主循环 WFI(main.cpp #if)。 */
|
||
#define CONFIG_MAIN_LOOP_WFI_ENABLE 0
|
||
/** @brief EtherCAT SYNC0 同步模式(#if)。 */
|
||
#define CONFIG_ETHERCAT_SYNC_MODE 0
|
||
/** @brief MOTOR-OTA INFO 级日志(握手/进度/流控 chatter);错误与关键事件恒保留。 */
|
||
#define CONFIG_OTA_RELAY_LOG_ENABLE 1
|
||
/** @brief CAN 初始化/自检 INFO 级日志;初始化失败与硬件错误恒保留。 */
|
||
#define CONFIG_CAN_INIT_LOG_ENABLE 1
|
||
/** @brief EtherCAT/EXMC 初始化 INFO 级日志;FAIL 恒保留。 */
|
||
#define CONFIG_ECAT_INIT_LOG_ENABLE 1
|
||
/** @brief HBI bring-up 诊断探针(bit-bang 探活 + predrive/回显 + 20s 周期复跑)。
|
||
* @note 硬件层已确认全通(IDX_0=0x1234、BYTE_TEST=0x87654321),默认关闭以清理上电日志,
|
||
* 并避免每次上电/每 20s 把 EXMC 引脚切成 GPIO 手动拉一遍。换板/补焊需重新排查浮空时置 1。
|
||
* 网页万用表通断测试 continuityDrive() 不受此开关影响,始终可用。 */
|
||
#define CONFIG_ESC_EXMC_DIAG 0
|
||
/** @brief 启动横幅与 main 进度打印。 */
|
||
#define CONFIG_APP_BANNER_LOG_ENABLE 1
|
||
|
||
/* ============================================================
|
||
* 日志分级宏:*_LOGI=INFO 级,由上方模块开关编译期裁剪,
|
||
* 格式串随之被链接器回收;LOG_ERR=错误/关键事件,恒保留。
|
||
* 使用文件需自行可见 printf 声明(<cstdio>)。
|
||
* ============================================================ */
|
||
#define LOG_ERR(...) printf(__VA_ARGS__)
|
||
#if CONFIG_OTA_RELAY_LOG_ENABLE
|
||
#define OTA_LOGI(...) printf(__VA_ARGS__)
|
||
#else
|
||
#define OTA_LOGI(...) ((void)0)
|
||
#endif
|
||
#if CONFIG_CAN_INIT_LOG_ENABLE
|
||
#define CAN_LOGI(...) printf(__VA_ARGS__)
|
||
#else
|
||
#define CAN_LOGI(...) ((void)0)
|
||
#endif
|
||
#if CONFIG_ECAT_INIT_LOG_ENABLE
|
||
#define ECAT_LOGI(...) printf(__VA_ARGS__)
|
||
#else
|
||
#define ECAT_LOGI(...) ((void)0)
|
||
#endif
|
||
#if CONFIG_APP_BANNER_LOG_ENABLE
|
||
#define APP_LOGI(...) printf(__VA_ARGS__)
|
||
#else
|
||
#define APP_LOGI(...) ((void)0)
|
||
#endif
|
||
|
||
/* ============================================================
|
||
* APP 固件版本号
|
||
* ============================================================ */
|
||
constexpr uint32_t APP_FW_VERSION_MAJOR = 1U;
|
||
constexpr uint32_t APP_FW_VERSION_MINOR = 5U;
|
||
constexpr uint32_t APP_FW_VERSION_PATCH = 43U; /* 1.5.43:修复 SAFEOP->OP 永远进不去(主站报 "进 OP 失败: AL=PREOP code=0x0000",且已边发 processdata 边等 3s 仍无效)——根因是 LAN9252 的 IRQ 引脚从未被使能,PDI_Isr 一次都没执行过。IRQ_CFG(0x054) 与 INT_EN(0x05C) 是 LAN9252 系统 CSR(HBI 索引直接可达,不走 CSR 间接端口),复位默认值均为 0,即 IRQ_EN=0(引脚永久去断言)+ ECAT_INT_EN=0(EtherCAT 事件不汇入 IRQ,DS 8.2.6/8.3.1,ECAT_INT 为 INT_STS/INT_EN 的 bit0);固件此前只配了 EXTI/GPIO/NVIC 侧(PB1 上拉输入+下降沿+preempt=1)与 EEPROM 的 SYNC0/1(0x0151=0xCC),从来没打开芯片侧的中断输出总闸。后果链:PDI_Isr 从不触发 → SSC 收不到 PROCESS_OUTPUT_EVENT → bEcatFirstOutputsReceived 恒 FALSE(该标志只在 PDI_Isr(ecatappl.c:305) 或 free-run 的 MainLoop 轮询分支(ecatappl.c:551, 条件 !bEscIntEnabled)里置位)→ AL_ControlInd 的 SAFEOP_2_OP 分支(ecatslv.c:1993 `nPdOutputSize == 0 || bEcatFirstOutputsReceived`) 因本工程有 32B 输出而永不成立 → 迁移被挂起(bApplEsmPending)后回落,AL Status Code 保持 0x0000(不是被拒绝,故不给 0x001B/0x001A)。注意本工程 SyncType 使 UpdateSyncManagerParameter 置 bEscIntEnabled=TRUE(ecatslv.c:951),因此 MainLoop 的 free-run 轮询兜底分支不执行,中断是唯一通路。EscLan9252::init() 在 DL_STATUS bit0 确认 PDI 就绪后新增 enableEcatIrqOutput():先写 INT_STS 清 ECAT_INT 悬留状态(R/WC),再置 INT_EN.ECAT_INT_EN,最后开 IRQ_CFG 总闸并回读校验,打印 [ECAT][ESC] IRQ output enabled(失败则 WARN 并指明 SAFEOP->OP 会卡)。极性与 ethercat_sync.cpp 保持一致:推挽 IRQ_TYPE=1 + 低有效 IRQ_POL=0,配对上拉输入的下降沿 EXTI;INT_DEAS 保持 0=禁用去断言定时器。AL Event Mask(0x204) 仍由 SSC 在状态迁移时自行维护,不在此处干预。配套修主站工具(tools/ecat):(a) _require_op_ready/enter_op 请求 OP 后改为边 send_processdata/receive_processdata 边 state_check 循环至多 3s(SSC 要求先收到首帧输出才 ack OP),中途回落则重发 OP 请求,失败信息按 AL code 分流排查方向;(b) 修正 state_check 超时单位——pysoem docstring 明确 "Timeout value in us",旧代码各处传 2000 实际只等 2ms(SOEM 默认 EC_TIMEOUTSTATE=2000000=2s),PREOP/SAFEOP 能过纯属从站 ack 快的侥幸,现统一用 EC_TIMEOUT_STATE_US=2_000_000 常量。1.5.42:修复主站 config_map 失败(SdoError "Unsupported access to an object" / "Attempt to read to a write only object",实测 0x1600/0x1A00 的 sub0/3/4 报错而 sub1/2 通过)——两个独立的对象字典 bug,均在从站侧,与主站工具无关。(1) REC 对象的 entry descriptor 数组给少了:OBJ_GetEntryDesc()(objdef.c:554) 与 OBJ_GetEntryOffset()(objdef.c:609) 只对 OBJCODE_ARR 复用 pEntryDesc[1] 描述所有子索引,对 OBJCODE_REC 是逐下标索引 pEntryDesc[Subindex];而 dc_app.c 把 0x1600/0x1A00/0x7000/0x6000/0x2000 全声明为 REC(4|OBJCODE_REC<<8) 却只提供 2 元素描述数组,sub3/sub4 越界读到相邻常量数组的垃圾 DataType/ObjAccess,正好解释"sub0/3/4 报错、sub1/2 侥幸通过"的错误模式(sub1/2 恰好落在合法项上)。现为 0x1600/0x1A00 补满 Sub0..Sub4 共 5 项(asPDOMappingEntryDesc),并把原共用的 asDataEntryDesc 拆成 asOutputEntryDesc/asInputEntryDesc(各 5 项)、asSyncDiagEntryDesc 补到 5 项;同时给数据子条目补 OBJACCESS_RXPDOMAPPING/TXPDOMAPPING(官方 sampleappl.h 的 0x7010/0x6000 同此,缺这两个标志主站校验 0x1600/0x1A00 的映射目标时会拒绝),输入侧 0x6000 由 READWRITE 收紧为 ACCESS_READ。0x1C12/0x1C13 是 ARR 保持 2 项不变。(2) 结构体从未被紧排:ecat_def.h 的 STRUCT_PACKED_START/MBX_STRUCT_PACKED_START/OBJ_STRUCT_PACKED_START 三对宏全部留空,注释还误写"AC6 不需要"——实际这些宏就是 SSC 紧排结构体的唯一手段,SSC 的 SDO 读写按"si0 占 16bit、其后各条目按 BitLength 紧排"算字节偏移(OBJ_GetEntryOffset),留空则按编译器自然对齐。armclang 编译期断言实测:{UINT16;UINT64[4]} 的 UINT64 落在字节 8 而非 2,{UINT16;UINT32 x4} 落在字节 4 而非 2,故 0x7000/0x6000/0x2000 的 SDO 单条目访问全部读写错位内存,SSC 内部 0x1C3x(TSYNCMANPAR)/0x10F1 等同样受影响(PDO 路径走 memcpy 未受影响,故此前回环测试无法暴露)。三对宏改为 __attribute__((packed)),并在 dc_app.c 加 _Static_assert 守卫 offsetof==2 与 sizeof==34 防回归。1.5.41:修正三处会误导诊断的日志缺陷(1.5.39 的 LAN9252 访问模型修复经实测已端到端成立:IDX=0x1234、BYTE_TEST=0x87654321、DL_STATUS bit0=1 且 waited 0ms、PDI_CTRL=0x8D、ESC_CFG bit0=0 Device Emulation 关闭、EEP_CSR 无错误位、CSR 写回环 0x0204 写 0x0A50 读回 PASS、SSC MainInit OK;waited 0ms 同时反证 1.5.37「EEPROM 加载竞态」确不存在,读全 0 纯因走错通路)。(1) [ECAT][DIAG] 的 EEP_CSR 位标签错且语义反:0x0502 的 bit11 是 Checksum Error 而非 loaded(真正的加载状态在 bit12,且 0=OK;见 ETG.1000.4 表 49 与 SSC esc.h ESC_EEPROM_ERROR_CRC/LOAD),旧版打印 "loaded=%u" 取 bit11,正常板子恒显示 loaded=0,字面像「EEPROM 未加载」,正是 1.5.37 那个已撤回结论的诱因;现改为 crc_err/load_err/ack_err/wr_err/busy 分位打印并注明全 0=正常。(2) [ECAT][SLAVE] init 终判在无主站时是假警报:s_escReady 要求 AL>=SAFEOP,而 AL 迁移只由主站写 AL Control(0x0120) 驱动、从站不自跳,故冷启动必然打 FAIL(partial),与紧随其后的 SSC MainInit OK 自相矛盾;现按 DL_STATUS 的 Physical Link 位 bit4/5/6(DS 12.14.19) 判定有无主站,空载报 WAIT_MASTER(实测空载 0x5503 三口 link/comm 全 0,接主站 0x5611),link up 却卡 AL 才报真问题并提示逐级 write_state+配 DC。(3) 串口日志丢字节:Usart0::putCharNonBlocking 在 1024B 环形缓冲满时静默丢弃且 putChar 忽略返回值,3M 波特率下 init 阶段诊断突发写入必溢出,实测掉字产生 "bus eaabled"/"pdi_type=0x8Dexect"/"[EAT][SLAVE]" 等伪影,直接污染判断依据;现 kTxBufSize 1024→4096,缓冲满时在临界区内轮询 TBE 就地发出最老字节腾位(drainOneByteLocked,走轮询不等中断,故 ISR 内 printf 亦不死锁;USART0 为 preempt=3 已被 BASEPRI 屏蔽,独占 s_txTail 无争用),仅 USART 外设不发送时才丢弃并累加 s_txDropped,新增 droppedBytes() 并在 init 报告尾部非 0 时打 WARN 自证日志完整性。1.5.40:清理上电 CAN 启动噪声——[CAN-DIAG] CH%u init_nom/init_fd/exit_ok 三行改为仅在本端控制器初始化失败(can_init/can_fd_init 返回失败,或退出 init mode 后 STAT.IWS 仍置位)时以 LOG_ERR 打印;正常上电(三通道 init_nom=1 init_fd=1 exit_ok=1)完全静默。判据只看 GD32 控制器自身,不含 TEC/REC——总线侧计数在未接从站时会因 RX 浮空噪声累积,与 1.5.36 移除 L0 自检 BUS_OFF/TEC/REC 检查同一原则。1.5.39:修复 LAN9252 访问模型根本性错误——EtherCAT 核心寄存器一直读 0/写丢弃(主站恒读 AL=INIT code=0 的真正根因,1.5.35/1.5.37 两次误判已撤回)。网络侧诊断(新增 tools/ecat/ecat_esc_regs.py,经 Npcap 裸 APRD 帧读 ESC + pysoem 读 SII)实测:EEPROM 加载正常(SII CRC=0x9B 相符)、DL_STATUS=0x5611 pdi_oper=1、ESC_CFG pdi_type=0x8D 已生效、AL Status=0x0001,即 ESC 侧一切正常,故障纯在 GD32 的 HBI 访问层。按 DS 12.11/表 12-13:HBI 索引直接寻址的只有 LAN9252 系统 CSR(BYTE_TEST 0x064 等)与访问端口,EtherCAT 核心 CSR(0x0000-0x0FFF:AL Status/Event、SyncManager、EEPROM 接口)必须经 ECAT_CSR_CMD(0x304)/ECAT_CSR_DATA(0x300) 间接访问,过程 RAM(0x1000-0x1FFF:邮箱/PDO)必须经 PRAM FIFO(数据口 0x000-0x03C + 地址长度/命令 0x308-0x314);旧代码把 16 位索引当统一地址空间直读直写,只有 BYTE_TEST 这类系统 CSR 恰好可达,所以「探活全过、业务全死」,且写路径从未被端到端验证过。EscLan9252 新增 csrRead/csrWrite(BUSY 轮询+size 1/2/4)与 pramRead/pramWrite(ADDR_LEN→BUSY→按 avail 轮询读写 FIFO,首/末 DWORD 按 addr&3 取有效字节,别名口轮换),initOnlyReadReg/WriteReg 改走 CSR 端口;hw_gd32exmc.cpp 的 escRead/escWrite 按地址自动路由 CSR/PRAM,AL Event(0x220)/AL Event Mask(0x204)/LED override/HW_GetSyncMan 全部改经 CSR 端口。附带修复:HW_Enable/DisableSyncManChannel 的 Activate 偏移 +4→+6(+4 是 SM Control,Activate 在 0x0806+8n)。1.5.38:修复看门狗 init 失败(SPI 0xA3 实测 crit_fail=0x1000)——FWDGT 的 PSC/RLD 写入经 LSI(IRC40K) 时钟域同步(PUD/RUD 由硬件清零),而 BOOT 只检测 FWDGT 复位标志、从不启动看门狗,冷启动时 LSI 未开,fwdgt_prescaler/reload_value_config 等 PUD/RUD 永远等不到清零、库超时返回 ERROR;该失败自始存在(旧代码忽略返回值时 FWDGT 实际按复位默认值 DIV4/0xFFF≈0.41s 运行,与配置 3.0s 不符,主循环喂狗快才未暴露)。Watchdog::init() 改为先 rcu_osci_on(RCU_IRC40K)+rcu_osci_stab_wait 再配置,新增故障码 kFaultLsiNotReady=4。1.5.37:修复 EEPROM 加载竞态致 EtherCAT 永不就绪(主站恒读 AL=INIT code=0 的根因)——LAN9252 RST# 释放后内部 EEPROM Loader 经 I2C 读 SII 约 30ms,加载完成前 EtherCAT 核心寄存器对 PDI(HBI) 读全 0、写静默丢弃;1.5.35 的 [ECAT][DIAG] 实测 RST# 释放 +3ms 时 DL_STATUS/ESC_CFG/EEP_CSR 全 0、写回环 FAIL,而 SSC 在 +4ms 就已完成 MainInit,AL Event Mask/邮箱 SM 配置全部落空。EscLan9252::init() 在 BYTE_TEST 通过后新增轮询 DL_STATUS(0x0110) bit0(PDI operational/EEPROM loaded,超时沿用 CONFIG_ESC_HBI_POLL_TIMEOUT_MS=300ms;成功打印等待时长,失败打印 DL_STATUS/EEP_CSR 原始值与排查提示)并新增 isCoreReady();initial.cpp 仅在 busReady&&coreReady 时放行 MainInit,总线通但核心未就绪报新故障码 kFaultEthercatCoreNotReady(=3,SPI 0xA3 fault_codes 同步可见)。订正 1.5.35 条目:写回环实际用 AL Event Mask(0x0204) 写 0x0A50 后还原,非 Station Alias(0x012)——后者在部分 ESC 上对 PDI 只读会造成假 FAIL。1.5.36:模块级故障码(fault_codes)——每模块 1B 原因码(0=成功),SPI 0xA3 INIT_STATUS 响应从 12B 扩到 25B([12..24] 按 ModuleBit 位序):canfd=原因码|(首个失败通道<<4)(1=控制器init失败 2=卡init mode 3=STB配置未生效)、ADC(1=RSTCLB超时 2=CLB超时 3=VDDA无效)、Scheduler(1=CEN 2=PSC 3=CAR 4=节拍未前进)、Watchdog(1=PSC 2=RLD 3=挂起)、EtherCAT(1=EXMC总线未就绪 2=SSC MainInit失败)、nvic/esp32_hold/usart0 各单码;init 报告失败模块名带 #XX 故障码后缀,码值定义集中在 sys/initial.h 注释。重要修正:CAN L0 自检移除 BUS_OFF 与 TEC/REC 检查——总线侧状态在通道未接从站(RX 浮空噪声累积 REC)时误报,「没接从站≠错误」;L0 现仅校验 GD32 控制器自身(init失败/卡init mode/STB输出配置),总线健康仍经 0xC1 反馈帧运行期上报(网页 CAN 页可见);CAN L0 按通道打 LOG_ERR(含 STAT/ERR 寄存器);无使能 CAN 通道(全关)属合法配置不再算失败。1.5.35:AL 恒卡 INIT 的判死诊断。主站侧根因已先修:tools/ecat/ecat_server.py 的 _require_op_ready 旧版只 state_check(SAFEOP) 而从不 write_state、且全程未请求过 PREOP——pysoem 的 state_check 只轮询等待、不发 AL Control,故从站从未被要求迁移(现象=AL INIT/code=0x0000 且无错误码);已改为 PREOP→config_map→[DC]→SAFEOP→OP 每步先 write_state 再 state_check。修完后主站确认真的发出 PREOP 请求,但从站仍恒 INIT/code=0x0000,故在 EthercatSlave::init() 增 [ECAT][DIAG] 一次性判死三点:DL_STATUS(0x110) bit0 PDI operational(为 0 则 ESC 静默丢弃 PDI 侧写入的 AL Status)、ESC_CFG(0x140) PDI 类型是否被 EEPROM 加载为 0x8D(HBI 16-bit)、EEP_CSR(0x502) EEPROM loaded/校验错(SII 校验失败会拒绝离开 INIT 且常不给 code);外加 HBI 写路径回环(0x012 Configured Station Alias 写 0xA55A 读回后还原)——此前所有上电探针验证的都是"读"(bit-bang IDX_0 / BYTE_TEST),而 esc_exmc_bus 的 EXMC 写回显测试只在 idx0_raw!=0x1234 的失败分支才跑、因 IDX 正确恒被跳过,故 HBI 写路径从未被端到端验证;若写坏,ECAT_Main 能读到 AL Control 事件却写不回 AL Status,与实测现象完全一致。注意主站读身份/AL 走 ESC 以太网侧+EEPROM(SII),不经过 GD32 的 HBI/PDI,"主站能读到身份"不能证明 PDI 写通。1.5.34:初始化状态检查补全覆盖——原"盲初始化"模块全部改为带验证:SysTick initMs 检查 SysTick_Config 返回值并验证 1ms 节拍真实前进(失败=FATAL 裸串口报告+停机,与 HXTAL FAIL 同级)、ADC 校准改带超时轮询(库函数 adc_calibration_enable 内部死等,硬件异常会永久挂住)并验证 VREFINT→VDDA 采样链、SchedulerTimer 回读 CEN/PSC/CAR 并验证 100us 中断节拍前进、USART0 回读 CTL0.UEN、Watchdog 检查 fwdgt PSC/RLD 的 ErrStatus 返回值+PUD/RUD 无挂起、NVIC 回读 AIRCR.PRIGROUP、ESP32_EN 回读门控置位;新增复位源采集(RCU_RSTSCK→ResetCauseBit 位图,init 报告打印);AppInitializer 导出 moduleMask/criticalFailMask/initState/resetCause getter;新增 SPI 0xA3 INIT_STATUS 命令(12B:模块位图+critical失败位图+复位源+init_state),身份块[15] 原 reserved 字节改填 init_state(旧 ESP32 忽略、旧 GD32 恒 0 与 OK 同义,不 bump feat_map_ver 前后兼容);CONFIG_SPI_MAX_COMMANDS 12→14。附带修复:system_gd32e50x.c 五处 HXTAL FAIL 裸串口诊断段寄存器 bug(CTL0 误写 STAT0 偏移 0x40013800 且漏开 APB2EN bit14 USART0EN,该诊断从未真正发出)——正确布局 CTL0 @ USART0+0x0C。1.5.33:HBI bring-up 诊断探针 EscExmcBus::diagDump 改由 CONFIG_ESC_EXMC_DIAG 门控(默认 0)——硬件层已确认全通(IDX_0=0x1234、BYTE_TEST=0x87654321),清理上电 [EXMC-DIAG] 噪声并停止 task_runner 的 20s 周期复跑,不再每次上电把 EXMC 引脚切成 GPIO 手动拉一遍;换板/补焊排查浮空时置 1 即恢复。网页万用表通断测试 continuityDrive() 及其复用的 bit-bang 辅助函数不受影响,始终可用。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;
|
||
|
||
|
||
/** @brief USART0 默认波特率。 */
|
||
constexpr uint32_t CONFIG_USART0_BAUDRATE = 3000000U; /* 3M:诊断打印高速输出,printf 阻塞极小、不拖慢 relay */
|
||
|
||
/** @brief ADC 外设实例。 */
|
||
constexpr uint32_t CONFIG_ADC_INSTANCE = ADC0;
|
||
/** @brief ADC 外部 VIN 检测通道号(原理图:PA6 -> VIN_ADC)。 */
|
||
constexpr uint32_t CONFIG_ADC_VIN_CHANNEL = ADC_CHANNEL_6;
|
||
/** @brief ADC 内部温度通道号。 */
|
||
constexpr uint32_t CONFIG_ADC_TEMP_CHANNEL = ADC_CHANNEL_16;
|
||
/** @brief ADC 内部参考电压通道号。 */
|
||
constexpr uint32_t CONFIG_ADC_VREFINT_CHANNEL = ADC_CHANNEL_17;
|
||
/** @brief ADC 满量程计数值。 */
|
||
constexpr float CONFIG_ADC_MAX_VALUE = 4095.0f;
|
||
/** @brief 内部参考电压典型值,单位 V。 */
|
||
constexpr float CONFIG_ADC_VREFINT_TYPICAL_VOLTAGE = 1.20f;
|
||
/** @brief 温度传感器 25℃ 对应电压,单位 V。 */
|
||
constexpr float CONFIG_ADC_TEMP_V25 = 1.43f;
|
||
/** @brief 温度传感器平均斜率,单位 V/℃。 */
|
||
constexpr float CONFIG_ADC_TEMP_AVG_SLOPE = 0.0043f;
|
||
/** @brief ADC 上电后稳定等待时间,单位 ms。 */
|
||
constexpr uint32_t CONFIG_ADC_STABILIZE_DELAY_MS = 2U;
|
||
/** @brief ADC 中值滤波窗口长度(最终样本数为该值 + 1)。 */
|
||
constexpr uint32_t CONFIG_ADC_FILTER_SIZE = 6U;
|
||
|
||
/** @brief CAN 状态报文标准帧 ID。 */
|
||
constexpr uint32_t CONFIG_CAN_STATUS_ID = 0x321U;
|
||
/** @brief ESP32 请求 DCU_APP 进入 Bootloader OTA 窗口的扩展帧 ID(备用 CAN 入口)。 */
|
||
constexpr uint32_t CONFIG_CAN_OTA_BOOT_REQ_ID = 0x00000320U;
|
||
/** @brief 进入 Bootloader OTA 请求魔术字节 0~3。 */
|
||
constexpr uint8_t CONFIG_CAN_OTA_BOOT_MAGIC0 = 0x4FU;
|
||
constexpr uint8_t CONFIG_CAN_OTA_BOOT_MAGIC1 = 0x54U;
|
||
constexpr uint8_t CONFIG_CAN_OTA_BOOT_MAGIC2 = 0x41U;
|
||
constexpr uint8_t CONFIG_CAN_OTA_BOOT_MAGIC3 = 0x21U;
|
||
/** @brief ESP32 在 APP 运行期通过 SPI 发送的进入 Bootloader OTA 命令。 */
|
||
constexpr uint8_t CONFIG_SPI_APP_OTA_BOOT_CMD = 0xB0U;
|
||
/** @brief SPI 进入 Bootloader OTA 命令确认状态:成功。 */
|
||
constexpr uint8_t CONFIG_SPI_APP_OTA_BOOT_ACK_OK = 0xB5U;
|
||
/** @brief SPI DATA_READY 输出端口(PB6 → ESP32;v2:低=有待读,高=空闲)。 */
|
||
constexpr uint32_t CONFIG_SPI_READY_PORT = GPIOB;
|
||
/** @brief SPI DATA_READY 输出引脚。 */
|
||
constexpr uint32_t CONFIG_SPI_READY_PIN = GPIO_PIN_6;
|
||
/** @brief APP SPI DMA/软件缓冲(字节)。业务 payload 上限 = 本值 − V2_OVERHEAD(20)。 */
|
||
constexpr uint16_t CONFIG_SPI_TX_BUF_SIZE = 256U;
|
||
constexpr uint16_t CONFIG_SPI_RX_BUF_SIZE = 256U;
|
||
constexpr uint16_t CONFIG_SPI_LOG_BUF_SIZE = 256U;
|
||
/** @brief 主动按铃超时:ESP32 未在该时间内来读则 cancelRing(ms)。 */
|
||
constexpr uint32_t CONFIG_SPI_RING_TIMEOUT_MS = 50U;
|
||
/** @brief SPI 命令 handler 注册表容量。
|
||
*
|
||
* 当前 init 注册 12 个:boot_request / ota_wait / ping / init_status / can_bridge /
|
||
* can_burst / can_feedback / id_snapshot / adc_feedback / motor_state / motor_ota / exmc_diag。
|
||
* registerHandler 表满时静默丢弃,motor_ota 曾因容量=8 被丢弃(0xD0 回 0xEE)。
|
||
* 取 14 留余量;新增 handler 时须确认本容量足够。 */
|
||
constexpr uint8_t CONFIG_SPI_MAX_COMMANDS = 14U;
|
||
/** @brief 每通道不重复 ID 快照表最大条目数(与 ESP32 CANFD_ID_SNAPSHOT_MAX 对齐)。 */
|
||
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,对应原理图 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;
|
||
|
||
/* ============================================================
|
||
* CAN-FD 位时序配置(三路 CAN0/CAN1/CAN2 共用)
|
||
* 时钟链: SYSCLK=180MHz → AHB=/1=180MHz(RCU_MODIFY_UP 强制)
|
||
* → APB1=/2=90MHz (CAN_CLK)
|
||
*
|
||
* 仲裁段目标: 1.0 Mbps = 90MHz / (9 × 10 TQ)
|
||
* 数据段目标: 2.0 Mbps = 90MHz / (9 × 5 TQ)
|
||
*
|
||
* @note RCU_MODIFY_UP 宏在 system_clock_180m_hxtal() 末尾将 AHB 从 /4
|
||
* 临时切到 /1,这是 GigaDevice 官方行为,不可删除。
|
||
* 最终 AHB=180MHz, APB1=90MHz, APB2=180MHz, TIMER2_CLK=180MHz。
|
||
* ============================================================ */
|
||
|
||
/** @brief 仲裁段预分频值。 */
|
||
constexpr uint32_t CONFIG_CAN_NOMINAL_PRESCALER = 9U;
|
||
/** @brief 仲裁段再同步跳跃宽度。
|
||
* 1TQ→2TQ:总线空闲期即持续 STUFF 接收错误(REC 冲 120+),OTA 数据帧被错误帧
|
||
* 击落触发应用层重发;放宽接收再同步容差(不改波特率/采样点,上限受 BS2=2TQ 限制)。 */
|
||
constexpr uint32_t CONFIG_CAN_NOMINAL_SJW = CAN_BT_SJW_2TQ;
|
||
/** @brief 仲裁段时间段 1(PHSEG1)。 */
|
||
constexpr uint32_t CONFIG_CAN_NOMINAL_BS1 = CAN_BT_BS1_7TQ;
|
||
/** @brief 仲裁段时间段 2(PHSEG2)。 */
|
||
constexpr uint32_t CONFIG_CAN_NOMINAL_BS2 = CAN_BT_BS2_2TQ;
|
||
|
||
/** @brief 数据段预分频值。 */
|
||
constexpr uint32_t CONFIG_CAN_DATA_PRESCALER = 9U;
|
||
/** @brief 数据段再同步跳跃宽度。 */
|
||
constexpr uint32_t CONFIG_CAN_DATA_SJW = CAN_BT_SJW_1TQ;
|
||
/** @brief 数据段时间段 1。 */
|
||
constexpr uint32_t CONFIG_CAN_DATA_BS1 = CAN_BT_BS1_3TQ;
|
||
/** @brief 数据段时间段 2。 */
|
||
constexpr uint32_t CONFIG_CAN_DATA_BS2 = CAN_BT_BS2_1TQ;
|
||
|
||
/* BRS / 启动探测 / 通道使能:见文件顶部「功能开关」 */
|
||
|
||
/** @brief CAN 接收过滤器目标标准帧 ID。 */
|
||
constexpr uint32_t CONFIG_CAN_RX_FILTER_ID = CONFIG_CAN_STATUS_ID;
|
||
/** @brief CAN 接收过滤器标准帧掩码;0x7FF 表示精确匹配 11-bit ID。 */
|
||
constexpr uint32_t CONFIG_CAN_RX_FILTER_MASK = 0x7FFU;
|
||
/** @brief 单次 CAN 接收解析任务最多消费的软件队列帧数。 */
|
||
constexpr uint32_t CONFIG_CAN_RX_PARSE_BUDGET = 48U;
|
||
|
||
/** @brief 用户调度定时器实例。 */
|
||
constexpr uint32_t CONFIG_SCHED_TIMER_INSTANCE = TIMER2;
|
||
/** @brief 用户调度定时器中断号。 */
|
||
constexpr IRQn_Type CONFIG_SCHED_TIMER_IRQn = TIMER2_IRQn;
|
||
/** @brief 用户调度定时器时钟使能宏参数。 */
|
||
constexpr rcu_periph_enum CONFIG_SCHED_TIMER_RCU = RCU_TIMER2;
|
||
/** @brief 用户调度定时器预分频值。
|
||
* 时钟链: SYSCLK=180MHz → AHB=/1=180MHz(RCU_MODIFY_UP 强制) → APB1=/2=90MHz → TIMER2_CLK=APB1×2=180MHz。
|
||
* 保持 100us tick: (PSC+1)×(PER+1)=18000 → 180×100 → PSC=179, PER=99。
|
||
*/
|
||
constexpr uint32_t CONFIG_SCHED_TIMER_PRESCALER = 179U;
|
||
/** @brief 用户调度定时器周期重装值。 */
|
||
constexpr uint32_t CONFIG_SCHED_TIMER_PERIOD = 99U;
|
||
/** @brief 用户调度定时器 NVIC 抢占优先级。 */
|
||
constexpr uint32_t CONFIG_SCHED_TIMER_IRQ_PREEMPT_PRIO = 1U;
|
||
/** @brief 用户调度定时器 NVIC 子优先级。 */
|
||
constexpr uint32_t CONFIG_SCHED_TIMER_IRQ_SUB_PRIO = 0U;
|
||
|
||
/** @brief 调度基准节拍:ADC VREF 采样周期,单位 100us tick。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_VREF_SAMPLE_TICKS = 5U;
|
||
/** @brief 调度基准节拍:ADC 温度采样/处理周期,单位 100us tick。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_TEMP_SAMPLE_TICKS = 10U;
|
||
/** @brief 调度基准节拍:10ms 计数周期,单位 100us tick。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_CAN_RX_TICKS = 100U;
|
||
/** @brief 调度基准节拍:CAN 周期发送任务周期,100 tick = 10ms。
|
||
* @note 原 1ms/帧过密,改为 10ms/帧以降低 CAN 总线负载与 GD32 邮箱压力。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_CAN_TX_TICKS = 100U;
|
||
/** @brief 调度基准节拍:心跳周期,单位 100us tick。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_HEARTBEAT_TICKS = 10000U;
|
||
/** @brief 调度基准节拍:多电机状态 0xC5 主动推送启动周期,2500 tick = 250ms。
|
||
* @note 独立于 1Hz heartbeat,避免连带加速 OTA Boot 轮询 / CAN 反馈快照刷新 /
|
||
* ADC 推送 / checkOffline 离线判定(3s 阈值)。前端 age 应稳定在 ~120ms。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_MOTOR_STATE_TICKS = 2500U;
|
||
/** @brief 调度基准节拍:APP 状态/诊断打印周期,50000 tick = 5s。 */
|
||
constexpr uint32_t CONFIG_TASK_PERIOD_DIAG_PRINT_TICKS = 50000U;
|
||
|
||
/* UART/SPI 调试开关:见文件顶部「功能开关」 */
|
||
|
||
/** @brief FWDGT 独立看门狗预分频值。 */
|
||
constexpr uint32_t CONFIG_FWDGT_PSC = FWDGT_PSC_DIV64;
|
||
/** @brief FWDGT 独立看门狗重载值。
|
||
* 超时 = (64 / 40000) * (RLD + 1) = 1.6ms * (RLD+1)
|
||
* RLD=1874 → 1.6ms * 1875 ≈ 3.0s
|
||
*/
|
||
constexpr uint32_t CONFIG_FWDGT_RLD = 1874U;
|
||
/** @brief FWDGT 超时近似值(毫秒),仅供文档参考。 */
|
||
constexpr uint32_t CONFIG_FWDGT_TIMEOUT_MS = 3000U;
|
||
|
||
/* ============================================================
|
||
* BOOT 版本在 OTA 配置页中的 Flash 存储地址
|
||
* 与 BOOT 工程 sys/config.h 保持一致
|
||
* ============================================================ */
|
||
constexpr uint32_t CONFIG_OTA_CONFIG_PAGE_ADDR = 0x0807E000U;
|
||
constexpr uint32_t CONFIG_BOOT_VERSION_ADDR0 = CONFIG_OTA_CONFIG_PAGE_ADDR + 0x18U;
|
||
constexpr uint32_t CONFIG_BOOT_VERSION_ADDR1 = CONFIG_OTA_CONFIG_PAGE_ADDR + 0x1CU;
|
||
constexpr uint32_t CONFIG_OTA_CONFIG_WORD_COUNT = 8U;
|
||
|
||
/* ============================================================
|
||
* NVIC 优先级分组与中断优先级分层
|
||
* (EtherCAT 实时架构改造:PRE4_SUB0,4 位抢占优先级)
|
||
* ============================================================ */
|
||
constexpr uint32_t CONFIG_NVIC_PRIORITY_GROUP = NVIC_PRIGROUP_PRE4_SUB0;
|
||
constexpr uint32_t CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC = 0U;
|
||
constexpr uint32_t CONFIG_IRQ_PREEMPT_SCHED = 1U;
|
||
constexpr uint32_t CONFIG_IRQ_PREEMPT_CAN = 2U;
|
||
constexpr uint32_t CONFIG_IRQ_PREEMPT_ETHERCAT_ESC = 1U;
|
||
constexpr uint32_t CONFIG_IRQ_PREEMPT_ETHERCAT_SYNC1 = 1U;
|
||
constexpr uint32_t CONFIG_IRQ_PREEMPT_SPI_USART = 3U;
|
||
/* ============================================================
|
||
* EtherCAT LAN9252 配置(开关见顶部 CONFIG_MAIN_LOOP_WFI / ETHERCAT_SYNC_MODE)
|
||
* ============================================================ */
|
||
/* 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;
|
||
/* Region0 = NE0 @ 0x60000000(GD32E50x 用户手册 Rev2.2 图25-3: Bank0 四 Region 各 64MB,
|
||
* HADDR[27:26]=00 选中 NE0)。LAN9252 CS 接 PD7=EXMC_NE0(数据手册 GD32E508xx
|
||
* Datasheet Rev1.8 LQFP100 引脚表: PD7 Alternate2 = EXMC_NE0/EXMC_NCE1)。
|
||
* 注意: GD32E508Vx (LQFP100) 封装只引出 NE0 一个 NOR/SRAM 片选引脚,
|
||
* NE1~NE3 仅在 LQFP144 (Zx) 上存在;因此必须使用 Region0(SNCTL0),不能用 Region1。 */
|
||
#ifndef EXMC_BANK0_NORSRAM_REGION0
|
||
#define EXMC_BANK0_NORSRAM_REGION0 ((uint32_t)0x00000000U)
|
||
#endif
|
||
#define CONFIG_ESC_EXMC_BANK_NOR_SRAM_REGION0 EXMC_BANK0_NORSRAM_REGION0
|
||
|
||
/* ---------- ESC 中断引脚(PB0/PB1/PB2,三个独立 EXTI 向量) ---------- */
|
||
/** @note 保留 PA0 给未来 STANDBY 模式唤醒(WKUP_PIN0)。 */
|
||
constexpr uint32_t CONFIG_ESC_SYNC0_PORT = GPIOB;
|
||
constexpr uint32_t CONFIG_ESC_SYNC0_PIN = GPIO_PIN_0;
|
||
constexpr exti_line_enum CONFIG_ESC_SYNC0_EXTI = EXTI_0;
|
||
constexpr IRQn_Type CONFIG_ESC_SYNC0_IRQn = EXTI0_IRQn;
|
||
constexpr uint32_t CONFIG_ESC_SYNC0_EXTI_SOURCE_PORT = GPIO_PORT_SOURCE_GPIOB;
|
||
constexpr uint32_t CONFIG_ESC_SYNC0_EXTI_SOURCE_PIN = GPIO_PIN_SOURCE_0;
|
||
|
||
constexpr uint32_t CONFIG_ESC_IRQ_PORT = GPIOB;
|
||
constexpr uint32_t CONFIG_ESC_IRQ_PIN = GPIO_PIN_1;
|
||
constexpr exti_line_enum CONFIG_ESC_IRQ_EXTI = EXTI_1;
|
||
constexpr IRQn_Type CONFIG_ESC_IRQ_IRQn = EXTI1_IRQn;
|
||
constexpr uint32_t CONFIG_ESC_IRQ_EXTI_SOURCE_PORT = GPIO_PORT_SOURCE_GPIOB;
|
||
constexpr uint32_t CONFIG_ESC_IRQ_EXTI_SOURCE_PIN = GPIO_PIN_SOURCE_1;
|
||
|
||
constexpr uint32_t CONFIG_ESC_SYNC1_PORT = GPIOB;
|
||
constexpr uint32_t CONFIG_ESC_SYNC1_PIN = GPIO_PIN_2;
|
||
constexpr exti_line_enum CONFIG_ESC_SYNC1_EXTI = EXTI_2;
|
||
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;
|
||
constexpr uint32_t CONFIG_EXMC_D2_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D2_PIN = GPIO_PIN_0;
|
||
constexpr uint32_t CONFIG_EXMC_D3_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D3_PIN = GPIO_PIN_1;
|
||
constexpr uint32_t CONFIG_EXMC_D4_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D4_PIN = GPIO_PIN_7;
|
||
constexpr uint32_t CONFIG_EXMC_D5_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D5_PIN = GPIO_PIN_8;
|
||
constexpr uint32_t CONFIG_EXMC_D6_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D6_PIN = GPIO_PIN_9;
|
||
constexpr uint32_t CONFIG_EXMC_D7_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D7_PIN = GPIO_PIN_10;
|
||
constexpr uint32_t CONFIG_EXMC_D8_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D8_PIN = GPIO_PIN_11;
|
||
constexpr uint32_t CONFIG_EXMC_D9_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D9_PIN = GPIO_PIN_12;
|
||
constexpr uint32_t CONFIG_EXMC_D10_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D10_PIN = GPIO_PIN_13;
|
||
constexpr uint32_t CONFIG_EXMC_D11_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D11_PIN = GPIO_PIN_14;
|
||
constexpr uint32_t CONFIG_EXMC_D12_PORT = GPIOE; constexpr uint32_t CONFIG_EXMC_D12_PIN = GPIO_PIN_15;
|
||
constexpr uint32_t CONFIG_EXMC_D13_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D13_PIN = GPIO_PIN_8;
|
||
constexpr uint32_t CONFIG_EXMC_D14_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D14_PIN = GPIO_PIN_9;
|
||
constexpr uint32_t CONFIG_EXMC_D15_PORT = GPIOD; constexpr uint32_t CONFIG_EXMC_D15_PIN = GPIO_PIN_10;
|
||
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 烧录功能可用。
|
||
* 注意 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;
|
||
/* 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 */
|