/** * @file esc_exmc_bus.cpp * @brief LAN9252 ESC 的 EXMC 16-bit 并行总线驱动实现。 */ #include "comm/esc_exmc_bus.h" #include "sys/config.h" #if CONFIG_ETHERCAT_ENABLE 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; /* 时序:按 LAN9252 HBI 要求配置 read/write wait state */ norsram_init.read_latency = EXMC_DEN_ALE_TR_6_HCLK; // 需按 LAN9252 HBI 时序实测调整 norsram_init.write_latency = EXMC_DEN_ALE_TR_6_HCLK; // 需按 LAN9252 HBI 时序实测调整 exmc_norsram_init(&norsram_init); exmc_norsram_enable(CONFIG_ESC_EXMC_BANK_NOR_SRAM_REGION1); #else /* EXMC 外设库未安装:仅占位,CONFIG_ETHERCAT_ENABLE=1 时需先安装 EXMC 组件。 */ #endif } uint16_t EscExmcBus::read16(uint32_t offset) { return ESC_EXMC_REG16(offset); } void EscExmcBus::write16(uint32_t offset, uint16_t data) { ESC_EXMC_REG16(offset) = data; } void EscExmcBus::readBlock(uint32_t offset, uint16_t *buf, size_t count) { for (size_t i = 0U; i < count; ++i) { buf[i] = ESC_EXMC_REG16(offset + (uint32_t)(i * 2U)); } } void EscExmcBus::writeBlock(uint32_t offset, const uint16_t *buf, size_t count) { for (size_t i = 0U; i < count; ++i) { ESC_EXMC_REG16(offset + (uint32_t)(i * 2U)) = buf[i]; } } #endif /* CONFIG_ETHERCAT_ENABLE */