Files

110 lines
3.0 KiB
C++
Raw Permalink Normal View History

/**
* @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);
}