diff --git a/bsp/imxrt/libraries/drivers/drv_eth.c b/bsp/imxrt/libraries/drivers/drv_eth.c index 81f7c2fbb1b8a7e1eed3d7e4ba255c799310bef9..532ed5ad404f8820a020a5a5c7ad55c39457c2ce 100644 --- a/bsp/imxrt/libraries/drivers/drv_eth.c +++ b/bsp/imxrt/libraries/drivers/drv_eth.c @@ -30,8 +30,13 @@ #include #include "lwipopts.h" +#ifdef SOC_IMXRT1170_SERIES #define ENET_RXBD_NUM (5) #define ENET_TXBD_NUM (3) +#else +#define ENET_RXBD_NUM (4) +#define ENET_TXBD_NUM (4) +#endif #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) #define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) @@ -48,16 +53,19 @@ #include #define MAX_ADDR_LEN 6 + +#ifdef SOC_IMXRT1170_SERIES #define ENET_RING_NUM 1U #define RING_ID 0 - typedef uint8_t rx_buffer_t[RT_ALIGN(ENET_TXBUFF_SIZE, ENET_BUFF_ALIGNMENT)]; typedef uint8_t tx_buffer_t[RT_ALIGN(ENET_TXBUFF_SIZE, ENET_BUFF_ALIGNMENT)]; #ifndef ENET_RXBUFF_NUM #define ENET_RXBUFF_NUM (ENET_RXBD_NUM * 2) #endif +#endif +#ifdef SOC_IMXRT1170_SERIES typedef void (*pbuf_free_custom_fn)(struct pbuf *p); /** A custom pbuf: like a pbuf, but following a function pointer to free it. */ @@ -76,6 +84,7 @@ typedef struct rx_pbuf_wrapper volatile bool buffer_used; /*!< Wrapped buffer is used by ENET */ } rx_pbuf_wrapper_t; +#endif struct rt_imxrt_eth { /* inherit from ethernet device */ @@ -93,11 +102,13 @@ struct rt_imxrt_eth enet_mii_speed_t speed; enet_mii_duplex_t duplex; +#ifdef SOC_IMXRT1170_SERIES enet_rx_bd_struct_t *RxBuffDescrip; enet_tx_bd_struct_t *TxBuffDescrip; rx_buffer_t *RxDataBuff; tx_buffer_t *TxDataBuff; rx_pbuf_wrapper_t RxPbufs[ENET_RXBUFF_NUM]; +#endif }; AT_NONCACHEABLE_SECTION_ALIGN(static enet_tx_bd_struct_t g_txBuffDescrip[ENET_TXBD_NUM], ENET_BUFF_ALIGNMENT); @@ -131,6 +142,7 @@ void _enet_tx_callback(struct rt_imxrt_eth *eth) } } +#ifdef SOC_IMXRT1170_SERIES static void _enet_callback(ENET_Type *base, enet_handle_t *handle, #if FSL_FEATURE_ENET_QUEUE > 1 @@ -139,6 +151,9 @@ static void _enet_callback(ENET_Type *base, enet_event_t event, enet_frame_info_t *frameInfo, void *userData) +#else +void _enet_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, void *userData) +#endif { switch (event) { @@ -212,6 +227,7 @@ static void _enet_clk_init(void) #endif } +#ifdef SOC_IMXRT1170_SERIES static void *_enet_rx_alloc(ENET_Type *base, void *userData, uint8_t ringId) { void *buffer = NULL; @@ -264,39 +280,56 @@ static void _enet_rx_release(struct pbuf *p) rx_pbuf_wrapper_t *wrapper = (rx_pbuf_wrapper_t *)p; _enet_rx_free(imxrt_eth_device.enet_base, wrapper->buffer, &imxrt_eth_device, 0); } +#endif static void _enet_config(void) { enet_config_t config; uint32_t sysClock; - enet_buffer_config_t buffConfig[ENET_RING_NUM]; - int i; -#ifdef PHY_USING_RTL8211F - EnableIRQ(ENET_1G_MAC0_Tx_Rx_1_IRQn); - EnableIRQ(ENET_1G_MAC0_Tx_Rx_2_IRQn); -#endif +/* prepare the buffer configuration. */ +#ifndef SOC_IMXRT1170_SERIES + enet_buffer_config_t buffConfig = + { + ENET_RXBD_NUM, + ENET_TXBD_NUM, + SDK_SIZEALIGN(ENET_RXBUFF_SIZE, ENET_BUFF_ALIGNMENT), + SDK_SIZEALIGN(ENET_TXBUFF_SIZE, ENET_BUFF_ALIGNMENT), + &g_rxBuffDescrip[0], + &g_txBuffDescrip[0], + &g_rxDataBuff[0][0], + &g_txDataBuff[0][0], + }; + /* Get default configuration. */ + /* + * config.miiMode = kENET_RmiiMode; + * config.miiSpeed = kENET_MiiSpeed100M; + * config.miiDuplex = kENET_MiiFullDuplex; + * config.rxMaxFrameLen = ENET_FRAME_MAX_FRAMELEN; + */ + ENET_GetDefaultConfig(&config); + config.interrupt = kENET_TxFrameInterrupt | kENET_RxFrameInterrupt; + config.miiSpeed = imxrt_eth_device.speed; + config.miiDuplex = imxrt_eth_device.duplex; + /* Set SMI to get PHY link status. */ + sysClock = CLOCK_GetFreq(kCLOCK_AhbClk); + + dbg_log(DBG_LOG, "deinit\n"); + ENET_Deinit(imxrt_eth_device.enet_base); + dbg_log(DBG_LOG, "init\n"); + ENET_Init(imxrt_eth_device.enet_base, &imxrt_eth_device.enet_handle, &config, &buffConfig, &imxrt_eth_device.dev_addr[0], sysClock); + dbg_log(DBG_LOG, "set call back\n"); + ENET_SetCallback(&imxrt_eth_device.enet_handle, _enet_callback, &imxrt_eth_device); + dbg_log(DBG_LOG, "active read\n"); + ENET_ActiveRead(imxrt_eth_device.enet_base); +#else + int i; + enet_buffer_config_t buffConfig[ENET_RING_NUM]; imxrt_eth_device.RxBuffDescrip = &g_rxBuffDescrip[0]; imxrt_eth_device.TxBuffDescrip = &g_txBuffDescrip[0]; imxrt_eth_device.RxDataBuff = &g_rxDataBuff[0]; imxrt_eth_device.TxDataBuff = &g_txDataBuff[0]; - - /* prepare the buffer configuration. */ - // enet_buffer_config_t buffConfig[RING_NUM] = - // { - // ENET_RXBD_NUM, - // ENET_TXBD_NUM, - // sizeof(rx_buffer_t), - // sizeof(tx_buffer_t), - // &imxrt_eth_device.RxBuffDescrip[0], - // &imxrt_eth_device.TxBuffDescrip[0], - // NULL, - // &imxrt_eth_device.TxDataBuff[0][0], - // true, - // true, - // NULL, - // }; buffConfig[0].rxBdNumber = ENET_RXBD_NUM; /* Receive buffer descriptor number. */ buffConfig[0].txBdNumber = ENET_TXBD_NUM; /* Transmit buffer descriptor number. */ buffConfig[0].rxBuffSizeAlign = sizeof(rx_buffer_t); /* Aligned receive data buffer size. */ @@ -325,6 +358,8 @@ static void _enet_config(void) config.miiDuplex = imxrt_eth_device.duplex; #ifdef PHY_USING_RTL8211F config.miiMode = kENET_RgmiiMode; + EnableIRQ(ENET_1G_MAC0_Tx_Rx_1_IRQn); + EnableIRQ(ENET_1G_MAC0_Tx_Rx_2_IRQn); #else config.miiMode = kENET_RmiiMode; #endif @@ -332,14 +367,7 @@ static void _enet_config(void) config.rxBuffFree = _enet_rx_free; config.userData = &imxrt_eth_device; /* Set SMI to get PHY link status. */ -#ifdef SOC_IMXRT1170_SERIES sysClock = CLOCK_GetRootClockFreq(kCLOCK_Root_Bus); -#else - sysClock = CLOCK_GetFreq(kCLOCK_AhbClk); -#endif - - // dbg_log(DBG_LOG, "deinit\n"); - // ENET_Deinit(imxrt_eth_device.enet_base); config.interrupt |= kENET_TxFrameInterrupt | kENET_RxFrameInterrupt | kENET_TxBufferInterrupt | kENET_LateCollisionInterrupt; config.callback = _enet_callback; @@ -359,6 +387,7 @@ static void _enet_config(void) // ENET_SetCallback(&imxrt_eth_device.enet_handle, _enet_callback, &imxrt_eth_device); dbg_log(DBG_LOG, "active read\n"); ENET_ActiveRead(imxrt_eth_device.enet_base); +#endif } #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP) @@ -453,6 +482,7 @@ static rt_err_t rt_imxrt_eth_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } +#ifdef SOC_IMXRT1170_SERIES static bool _ENET_TxDirtyRingAvailable(enet_tx_dirty_ring_t *txDirtyRing) { return !txDirtyRing->isFull; @@ -516,7 +546,32 @@ static void _ENET_ActiveSendRing(ENET_Type *base, uint8_t ringId) /* Write to active tx descriptor */ *txDesActive = 0; } +#else +static void _ENET_ActiveSend(ENET_Type *base, uint32_t ringId) +{ + assert(ringId < FSL_FEATURE_ENET_QUEUE); + + switch (ringId) + { + case 0: + base->TDAR = ENET_TDAR_TDAR_MASK; + break; +#if FSL_FEATURE_ENET_QUEUE > 1 + case 1: + base->TDAR1 = ENET_TDAR1_TDAR_MASK; + break; + case 2: + base->TDAR2 = ENET_TDAR2_TDAR_MASK; + break; +#endif /* FSL_FEATURE_ENET_QUEUE > 1 */ + default: + base->TDAR = ENET_TDAR_TDAR_MASK; + break; + } +} +#endif +#ifdef SOC_IMXRT1170_SERIES static status_t _ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, const uint8_t *data, @@ -723,6 +778,166 @@ static status_t _ENET_SendFrame(ENET_Type *base, } return result; } +#else +static status_t _ENET_SendFrame(ENET_Type *base, enet_handle_t *handle, const uint8_t *data, uint32_t length) +{ + assert(handle); + assert(data); + + volatile enet_tx_bd_struct_t *curBuffDescrip; + uint32_t len = 0; + uint32_t sizeleft = 0; + uint32_t address; + + /* Check the frame length. */ + if (length > ENET_FRAME_MAX_FRAMELEN) + { + return kStatus_ENET_TxFrameOverLen; + } + + /* Check if the transmit buffer is ready. */ + curBuffDescrip = handle->txBdCurrent[0]; + if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK) + { + return kStatus_ENET_TxFrameBusy; + } +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + bool isPtpEventMessage = false; + /* Check PTP message with the PTP header. */ + isPtpEventMessage = ENET_Ptp1588ParseFrame(data, NULL, true); +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + /* One transmit buffer is enough for one frame. */ + if (handle->txBuffSizeAlign[0] >= length) + { + /* Copy data to the buffer for uDMA transfer. */ +#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET + address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer, kMEMORY_DMA2Local); +#else + address = (uint32_t)curBuffDescrip->buffer; +#endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ + + pbuf_copy_partial((const struct pbuf *)data, (void *)address, length, 0); + + /* Set data length. */ + curBuffDescrip->length = length; +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + /* For enable the timestamp. */ + if (isPtpEventMessage) + { + curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + else + { + curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + curBuffDescrip->control |= (ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK); + + /* Increase the buffer descriptor address. */ + if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) + { + handle->txBdCurrent[0] = handle->txBdBase[0]; + } + else + { + handle->txBdCurrent[0]++; + } +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL + /* Add the cache clean maintain. */ +#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET + address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer, kMEMORY_DMA2Local); +#else + address = (uint32_t)curBuffDescrip->buffer; +#endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ + DCACHE_CleanByRange(address, length); +#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ + /* Active the transmit buffer descriptor. */ + _ENET_ActiveSend(base, 0); + + return kStatus_Success; + } + else + { + /* One frame requires more than one transmit buffers. */ + do + { +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + /* For enable the timestamp. */ + if (isPtpEventMessage) + { + curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + else + { + curBuffDescrip->controlExtend1 &= ~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + + /* Increase the buffer descriptor address. */ + if (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_WRAP_MASK) + { + handle->txBdCurrent[0] = handle->txBdBase[0]; + } + else + { + handle->txBdCurrent[0]++; + } + /* update the size left to be transmit. */ + sizeleft = length - len; + if (sizeleft > handle->txBuffSizeAlign[0]) + { + /* Data copy. */ +#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET + address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer, kMEMORY_DMA2Local); +#else + address = (uint32_t)curBuffDescrip->buffer; +#endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ + memcpy((void *)address, data + len, handle->txBuffSizeAlign[0]); + /* Data length update. */ + curBuffDescrip->length = handle->txBuffSizeAlign[0]; + len += handle->txBuffSizeAlign[0]; + /* Sets the control flag. */ + curBuffDescrip->control &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; + curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; + /* Active the transmit buffer descriptor*/ + _ENET_ActiveSend(base, 0); + } + else + { +#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET + address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer, kMEMORY_DMA2Local); +#else + address = (uint32_t)curBuffDescrip->buffer; +#endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ + memcpy((void *)address, data + len, sizeleft); + curBuffDescrip->length = sizeleft; + /* Set Last buffer wrap flag. */ + curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK; +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL + /* Add the cache clean maintain. */ +#if defined(FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET) && FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET + address = MEMORY_ConvertMemoryMapAddress((uint32_t)curBuffDescrip->buffer, kMEMORY_DMA2Local); +#else + address = (uint32_t)curBuffDescrip->buffer; +#endif /* FSL_FEATURE_MEMORY_HAS_ADDRESS_OFFSET */ + DCACHE_CleanByRange(address, handle->txBuffSizeAlign[0]); +#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ + /* Active the transmit buffer descriptor. */ + _ENET_ActiveSend(base, 0); + + return kStatus_Success; + } + + /* Get the current buffer descriptor address. */ + curBuffDescrip = handle->txBdCurrent[0]; + + } while (!(curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)); + + return kStatus_ENET_TxFrameBusy; + } +} +#endif /* ethernet device interface */ /* transmit packet. */ @@ -742,7 +957,11 @@ rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p) do { +#ifdef SOC_IMXRT1170_SERIES result = _ENET_SendFrame(imxrt_eth_device.enet_base, enet_handle, (const uint8_t *)p, p->tot_len, RING_ID, false, NULL); +#else + result = _ENET_SendFrame(imxrt_eth_device.enet_base, enet_handle, (const uint8_t *)p, p->tot_len); +#endif if (result == kStatus_ENET_TxFrameBusy) { @@ -766,8 +985,12 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) ENET_Type *enet_base = imxrt_eth_device.enet_base; enet_data_error_stats_t *error_statistic = &imxrt_eth_device.error_statistic; - /* Get the Frame size */ +/* Get the Frame size */ +#ifdef SOC_IMXRT1170_SERIES status = ENET_GetRxFrameSize(enet_handle, &length, RING_ID); +#else + status = ENET_GetRxFrameSize(enet_handle, &length); +#endif /* Call ENET_ReadFrame when there is a received frame. */ if (length != 0) @@ -777,7 +1000,11 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) if (p != NULL) { +#ifdef SOC_IMXRT1170_SERIES status = ENET_ReadFrame(enet_base, enet_handle, p->payload, length, RING_ID, NULL); +#else + status = ENET_ReadFrame(enet_base, enet_handle, p->payload, length); +#endif if (status == kStatus_Success) { #ifdef ETH_RX_DUMP @@ -800,10 +1027,17 @@ struct pbuf *rt_imxrt_eth_rx(rt_device_t dev) { dbg_log(DBG_WARNING, "ENET_GetRxFrameSize: kStatus_ENET_RxFrameError\n"); /* Update the received buffer when error happened. */ +#ifdef SOC_IMXRT1170_SERIES /* Get the error information of the received g_frame. */ ENET_GetRxErrBeforeReadFrame(enet_handle, error_statistic, RING_ID); /* update the receive buffer. */ ENET_ReadFrame(enet_base, enet_handle, NULL, 0, RING_ID, NULL); +#else + /* Get the error information of the received g_frame. */ + ENET_GetRxErrBeforeReadFrame(enet_handle, error_statistic); + /* update the receive buffer. */ + ENET_ReadFrame(enet_base, enet_handle, NULL, 0); +#endif } ENET_EnableInterrupts(enet_base, kENET_RxFrameInterrupt);