AT91 ARM EMAC 轮询问题

AT91 ARM EMAC polling issue

我正在使用 atmel 的 lwip 示例。与 PHY 接口是可以的。它可以 link 甚至自动协商。 Netif 正在上涨。但是当我开始轮询 netif 时,什么也没有发生。我已将问题缩小到 EMAC_Poll

unsigned char EMAC_Poll(unsigned char *pFrame, unsigned int frameSize, unsigned int *pRcvSize)
{
    unsigned short bufferLength;
    unsigned int   tmpFrameSize=0;
    unsigned char  *pTmpFrame=0;
    unsigned int   tmpIdx = rxTd.idx;
    volatile EmacRxTDescriptor *pRxTd = rxTd.td + rxTd.idx;

    ASSERT(pFrame, "F: EMAC_Poll\n\r");

    char isFrame = 0;
    // Set the default return value
    *pRcvSize = 0;

    // Process received RxTd
    while ((pRxTd->addr & EMAC_RX_OWNERSHIP_BIT) == EMAC_RX_OWNERSHIP_BIT) {
        // Never got there.
        ...
    }
    return EMAC_RX_NO_DATA;
}


typedef struct {
   volatile EmacRxTDescriptor td[RX_BUFFERS];
   EMAC_RxCallback rxCb; /// Callback function to be invoked once a frame has been received
   unsigned short idx;
} RxTd;

/// Describes the type and attribute of Receive Transfer descriptor.
typedef struct _EmacRxTDescriptor {
    unsigned int addr;
    unsigned int status;
} __attribute__((packed, aligned(8))) EmacRxTDescriptor, *PEmacRxTDescriptor;

有 while 循环,但条件永远不会成立。 我对什么是 RxTd 以及这种情况的确切含义有非常模糊的介绍。但是我看不出 thise RxTd 会如何改变以通过条件。 RxTd 的所有引用都指向相同的 emac.c 模块。他们中的大多数在那个轮询函数中并在 EMAC_ResetRx 函数中休息。

static void EMAC_ResetRx(void)
{
    unsigned int Index;
    unsigned int Address;

    // Disable RX
    AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_RE;
    // Setup the RX descriptors.
    rxTd.idx = 0;
    for(Index = 0; Index < RX_BUFFERS; Index++) {

        Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
        // Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
        rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
        rxTd.td[Index].status = 0;
    }
    rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;
    // Receive Buffer Queue Pointer Register
    AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
}

我不太明白最后一行,但看起来 rxTd 是用 AT91 本身自动填充的。如果是这样,可能存在 packing/aligment 问题,但 Atmel 在 RxTd 结构定义上添加了 __attribute__ ((packed, aligned(8)))。无论如何,有人可以描述数据输入的机制或告诉我问题出在哪里吗? 顺便说一句,如果这很重要,我正在使用 gcc。 更新: 我检查了 RSR 并注意到它从 0 开始,然后在秒后转到 2。 2- 表示捕获了新数据。 更新: 所以我在我的芯片的数据表中读到了 emac 的功能。我是正确的。该 RBQP 寄存器必须指向描述符数组。每个描述符由地址和状态字段组成。数据表指出 "bit zero of address field is written to one to show the buffer has been used"。然后 ARM 使用该数组中的另一个 rx 描述符。我猜 "has been used" 表示缓冲区已填充帧数据并准备好进行处理。这一定意味着数据不会进入该缓冲区。但它必须存在,因为 REC 变高。此外,我检查过 NCR 中的 RE 已启动并且 MI 已启用。我不知道哪里出了问题。

我花了整整一周的时间来解决它。有趣的是,如果我转储内存并查看所有这些地址——数据一直都在那里!所以关键是 禁用 I 和 D 缓存以及 MMU 本身 。希望对大家有所帮助。