rt thread smart适配野火imx6ull开发板的KSZ8081网卡

您所在的位置:网站首页 rtthread移植到imx6ull rt thread smart适配野火imx6ull开发板的KSZ8081网卡

rt thread smart适配野火imx6ull开发板的KSZ8081网卡

2024-06-09 14:46| 来源: 网络整理| 查看: 265

原理图

野火和nxp的imx6ull都采用KSZ8081网卡,电路图一致。 在这里插入图片描述 ENET1_nRST复位引脚连接在了74lv595上,因此需要先驱动74lv595。 在这里插入图片描述 74lv595利用BOOT_MODE0、BOOT_MODE1、SNVS_TAMPER7、SNVS_TAMPER8四个引脚最多可以驱动8个引脚,但是野火的输出端只连接了两个。

引脚配置

在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 BOOT_MODE0、BOOT_MODE1、SNVS_TAMPER8四个引脚的复用功能寄存器如上图。需要将它们复用成如下引脚: BOOT_MODE0——> GPIO5_IO10、 BOOT_MODE1——> GPIO5_IO11、 SNVS_TAMPER7——> GPIO5_IO07、 SNVS_TAMPER8——> GPIO5_IO08 关于这四个引脚是如何复位的,我参考了正点原子“蜂鸣器实验”章节,其原理图如下: 在这里插入图片描述 这里需要将SNVS_TAMPER1复用为——> GPIO5_IO01,其源码如下:

void beep_init(void) { /* 1、初始化IO复用,复用为GPIO5_IO01 */ IOMUXC_SetPinMux(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0); /* 2、、配置GPIO1_IO03的IO属性 *bit 16:0 HYS关闭 *bit [15:14]: 00 默认下拉 *bit [13]: 0 kepper功能 *bit [12]: 1 pull/keeper使能 *bit [11]: 0 关闭开路输出 *bit [7:6]: 10 速度100Mhz *bit [5:3]: 110 R0/6驱动能力 *bit [0]: 0 低转换率 */ IOMUXC_SetPinConfig(IOMUXC_SNVS_SNVS_TAMPER1_GPIO5_IO01,0X10B0); /* 3、初始化GPIO,GPIO5_IO01设置为输出 */ GPIO5->GDIR |= (1 *((volatile uint32_t *)muxRegister) = IOMUXC_SW_MUX_CTL_PAD_MUX_MODE(muxMode) | IOMUXC_SW_MUX_CTL_PAD_SION(inputOnfield); if (inputRegister) { *((volatile uint32_t *)inputRegister) = IOMUXC_SELECT_INPUT_DAISY(inputDaisy); } } /*! * @brief Sets the IOMUXC pin configuration. * @note The previous five parameters can be filled with the pin function ID macros. * * This is an example to set pin configuration for IOMUXC_GPIO1_IO02_I2C1_SCL: * @code * IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO02_I2C1_SCL, IOMUXC_SW_PAD_CTL_PAD_PUE_MASK | IOMUXC_SW_PAD_CTL_PAD_PUS(2U)); * @endcode * * @param muxRegister The pin mux register. * @param muxMode The pin mux mode. * @param inputRegister The select input register. * @param inputDaisy The input daisy. * @param configRegister The config register. * @param configValue The pin config value. */ static inline void IOMUXC_SetPinConfig(uint32_t muxRegister, uint32_t muxMode, uint32_t inputRegister, uint32_t inputDaisy, uint32_t configRegister, uint32_t configValue) { if (configRegister) { *((volatile uint32_t *)configRegister) = configValue; } }

for example

IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0); IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03, 0X10B0);

