Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ethernet и STM32F407
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
isz
Добрый день.
Сломал голову на проблеме при отправке 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(&eth_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(&eth_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();
  }
}
isz
Отвечаю сам себе.
Причина банальна - невнимательность. Не перевел выводы в самый быстрый режим.
Это строчка все исправила:
Код
EthPins::SetSpeed(EthPins::Speed::Fastest);
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.