/* * Copyright (c) 2015, Freescale Semiconductor, Inc. * Copyright 2016-2020 NXP * All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include "pin_mux.h" #include "clock_config.h" #include "board.h" #include "fsl_debug_console.h" #include "fsl_enet.h" #include "fsl_phy.h" #if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET #include "fsl_memory.h" #endif #include "fsl_enet_mdio.h" #include "fsl_phyksz8081.h" #include "fsl_gpio.h" #include "fsl_iomuxc.h" /******************************************************************************* * Definitions ******************************************************************************/ #define EXAMPLE_ENET ENET #define EXAMPLE_PHY_ADDRESS 0x02U /* MDIO operations. */ #define EXAMPLE_MDIO_OPS enet_ops /* PHY operations. */ #define EXAMPLE_PHY_OPS phyksz8081_ops /* ENET clock frequency. */ #define EXAMPLE_CLOCK_FREQ CLOCK_GetRootClockFreq(kCLOCK_Root_Bus) #define ENET_RXBD_NUM (4) #define ENET_TXBD_NUM (4) #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) #define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) #define ENET_DATA_LENGTH (1000) #define ENET_TRANSMIT_DATA_NUM (20) #ifndef APP_ENET_BUFF_ALIGNMENT #define APP_ENET_BUFF_ALIGNMENT ENET_BUFF_ALIGNMENT #endif #ifndef PHY_AUTONEGO_TIMEOUT_COUNT #define PHY_AUTONEGO_TIMEOUT_COUNT (100000) #endif #ifndef PHY_STABILITY_DELAY_US #define PHY_STABILITY_DELAY_US (0U) #endif /******************************************************************************* * Prototypes ******************************************************************************/ /*! @brief Build ENET broadcast frame. */ static void ENET_BuildBroadCastFrame(void); /******************************************************************************* * Variables ******************************************************************************/ /*! @brief Buffer descriptors should be in non-cacheable region and should be align to "ENET_BUFF_ALIGNMENT". */ AT_NONCACHEABLE_SECTION_ALIGN(enet_rx_bd_struct_t g_rxBuffDescrip[ENET_RXBD_NUM], ENET_BUFF_ALIGNMENT); AT_NONCACHEABLE_SECTION_ALIGN(enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM], ENET_BUFF_ALIGNMENT); /*! @brief The data buffers can be in cacheable region or in non-cacheable region. * If use cacheable region, the alignment size should be the maximum size of "CACHE LINE SIZE" and "ENET_BUFF_ALIGNMENT" * If use non-cache region, the alignment size is the "ENET_BUFF_ALIGNMENT". */ SDK_ALIGN(uint8_t g_rxDataBuff[ENET_RXBD_NUM][SDK_SIZEALIGN(ENET_RXBUFF_SIZE, APP_ENET_BUFF_ALIGNMENT)], APP_ENET_BUFF_ALIGNMENT); SDK_ALIGN(uint8_t g_txDataBuff[ENET_TXBD_NUM][SDK_SIZEALIGN(ENET_TXBUFF_SIZE, APP_ENET_BUFF_ALIGNMENT)], APP_ENET_BUFF_ALIGNMENT); enet_handle_t g_handle; uint8_t g_frame[ENET_DATA_LENGTH + 14]; /*! @brief The MAC address for ENET device. */ uint8_t g_macAddr[6] = {0xd4, 0xbe, 0xd9, 0x45, 0x22, 0x60}; /*! @brief Enet PHY and MDIO interface handler. */ static mdio_handle_t mdioHandle = {.ops = &EXAMPLE_MDIO_OPS}; static phy_handle_t phyHandle = {.phyAddr = EXAMPLE_PHY_ADDRESS, .mdioHandle = &mdioHandle, .ops = &EXAMPLE_PHY_OPS}; /******************************************************************************* * Code ******************************************************************************/ void BOARD_InitModuleClock(void) { const clock_sys_pll1_config_t sysPll1Config = { .pllDiv2En = true, }; CLOCK_InitSysPll1(&sysPll1Config); clock_root_config_t rootCfg = {.mux = 4, .div = 10}; /* Generate 50M root clock. */ CLOCK_SetRootClock(kCLOCK_Root_Enet1, &rootCfg); /* Select syspll2pfd3, 528*18/24 = 396M */ CLOCK_InitPfd(kCLOCK_PllSys2, kCLOCK_Pfd3, 24); rootCfg.mux = 7; rootCfg.div = 2; CLOCK_SetRootClock(kCLOCK_Root_Bus, &rootCfg); /* Generate 198M bus clock. */ } void IOMUXC_SelectENETClock(void) { IOMUXC_GPR->GPR4 |= 0x3; /* 50M ENET_REF_CLOCK output to PHY and ENET module. */ } /*! @brief Build Frame for transmit. */ static void ENET_BuildBroadCastFrame(void) { uint32_t count = 0; uint32_t length = ENET_DATA_LENGTH - 14; for (count = 0; count < 6U; count++) { g_frame[count] = 0xFFU; } memcpy(&g_frame[6], &g_macAddr[0], 6U); g_frame[12] = (length >> 8) & 0xFFU; g_frame[13] = length & 0xFFU; for (count = 0; count < length; count++) { g_frame[count + 14] = count % 0xFFU; } } /*! * @brief Main function */ int main(void) { enet_config_t config; phy_config_t phyConfig = {0}; uint32_t length = 0; bool link = false; bool autonego = false; phy_speed_t speed; phy_duplex_t duplex; uint32_t testTxNum = 0; status_t status; enet_data_error_stats_t eErrStatic; volatile uint32_t count = 0; /* Hardware Initialization. */ gpio_pin_config_t gpio_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode}; BOARD_ConfigMPU(); BOARD_InitPins(); BOARD_BootClockRUN(); BOARD_InitDebugConsole(); BOARD_InitModuleClock(); IOMUXC_SelectENETClock(); GPIO_PinInit(GPIO9, 11, &gpio_config); GPIO_PinInit(GPIO12, 12, &gpio_config); /* Pull up the ENET_INT before RESET. */ GPIO_WritePinOutput(GPIO9, 11, 1); GPIO_WritePinOutput(GPIO12, 12, 0); SDK_DelayAtLeastUs(10000, CLOCK_GetFreq(kCLOCK_CpuClk)); GPIO_WritePinOutput(GPIO12, 12, 1); SDK_DelayAtLeastUs(6, CLOCK_GetFreq(kCLOCK_CpuClk)); PRINTF("\r\nENET example start.\r\n"); /* Prepare the buffer configuration. */ enet_buffer_config_t buffConfig[] = {{ ENET_RXBD_NUM, ENET_TXBD_NUM, SDK_SIZEALIGN(ENET_RXBUFF_SIZE, APP_ENET_BUFF_ALIGNMENT), SDK_SIZEALIGN(ENET_TXBUFF_SIZE, APP_ENET_BUFF_ALIGNMENT), &g_rxBuffDescrip[0], &g_txBuffDescrip[0], &g_rxDataBuff[0][0], &g_txDataBuff[0][0], true, true, NULL, }}; /* Get default configuration. */ /* * config.miiMode = kENET_RmiiMode; * config.miiSpeed = kENET_MiiSpeed100M; * config.miiDuplex = kENET_MiiFullDuplex; * config.rxMaxFrameLen = ENET_FRAME_MAX_FRAMELEN; */ ENET_GetDefaultConfig(&config); /* The miiMode should be set according to the different PHY interfaces. */ #ifdef EXAMPLE_PHY_INTERFACE_RGMII config.miiMode = kENET_RgmiiMode; #else config.miiMode = kENET_RmiiMode; #endif config.macSpecialConfig |= kENET_ControlMIILoopEnable; // phyConfig.phyAddr = EXAMPLE_PHY_ADDRESS; // phyConfig.autoNeg = true; // mdioHandle.resource.base = EXAMPLE_ENET; // mdioHandle.resource.csrClock_Hz = EXAMPLE_CLOCK_FREQ; // // /* Initialize PHY and wait auto-negotiation over. */ // PRINTF("Wait for PHY init...\r\n"); // do // { // status = PHY_Init(&phyHandle, &phyConfig); // if (status == kStatus_Success) // { // PRINTF("Wait for PHY link up...\r\n"); // /* Wait for auto-negotiation success and link up */ // count = PHY_AUTONEGO_TIMEOUT_COUNT; // do // { // PHY_GetAutoNegotiationStatus(&phyHandle, &autonego); // PHY_GetLinkStatus(&phyHandle, &link); // if (autonego && link) // { // break; // } // } while (--count); // if (!autonego) // { // PRINTF("PHY Auto-negotiation failed. Please check the cable connection and link partner setting.\r\n"); // } // } // } while (!(link && autonego)); // //#if PHY_STABILITY_DELAY_US // /* Wait a moment for PHY status to be stable. */ // SDK_DelayAtLeastUs(PHY_STABILITY_DELAY_US, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY); //#endif // // /* Get the actual PHY link speed. */ // PHY_GetLinkSpeedDuplex(&phyHandle, &speed, &duplex); // /* Change the MII speed and duplex for actual link status. */ // config.miiSpeed = (enet_mii_speed_t)speed; // config.miiDuplex = (enet_mii_duplex_t)duplex; ENET_Init(EXAMPLE_ENET, &g_handle, &config, &buffConfig[0], &g_macAddr[0], EXAMPLE_CLOCK_FREQ); ENET_ActiveRead(EXAMPLE_ENET); /* Build broadcast for sending. */ ENET_BuildBroadCastFrame(); while (1) { /* Get the Frame size */ status = ENET_GetRxFrameSize(&g_handle, &length, 0); /* Call ENET_ReadFrame when there is a received frame. */ if (length != 0) { /* Received valid frame. Deliver the rx buffer with the size equal to length. */ uint8_t *data = (uint8_t *)malloc(length); status = ENET_ReadFrame(EXAMPLE_ENET, &g_handle, data, length, 0, NULL); if (status == kStatus_Success) { PRINTF(" A frame received. the length %d ", length); PRINTF(" Dest Address %02x:%02x:%02x:%02x:%02x:%02x Src Address %02x:%02x:%02x:%02x:%02x:%02x \r\n", data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11]); } free(data); } else if (status == kStatus_ENET_RxFrameError) { /* Update the received buffer when error happened. */ /* Get the error information of the received g_frame. */ ENET_GetRxErrBeforeReadFrame(&g_handle, &eErrStatic, 0); /* update the receive buffer. */ ENET_ReadFrame(EXAMPLE_ENET, &g_handle, NULL, 0, 0, NULL); } if (testTxNum < ENET_TRANSMIT_DATA_NUM) { /* Send a multicast frame when the PHY is link up. */ if (kStatus_Success == PHY_GetLinkStatus(&phyHandle, &link)) { if (1) { testTxNum++; if (kStatus_Success == ENET_SendFrame(EXAMPLE_ENET, &g_handle, &g_frame[0], ENET_DATA_LENGTH, 0, false, NULL)) { PRINTF("The %d frame transmitted success!\r\n", testTxNum); } else { PRINTF(" \r\nTransmit frame failed!\r\n"); } } } } } }