2026-06-26 00:57:59 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @file esc_exmc_bus.cpp
|
|
|
|
|
|
* @brief LAN9252 ESC 的 EXMC 16-bit 并行总线驱动实现。
|
|
|
|
|
|
*/
|
|
|
|
|
|
#include "comm/esc_exmc_bus.h"
|
|
|
|
|
|
#include "sys/config.h"
|
|
|
|
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
|
|
#include "gd32e50x_rcu.h"
|
|
|
|
|
|
#include "gd32e50x_gpio.h"
|
|
|
|
|
|
#ifdef EXMC_NORSRAM_REGION1
|
|
|
|
|
|
#include "gd32e50x_exmc.h"
|
|
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 内存映射访问宏:基址 + 偏移(按 16-bit 半字对齐,LAN9252 HBI 地址左移 1 位)。
|
|
|
|
|
|
* 使用 volatile uint16_t* 转换避免依赖 CMSIS 的 __IO 宏。 */
|
|
|
|
|
|
#define ESC_EXMC_REG16(offset) (*(volatile uint16_t*)(CONFIG_ESC_EXMC_BASE_ADDR + (offset)))
|
|
|
|
|
|
|
|
|
|
|
|
void EscExmcBus::init()
|
|
|
|
|
|
{
|
|
|
|
|
|
/* 使能 GPIO 与 EXMC 时钟 */
|
|
|
|
|
|
rcu_periph_clock_enable(RCU_GPIOD);
|
|
|
|
|
|
rcu_periph_clock_enable(RCU_GPIOE);
|
|
|
|
|
|
rcu_periph_clock_enable(RCU_AF);
|
|
|
|
|
|
#ifdef EXMC_NORSRAM_REGION1
|
|
|
|
|
|
rcu_periph_clock_enable(RCU_EXMC);
|
|
|
|
|
|
|
|
|
|
|
|
/* 配置 16-bit 数据线 D0-D15 为 AF 推挽 */
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D0_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D0_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D1_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D1_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D2_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D2_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D3_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D3_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D4_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D4_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D5_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D5_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D6_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D6_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D7_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D7_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D8_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D8_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D9_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D9_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D10_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D10_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D11_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D11_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D12_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D12_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D13_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D13_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D14_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D14_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_D15_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_D15_PIN);
|
|
|
|
|
|
|
|
|
|
|
|
/* 控制线:A16 / NOE / NWE / NE1 */
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_A16_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_A16_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_NOE_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_NOE_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_NWE_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_NWE_PIN);
|
|
|
|
|
|
gpio_init(CONFIG_EXMC_NE1_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, CONFIG_EXMC_NE1_PIN);
|
|
|
|
|
|
|
|
|
|
|
|
/* EXMC NOR/SRAM Region1 时序配置(16-bit,非复用,异步) */
|
|
|
|
|
|
exmc_norsram_parameter_struct norsram_init;
|
|
|
|
|
|
exmc_norsram_struct_para_init(&norsram_init);
|
|
|
|
|
|
norsram_init.norsram_region = CONFIG_ESC_EXMC_BANK_NOR_SRAM_REGION1;
|
|
|
|
|
|
norsram_init.write_mode = EXMC_ASYN_WRITE;
|
|
|
|
|
|
norsram_init.read_mode = EXMC_ASYN_READ;
|
|
|
|
|
|
norsram_init.nwait_mode = EXMC_NWAIT_DISABLE;
|
|
|
|
|
|
norsram_init.asyn_wait = DISABLE;
|
|
|
|
|
|
norsram_init.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;
|
|
|
|
|
|
norsram_init.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;
|
2026-07-15 02:49:37 +08:00
|
|
|
|
/* TODO(spec): 时序:按 LAN9252 HBI 要求配置 read/write wait state
|
2026-07-02 02:02:41 +08:00
|
|
|
|
* LAN9252 HBI 最小 read/write cycle = 100ns。
|
|
|
|
|
|
* AHB=180MHz(RCU_MODIFY_UP 强制 /1),1 HCLK = 5.6ns。
|
|
|
|
|
|
* 6 HCLK = 33ns → 不满足,需 ≥ 18 HCLK 才能达到 100ns。
|
|
|
|
|
|
* 当前 ESC 未启用(selfTest FAIL),EXMC 库未纳入编译,此参数仅占位。
|
|
|
|
|
|
* 启用 ESC 时需安装 EXMC 库并实测调整 HCLK 数。 */
|
|
|
|
|
|
norsram_init.read_latency = EXMC_DEN_ALE_TR_6_HCLK; // 占位,启用 ESC 时需调整为 ≥18 HCLK
|
|
|
|
|
|
norsram_init.write_latency = EXMC_DEN_ALE_TR_6_HCLK; // 占位,启用 ESC 时需调整为 ≥18 HCLK
|
2026-06-26 00:57:59 +08:00
|
|
|
|
exmc_norsram_init(&norsram_init);
|
|
|
|
|
|
exmc_norsram_enable(CONFIG_ESC_EXMC_BANK_NOR_SRAM_REGION1);
|
|
|
|
|
|
#else
|
2026-07-15 02:49:37 +08:00
|
|
|
|
/* EXMC 外设库未安装(gd32e50x_exmc.h 缺失):EtherCAT ESC EXMC 总线初始化为空,
|
|
|
|
|
|
* 运行期 selfTest 必失败,EtherCAT 自动禁用。启用 ESC 需先安装 EXMC 组件。 */
|
|
|
|
|
|
#warning "EXMC peripheral library not included; EtherCAT ESC EXMC bus init is a no-op"
|
2026-06-26 00:57:59 +08:00
|
|
|
|
#endif
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-29 01:51:02 +08:00
|
|
|
|
__attribute__((section(".ramfunc"), noinline))
|
2026-06-26 00:57:59 +08:00
|
|
|
|
uint16_t EscExmcBus::read16(uint32_t offset)
|
|
|
|
|
|
{
|
|
|
|
|
|
return ESC_EXMC_REG16(offset);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-06-29 01:51:02 +08:00
|
|
|
|
__attribute__((section(".ramfunc"), noinline))
|
2026-06-26 00:57:59 +08:00
|
|
|
|
void EscExmcBus::write16(uint32_t offset, uint16_t data)
|
|
|
|
|
|
{
|
|
|
|
|
|
ESC_EXMC_REG16(offset) = data;
|
|
|
|
|
|
}
|