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

Ethernet и STM32F407

Добрый день.

Сломал голову на проблеме при отправке 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 вижу следующее:

wireshark.png

Некоторые ошибки пометил. Почему так получается никак не могу понять. Код практически идентичен различным примерам. Где закралась ошибка не вижу своим замыленым взглядом. Прослеживал отладчиком до самой отправки. Данные целые и в буфере 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);

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


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

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

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

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

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

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

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

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

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

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