isz 0 18 декабря, 2016 Опубликовано 18 декабря, 2016 (изменено) · Жалоба Добрый день. Сломал голову на проблеме при отправке ethernet фреймов. Работа ведется на отладочной плате и код из CubeMX на ней работает. Прием в моем коде тоже корректно работает. Для проверки сократил код до минимума. Вот его кусок: uint8_t testData[128]; uint8_t dest_mac[]={0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; uint8_t my_mac[]={0x00,0x80,0xE1,0x00,0x57,0x23}; int main () { InitHw(); while (ethernetif_init(my_mac)!=ETH_SUCCESS); for(uint8_t a=0; a< 128; a++) testData[a]=a; memcpy(testData,dest_mac,6); memcpy(testData+6,my_mac,6); for (;;) { ethernetif_output(testData, 128); volatile uint32_t i; for(i=0; i<10000000;i++); } } Функции ethernetif_init и ethernetif_output - это переделанные функции из апнота AN3966 (LwIP TCP/IP stack demonstration for STM32F4x7 microcontrollers) с сайта ST. Библиотека STM32F4x7_ETH_Driver от туда же без переделок. На компе в WireShark вижу следующее: Некоторые ошибки пометил. Почему так получается никак не могу понять. Код практически идентичен различным примерам. Где закралась ошибка не вижу своим замыленым взглядом. Прослеживал отладчиком до самой отправки. Данные целые и в буфере testData и потом в буферах Tx_Buff из библиотеки. Вот код функций uint32_t ethernetif_init(uint8_t* mac) { Clock::EthMacClock::Enable(); Clock::EthMacTxClock::Enable(); Clock::EthMacRxClock::Enable(); Clock::SyscfgClock::Enable(); // Select MII or RMII uint32_t temp = (SYSCFG->PMC&(~SYSCFG_PMC_MII_RMII_SEL))|SYSCFG_PMC_MII_RMII_SEL; SYSCFG->PMC|= temp; EthPins::SetConfiguration(EthPins::Configuration::AltFunc); EthPins::AltFuncNumber(11); // Enable ethernet interrupts NVIC_EnableIRQ(ETH_IRQn); return low_level_init(mac); } static uint32_t low_level_init(uint8_t* mac) { int i; ETH_SoftwareReset(); ETH_StructInit(ð_init); eth_init.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable; // ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Disable; // ETH_InitStructure.ETH_Speed = ETH_Speed_10M; // ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex; eth_init.ETH_LoopbackMode = ETH_LoopbackMode_Disable; eth_init.ETH_RetryTransmission = ETH_RetryTransmission_Disable; eth_init.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable; eth_init.ETH_ReceiveAll = ETH_ReceiveAll_Disable; eth_init.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable; eth_init.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable; eth_init.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect; eth_init.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect; #ifdef CHECKSUM_BY_HARDWARE eth_init.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable; #endif /*------------------------ DMA -----------------------------------*/ /* When we use the Checksum offload feature, we need to enable the Store and Forward mode: the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum, if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */ eth_init.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable; eth_init.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable; eth_init.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable; eth_init.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable; eth_init.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable; eth_init.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable; eth_init.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable; eth_init.ETH_FixedBurst = ETH_FixedBurst_Enable; eth_init.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat; eth_init.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat; eth_init.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1; while (ETH_GetSoftwareResetStatus() == SET); if (ETH_Init(ð_init, 1)==ETH_ERROR)return ETH_ERROR; /* initialize MAC address in ethernet MAC */ ETH_MACAddressConfig(ETH_MAC_Address0, mac); /* Initialize Tx Descriptors list: Chain Mode */ ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB); /* Initialize Rx Descriptors list: Chain Mode */ ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB); for(i=0; i<ETH_RXBUFNB; i++) { ETH_DMARxDescReceiveITConfig(&DMARxDscrTab[i], ENABLE); } #ifdef CHECKSUM_BY_HARDWARE /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */ for(i=0; i<ETH_TXBUFNB; i++) { ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull); } #endif // /* Note: TCP, UDP, ICMP checksum checking for received frame are enabled in DMA config */ /* Enable the Ethernet Rx Interrupt */ ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE); /* Enable MAC and DMA transmission and reception */ ETH_Start(); return ETH_SUCCESS; } void ethernetif_output(uint8_t* buf, uint16_t len ) { uint8_t *buffer; __IO ETH_DMADESCTypeDef *DmaTxDesc; uint16_t framelength = 0; uint32_t byteslefttocopy = 0; uint32_t payloadoffset = 0; // if (txMutex.try_lock(netifGUARD_BLOCK_TIME)) { DmaTxDesc = DMATxDescToSet; buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); // bufferoffset = 0; if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET) { goto error; } /* Get bytes in current lwIP buffer */ byteslefttocopy = len; payloadoffset = 0; /* Check if the length of data to copy is bigger than Tx buffer size*/ while( byteslefttocopy > ETH_TX_BUF_SIZE ) { /* Copy data to Tx buffer*/ memcpy(buffer , buf + payloadoffset, (ETH_TX_BUF_SIZE ) ); /* Point to next descriptor */ DmaTxDesc = (ETH_DMADESCTypeDef *)(DmaTxDesc->Buffer2NextDescAddr); /* Check if the buffer is available */ if((DmaTxDesc->Status & ETH_DMATxDesc_OWN) != (uint32_t)RESET) { goto error; } buffer = (uint8_t *)(DmaTxDesc->Buffer1Addr); byteslefttocopy = byteslefttocopy - ETH_TX_BUF_SIZE; payloadoffset = payloadoffset + ETH_TX_BUF_SIZE; framelength = framelength + ETH_TX_BUF_SIZE; } /* Copy the remaining bytes */ memcpy( buffer , buf + payloadoffset, byteslefttocopy ); // bufferoffset = bufferoffset + byteslefttocopy; framelength = framelength + byteslefttocopy; /* Prepare transmit descriptors to give to DMA*/ ETH_Prepare_Transmit_Descriptors(framelength); /* Give semaphore and exit */ error: // txMutex.unlock(); } } Изменено 18 декабря, 2016 пользователем isz Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
isz 0 18 декабря, 2016 Опубликовано 18 декабря, 2016 · Жалоба Отвечаю сам себе. Причина банальна - невнимательность. Не перевел выводы в самый быстрый режим. Это строчка все исправила: EthPins::SetSpeed(EthPins::Speed::Fastest); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться