未验证 提交 58769e67 编写于 作者: o777788's avatar o777788 提交者: GitHub

修复imxrt1170网络驱动问题 (#6342)

1、修复ksz8081.c编译错误;
2、修复rt1170网络驱动问题
上级 b11cb41a
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* 2017-10-10 Tanek the first version * 2017-10-10 Tanek the first version
* 2019-5-10 misonyo add DMA TX and RX function * 2019-5-10 misonyo add DMA TX and RX function
* 2020-10-14 wangqiang use phy device in phy monitor thread * 2020-10-14 wangqiang use phy device in phy monitor thread
* 2022-08-29 xjy198903 add 1170 rgmii support
*/ */
#include <rtthread.h> #include <rtthread.h>
...@@ -29,8 +30,8 @@ ...@@ -29,8 +30,8 @@
#include <netif/ethernetif.h> #include <netif/ethernetif.h>
#include "lwipopts.h" #include "lwipopts.h"
#define ENET_RXBD_NUM (4) #define ENET_RXBD_NUM (5)
#define ENET_TXBD_NUM (4) #define ENET_TXBD_NUM (3)
#define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN) #define ENET_RXBUFF_SIZE (ENET_FRAME_MAX_FRAMELEN)
#define ENET_TXBUFF_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) ...@@ -122,6 +123,7 @@ void _enet_rx_callback(struct rt_imxrt_eth *eth)
void _enet_tx_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) if (eth->tx_is_waiting == RT_TRUE)
{ {
eth->tx_is_waiting = RT_FALSE; 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) ...@@ -451,6 +453,277 @@ static rt_err_t rt_imxrt_eth_control(rt_device_t dev, int cmd, void *args)
return RT_EOK; 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 */ /* ethernet device interface */
/* transmit packet. */ /* transmit packet. */
rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p) 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) ...@@ -469,7 +742,7 @@ rt_err_t rt_imxrt_eth_tx(rt_device_t dev, struct pbuf *p)
do 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) if (result == kStatus_ENET_TxFrameBusy)
{ {
...@@ -730,7 +1003,7 @@ static int rt_hw_imxrt_eth_init(void) ...@@ -730,7 +1003,7 @@ static int rt_hw_imxrt_eth_init(void)
tid = rt_thread_create("phy", tid = rt_thread_create("phy",
phy_monitor_thread_entry, phy_monitor_thread_entry,
RT_NULL, RT_NULL,
1024, 4096,
RT_THREAD_PRIORITY_MAX - 2, RT_THREAD_PRIORITY_MAX - 2,
2); 2);
if (tid != RT_NULL) if (tid != RT_NULL)
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2020-10-14 wangqiang the first version * 2020-10-14 wangqiang the first version
* 2022-08-29 xjy198903 add rt1170 support
*/ */
#include <rtthread.h> #include <rtthread.h>
...@@ -71,7 +72,12 @@ ...@@ -71,7 +72,12 @@
#define PHY_TIMEOUT_COUNT 0x3FFFFFFU #define PHY_TIMEOUT_COUNT 0x3FFFFFFU
/* defined the Reset pin, PORT and PIN config by menuconfig */ /* 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) #define RESET_PIN GET_PIN(PHY_RESET_PORT, PHY_RESET_PIN)
#endif
/******************************************************************************* /*******************************************************************************
* Prototypes * Prototypes
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册