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);
|
|||
|
|
}
|