Files
DCU_APP/GD32E508_DCU_APP/sys/esp32_en.cpp
T
cbb 28d8426052 feat(ethercat): 添加ESP32使能控制功能通过EtherCAT SDO
添加0x2503对象字典项用于通过EtherCAT SDO控制ESP32 WiFi使能信号,
解决WiFi关断后无法重新开启的问题。同时添加sys/esp32_en.h/.cpp文件
提供GPIO控制接口。

SPI诊断命令(0xA2)扩展支持ESP32 EN引脚控制,用于诊断备援。
ESP32掉电重启后自动清理SPI链路状态,防止通信异常。
2026-09-24 03:18:18 +08:00

110 lines
3.0 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 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);
}