/** * @file esc_lan9252.cpp * @brief LAN9252 EtherCAT ESC 驱动实现。 */ #include "comm/esc_lan9252.h" #include "comm/esc_exmc_bus.h" #include "sys/config.h" #if CONFIG_ETHERCAT_ENABLE namespace { /* LAN9252 ESC 关键寄存器地址(字节偏移,EXMC 访问) */ constexpr uint16_t LAN9252_REG_CHIP_ID_L = 0x0000U; /**< 芯片 ID 低 16 位(=0x4321)。 */ constexpr uint16_t LAN9252_REG_CHIP_ID_H = 0x0002U; /**< 芯片 ID 高 16 位(=0x8765)。 */ constexpr uint32_t LAN9252_CHIP_ID_VALUE = 0x87654321U; /**< 期望的 32-bit 芯片 ID。 */ /* PDI 内存基址偏移(实际取决于 LAN9252 PDI 配置,这里为示意值) */ constexpr uint16_t LAN9252_PDI_BASE_OFFSET = 0x1000U; } void EscLan9252::init() { EscExmcBus::init(); /* TODO: 配置 ESC 中断使能、AL 控制等基本寄存器(留待协议栈集成阶段实现) */ } bool EscLan9252::selfTest() { const uint16_t id_low = readReg(LAN9252_REG_CHIP_ID_L); const uint16_t id_high = readReg(LAN9252_REG_CHIP_ID_H); const uint32_t chip_id = ((uint32_t)id_high << 16) | id_low; return (chip_id == LAN9252_CHIP_ID_VALUE); } uint16_t EscLan9252::readReg(uint16_t addr) { /* ESC 寄存器地址按字节寻址,EXMC 16-bit 访问需要地址左移 1 位 */ return EscExmcBus::read16((uint32_t)addr << 1U); } void EscLan9252::writeReg(uint16_t addr, uint16_t val) { EscExmcBus::write16((uint32_t)addr << 1U, val); } void EscLan9252::readPdi(uint16_t offset, uint8_t *buf, size_t len) { if (buf == nullptr || len == 0U) { return; } /* PDI 按 16-bit 读取,非对齐字节需特殊处理(此处简化为按半字读取) */ const uint32_t exmc_offset = (uint32_t)(LAN9252_PDI_BASE_OFFSET + offset) << 1U; const size_t half_count = len / 2U; for (size_t i = 0U; i < half_count; ++i) { uint16_t w = EscExmcBus::read16(exmc_offset + (uint32_t)(i * 2U)); buf[i * 2U] = (uint8_t)(w & 0xFFU); buf[i * 2U + 1] = (uint8_t)((w >> 8) & 0xFFU); } /* 处理奇数字节 */ if ((len & 1U) != 0U) { uint16_t w = EscExmcBus::read16(exmc_offset + (uint32_t)(half_count * 2U)); buf[half_count * 2U] = (uint8_t)(w & 0xFFU); } } void EscLan9252::writePdi(uint16_t offset, const uint8_t *buf, size_t len) { if (buf == nullptr || len == 0U) { return; } const uint32_t exmc_offset = (uint32_t)(LAN9252_PDI_BASE_OFFSET + offset) << 1U; const size_t half_count = len / 2U; for (size_t i = 0U; i < half_count; ++i) { uint16_t w = (uint16_t)buf[i * 2U] | ((uint16_t)buf[i * 2U + 1] << 8); EscExmcBus::write16(exmc_offset + (uint32_t)(i * 2U), w); } if ((len & 1U) != 0U) { EscExmcBus::write16(exmc_offset + (uint32_t)(half_count * 2U), (uint16_t)buf[half_count * 2U]); } } #endif /* CONFIG_ETHERCAT_ENABLE */