Files
DCU_APP/GD32E508_DCU_APP/sys/initial.cpp
T
cbb cfe7725b26 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
2026-09-01 03:07:48 +08:00

175 lines
5.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file initial.cpp
* @brief 应用启动初始化:模块成功置位,结束统一报告结果。
*
* 顺序:
* NVIC → SysTick → ESP32_EN 保持 → USART0 → AppSpi(尽早 HELLO 探活)→
* ADC → CANFD → OtaBootRequest → TaskManager → Scheduler →
* EtherCAT(+Sync 可选) → Watchdog → report
*/
#include "sys/initial.h"
#include "device/canfd.h"
#include "device/usart0.h"
#include "device/timer.h"
#include "device/adc.h"
#include "device/watchdog.h"
#include "device/spi/app_spi_command.h"
#include "sys/systick.h"
#include "sys/ota_boot_request.h"
#include "sys/task_manager.h"
#include "sys/config.h"
#include "comm/esc_lan9252.h"
#include "comm/ethercat_slave.h"
#include "comm/ethercat_sync.h"
extern "C" {
uint16_t MainInit(void);
void MainLoop(void);
}
uint32_t AppInitializer::s_mask = 0U;
namespace {
struct InitEntry {
uint32_t bit;
const char *name;
bool critical;
};
static const InitEntry kEntries[] = {
{ AppInitializer::kNvic, "nvic", true },
{ AppInitializer::kSysTick, "systick", true },
{ AppInitializer::kEsp32Hold, "esp32_hold", true },
{ AppInitializer::kUsart0, "usart0", true },
{ AppInitializer::kAppSpi, "app_spi", true },
{ AppInitializer::kAdc, "adc", true },
{ AppInitializer::kCanFd, "canfd", true },
{ AppInitializer::kOtaBootReq, "ota_boot_req", true },
{ AppInitializer::kTaskManager, "task_manager", true },
{ AppInitializer::kScheduler, "scheduler", true },
{ AppInitializer::kEthercat, "ethercat", false },
{ AppInitializer::kEthercatSync, "ethercat_sync", false },
{ AppInitializer::kWatchdog, "watchdog", true },
};
} // namespace
void AppInitializer::mark(ModuleBit b)
{
s_mask |= static_cast<uint32_t>(b);
}
void AppInitializer::report()
{
bool critical_ok = true;
bool all_ok = true;
char fail_list[160] = {0};
size_t fail_len = 0U;
for (size_t i = 0; i < sizeof(kEntries) / sizeof(kEntries[0]); ++i) {
const InitEntry &e = kEntries[i];
const bool ok = (s_mask & e.bit) != 0U;
if (ok) {
continue;
}
all_ok = false;
if (e.critical) {
critical_ok = false;
}
if (fail_len + 2U < sizeof(fail_list)) {
if (fail_len > 0U) {
fail_list[fail_len++] = ',';
}
const char *p = e.name;
while (*p != '\0' && fail_len + 1U < sizeof(fail_list)) {
fail_list[fail_len++] = *p++;
}
fail_list[fail_len] = '\0';
}
}
if (critical_ok && all_ok) {
printf("[APP] init: OK (all modules)\r\n");
} else if (critical_ok) {
printf("[APP] init: OK (critical), skipped/failed: %s\r\n",
fail_list[0] != '\0' ? fail_list : "?");
} else {
printf("[APP] init: FAIL, modules: %s\r\n",
fail_list[0] != '\0' ? fail_list : "?");
}
}
void AppInitializer::init()
{
s_mask = 0U;
nvic_priority_group_set(CONFIG_NVIC_PRIORITY_GROUP);
mark(kNvic);
SysTickTimer::initMs();
mark(kSysTick);
rcu_periph_clock_enable(RCU_GPIOC);
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();
mark(kUsart0);
/* SPI 尽早就绪:OTA FINISH 跳转后 ESP32 用 HELLO 探活,不能等 CAN 上电延时 */
AppSpiCommandBus.init();
mark(kAppSpi);
Adc::init();
mark(kAdc);
CanFd::init();
/* L0 通过才置 canfd 位 */
if (CanFd::selfTestL0()) {
mark(kCanFd);
}
OtaBootRequest::init();
mark(kOtaBootReq);
TaskManager::init();
mark(kTaskManager);
SchedulerTimer::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)。 */
EthercatSlave::init();
if (EscLan9252::isBusReady()) {
const uint16_t sscResult = MainInit();
if (sscResult == 0U) {
mark(kEthercat);
EthercatSync::init();
mark(kEthercatSync);
printf("[ECAT] SSC MainInit OK, sync ISR enabled\r\n");
} else {
printf("[ECAT] SSC MainInit FAIL (code=0x%04X)\r\n", (unsigned)sscResult);
}
} else {
printf("[ECAT] EXMC bus not ready, SSC skipped\r\n");
}
Watchdog::init();
mark(kWatchdog);
report();
}