M0HAX 0 22 октября, 2015 Опубликовано 22 октября, 2015 (изменено) · Жалоба Здравствуйте! Из демопакета 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. Она больше нигде не используется в драйвере. Может кто разъяснит? Изменено 22 октября, 2015 пользователем M0HAX Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Yogen 0 9 сентября, 2016 Опубликовано 9 сентября, 2016 · Жалоба Тоже интересует этот вопрос. Все пакеты дублируются с маленькой паузой, благо отбраковываются принимающей стороной. Удалось разобраться зачем так сделано или исправить? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться