Я использую пример lwip от atmel. Взаимодействие с PHY в порядке. Он может связываться и даже автоматически вести переговоры. Нетиф растет. Но когда я начинаю опрашивать 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 и что именно означает это условие. Однако я не вижу, как этот 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 добавил __attribute__ ((packed, aligned(8)))
в определение структуры RxTd. В любом случае, может ли кто-нибудь описать механизм ввода данных или сказать мне, в чем может быть проблема? Кстати, я использую gcc, если это имеет значение. UPD: я проверил RSR и заметил, что он начинается с 0, а затем переходит к 2 через секунду. 2- означает, что новые данные были захвачены. UPD: Итак, я прочитал о функции emac в даташите на свой чип. Я был прав. Этот регистр RBQP должен указывать на массив дескрипторов. Каждый дескриптор состоит из поля адреса и статуса. В таблице данных указано, что «нулевой бит поля адреса записывается в единицу, чтобы показать, что буфер использовался». Затем ARM использует другой дескриптор rx из этого массива. Я предполагаю, что под «был использован» они подразумевают, что этот буфер заполнен данными кадра и готов к обработке. Это должно означать, что данные просто не попадают в этот буфер. Но он должен быть там, потому что REC становится высоким. Кроме того, я проверил, что RE в NCR работает, а MI включен. Я понятия не имею, что случилось.