feat(ethercat): 添加ESP32使能控制功能通过EtherCAT SDO
添加0x2503对象字典项用于通过EtherCAT SDO控制ESP32 WiFi使能信号, 解决WiFi关断后无法重新开启的问题。同时添加sys/esp32_en.h/.cpp文件 提供GPIO控制接口。 SPI诊断命令(0xA2)扩展支持ESP32 EN引脚控制,用于诊断备援。 ESP32掉电重启后自动清理SPI链路状态,防止通信异常。
This commit is contained in:
@@ -214,6 +214,8 @@ constexpr uint32_t CONFIG_SPI_RING_TIMEOUT_MS = 50U;
|
||||
* registerHandler 表满时静默丢弃,motor_ota 曾因容量=8 被丢弃(0xD0 回 0xEE)。
|
||||
* 取 14 留余量;新增 handler 时须确认本容量足够。 */
|
||||
constexpr uint8_t CONFIG_SPI_MAX_COMMANDS = 14U;
|
||||
/** @brief GD32 APP 版本(HELLO_ACK/PING 身份块;改功能后请递增便于现场核对)。 */
|
||||
/* 版本号在 app_spi_cmd_ping.cpp fillGd32AppIdentityPayload 维护 */
|
||||
/** @brief 每通道不重复 ID 快照表最大条目数(与 ESP32 CANFD_ID_SNAPSHOT_MAX 对齐)。 */
|
||||
constexpr uint8_t CONFIG_CANFD_ID_SNAPSHOT_MAX = 16U;
|
||||
/** @brief 快照条目最大数据字节数(CAN FD DLC 上限)。 */
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @file esp32_en.cpp
|
||||
* @brief ESP32 EN (PC9) 驱动。PC9 拉高后延时 1.2s 复位 SPI,避开起机毛刺。
|
||||
*/
|
||||
#include "sys/esp32_en.h"
|
||||
#include "sys/config.h"
|
||||
#include "sys/task_manager.h"
|
||||
#include "device/spi/app_spi_command.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace {
|
||||
|
||||
/** @brief PC9 拉高后延时多久再清 SPI(等 ESP32 ROM/APP 引脚初始化毛刺结束)。 */
|
||||
constexpr uint32_t kPostBootRelinkDelayMs = 1200U;
|
||||
|
||||
/** @brief 延时复位排期;0=无。 */
|
||||
volatile uint32_t s_relinkAtMs = 0U;
|
||||
|
||||
void drivePinLow()
|
||||
{
|
||||
gpio_init(CONFIG_ESP32_RESET_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
|
||||
CONFIG_ESP32_RESET_PIN);
|
||||
gpio_bit_reset(CONFIG_ESP32_RESET_PORT, CONFIG_ESP32_RESET_PIN);
|
||||
}
|
||||
|
||||
void drivePinHigh()
|
||||
{
|
||||
gpio_init(CONFIG_ESP32_RESET_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ,
|
||||
CONFIG_ESP32_RESET_PIN);
|
||||
gpio_bit_set(CONFIG_ESP32_RESET_PORT, CONFIG_ESP32_RESET_PIN);
|
||||
}
|
||||
|
||||
void floatPin()
|
||||
{
|
||||
gpio_init(CONFIG_ESP32_RESET_PORT, GPIO_MODE_IN_FLOATING, 0,
|
||||
CONFIG_ESP32_RESET_PIN);
|
||||
}
|
||||
|
||||
bool readPin()
|
||||
{
|
||||
return gpio_input_bit_get(CONFIG_ESP32_RESET_PORT, CONFIG_ESP32_RESET_PIN) == SET;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
uint8_t Esp32En::drive(uint8_t action)
|
||||
{
|
||||
switch (action) {
|
||||
case 0: /* 拉高(开 WiFi) */
|
||||
case 2:
|
||||
/* ESP32 仍死着:先清一次 SPI;起机毛刺会在 1.2s 后再清一次 */
|
||||
s_relinkAtMs = 0U;
|
||||
AppSpiCommandBus.resetEsp32Link();
|
||||
drivePinHigh();
|
||||
s_relinkAtMs = TaskManager::state().tick_1ms + kPostBootRelinkDelayMs;
|
||||
break;
|
||||
case 1: /* 拉低保持(关 WiFi) */
|
||||
s_relinkAtMs = 0U;
|
||||
drivePinLow();
|
||||
AppSpiCommandBus.resetEsp32Link();
|
||||
break;
|
||||
case 3: /* 浮空 */
|
||||
s_relinkAtMs = 0U;
|
||||
floatPin();
|
||||
AppSpiCommandBus.resetEsp32Link();
|
||||
break;
|
||||
case 4: /* 只读 */
|
||||
break;
|
||||
case 5: /* 仅复位 SPI(诊断;ESP32 空闲时调用,再让它 HELLO) */
|
||||
s_relinkAtMs = 0U;
|
||||
AppSpiCommandBus.resetEsp32Link();
|
||||
break;
|
||||
default:
|
||||
return 0xEEU;
|
||||
}
|
||||
|
||||
const bool level = readPin();
|
||||
static const char *const kName[6] = {
|
||||
"restore HIGH", "drive LOW (hold)", "drive HIGH", "float", "read-only", "spi-relink"};
|
||||
printf("[APP][ESP32_EN] %s -> pin reads %s\r\n", kName[action],
|
||||
level ? "HIGH" : "LOW");
|
||||
return level ? 1U : 0U;
|
||||
}
|
||||
|
||||
void Esp32En::poll()
|
||||
{
|
||||
if (s_relinkAtMs == 0U) {
|
||||
return;
|
||||
}
|
||||
const uint32_t now = TaskManager::state().tick_1ms;
|
||||
if ((int32_t)(now - s_relinkAtMs) < 0) {
|
||||
return;
|
||||
}
|
||||
s_relinkAtMs = 0U;
|
||||
AppSpiCommandBus.resetEsp32Link();
|
||||
printf("[APP][ESP32_EN] post-boot SPI relink (glitch window over)\r\n");
|
||||
}
|
||||
|
||||
void Esp32En::cancelRelinkFromSpi()
|
||||
{
|
||||
/* HELLO/业务帧已进来:不必再延时复位(会打断建连) */
|
||||
s_relinkAtMs = 0U;
|
||||
}
|
||||
|
||||
/* EtherCAT SDO 0x2503 回调入口(dc_app.c 为 C 侧)。 */
|
||||
extern "C" uint8_t EcatEsp32EnDrive(uint8_t action)
|
||||
{
|
||||
return Esp32En::drive(action);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file esp32_en.h
|
||||
* @brief ESP32 EN/RESET (PC9 / WLESS_EN) 手动控制 —— 网页开关经 EtherCAT SDO 0x2503 下发。
|
||||
*
|
||||
* 硬件语义(见 sys/config.h CONFIG_ESP32_RESET_*):
|
||||
* - PC9 推挽高 = 释放 ESP_CHIP_EN,ESP32 运行、WiFi 可用
|
||||
* - PC9 推挽低 = 按死 EN,ESP32 硬复位/掉使能,WiFi 与 HTTP 全断
|
||||
* - PC9 浮空 = 外部 C41/U11 把 ESP_CHIP_EN 拉低,同样关断(与复位后一致)
|
||||
*
|
||||
* 控制必须走 EtherCAT(与 ESP32 解耦):WiFi 关断后 ESP32 已死,
|
||||
* 经 /spi/send 的路径关得掉、开不回来。
|
||||
* 恢复:再次 SDO 写 action 0/2 拉高;或 GD32 复位/重新上电(initial.cpp 无条件拉高)。
|
||||
*
|
||||
* SPI 重建:ESP32 冷启动的 GPIO 毛刺会再次弄脏 SPI 链路,故拉高 PC9 后
|
||||
* 在起机窗口内多次 resetEsp32Link(),赶在 HELLO 前把 session/DMA 清干净。
|
||||
*/
|
||||
#ifndef SYS_ESP32_EN_H
|
||||
#define SYS_ESP32_EN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
class Esp32En {
|
||||
public:
|
||||
/**
|
||||
* @brief 驱动/回读 ESP32 EN(PC9)。EtherCAT SDO 0x2503 转发到此。
|
||||
* @param action 0=拉高(开) 1=拉低保持(关) 2=拉高 3=浮空 4=只读 5=仅复位 SPI
|
||||
* @return 实际引脚电平 0/1(与 nrstDrive 同口径);0xEE=无效 action。
|
||||
*/
|
||||
static uint8_t drive(uint8_t action);
|
||||
|
||||
/**
|
||||
* @brief 起机窗口内补清 SPI 链路(TaskRunner::runPending 每圈调用)。
|
||||
* @note 无排期时立即返回。PC9 拉高后早期少量补清;一旦收到 CS 事务即停,
|
||||
* 避免打断正在建连的 HELLO。
|
||||
*/
|
||||
static void poll();
|
||||
|
||||
/** @brief SPI 收到任意 CS 事务时取消剩余补清(由 processCommand 调用)。 */
|
||||
static void cancelRelinkFromSpi();
|
||||
};
|
||||
|
||||
#endif /* SYS_ESP32_EN_H */
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "sys/motor_ota_relay.h"
|
||||
#include "sys/task_manager.h"
|
||||
#include "sys/cpu_load.h"
|
||||
#include "sys/esp32_en.h"
|
||||
#include "sys/task_runner.h"
|
||||
#include "comm/ethercat_slave.h"
|
||||
#include "comm/ethercat_sync.h"
|
||||
@@ -575,6 +576,9 @@ void TaskRunner::runPending()
|
||||
* 主动推送已随 2026-08 请求驱动改造移除,此处仅需消费请求响应的按铃。 */
|
||||
AppSpiCommandBus.poll();
|
||||
|
||||
/* PC9 拉高后 ESP32 起机窗口内的 SPI 补清(GPIO 毛刺会弄脏链路)。 */
|
||||
Esp32En::poll();
|
||||
|
||||
/* 0xB0 进 BOOT:必须每圈检查,不能只靠 1Hz TASK_HEARTBEAT。
|
||||
* 否则 Flash 写/复位被拖到下一秒,ESP32 HELLO 一直 role=app 超时。 */
|
||||
if (OtaBootRequest::isRebootPending()) {
|
||||
|
||||
Reference in New Issue
Block a user