Проблема опроса AT91 ARM EMAC

Я использую пример 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 включен. Я понятия не имею, что случилось.


person G0867532    schedule 20.11.2018    source источник


Ответы (1)


Я потратил целую неделю, чтобы решить эту проблему. Самое смешное, что если я сделал дамп памяти и посмотрел все эти адреса - данные были там все время! Таким образом, ключевым моментом было отключение кэширования I и D и самого MMU. Надеюсь, это поможет кому-то.

person G0867532    schedule 23.11.2018