Перейти к содержанию
    

Ethernet, FreeRTOS и LPC2388

Здравствуйте!

Из демопакета FreeRTOS взял драйвер Ethernet для CORTEX LPC1768 и переделал под LPC2388.

 

Имеем процедуру передачи данных:

#define emacTX_DESC_INDEX (0)
/* EMAC variables located in ETHERNET_RAM */
#define ETHERNET_RAM  0x7FE00000UL
#define RX_DESC_BASE        (ETHERNET_RAM)            /* 0x7FE00000*/    
#define RX_STAT_BASE        (RX_DESC_BASE + NUM_RX_FRAG*(2*4))  /* =0x7FE00018, 2 * uint32_t, see RX_DESC_TypeDef */
#define TX_DESC_BASE        (RX_STAT_BASE + NUM_RX_FRAG*(2*4))  /* =0x7FE00030, 2 * uint32_t, see RX_STAT_TypeDef */
#define TX_STAT_BASE        (TX_DESC_BASE + NUM_TX_FRAG*(2*4))  /* =0x7FE00040, 2 * uint32_t, see TX_DESC_TypeDef */
#define ETH_BUF_BASE        (TX_STAT_BASE + NUM_TX_FRAG*(1*4))  /* =0x7FE00048, 1 * uint32_t, see TX_STAT_TypeDef */

/* RX and TX descriptor and status definitions. */
#define RX_DESC_PACKET(i)   (*(unsigned int *)(RX_DESC_BASE   + 8*i)) /* =0x7FE00000, =0x7FE00008, =0x7FE00010 */    
#define RX_DESC_CTRL(i)     (*(unsigned int *)(RX_DESC_BASE+4 + 8*i)) /* =0x7FE00004, =0x7FE0000C, =0x7FE00014 */
#define RX_STAT_INFO(i)     (*(unsigned int *)(RX_STAT_BASE   + 8*i)) /* =0x7FE00018, =0x7FE00020, =0x7FE00028 */
#define RX_STAT_HASHCRC(i)  (*(unsigned int *)(RX_STAT_BASE+4 + 8*i)) /* =0x7FE0001C, =0x7FE00024, =0x7FE0002C */
#define TX_DESC_PACKET(i)   (*(unsigned int *)(TX_DESC_BASE   + 8*i)) /* =0x7FE00030, =0x7FE00038              */
#define TX_DESC_CTRL(i)     (*(unsigned int *)(TX_DESC_BASE+4 + 8*i)) /* =0x7FE00034, =0x7FE0003C              */
#define TX_STAT_INFO(i)     (*(unsigned int *)(TX_STAT_BASE   + 4*i)) /* =0x7FE00040, =0x7FE00044              */
#define ETH_BUF(i)          ( ETH_BUF_BASE + ETH_FRAG_SIZE*i )    /* =0x7FE00048, =0x7FE00648, =0x7FE00C48 */    
#define ETH_NUM_BUFFERS        ( NUM_TX_FRAG + NUM_RX_FRAG + 1 ) /* There are in fact 2 more buffers than descriptors as the two Tx descriptors use the same buffer to speed up the uip Tx. */

.......................
void vSendEMACTxData( unsigned short usTxDataLen ){
unsigned long ulAttempts = 0UL;

    /* Check to see if the Tx descriptor is free, indicated by its buffer being    NULL. */
    while( TX_DESC_PACKET( emacTX_DESC_INDEX ) != ( unsigned long ) NULL )    {

        /* Wait for the Tx descriptor to become available. */
        vTaskDelay( emacBUFFER_WAIT_DELAY );
        ulAttempts++;
        if( ulAttempts > emacBUFFER_WAIT_ATTEMPTS )    {
            /* Something has gone wrong as the Tx descriptor is still in use.
            Clear it down manually, the data it was sending will probably be
            lost. */
            prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) );
            break;
        }
    }

    /* Setup the Tx descriptor for transmission.  Remember the length of the data being sent so the second descriptor can be used to send it again from within the ISR. */
    usSendLen = usTxDataLen - 1;
    TX_DESC_PACKET( emacTX_DESC_INDEX ) = ( unsigned long ) uip_buf;
    TX_DESC_CTRL( emacTX_DESC_INDEX ) = ( usTxDataLen | TCTRL_LAST | TCTRL_INT );
    EMAC->TxProduceIndex = ( emacTX_DESC_INDEX + 1 );

    /* uip_buf is being sent by the Tx descriptor.  Allocate a new buffer. */
    uip_buf = prvGetNextBuffer();
}

 

и само прерывание

 

__arm void vEMAC_ISR(){
unsigned long ulStatus;
long lHigherPriorityTaskWoken = pdFALSE;

    ulStatus = EMAC->IntStatus;

    /* Clear the interrupt. */
    EMAC->IntClear = ulStatus;

        if (ulStatus & INT_TX_ERR){
          LEDSOn(_VD1);
          
        };  
            
    if (ulStatus & INT_RX_DONE){
      /* Ensure the uIP task is not blocked as data has arrived. */
      xSemaphoreGiveFromISR(xEMACSemaphore, &lHigherPriorityTaskWoken);
    };

    if (ulStatus & INT_TX_DONE){
        if (usSendLen > 0){
          /* Send the data again, using the second descriptor.  As there are only two descriptors the index is set back to 0. */
          TX_DESC_PACKET( ( emacTX_DESC_INDEX + 1 ) ) = TX_DESC_PACKET( emacTX_DESC_INDEX );
          TX_DESC_CTRL( ( emacTX_DESC_INDEX + 1 ) ) = ( usSendLen | TCTRL_LAST | TCTRL_INT );
          EMAC->TxProduceIndex = ( emacTX_DESC_INDEX );

          /* This is the second Tx so set usSendLen to 0 to indicate that the Tx descriptors will be free again. */
          usSendLen = 0UL;
        } else {
          /* The Tx buffer is no longer required. */
          prvReturnBuffer( ( unsigned char * ) TX_DESC_PACKET( emacTX_DESC_INDEX ) );
                  TX_DESC_PACKET( emacTX_DESC_INDEX ) = (unsigned long)NULL;
        };
    };

    portEND_SWITCHING_ISR( lHigherPriorityTaskWoken );

  VICADDRESS = 0;
}

 

При вызове vSendEMACTxData в драйвере запоминается глобальная переменная usSendLen, затем после EMAC->TxProduceIndex = ( emacTX_DESC_INDEX + 1 ); вызывается прерывание с выставленным битом INT_TX_DONE в статусе. И вот здесь непонятно, почему так делается внутри "if". Ведь бит INT_TX_DONE означает, что уже все передано, но почему автор драйвера снова копирует эти же данные в следующий дескриптор и снова их передает? Ладно,если бы проверялся бит,отвечающий за ошибки передачи, и затем снова пакет бы передался заново, но тут получается так, что пакет передается повторно при каждой новой передаче.

Не понимаю смысла этой глобальной переменной usSendLen. Она больше нигде не используется в драйвере. Может кто разъяснит?

Изменено пользователем M0HAX

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Тоже интересует этот вопрос. Все пакеты дублируются с маленькой паузой, благо отбраковываются принимающей стороной. Удалось разобраться зачем так сделано или исправить?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...