这 里 使 用 了 两 个 函 数 IOMUXC_SetPinMux 和 IOMUXC_SetPinConfig , 其 中 函 数 IOMUXC_SetPinMux 是 用 来 设 置 IO 复 用 功 能 的 , 最 终 肯 定 设 置 的 是 寄 存 器 “IOMUXC_SW_MUX_CTL_PAD_XX”。函数 IOMUXC_SetPinConfig 设置的是 IO 的上下拉、 速度等的,也就是寄存器“IOMUXC_SW_PAD_CTL_PAD_XX”。 函数 IOMUXC_SetPinMux 有 6 个参数,这 6 个参数的函数如下: muxRegister : IO 的 复 用 寄 存 器 地 址 , 比 如 GPIO1_IO03 的 IO 复 用 寄 存 器 SW_MUX_CTL_PAD_GPIO1_IO03 的地址为 0X020E0068。 muxMode: IO 复用值,也就是 ALT0~ALT8,对应数字 0~8,比如要将 GPIO1_IO03 设置 为 GPIO 功能的话此参数就要设置为 5。 inputRegister:外设输入 IO 选择寄存器地址,有些 IO 在设置为其他的复用功能以后还需 要设置 IO 输入寄存器,比如 GPIO1_IO03 要复用为 UART1_RX 的话还需要设置寄存器 UART1_RX_DATA_SELECT_INPUT,此寄存器地址为 0X020E0624。 inputDaisy:寄存器 inputRegister 的值,比如 GPIO1_IO03 要作为 UART1_RX 引脚的话此 参数就是 1。 configRegister:未使用,函数 IOMUXC_SetPinConfig 会使用这个寄存器。 inputOnfield : IO 软 件 输 入 使 能 , 以 GPIO1_IO03 为 例 就 是 寄 存 器 SW_MUX_CTL_PAD_GPIO1_IO03 的 SION 位(bit4)。如果需要使能 GPIO1_IO03 的软件输入功能的话此参数应该为 1,否则的话就为 0。 在这里插入图片描述 函数 IOMUXC_SetPinConfig 有 6 个参数,其中前五个参数和函数 IOMUXC_SetPinMux 一 样,但是此函数只使用了参数 configRegister 和 configValue,cofigRegister 参数是 IO 配置寄存 器地址,比如 GPIO1_IO03 的 IO 配置寄存器为 IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03, 其地址为 0X020E02F4,参数 configValue 就是要写入到寄存器 configRegister 的值。同理,“示例代码 12.3.3.1”的 43 行展开以后就是: IOMUXC_SetPinConfig(0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U, 0X10B0); 根据函数 IOMUXC_SetPinConfig 的源码可以知道,上面函数就是将寄存器 0x020E02F4 的值设置为 0X10B0。函数 IOMUXC_SetPinMux 和 IOMUXC_SetPinConfig 就讲解到这里,我们 以后就可以使用这两个函数来方便的配置 IO 的复用功能和 IO 配置。

imx6ull_iomuxc

art-pi smart里的imx6ull_iomuxc和上面两个函数类似,但也存在一些差别:

struct imx6ull_iomuxc { rt_uint32_t muxRegister; rt_uint32_t muxMode; rt_uint32_t inputRegister; rt_uint32_t inputDaisy; rt_uint32_t configRegister; rt_uint32_t inputOnfield; rt_uint32_t configValue; }; void imx6ull_gpio_init(const struct imx6ull_iomuxc *gpio) { rt_uint32_t mux_reg_vaddr = 0; rt_uint32_t input_reg_vaddr = 0; rt_uint32_t config_reg_vaddr = 0; mux_reg_vaddr = (rt_uint32_t)(gpio->muxRegister ? (rt_uint32_t)imx6ull_get_periph_vaddr(gpio->muxRegister) : gpio->muxRegister); input_reg_vaddr = (rt_uint32_t)(gpio->inputRegister ? (rt_uint32_t)imx6ull_get_periph_vaddr(gpio->inputRegister) : gpio->inputRegister); config_reg_vaddr = (rt_uint32_t)(gpio->configRegister ? (rt_uint32_t)imx6ull_get_periph_vaddr(gpio->configRegister) : gpio->configRegister); IOMUXC_SetPinMux(mux_reg_vaddr, gpio->muxMode, input_reg_vaddr, gpio->inputDaisy, config_reg_vaddr, gpio->inputOnfield); IOMUXC_SetPinConfig(mux_reg_vaddr, gpio->muxMode, input_reg_vaddr, gpio->inputDaisy, config_reg_vaddr, gpio->configValue); } #define IOMUXC_GPIO1_IO06_ENET1_MDIO 0x020E0074U, 0x0U, 0x020E0578U, 0x0U, 0x020E0300U #define IOMUXC_GPIO1_IO07_ENET1_MDC 0x020E0078U, 0x0U, 0x00000000U, 0x0U, 0x020E0304U static struct imx6ull_iomuxc mdio_gpio[2] = { {IOMUXC_GPIO1_IO06_ENET1_MDIO,0U,0xB029}, {IOMUXC_GPIO1_IO07_ENET1_MDC,0U,0xB0E9} }; 完全展开后是: static struct imx6ull_iomuxc mdio_gpio[2] = { {0x020E0074U, 0x0U, 0x020E0578U, 0x0U, 0x020E0300U,0U,0xB029}, {0x020E0078U, 0x0U, 0x00000000U, 0x0U, 0x020E0304U,0U,0xB0E9} }; 注意点:0xB029(configValue)是用于设置0x020E0300U(configRegister)寄存器的。 NXP官方源码IAR

