diff --git a/bsp/imxrt/libraries/drivers/drv_eth.c b/bsp/imxrt/libraries/drivers/drv_eth.c index 6fa053337d8349317ec8abdafb4d5987d102ff8f..81f7c2fbb1b8a7e1eed3d7e4ba255c799310bef9 100644 --- a/bsp/imxrt/libraries/drivers/drv_eth.c +++ b/bsp/imxrt/libraries/drivers/drv_eth.c @@ -8,6 +8,7 @@ * 2017-10-10 Tanek the first version * 2019-5-10 misonyo add DMA TX and RX function * 2020-10-14 wangqiang use phy device in phy monitor thread + * 2022-08-29 xjy198903 add 1170 rgmii support */ #include @@ -29,8 +30,8 @@ #include #include "lwipopts.h" -#define ENET_RXBD_NUM (4) -#define ENET_TXBD_NUM (4) +#define ENET_RXBD_NUM (5) +#define ENET_TXBD_NUM (3) #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) #define ENET_TXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) @@ -122,6 +123,7 @@ void _enet_rx_callback(struct rt_imxrt_eth *eth) void _enet_tx_callback(struct rt_imxrt_eth *eth) { + dbg_log(DBG_LOG, "_enet_tx_callback\n"); if (eth->tx_is_waiting == RT_TRUE) { eth->tx_is_waiting = RT_FALSE; @@ -451,6 +453,277 @@ static rt_err_t rt_imxrt_eth_control(rt_device_t dev, int cmd, void *args) return RT_EOK; } +static bool _ENET_TxDirtyRingAvailable(enet_tx_dirty_ring_t *txDirtyRing) +{ + return !txDirtyRing->isFull; +} + +static uint16_t _ENET_IncreaseIndex(uint16_t index, uint16_t max) +{ + assert(index < max); + + /* Increase the index. */ + index++; + if (index >= max) + { + index = 0; + } + return index; +} + +static void _ENET_ActiveSendRing(ENET_Type *base, uint8_t ringId) +{ + assert(ringId < (uint8_t)FSL_FEATURE_ENET_INSTANCE_QUEUEn(base)); + + volatile uint32_t *txDesActive = NULL; + + /* Ensure previous data update is completed with Data Synchronization Barrier before activing Tx BD. */ + __DSB(); + + switch (ringId) + { + case 0: + txDesActive = &(base->TDAR); + break; +#if FSL_FEATURE_ENET_QUEUE > 1 + case 1: + txDesActive = &(base->TDAR1); + break; + case 2: + txDesActive = &(base->TDAR2); + break; +#endif /* FSL_FEATURE_ENET_QUEUE > 1 */ + default: + txDesActive = &(base->TDAR); + break; + } + +#if defined(FSL_FEATURE_ENET_HAS_ERRATA_007885) && FSL_FEATURE_ENET_HAS_ERRATA_007885 + /* There is a TDAR race condition for mutliQ when the software sets TDAR + * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles). + * This will cause the udma_tx and udma_tx_arbiter state machines to hang. + * Software workaround: introduces a delay by reading the relevant ENET_TDARn_TDAR 4 times + */ + for (uint8_t i = 0; i < 4U; i++) + { + if (*txDesActive == 0U) + { + break; + } + } +#endif + + /* Write to active tx descriptor */ + *txDesActive = 0; +} + +static status_t _ENET_SendFrame(ENET_Type *base, + enet_handle_t *handle, + const uint8_t *data, + uint32_t length, + uint8_t ringId, + bool tsFlag, + void *context) +{ + assert(handle != NULL); + assert(data != NULL); + assert(FSL_FEATURE_ENET_INSTANCE_QUEUEn(base) != -1); + assert(ringId < (uint8_t)FSL_FEATURE_ENET_INSTANCE_QUEUEn(base)); + + volatile enet_tx_bd_struct_t *curBuffDescrip; + enet_tx_bd_ring_t *txBdRing = &handle->txBdRing[ringId]; + enet_tx_dirty_ring_t *txDirtyRing = &handle->txDirtyRing[ringId]; + enet_frame_info_t *txDirty = NULL; + uint32_t len = 0; + uint32_t sizeleft = 0; + uint32_t address; + status_t result = kStatus_Success; + uint32_t src; + uint32_t configVal; + bool isReturn = false; + uint32_t primask; + + /* Check the frame length. */ + if (length > ENET_FRAME_TX_LEN_LIMITATION(base)) + { + result = kStatus_ENET_TxFrameOverLen; + } + else + { + /* Check if the transmit buffer is ready. */ + curBuffDescrip = txBdRing->txBdBase + txBdRing->txGenIdx; + if (0U != (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)) + { + result = kStatus_ENET_TxFrameBusy; + } + /* Check txDirtyRing if need frameinfo in tx interrupt callback. */ + else if ((handle->txReclaimEnable[ringId]) && !_ENET_TxDirtyRingAvailable(txDirtyRing)) + { + result = kStatus_ENET_TxFrameBusy; + } + else + { + /* One transmit buffer is enough for one frame. */ + if (handle->txBuffSizeAlign[ringId] >= 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); +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL + if (handle->txMaintainEnable[ringId]) + { + DCACHE_CleanByRange(address, length); + } +#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ + /* Set data length. */ + curBuffDescrip->length = (uint16_t)length; +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + /* For enable the timestamp. */ + if (tsFlag) + { + curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + else + { + curBuffDescrip->controlExtend1 &= (uint16_t)(~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. */ + txBdRing->txGenIdx = _ENET_IncreaseIndex(txBdRing->txGenIdx, txBdRing->txRingLen); + + /* Add context to frame info ring */ + if (handle->txReclaimEnable[ringId]) + { + txDirty = txDirtyRing->txDirtyBase + txDirtyRing->txGenIdx; + txDirty->context = context; + txDirtyRing->txGenIdx = _ENET_IncreaseIndex(txDirtyRing->txGenIdx, txDirtyRing->txRingLen); + if (txDirtyRing->txGenIdx == txDirtyRing->txConsumIdx) + { + txDirtyRing->isFull = true; + } + primask = DisableGlobalIRQ(); + txBdRing->txDescUsed++; + EnableGlobalIRQ(primask); + } + + /* Active the transmit buffer descriptor. */ + _ENET_ActiveSendRing(base, ringId); + } + else + { + /* One frame requires more than one transmit buffers. */ + do + { +#ifdef ENET_ENHANCEDBUFFERDESCRIPTOR_MODE + /* For enable the timestamp. */ + if (tsFlag) + { + curBuffDescrip->controlExtend1 |= ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK; + } + else + { + curBuffDescrip->controlExtend1 &= (uint16_t)(~ENET_BUFFDESCRIPTOR_TX_TIMESTAMP_MASK); + } +#endif /* ENET_ENHANCEDBUFFERDESCRIPTOR_MODE */ + + /* Update the size left to be transmit. */ + sizeleft = length - len; +#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 */ + src = (uint32_t)data + len; + + /* Increase the current software index of BD */ + txBdRing->txGenIdx = _ENET_IncreaseIndex(txBdRing->txGenIdx, txBdRing->txRingLen); + + if (sizeleft > handle->txBuffSizeAlign[ringId]) + { + /* Data copy. */ + (void)memcpy((void *)(uint32_t *)address, (void *)(uint32_t *)src, + handle->txBuffSizeAlign[ringId]); +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL + if (handle->txMaintainEnable[ringId]) + { + /* Add the cache clean maintain. */ + DCACHE_CleanByRange(address, handle->txBuffSizeAlign[ringId]); + } +#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ + /* Data length update. */ + curBuffDescrip->length = handle->txBuffSizeAlign[ringId]; + len += handle->txBuffSizeAlign[ringId]; + /* Sets the control flag. */ + configVal = (uint32_t)curBuffDescrip->control; + configVal &= ~ENET_BUFFDESCRIPTOR_TX_LAST_MASK; + configVal |= ENET_BUFFDESCRIPTOR_TX_READY_MASK; + curBuffDescrip->control = (uint16_t)configVal; + + if (handle->txReclaimEnable[ringId]) + { + primask = DisableGlobalIRQ(); + txBdRing->txDescUsed++; + EnableGlobalIRQ(primask); + } + + /* Active the transmit buffer descriptor*/ + _ENET_ActiveSendRing(base, ringId); + } + else + { + (void)memcpy((void *)(uint32_t *)address, (void *)(uint32_t *)src, sizeleft); +#if defined(FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL) && FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL + if (handle->txMaintainEnable[ringId]) + { + /* Add the cache clean maintain. */ + DCACHE_CleanByRange(address, sizeleft); + } +#endif /* FSL_SDK_ENABLE_DRIVER_CACHE_CONTROL */ + curBuffDescrip->length = (uint16_t)sizeleft; + /* Set Last buffer wrap flag. */ + curBuffDescrip->control |= ENET_BUFFDESCRIPTOR_TX_READY_MASK | ENET_BUFFDESCRIPTOR_TX_LAST_MASK; + + if (handle->txReclaimEnable[ringId]) + { + /* Add context to frame info ring */ + txDirty = txDirtyRing->txDirtyBase + txDirtyRing->txGenIdx; + txDirty->context = context; + txDirtyRing->txGenIdx = _ENET_IncreaseIndex(txDirtyRing->txGenIdx, txDirtyRing->txRingLen); + if (txDirtyRing->txGenIdx == txDirtyRing->txConsumIdx) + { + txDirtyRing->isFull = true; + } + primask = DisableGlobalIRQ(); + txBdRing->txDescUsed++; + EnableGlobalIRQ(primask); + } + + /* Active the transmit buffer descriptor. */ + _ENET_ActiveSendRing(base, ringId); + isReturn = true; + break; + } + /* Update the buffer descriptor address. */ + curBuffDescrip = txBdRing->txBdBase + txBdRing->txGenIdx; + } while (0U == (curBuffDescrip->control & ENET_BUFFDESCRIPTOR_TX_READY_MASK)); + + if (isReturn == false) + { + result = kStatus_ENET_TxFrameBusy; + } + } + } + } + return result; +} + /* ethernet device interface */ /* transmit packet. */ rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p) @@ -469,7 +742,7 @@ rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p) do { - result = ENET_SendFrame(imxrt_eth_device.enet_base, enet_handle, (const uint8_t *)p, p->tot_len, RING_ID, false, NULL); + result = _ENET_SendFrame(imxrt_eth_device.enet_base, enet_handle, (const uint8_t *)p, p->tot_len, RING_ID, false, NULL); if (result == kStatus_ENET_TxFrameBusy) { @@ -730,7 +1003,7 @@ static int rt_hw_imxrt_eth_init(void) tid = rt_thread_create("phy", phy_monitor_thread_entry, RT_NULL, - 1024, + 4096, RT_THREAD_PRIORITY_MAX - 2, 2); if (tid != RT_NULL) diff --git a/bsp/imxrt/libraries/drivers/drv_ksz8081.c b/bsp/imxrt/libraries/drivers/drv_ksz8081.c index 151ef42ab624b6f87df3de922d546b6640a1d384..3d89bdd86fa8f6bbcd953e2d35cf8c65cfd95213 100644 --- a/bsp/imxrt/libraries/drivers/drv_ksz8081.c +++ b/bsp/imxrt/libraries/drivers/drv_ksz8081.c @@ -6,6 +6,7 @@ * Change Logs: * Date Author Notes * 2020-10-14 wangqiang the first version + * 2022-08-29 xjy198903 add rt1170 support */ #include @@ -71,7 +72,12 @@ #define PHY_TIMEOUT_COUNT 0x3FFFFFFU /* defined the Reset pin, PORT and PIN config by menuconfig */ +#ifdef SOC_IMXRT1170_SERIES +#define RESET_PIN GET_PIN(PHY_RESET_KSZ8081_PORT, PHY_RESET_KSZ8081_PIN) +#else #define RESET_PIN GET_PIN(PHY_RESET_PORT, PHY_RESET_PIN) +#endif + /******************************************************************************* * Prototypes