我正在使用 atmel 的 lwip 示例。与 PHY 接口(interface)是可以的。它可以链接甚至自动协商。 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 本身自动填充的。如果是这样,则可能存在打包/对齐问题,但 Atmel 在 RxTd 结构定义中添加了 __attribute__ ((packed, aligned(8)))
。无论如何,有人可以描述数据输入的机制或告诉我问题出在哪里吗?
顺便说一句,如果这很重要,我正在使用 gcc。
更新:
我检查了 RSR 并注意到它从 0 开始,然后在秒后转到 2。 2- 表示捕获了新数据。
更新:
所以我在我的芯片的数据表中读到了 emac 的功能。我是对的。该 RBQP 寄存器必须指向描述符数组。每个描述符由地址和状态字段组成。数据表指出“地址字段的位零被写入一以显示缓冲区已被使用”。然后 ARM 使用该数组中的另一个 rx 描述符。我猜“已被使用”是指该缓冲区已填充帧数据并准备好进行处理。这一定意味着数据不会进入该缓冲区。但它必须存在,因为 REC 变高。此外,我检查过 NCR 中的 RE 已启动并且 MI 已启用。我不知道出了什么问题。
最佳答案
我花了整整一周的时间来解决它。有趣的是,如果我转储内存并查看所有这些地址——数据一直都在那里!所以关键是禁用 I 和 D 缓存以及 MMU 本身。希望它能对某人有所帮助。
关于c - AT91 ARM EMAC 轮询问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53389330/