nxp官方也提供了以太网的IAR工程,里面正是用到了74lv595,可以在官方的sdk里找到代码。其74lv595相关的代码如下:

#define NXP74LV595_INPUT_STCP_GPIO GPIO5 #define NXP74LV595_INPUT_STCP_PIN 7U #define NXP74LV595_INPUT_OE_GPIO GPIO5 #define NXP74LV595_INPUT_OE_PIN 8U #define NXP74LV595_INPUT_SDI_GPIO GPIO5 #define NXP74LV595_INPUT_SDI_PIN 10U #define NXP74LV595_INPUT_SHCP_GPIO GPIO5 #define NXP74LV595_INPUT_SHCP_PIN 11U typedef enum _NXP74LV595_signal { kSignal_NXP74LV595_Low = 0U, kSignal_NXP74LV595_High = 1U } NXP74LV595_signal_t; typedef enum _NXP74LV595_parOutputPins { kNXP74LV595_HDMI_nRST = 0U, kNXP74LV595_ENET1_nRST = 1U, kNXP74LV595_ENET2_nRST = 2U, kNXP74LV595_CAN1_2_STBY = 3U, kNXP74LV595_BT_nPWD = 4U, kNXP74LV595_CSI_RST = 5U, kNXP74LV595_CSI_PWDN = 6U, kNXP74LV595_LCD_nPWREN = 7U } NXP74LV595_parOutputPins_t; /*Initial output value of NXP74LV595*/ static uint8_t s_NXP74LV595Output = 0U; void Delay(uint32_t ticks) { while (ticks--) { __NOP(); } } /* Set parallel pins output value of 74LV595 */ void BOARD_NXP74LV595_SetValue(NXP74LV595_parOutputPins_t pin, NXP74LV595_signal_t value) { uint8_t shiftNumber; uint8_t mask; /*Init GPIO pins and open output gate of 74LV595*/ NXP74LV595_INPUT_OE_GPIO->DR &= ~(1U NXP74LV595_INPUT_SDI_GPIO->DR &= ~(1U /* IOX_SDI */ MX6_PAD_BOOT_MODE0__GPIO5_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL), /* IOX_SHCP */ MX6_PAD_BOOT_MODE1__GPIO5_IO11 | MUX_PAD_CTRL(NO_PAD_CTRL), /* IOX_STCP */ MX6_PAD_SNVS_TAMPER7__GPIO5_IO07 | MUX_PAD_CTRL(NO_PAD_CTRL), /* IOX_nOE */ MX6_PAD_SNVS_TAMPER8__GPIO5_IO08 | MUX_PAD_CTRL(NO_PAD_CTRL), }; static enum qn_level seq[3][2] = { {0, 1}, {1, 1}, {0, 0} }; static enum qn_func qn_output[8] = { qn_reset, qn_reset, qn_reset, qn_enable, qn_disable, qn_reset, qn_disable, qn_disable }; static void iox74lv_init(void) { int i; gpio_direction_output(IOX_OE, 0); for (i = 7; i >= 0; i--) { gpio_direction_output(IOX_SHCP, 0); gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]); udelay(500); gpio_direction_output(IOX_SHCP, 1); udelay(500); } gpio_direction_output(IOX_STCP, 0); udelay(500); /* * shift register will be output to pins */ gpio_direction_output(IOX_STCP, 1); for (i = 7; i >= 0; i--) { gpio_direction_output(IOX_SHCP, 0); gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]); udelay(500); gpio_direction_output(IOX_SHCP, 1); udelay(500); } gpio_direction_output(IOX_STCP, 0); udelay(500); /* * shift register will be output to pins */ gpio_direction_output(IOX_STCP, 1); }; void iox74lv_set(int index) { int i; for (i = 7; i >= 0; i--) { gpio_direction_output(IOX_SHCP, 0); if (i == index) gpio_direction_output(IOX_SDI, seq[qn_output[i]][0]); else gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]); udelay(500); gpio_direction_output(IOX_SHCP, 1); udelay(500); } gpio_direction_output(IOX_STCP, 0); udelay(500); /* * shift register will be output to pins */ gpio_direction_output(IOX_STCP, 1); for (i = 7; i >= 0; i--) { gpio_direction_output(IOX_SHCP, 0); gpio_direction_output(IOX_SDI, seq[qn_output[i]][1]); udelay(500); gpio_direction_output(IOX_SHCP, 1); udelay(500); } gpio_direction_output(IOX_STCP, 0); udelay(500); /* * shift register will be output to pins */ gpio_direction_output(IOX_STCP, 1); }; KSZ8081驱动 74lv595驱动 #ifndef __DRV_74LV595_H__ #define __DRV_74LV595_H__ #include #include "fsl_phy.h" #include "imx6ull.h" #include "drv_common.h" typedef enum _NXP74LV595_signal { kSignal_NXP74LV595_Low = 0U, kSignal_NXP74LV595_High = 1U } NXP74LV595_signal_t; typedef enum _NXP74LV595_parOutputPins { kNXP74LV595_HDMI_nRST = 0U, kNXP74LV595_ENET1_nRST = 1U, kNXP74LV595_ENET2_nRST = 2U, kNXP74LV595_CAN1_2_STBY = 3U, kNXP74LV595_BT_nPWD = 4U, kNXP74LV595_CSI_RST = 5U, kNXP74LV595_CSI_PWDN = 6U, kNXP74LV595_LCD_nPWREN = 7U } NXP74LV595_parOutputPins_t; void BOARD_NXP74LV595_SetValue_Init(void); void BOARD_NXP74LV595_SetValue(NXP74LV595_parOutputPins_t pin, NXP74LV595_signal_t value); #endif /* __DRV_74LV595_H__ */ #include "drv_74lv595.h" #define NXP74LV595_INPUT_STCP_GPIO GPIO5 #define NXP74LV595_INPUT_STCP_PIN 7U #define NXP74LV595_INPUT_OE_GPIO GPIO5 #define NXP74LV595_INPUT_OE_PIN 8U #define NXP74LV595_INPUT_SDI_GPIO GPIO5 #define NXP74LV595_INPUT_SDI_PIN 10U #define NXP74LV595_INPUT_SHCP_GPIO GPIO5 #define NXP74LV595_INPUT_SHCP_PIN 11U /*Initial output value of NXP74LV595*/ static uint8_t s_NXP74LV595Output = 0U; static struct imx6ull_iomuxc _74lv595_gpio[4] = { {IOMUXC_SNVS_BOOT_MODE0_GPIO5_IO10,0U,0x110B0}, {IOMUXC_SNVS_BOOT_MODE1_GPIO5_IO11,0U,0x110B0}, {IOMUXC_SNVS_SNVS_TAMPER7_GPIO5_IO07,0U,0x110B0}, {IOMUXC_SNVS_SNVS_TAMPER8_GPIO5_IO08,0U,0x110B0}, }; void Delay(uint32_t ticks) { while (ticks--) { __NOP(); //__ASM("nop"); } } void BOARD_NXP74LV595_SetValue_Init(void) { imx6ull_gpio_init(&_74lv595_gpio[0]); imx6ull_gpio_init(&_74lv595_gpio[1]); imx6ull_gpio_init(&_74lv595_gpio[2]); imx6ull_gpio_init(&_74lv595_gpio[3]); } /* Set parallel pins output value of 74LV595 */ //GDIR寄存器输入0,输出1; void BOARD_NXP74LV595_SetValue(NXP74LV595_parOutputPins_t pin, NXP74LV595_signal_t value) { uint8_t shiftNumber; uint8_t mask; /*Init GPIO pins and open output gate of 74LV595*/ GPIO_Type *OE_GPIO = (GPIO_Type *)rt_ioremap((void *)GPIO5,0x1000); GPIO_Type *STCP_GPIO = (GPIO_Type *)rt_ioremap((void *)GPIO5,0x1000); GPIO_Type *SDI_GPIO = (GPIO_Type *)rt_ioremap((void *)GPIO5,0x1000); GPIO_Type *SHCP_GPIO = (GPIO_Type *)rt_ioremap((void *)GPIO5,0x1000); OE_GPIO->DR &= ~(1U SDI_GPIO->DR &= ~(1U {IOMUXC_GPIO1_IO06_ENET1_MDIO,0U,0xB029}, {IOMUXC_GPIO1_IO07_ENET1_MDC,0U,0xB0E9} }; #else static struct imx6ull_iomuxc mdio_gpio[2] = { {IOMUXC_GPIO1_IO06_ENET2_MDIO,0U,0xB029}, {IOMUXC_GPIO1_IO07_ENET2_MDC,0U,0xB0E9}, }; #endif enum { #ifdef RT_USING_ENET1 DEV_ENET1, #endif #ifdef RT_USING_ENET2 DEV_ENET2, #endif DEV_ENET_MAX, }; static struct rt_imx6ul_ethps _imx6ul_eth_device[DEV_ENET_MAX] = { #ifdef RT_USING_ENET1 { .dev_addr = {0xa8,0x5e,0x45,0x91,0x92,0x93}, .mac_name = "e1", .irq_name = "emac1_intr", .enet_phy_base_addr = ENET1, .irq_num = IMX_INT_ENET1, .phy_num = 2, .mac_num = 1, .phy_id = 0x22, .buffConfig = { ENET_RXBD_NUM, ENET_TXBD_NUM, ENET_RXBUFF_ALIGN_SIZE, ENET_TXBUFF_ALIGN_SIZE, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, ENET_RXBUFF_TOTAL_SIZE, ENET_TXBUFF_TOTAL_SIZE }, .gpio = { {IOMUXC_ENET1_RX_DATA0_ENET1_RDATA00,0U,0xB0E9}, {IOMUXC_ENET1_RX_DATA1_ENET1_RDATA01,0U,0xB0E9}, {IOMUXC_ENET1_RX_EN_ENET1_RX_EN,0U,0xB0E9}, {IOMUXC_ENET1_RX_ER_ENET1_RX_ER,0U,0xB0E9}, {IOMUXC_ENET1_TX_CLK_ENET1_REF_CLK1,1U,0x00F0}, {IOMUXC_ENET1_TX_DATA0_ENET1_TDATA00,0U,0xB0E9}, {IOMUXC_ENET1_TX_DATA1_ENET1_TDATA01,0U,0xB0E9}, {IOMUXC_ENET1_TX_EN_ENET1_TX_EN,0U,0xB0E9} } }, #endif #ifdef RT_USING_ENET2 { .dev_addr = {0xa8,0x5e,0x45,0x01,0x02,0x03}, .mac_name = "e2", .irq_name = "emac2_intr", .enet_phy_base_addr = ENET2, .irq_num = IMX_INT_ENET2, .phy_num = 1, .mac_num = 2, .phy_id = 0x22, .buffConfig = { ENET_RXBD_NUM, ENET_TXBD_NUM, ENET_RXBUFF_ALIGN_SIZE, ENET_TXBUFF_ALIGN_SIZE, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, RT_NULL, ENET_RXBUFF_TOTAL_SIZE, ENET_TXBUFF_TOTAL_SIZE }, .gpio = { {IOMUXC_ENET2_RX_DATA0_ENET2_RDATA00,0U,0xB0E9}, {IOMUXC_ENET2_RX_DATA1_ENET2_RDATA01,0U,0xB0E9}, {IOMUXC_ENET2_RX_EN_ENET2_RX_EN,0U,0xB0E9}, {IOMUXC_ENET2_RX_ER_ENET2_RX_ER,0U,0xB0E9}, {IOMUXC_ENET2_TX_CLK_ENET2_REF_CLK2,1U,0x00F0}, {IOMUXC_ENET2_TX_DATA0_ENET2_TDATA00,0U,0xB0E9}, {IOMUXC_ENET2_TX_DATA1_ENET2_TDATA01,0U,0xB0E9}, {IOMUXC_ENET2_TX_EN_ENET2_TX_EN,0U,0xB0E9} } }, #endif }; void imx6ul_eth_link_change(struct rt_imx6ul_ethps *imx6ul_device,rt_bool_t up) { if(up) { LOG_D("enet%d link up\n",imx6ul_device->mac_num); eth_device_linkchange(&imx6ul_device->parent, RT_TRUE); imx6ul_device->phy_link_status = RT_TRUE; } else { LOG_D("enet%d link down\n",imx6ul_device->mac_num); eth_device_linkchange(&imx6ul_device->parent, RT_FALSE); imx6ul_device->phy_link_status = RT_FALSE; } } void ENET_InitModuleClock(void) { const clock_enet_pll_config_t config = {true, true, false, 1, 1}; CLOCK_InitEnetPll(&config); } rt_err_t enet_buffer_init(enet_buffer_config_t *buffConfig) { void *tx_buff_addr = RT_NULL; void *rx_buff_addr = RT_NULL; void *tx_bd_addr = RT_NULL; void *rx_bd_addr = RT_NULL; if(((SYS_PAGE_SIZE LOG_E("ERROR: rx buff page alloc failed\n"); return RT_ERROR; } buffConfig->rxBufferAlign = (void *)rt_ioremap_nocache(virtual_to_physical(rx_buff_addr), (SYS_PAGE_SIZE LOG_E("ERROR: rx bd page alloc failed\n"); return RT_ERROR; } buffConfig->rxBdStartAddrAlign = (void *)rt_ioremap_nocache(virtual_to_physical(rx_bd_addr), (SYS_PAGE_SIZE rt_err_t state; struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev; ENET_Type *base_addr = RT_NULL; enet_config_t *config; enet_handle_t *handle; enet_buffer_config_t *buffConfig; rt_uint32_t reg_value; imx6ul_device->enet_virtual_base_addr = (ENET_Type *)rt_ioremap((void *)imx6ul_device->enet_phy_base_addr,SYS_PAGE_SIZE); base_addr = imx6ul_device->enet_virtual_base_addr; config = &imx6ul_device->config; handle = &imx6ul_device->handle; buffConfig = &imx6ul_device->buffConfig; for (int i=0; igpio); i++) { imx6ull_gpio_init(&imx6ul_device->gpio[i]); } IOMUXC_GPR_Type *GPR1 = (IOMUXC_GPR_Type *)rt_ioremap((void *)IOMUXC_GPR,0x1000); if(imx6ul_device->mac_num == 1) { reg_value = GPR1->GPR1; reg_value &= ~(IOMUXC_GPR_GPR1_ENET1_CLK_SEL_MASK | IOMUXC_GPR_GPR1_ENET1_CLK_SEL_MASK); reg_value |= IOMUXC_GPR_GPR1_ENET1_TX_CLK_DIR(1); reg_value |= IOMUXC_GPR_GPR1_ENET1_CLK_SEL(0); GPR1->GPR1 = reg_value; } else if(imx6ul_device->mac_num == 2) { reg_value = GPR1->GPR1; reg_value &= ~(IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK | IOMUXC_GPR_GPR1_ENET2_CLK_SEL_MASK); reg_value |= IOMUXC_GPR_GPR1_ENET2_TX_CLK_DIR(1); reg_value |= IOMUXC_GPR_GPR1_ENET2_CLK_SEL(0); GPR1->GPR1 = reg_value; } ENET_InitModuleClock(); ENET_GetDefaultConfig(config); config->interrupt |= (ENET_RX_INTERRUPT); state = enet_buffer_init(buffConfig); if(state != RT_EOK) { return state; } ENET_Init(base_addr, handle, config, buffConfig, &imx6ul_device->dev_addr[0], SYS_CLOCK_HZ); ENET_ActiveRead(base_addr); rt_hw_interrupt_install(imx6ul_device->irq_num, (rt_isr_handler_t)ENET_DriverIRQHandler, (void *)base_addr,imx6ul_device->irq_name); rt_hw_interrupt_umask(imx6ul_device->irq_num); return RT_EOK; } static rt_err_t rt_imx6ul_eth_open(rt_device_t dev, rt_uint16_t oflag) { return RT_EOK; } static rt_err_t rt_imx6ul_eth_close(rt_device_t dev) { return RT_EOK; } static rt_size_t rt_imx6ul_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { return 0; } static rt_size_t rt_imx6ul_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { return 0; } static rt_err_t rt_imx6ul_eth_control(rt_device_t dev, int cmd, void *args) { struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev; switch (cmd) { case NIOCTL_GADDR: /* get MAC address */ if (args) { rt_memcpy(args, imx6ul_device->dev_addr, MAX_ADDR_LEN); } else { return -RT_ERROR; } break; default : break; } return RT_EOK; } static status_t read_data_from_eth(rt_device_t dev,void *read_data,uint16_t *read_length) { status_t status = 0; uint16_t length = 0; ENET_Type *base_addr = RT_NULL; enet_config_t *config; enet_handle_t *handle; enet_buffer_config_t *buffConfig; struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev; base_addr = imx6ul_device->enet_virtual_base_addr; config = &imx6ul_device->config; handle = &imx6ul_device->handle; buffConfig = &imx6ul_device->buffConfig; /* Get the Frame size */ status = ENET_ReadFrame(base_addr,handle,config,read_data,&length); if((status == kStatus_ENET_RxFrameEmpty)||(status == kStatus_ENET_RxFrameError)) { ENET_EnableInterrupts(base_addr,ENET_RX_INTERRUPT); if(status == kStatus_ENET_RxFrameError) { /*recv error happend reinitialize mac*/ ENET_Init(base_addr, handle, config, buffConfig, &imx6ul_device->dev_addr[0], SYS_CLOCK_HZ); ENET_ActiveRead(base_addr); return kStatus_ENET_RxFrameError; } else if(status == kStatus_ENET_RxFrameEmpty) { return kStatus_ENET_RxFrameEmpty; } } *read_length = length; return status; } /* transmit data*/ rt_err_t rt_imx6ul_eth_tx(rt_device_t dev, struct pbuf *p) { rt_err_t ret = RT_ERROR; struct pbuf *q = RT_NULL; uint16_t offset = 0; uint32_t last_flag = 0; status_t status; ENET_Type *base_addr = RT_NULL; enet_handle_t *handle; struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)dev; base_addr = imx6ul_device->enet_virtual_base_addr; handle = &imx6ul_device->handle; RT_ASSERT(p); for(q = p;q != RT_NULL;q=q->next) { if(q->next == RT_NULL) { last_flag = 1; } else { last_flag = 0; } status = ENET_SendFrame(base_addr, handle, q->payload, q->len,last_flag); offset = offset + q->len; if(status == kStatus_Success) { } else { return RT_ERROR; } } if(offset > ENET_FRAME_MAX_FRAMELEN) { LOG_E("net error send length %d exceed max length\n",offset); } return ret; } struct pbuf *rt_imx6ul_eth_rx(rt_device_t dev) { static struct pbuf *p_s = RT_NULL; struct pbuf *p = RT_NULL; status_t status; uint16_t length = 0; if(p_s == RT_NULL) { p_s = pbuf_alloc(PBUF_RAW, ENET_FRAME_MAX_FRAMELEN, PBUF_POOL); if(p_s == RT_NULL) { return RT_NULL; } } p = p_s; status = read_data_from_eth(dev,p->payload,&length); if(status == kStatus_ENET_RxFrameEmpty) { return RT_NULL; } else if(status == kStatus_ENET_RxFrameError) { return RT_NULL; } if(length > ENET_FRAME_MAX_FRAMELEN) { LOG_E("net error recv length %d exceed max length\n",length); return RT_NULL; } pbuf_realloc(p, length); p_s = RT_NULL; return p; } int32_t get_instance_by_base(void *base) { int32_t i = 0; int32_t instance = 0; for(i = 0; i break; } } if(i == DEV_ENET_MAX) { return -1; } return instance; } void rx_enet_callback(void *base) { int32_t instance = 0; instance = get_instance_by_base(base); if(instance == -1) { LOG_E("interrput match base addr error \n"); return; } eth_device_ready(&(_imx6ul_eth_device[instance].parent)); ENET_DisableInterrupts(base,ENET_RX_INTERRUPT); } void tx_enet_callback(void *base) { ENET_DisableInterrupts(base,ENET_TX_INTERRUPT); } /*phy link detect thread*/ static void phy_detect_thread_entry(void *param) { bool link = false; phy_speed_t speed; phy_duplex_t duplex; ENET_Type *base_addr = RT_NULL; struct rt_imx6ul_ethps *imx6ul_device = (struct rt_imx6ul_ethps *)param; base_addr = imx6ul_device->enet_virtual_base_addr; // phy_reset(imx6ul_device->phy_base_addr,imx6ul_device->phy_gpio_pin); if(imx6ul_device->mac_num == 1) { BOARD_NXP74LV595_SetValue(kNXP74LV595_ENET1_nRST,kSignal_NXP74LV595_Low); rt_thread_delay(50); BOARD_NXP74LV595_SetValue(kNXP74LV595_ENET1_nRST,kSignal_NXP74LV595_High); } else if(imx6ul_device->mac_num == 2) { BOARD_NXP74LV595_SetValue(kNXP74LV595_ENET2_nRST,kSignal_NXP74LV595_Low); rt_thread_delay(50); BOARD_NXP74LV595_SetValue(kNXP74LV595_ENET2_nRST,kSignal_NXP74LV595_High); } rt_thread_mdelay(100); PHY_Init(base_addr, imx6ul_device->phy_num, SYS_CLOCK_HZ,imx6ul_device->phy_id); int i = 0; for(i = 0;i /* Get the actual PHY link speed. */ PHY_GetLinkSpeedDuplex(base_addr, imx6ul_device->phy_num, &speed, &duplex); /* Change the MII speed and duplex for actual link status. */ imx6ul_device->config.miiSpeed = (enet_mii_speed_t)speed; imx6ul_device->config.miiDuplex = (enet_mii_duplex_t)duplex; break; } else { LOG_E("PHY : %s , Link down, please check the cable connection and link partner setting.\r\n",imx6ul_device->mac_name); } } // PHY_GetLinkStatus(base_addr, imx6ul_device->phy_num, &link); // if (link) // { // /* Get the actual PHY link speed. */ // PHY_GetLinkSpeedDuplex(base_addr, imx6ul_device->phy_num, &speed, &duplex); // /* Change the MII speed and duplex for actual link status. */ // imx6ul_device->config.miiSpeed = (enet_mii_speed_t)speed; // imx6ul_device->config.miiDuplex = (enet_mii_duplex_t)duplex; // } // else // { // LOG_E("\r\nPHY Link down, please check the cable connection and link partner setting.\r\n"); // } while(1) { PHY_GetLinkStatus(base_addr, imx6ul_device->phy_num, &link); if(link != imx6ul_device->phy_link_status) { if(link == true) { PHY_StartNegotiation(base_addr,imx6ul_device->phy_num); } imx6ul_eth_link_change(imx6ul_device,link); } rt_thread_delay(DETECT_DELAY_ONE_SECOND); } } _internal_ro struct rt_device_ops _k_enet_ops = { rt_imx6ul_eth_init, rt_imx6ul_eth_open, rt_imx6ul_eth_close, rt_imx6ul_eth_read, rt_imx6ul_eth_write, rt_imx6ul_eth_control, }; static int imx6ul_eth_init(void) { rt_err_t state = RT_EOK; char link_detect[10]; #if 1 imx6ull_gpio_init(&mdio_gpio[0]); imx6ull_gpio_init(&mdio_gpio[1]); #endif BOARD_NXP74LV595_SetValue_Init(); BOARD_NXP74LV595_SetValue(kNXP74LV595_ENET1_nRST,kSignal_NXP74LV595_High); BOARD_NXP74LV595_SetValue(kNXP74LV595_ENET2_nRST,kSignal_NXP74LV595_High); for (int idx=0; idx LOG_E("emac device init success\n"); } else { LOG_E("emac device init faild: %d", state); state = -RT_ERROR; } rt_sprintf(link_detect,"link_d%d",_imx6ul_eth_device[idx].mac_num); /* start phy link detect */ rt_thread_t phy_link_tid; phy_link_tid = rt_thread_create(link_detect, phy_detect_thread_entry, &_imx6ul_eth_device[idx], 4096, RT_THREAD_PRIORITY_MAX - 2, 2); if (phy_link_tid != RT_NULL) { rt_thread_startup(phy_link_tid); } memset(link_detect,0,sizeof(link_detect)); } return state; } INIT_DEVICE_EXPORT(imx6ul_eth_init); #endif

kernel\bsp\yh\libraries\sdk\devices\MCIMX6Y2\drivers\fsl_phy.c添加如下宏定义 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3