Files
DCU_APP/GD32E508_DCU_APP/sys/config.h
T

423 lines
64 KiB
C++
Raw Normal View History

2026-07-20 02:36:56 +08:00
/**
* @file config.h
* @brief 应用级集中�置项定义。
* @note 用于统一管�当�项目中�调的外设�时��通信与算法常�。
*/
#ifndef SYS_CONFIG_H
#define SYS_CONFIG_H
#include <stdint.h>
#include <stddef.h>
#include "gd32e50x.h"
2026-07-20 02:36:56 +08:00
/* ============================================================
* 功能开关(调试/特性总闸 — 改这里��开关,改完�编)
* 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
2026-07-20 02:36:56 +08:00
/**
* @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;
2026-07-20 02:36:56 +08:00
/** @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
2026-07-20 02:36:56 +08:00
/** @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 带宽。 */
2026-07-20 02:36:56 +08:00
constexpr bool CONFIG_CAN_CH0_ENABLE = true;
constexpr bool CONFIG_CAN_CH1_ENABLE = true;
constexpr bool CONFIG_CAN_CH2_ENABLE = true;
2026-07-20 02:36:56 +08:00
/** @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
2026-07-20 02:36:56 +08:00
/* ============================================================
* APP 固件版本�
* ============================================================ */
constexpr uint32_t APP_FW_VERSION_MAJOR = 1U;
constexpr uint32_t APP_FW_VERSION_MINOR = 5U;
constexpr uint32_t APP_FW_VERSION_PATCH = 58U; /* 1.5.58:修å¤� EtherCAT 链路 CONFIG 回显目标值å�¶å�‘离谱浮点(如 -3.2e26°)。根因:桥段 1/段 3"最近一帧快照"是多字段一组(id/dlc/data),生产者 onCanFrame(主循环 taskCanRxParse) 先写数æ�®å�Žå†™ id,而 s_rxValid ç½®ä½�å�Žæ°¸ä¸�清零,原"最å�Žç½®ä½�ä¿�è¯�一致"注释ä¸�æˆ�ç«‹ï¼›DC 模å¼�下 buildInput 在 Sync0_Isr(preempt=0,critical.h çš„ BASEPRI 方案挡ä¸�ä½�它)执行,ISR 抢å� åœ¨æ•°æ�® memcpy 与 id 赋值之间时,PDO 带出"æ–° STATUS æ•°æ�®+æ—§ CONFIG ID",å‰�端 dispatchFrame 按 CONFIG 布局解 STATUS 字节(电压 B11-12+角度低字节 B13-14 被当æˆ� Target_Angle)。误标窗å�£å�ªåœ¨ CONFIG 回显å�Žçš„下一帧 STATUS 更新瞬间存在,故"调用时å�¶å�‘"ï¼›STATUS 走段 2 窗å�£æŒ‰æ§½ seq 判活ä¸�å�—å½±å“�,与症状å�»å�ˆã€‚修法:快照组加 seqlock(s_xrxSeq 奇=正在写,å‰�å�Ž __DMB 防编译器把é�ž volatile çš„ memcpy 挪出窗å�£),消费者判一次奇å�¶(å�•æ ¸ ISR 期间生产者必然冻结),奇数则本周期跳过段 1/段 3(开头已清零=无效),下周期自愈;零关中断ã€�é›¶ Sync0 抖动。é…�套:批é‡�环 head/tail å�‘布å‰�è¡¥ __DMB——å�Œç±»ç¼–译器é‡�排éš�患,volatile 自åº�ä¸�约æ�Ÿç›¸é‚»é�ž volatile memcpy。 1.5.57:EXMC æ—¶åº�ä½™é‡�ä¿®å¤�——rw/wr_timing.bus_latency 1→4。LAN9252 DS 表 9-4/9-5 è¦�求 trdrd/twrwr/twrrd ≥13ns,该间隔由 EXMC 在两次访问间æ�’入的总线空闲期承担 =(1 固有 + BUSLAT) HCLK:原 BUSLAT=1 å�ªæœ‰ 2 HCLK≈11.1ns,**低于 13ns 下é™�**,常温é�  AHB å�–指间隙å�¶ç„¶å…œåº•刚好å�¯ç”¨ï¼Œæ¸©åº¦å�‡é«˜(传播延迟增大)/电压下é™�(驱动å‡�å¼±)å�³è¶Šç•Œâ€”—正是实测到的"温漂/压é™�æ—¶å�¶å�‘读到 0xFFFF 或错值"。BUSLAT=4 → 5 HCLK≈27.8ns,余é‡� 2.1 å€�覆盖全温区。注æ„� 2026-08-20 那轮"慢档 16/16/256 无效故排除速度因素"的结论å�ªå¯¹å½“时的症状æˆ�立:那次读全 0/FFFF 的真因是访问模型错误(直读核心 CSR 索引空间,1.5.39 ä¿®å¤�),时åº�ä½™é‡�需按 DS 独立核算,ä¸�能沿用该结论认为时åº�无关。代价:æ¯�次 HBI 访问多 3 HCLK(16.7ns),满载 1024B 过程数æ�®æŒ‰æ¯� DWORD 两次 16-bit 访问计增加约 8.6us(相对原 218us 增幅 3.9%),4ms 周期å� ç”¨ 5.4%→5.7%,无实质影å“�。é…�套:SNTCFG0 按ä½�域解ç �回读打å�°(ASET/AHLD/DSET/BUSLAT),BUSLAT<4 时打 WARN,é�¿å…�ä½�域写错或库截断é�™é»˜å¤±æ•ˆâ€”—烧录å�Žä¸²å�£åº”è§� BUSLAT=4。 1.5.56:扩到 DPRAM 硬上é™�:输出 48×64bit=384B,输入 80×64bit=640B(é�žå¯¹ç§°ï¼‰ã€‚ 1.5.54:EtherCAT æ”¶å�‘模å�—类化——新增 comm/ethercat_pdo.h/.cpp çš„ EthercatPdo 类,与 EthercatSlave / EthercatSync å�Œé£Žæ ¼çš„å…¨é�™æ€�类。SSC 把一个 EtherCAT 周期拆æˆ�三个回调,类按这三步å�„给一个入å�£ï¼šAPPL_OutputMapping→readOutputs()(å�–走主站下å�‘çš„ 32B)ã€�APPL_Application→process()(跑应用逻辑,当å‰�是 PDO↔CAN 转å�‘)ã€�APPL_InputMapping→writeInputs()(交回 32B)。过程数æ�®ç¼“冲区(s_out/s_in)与周期计数(outputCycles/inputCycles,å�¯ä½œ"主站确实在å�‘过程数æ�®"çš„è¯�æ�®)归本类所有;dc_app.c 退回纯 SSC ç§»æ¤�层,å�ªä¿�留对象字典(0x7000/0x6000 çš„ packed 结构体是 SDO 存储必须留在 C ä¾§)与三行 extern "C" 转å�‘(EcatPdo_ReadOutputs/Process/WriteInputs)。process() 内先 processOutput å�Ž buildInput,顺åº�ä¸�能å��:buildInput è¦�把本周期刚执行的 seq 回显æˆ� ack,å��过æ�¥ ack 会æ�’滞å�Žä¸€æ‹�。输入数æ�®ä»�ç»� 0x6000 对象存储中转å†�交给 ESC,ä¿�è¯�主站 SDO 读 0x6000 与过程数æ�®å†…容一致。ä¸�加临界区:DC 模å¼�下 readOutputs/writeInputs 在 Sync0_Isrã€�process() 在主循环,但两者都是å�•写者整å�—读写,32B memcpy 撕裂最å��让æŸ�周期读到上/下å�Šå¸§æ··å�ˆï¼Œè€Œ seq 是å�•字节è¦�么旧è¦�么新ä¸�会产生第三个值,沿触å�‘语义无害——在 ISR 里关中断å��而拖累抖动。 1.5.53:新增 EtherCAT PDO ↔ CAN 转å�‘æ¡¥(comm/ethercat_can_bridge.h/.cpp),主站å�¯ç›´æŽ¥ç”¨è¿‡ç
03:00 主站侧探针钉死完整��链(楔死��未断电):
(1) ESC/SSC 邮箱处�全程活�:手动注入�法 CoE 请求(写满 SM0 256B)� 200ms 内 SM1 出�应;
(2) 但�应帧头出现在 SM1 start+8 而� start(�会�累积:第一轮 +4��续 +8),� 8 字节全零;
(3) 网络侧(FPRD)读 SM0/SM1 寄存器�正确(start=0x1000/0x1200,ctl=0x26/0x22,act=01);
=> SSC 的 u16EscAddrSendMbx(Init→PreOP 时� GetSyncMan→CSR 间接读)拿到了错值,�应写到错�地�,
主站按�议从 0x1200 读永远对�上帧头 → SOEM 报 WkcError/MailboxError;且预清��枚举
(�跑 StartMailboxHandler �读)�错 → 死�,断电�清零。错��会� +4(DWORD 粒度)指�
HBI 访问层状�残留(CSR 间接读或 PRAM 引擎,�因待串�日志确凿——两��因下述自愈�有效)。
修�:EcatDbg_GuardAleventMask 扩展自愈(0):AL>=PREOP 且 bMbxRunning 时,读 SM 寄存器真值
(0x0800/0x0808 的 start/len)与 SSC 缓存(u16EscAddrReceiveMbx/SendMbx/Receive/SendMbxSize)比对,
失��写回+WARN(旧值/寄存器值一并打�——下次串��现一行�区分"CSR 读错"还是"��污染")。
��仅在 Stop/StartMailboxHandler(主循环上下文)被写,守护�上下文无并�。
守护周期 1s→250ms(task_runner ethercatAleMaskGuard,节�� g_app_uptime_sec→g_scheduler.tick_1ms):
自愈必须快过主站 SDO 超时(~700ms),�则永远�在主站放弃之�形�虚设。
邮箱自愈+主站侧预清�(ecat_server.py 1.5.51)+自动�试三层�加:错��生 → 250ms 内写回 →
主站�试�功,彻底消除"断电���"。
主站工具�步(tools/ecat/ecat_server.py):config_map 失败转储扩展为全部 4 个 SM 寄存器
(0x0800..0x081F;此� 0x0810/0x0818 曾误标为 SM0/SM1,实为 SM2/SM3——已修正),
并注明"SM0/SM1 �置正常��续失败=SSC 邮箱地�错�楔死"的判别法。 /* 1.5.51:主站工具修�"�������→闪退"(tools/ecat/ecat_server.py),GD32 功能代�零改动(无需�新烧录;bump 仅为�更记录与编译纪律)。
02:05 �现脚本(faulthandler)钉死闪退根因:�一连接内�� op/start↔op/stop ��枚举时,从站邮箱�轮退化
(第 2 轮起 OP � SDO 读 0x2000 全 WkcError——�用户日志"报个读�失败"),第 4 轮 config_map() 内 SOEM CoE
分段读(ethercatcoe.c ecx_SDOread 的 memcpy 无边界检查,上游缺陷)�到楔死邮箱的错�帧 → 原生访问�例
(0xC0000005) → �务�进程闪退�GUI 连带退出——与用户 01:40 日志�行��(01:40:30"进入 OP"�
无任何输出=进程死在 config_map,�应未�回传,"��"� SOEM 分段循环死循环)。
修�:_require_op_ready 入�无�件"回 INIT|ACK + config_init �枚举"预清�(等效实测�有效的
"断开�连",�从站�本 ~100ms),api_op_start 自动�试简化为直接�跑;�修 ecat_server.py 第 99 行
上一轮编辑粘连("g_op_active = Falseg_httpd = None" 被 Python 当链�赋值,g_httpd 全局缺失�
g_op_active �值错� None,全� falsy 侥幸工作);config_map 失败分支新增邮箱 SM 寄存器现场转储
(0x0810/0x0818 � 8B,start/len/ctl/status/activate/pdi)。
02:12 探针进一步定性(楔死��未断电):AL 状�机活�(PREOP/SAFEOP 都 ack)但 SSC 完全�处�邮箱——
SM0/SM1 activate/StartAddr 异常(INIT �读回全零�PREOP �读回 SII 值 ctl=0x64/0x20 act=0)�
config_map 跑完会�写全部 SM(SOI 使能)但 SDO �然全败�close+open 也救�回�
SOEM 读到的"错误帧" Detail=0x1300/0x2300/0x3300 �会�递增(=邮箱计数器字节模�,读回的是错�帧)。
结论:从站侧楔死为固件层问题(疑似 PDI 通路/AL Event Mask 0x204 实测=0x03F3 或 SSC 邮箱处�挂起),
主站任何手段(�断开�连)都救�回,必须断电��——从站根因待串�抓�(下次�现时串�
看主循环 5s 心跳 [ECAT][HB] 是��跳 + AEM WARN 是�出现)。
30 轮��压测:修��第 4 轮必崩(0xC0000005);修�� 30 轮零崩溃零�死
(第 16 轮起从站进入上述硬楔死�主站侧全部为���的干净报错,直至压测结�)。 /* 1.5.50:主站工具诊断盲区修�(tools/ecat 两文件),GD32 功能代�零改动(无需�新烧录,�上 1.5.49 �最新;bump 仅为�更记录与编译纪律)。01:31 �测确认 1.5.48 的自动�试机制工作正常:首败("进 PREOP 失败: AL=INIT code=0x0000")�自动��,OP 真实建立�UI 周期正确增长。首败根因定�:�止回 INIT 时 SSC MBX_StopMailboxHandler �用了邮箱 SM0/SM1(mailbox.c:359-361),而 CheckSmSettings 在 INIT→PREOP �求邮箱 SM 已使能(ecatslv.c:416-418),拒��移且从站自身无�新使能路径(死�闭环)——自动�试里 config_init() �写 SM0/SM1(ethercatconfig.c:279-280)正是解�,与"断开�连有效"�机�。修�:PREOP/SAFEOP 失败分支改用 read_state() �真实 AL Status Code(旧报文的 code=0x0000 是 SOEM 广播 state_check �刷新 al_status 的陈旧缓存,与 OP 循环�款盲区),下次首败将显示真实错误�(预期 0x0016/0x001D 类 INVALIDMBXCFGINPREOP)确凿验�根因。 /* 1.5.49:SM2 事件楔死自愈——01:03 串�日志钉死现场(evt=0x0400 在 0x220 挂起 10s 无人处��escirq 仅 2.6/s �� AL Control 事件跳动�9s ESM 超时报 0x001B�[ECAT][AEM] 一次未打�=其�置 bEscIntEnabled==FALSE 未满足):PDI_Isr 被调用了 13 次�从未执行 SM2 分支(ecatappl.c:287 的 ALEvent&PROCESS_OUTPUT_EVENT 从未命中),bEcatFirstOutputsReceived 永�置�,SAFEOP→OP 挂到 ESM 超时。dc_app.c EcatDbg_GuardAleventMask() 扩展自愈(2):SAFEOP 下检测"0x220 bit10 挂起 + 标志未置�"�从主循环直接替 PDI_Isr 完�工作——置� bEcatFirstOutputsReceived + 读 SM2 首/末字应答事件(ecatappl.c:317-320 �款);�议等价:bit10 挂起=主站已写过 SM2=WKC=3/3 ��的"收到输出"�立,AL_ControlRes 下一个 MainLoop 周期�完� OP。守护(1) 0x204 缺�自愈�留并解除 bEscIntEnabled�置(改判 AL>=SAFEOP+nPdOutputSize>0)。WARN �带全部内部旗标(bEscInt/bDcSync/mask_exp/mask_act/wd 看门狗状�),下次�现一行日志��定�楔死路径(嫌疑:bEscIntEnabled 被�路径�外清零�或 PDI_Isr 读 0x220 的 CSR 间接端�结果�� bit10)。自愈仅在 SAFEOP+标志未置�时触�,OP �下 LRW �周期置�/清除 bit10 属正常�误报。1.5.48:修�"�止回 INIT ��进 OP"概率性挂起(SAFEOP+0x001B, WKC=3/3 但 9s ESM 超时拒�)。00:58 �测��链定案:主站 LRW WKC=3/3(输出确实写进 SM2)且看门狗 1000ms(�会被周期触�)——唯一解释是 bEcatFirstOutputsReceived 未被置�,该标志�在 PDI_Isr 收到 SM2 事件时置�,而 IRQ 上报由 AL Event Mask(0x204) bit10 控制:第二次会�中 0x204 �外丢 SM2 � → PDI_Isr 永�触� → SAFEOP→OP 挂到 ESM 超时报 0x001B。第一次连接�功��止�连失败 = 状�残留特�(残留的确切��由新增的 [ECAT][AEM] WARN 日志在下次�现时�获)。修�(1)固件守护:dc_app.c 新增 EcatDbg_GuardAleventMask()(task_runner � 1s � ethercatAleMaskGuard 调用,runPending 主路径挂载��赖诊断任务频率)——从站 AL>=SAFEOP 且 bEscIntEnabled 且 nPdOutputSize>0 时读 0x204 实际值,缺 u16ALEventMask 任一�� HW_SetALEventMask 补写并打 WARN(actual/expect/restore 三值),PREOP/INIT �干预(SSC 本�就�置 SM2/SM3 �)。修�(2)主站工具(tools/ecat ecat_server.py):(a) OP 等待循环� 1s SDO 读从站 0x2000:3(escirq 计数),�滞�直接报"PDI_Isr 未触�→0x204 丢 SM2 �"判别性��;(b) api_op_start 失败�自动�试一次:带 ACK 完整回 INIT(state_check 确认)+config_init �枚举(�写 SM/FMMU,等效"断开�连"的核心步骤,实测该�作能��)+完整�列�跑,用户无需手动断开�连。 /* 1.5.48:修�"�止回 INIT ��进 OP"概率性挂起(SAFEOP+0x001B, WKC=3/3 但 9s ESM 超时拒�)
2026-07-15 02:49:37 +08:00
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;
2026-07-20 02:36:56 +08:00
/* 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;
2026-07-20 02:36:56 +08:00
/* 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;
/* ============================================================
2026-07-20 02:36:56 +08:00
* 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;
2026-07-20 02:36:56 +08:00
/* 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。 */
2026-07-20 02:36:56 +08:00
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 */