添加0x2503对象字典项用于通过EtherCAT SDO控制ESP32 WiFi使能信号, 解决WiFi关断后无法重新开启的问题。同时添加sys/esp32_en.h/.cpp文件 提供GPIO控制接口。 SPI诊断命令(0xA2)扩展支持ESP32 EN引脚控制,用于诊断备援。 ESP32掉电重启后自动清理SPI链路状态,防止通信异常。
110 lines
3.0 KiB
C++
110 lines
3.0 KiB
C++
/**
|
||
* @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);
|
||
}
|