H743 网络问题

2019-07-20 04:07发布

小弟最近在调试 H743 的网络,遇到了一些问题。
程序是在官方例程上改的,
现象是 ,
一、开机复位,开始 ping 是好的 <1ms,大概过 200包左右,就会延迟很高,或者ping 不通。但是有时候一直都是好的。
二、 外面发进来的数据可以进中断,但是接到的数据是之前发的,比如我发五个ping 包,每个包都有一个编码,收到和发送我都打印出这个编码。当我发完第五个时候 ,才显示收到第三个,发送第三个包。

下面是网络相关的 代码

MPU 部分

static void MPU_Config(void)
{
  MPU_Region_InitTypeDef MPU_InitStruct;

  /* Disable the MPU */
  HAL_MPU_Disable();

  /* Configure the MPU attributes as Device not cacheable
     for ETH DMA descriptors */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;                      //区域使能/禁止
  MPU_InitStruct.BaseAddress = 0x30040000;                        //配置区域基地址
  MPU_InitStruct.Size = MPU_REGION_SIZE_256B;                     //区域容量
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;       //设置访问权限
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;            //禁止/允许缓冲
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;          //禁止/允许缓存
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;          //禁止/允许共享
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;                     //区域编号
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;                   //类型扩展级别
  MPU_InitStruct.SubRegionDisable = 0x00;                         //子 region 除能位段设置
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;     //允许/禁止取指

  HAL_MPU_ConfigRegion(&MPU_InitStruct);

  /* Configure the MPU attributes as Cacheable write through */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;                      //区域使能/禁止
  MPU_InitStruct.BaseAddress = 0x30020000;                        //配置区域基地址
  MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;                    //区域容量
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;       //设置访问权限
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;        //禁止/允许缓冲
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;              //禁止/允许缓存
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;          //禁止/允许共享
  MPU_InitStruct.Number = MPU_REGION_NUMBER1;                     //区域编号
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;                   //类型扩展级别
  MPU_InitStruct.SubRegionDisable = 0x00;                         //子 region 除能位段设置
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;     //允许/禁止取指

  HAL_MPU_ConfigRegion(&MPU_InitStruct);

  /* Enable the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

时钟部分
void  BSP_ClkInit (void)
{
    RCC_ClkInitTypeDef  RCC_ClkInit;
    RCC_OscInitTypeDef  RCC_OscInit;
    RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

    PWR->CR3 &= ~PWR_CR3_SCUEN;                                 /* Supply configuration updated locked.                 */

    __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);  /* See Note 2.                                      */

    while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {
        ;
    }
    /* Enable D2 domain SRAM3 Clock (0x30040000 AXI)*/
    __HAL_RCC_D2SRAM3_CLK_ENABLE();
    /* Enable D2 domain SRAM2 Clock (0x30020000 AXI)*/
    __HAL_RCC_D2SRAM2_CLK_ENABLE();
                                                                /* Enable HSE Osc and activate PLL with HSE as source   */
    RCC_OscInit.OscillatorType = RCC_OSCILLATORTYPE_HSE;        /* HSE = 8 MHz                                          */
    RCC_OscInit.HSEState       = RCC_HSE_BYPASS;
    RCC_OscInit.HSIState       = RCC_HSI_OFF;
    RCC_OscInit.CSIState       = RCC_CSI_OFF;
    RCC_OscInit.PLL.PLLState   = RCC_PLL_ON;
    RCC_OscInit.PLL.PLLSource  = RCC_PLLSOURCE_HSE;

    RCC_OscInit.PLL.PLLM       = 4u;                            /* f(REF_CK)    = HSE / PLLM          = 2MHz            */
    RCC_OscInit.PLL.PLLN       = 400u;                          /* f(VCO clock) = f(REF_CK) * PLLN    = 800MHz          */
    RCC_OscInit.PLL.PLLP       = 2u;                            /* PLL(P CLK)   = f(VCO clock) / PLLR = 400MHz          */
    RCC_OscInit.PLL.PLLR       = 2u;                            /* PLL(R CLK)   = f(VCO clock) / PLLR = 400MHz          */
    RCC_OscInit.PLL.PLLQ       = 4u;                            /* PLL(Q CLK)   = f(VCO clock) / PLLQ = 200MHz          */

    RCC_OscInit.PLL.PLLVCOSEL  = RCC_PLL1VCOWIDE;
    RCC_OscInit.PLL.PLLRGE     = RCC_PLL1VCIRANGE_2;

    if (HAL_RCC_OscConfig(&RCC_OscInit) != HAL_OK) {
        while(1u);                                              /* STOP if error                                        */
    }

                                                                /* ----- CFG SYSCLK SOURCE AND BUS CLOCK DIVIDERS ----- */
    RCC_ClkInit.ClockType      = (RCC_CLOCKTYPE_SYSCLK   |
                                  RCC_CLOCKTYPE_HCLK     |
                                  RCC_CLOCKTYPE_D1PCLK1  |
                                  RCC_CLOCKTYPE_PCLK1    |
                                  RCC_CLOCKTYPE_PCLK2    |
                                  RCC_CLOCKTYPE_D3PCLK1);

    RCC_ClkInit.SYSCLKSource   = RCC_SYSCLKSOURCE_PLLCLK;       /* Select PLL as system clock source.                   */
    RCC_ClkInit.SYSCLKDivider  = RCC_SYSCLK_DIV1;               /* SYSCLK  = PLL(P CLK) = 400MHz                        */
    RCC_ClkInit.AHBCLKDivider  = RCC_HCLK_DIV2;                 /* HCLK    = AHBxCLK = SYSCLK / AHBPRES(2) = 200MHz.    */
    RCC_ClkInit.APB3CLKDivider = RCC_APB3_DIV2;                 /* APB3CLK = AHB3CLK / APB3DIV(2)          = 100MHz.    */
    RCC_ClkInit.APB1CLKDivider = RCC_APB1_DIV2;                 /* APB1CLK = AHB1CLK / APB1DIV(2)          = 100MHz.    */
    RCC_ClkInit.APB2CLKDivider = RCC_APB2_DIV2;                 /* APB2CLK = AHB2CLK / APB2DIV(2)          = 100MHz.    */
    RCC_ClkInit.APB4CLKDivider = RCC_APB4_DIV2;                 /* APB2CLK = AHB4CLK / APB4DIV(2)          = 100MHz.    */

    if (HAL_RCC_ClockConfig(&RCC_ClkInit, FLASH_LATENCY_4) != HAL_OK) {
        while(1u);                                              /* STOP if error                                        */
    }
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_USART3;
    PeriphClkInitStruct.Usart234578ClockSelection = RCC_USART234578CLKSOURCE_D2PCLK1;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
        while(1u);                                              /* STOP if error                                        */
    }
    __HAL_RCC_CSI_ENABLE();                                     /* activate CSI clk mondatory for I/O Compensation Cell */
    __HAL_RCC_SYSCFG_CLK_ENABLE();                              /* Enable SYSCFG clk mondatory for I/O Compensation Cell*/
    HAL_EnableCompensationCell();                               /* Enables the I/O Compensation Cell                    */
}

描述符
#pragma location=0x30040000
ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30040060
ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */
#pragma location=0x30040200
uint8_t Rx_Buff[ETH_RX_DESC_CNT][ETH_RX_BUFFER_SIZE]; /* Ethernet Receive Buffers */



发送函数

int8_t ETH_SendTxPkt(uint8_t *buffer, uint32_t len)
{
  int8_t errval = HAL_OK;
  uint32_t framelen = 0;
  ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];

  memset(Txbuffer, 0 , ETH_TX_DESC_CNT * sizeof(ETH_BufferTypeDef));

  Txbuffer[0].buffer  = buffer;
  Txbuffer[0].len     = len;
  Txbuffer[0].next    = NULL;

  framelen           += len;

  TxConfig.Length     = framelen;
  TxConfig.TxBuffer   = Txbuffer;

  HAL_ETH_Transmit(&EthHandle, &TxConfig, 0);

  return errval;
}

接收函数

/**
  * @brief  Ethernet Rx Transfer completed callback
  * @param  heth: ETH handle
  * @retval None
  */
void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
  CPU_INT08U err;
  rxInts++;
  err = OSSemPost(RxPktSemaphore);

  if (err != OS_ERR_NONE)
  {
    printf("Post RxPkt Semaphore Error ! ");
  }
}




void  EthifTask (void *p_arg)
{
  (void)p_arg;
  ETH_BufferTypeDef RxBuff;
  uint32_t framelength = 0;
  CPU_INT08U err;

  for (;;)
  {
    OSSemPend(RxPktSemaphore, 0, &err);
    if ((err != OS_NONE_ERR) && (err != OS_SEM_TIMEOUT))
      dtrap();

    if (HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff) == HAL_OK)
    {
      HAL_ETH_GetRxDataLength(&EthHandle, &framelength);

      /* Invalidate data cache for ETH Rx Buffers */
      SCB_InvalidateDCache_by_Addr((uint32_t *)Rx_Buff, (ETH_RX_DESC_CNT * ETH_RX_BUFFER_SIZE));

      if (current_pbuf_idx < (ETH_RX_DESC_CNT - 1))
      {
        current_pbuf_idx++;
      }
      else
      {
        current_pbuf_idx = 0;
      }
    }

#ifdef ALT_INICHE
    input_ippkt(RxBuff.buffer, framelength);
#endif
    /* Build Rx descriptor to be ready for next data reception */
    HAL_ETH_BuildRxDescriptors(&EthHandle);
  }
}



网络初始化

void ENET_Configuration(void)
{
  uint32_t idx, duplex, speed = 0;
  int32_t PHYLinkState;
  ETH_MACConfigTypeDef MACConf;

#if OS_TASK_NAME_EN > 0u
    CPU_INT08U  os_err;
#endif

#ifdef ALT_INICHE
  NET ifp;
  ifp = &netstatic[ifacess];
#endif

  EthHandle.Instance = ETH;  
  EthHandle.Init.MACAddr = (uint8_t *)mac_addr;
  EthHandle.Init.MediaInterface = HAL_ETH_RMII_MODE;
  EthHandle.Init.RxDesc = DMARxDscrTab;
  EthHandle.Init.TxDesc = DMATxDscrTab;
  EthHandle.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;

  /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
  HAL_ETH_Init(&EthHandle);

  for(idx = 0; idx < ETH_RX_DESC_CNT; idx ++)
  {
    HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
  }

  memset(&TxConfig, 0 , sizeof(ETH_TxPacketConfig));  
  TxConfig.Attributes = ETH_TX_PACKETS_FEATURES_CSUM | ETH_TX_PACKETS_FEATURES_CRCPAD;
  TxConfig.ChecksumCtrl = ETH_CHECKSUM_IPHDR_PAYLOAD_INSERT_PHDR_CALC;
  TxConfig.CRCPadCtrl = ETH_CRC_PAD_INSERT;
//==============================================================================================================================
  RxPktSemaphore = OSSemCreate(0);
  OSEventNameSet(RxPktSemaphore,  (INT8U *)(void *)RxPktSemName,   &os_err);
  if (os_err != OS_NONE_ERR)
  {
    /* All other errors are fatal */
    printf("Task Name Set error /(RTOS error code:%d/) on %s ", os_err, (INT8U *)RxPktSemName);
    panic("Task Name Set error");
  }
//==============================================================================================================================
  os_err = OSTaskCreateExt( EthifTask,                               /* Create the Ethif task                              */
                            0,
                            &EthifTaskStk[APP_CFG_ETHIF_TASK_STK_SIZE - 1u],
                            APP_CFG_ETHIF_TASK_PRIO,
                            APP_CFG_ETHIF_TASK_PRIO,
                            &EthifTaskStk[0u],
                            APP_CFG_ETHIF_TASK_STK_SIZE,
                            0u,
                            (OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
  if (os_err != OS_NONE_ERR)
  {
    /* All other errors are fatal */
    printf("Task Name Set error /(RTOS error code:%d/) on %s ", os_err, EthifTaskName);
    panic("Task Name Set error");
  }

#if OS_TASK_NAME_EN > 0u
  OSTaskNameSet(         APP_CFG_ETHIF_TASK_PRIO,
                (INT8U *)EthifTaskName,
                         &os_err);
  if (os_err != OS_NONE_ERR)
  {
    /* All other errors are fatal */
    printf("Task Name Set error /(RTOS error code:%d/) on %s ", os_err, EthifTaskName);
    panic("Task Name Set error");
  }
#endif
  printf("Created "%s" task (Prio: %d) ", (char *)EthifTaskName, APP_CFG_ETHIF_TASK_PRIO);
//==============================================================================================================================
#if ETHLINK > 0
  os_err = OSTaskCreateExt( EthLinkTask,                               /* Create the EthLink task                              */
                            0,
                            &EthLinkTaskStk[APP_CFG_ETHLINK_TASK_STK_SIZE - 1u],
                            APP_CFG_ETHLINK_TASK_PRIO,
                            APP_CFG_ETHLINK_TASK_PRIO,
                            &EthLinkTaskStk[0u],
                            APP_CFG_ETHLINK_TASK_STK_SIZE,
                            0u,
                            (OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
  if (os_err != OS_NONE_ERR)
  {
    /* All other errors are fatal */
    printf("Task Name Set error /(RTOS error code:%d/) on %s ", os_err, EthLinkTaskName);
    panic("Task Name Set error");
  }

#if OS_TASK_NAME_EN > 0u
  OSTaskNameSet(         APP_CFG_ETHLINK_TASK_PRIO,
                (INT8U *)EthLinkTaskName,
                         &os_err);
  if (os_err != OS_NONE_ERR)
  {
    /* All other errors are fatal */
    printf("Task Name Set error /(RTOS error code:%d/) on %s ", os_err, EthLinkTaskName);
    panic("Task Name Set error");
  }
#endif
  printf("Created "%s" task (Prio: %d) ", (char *)EthLinkTaskName, APP_CFG_ETHLINK_TASK_PRIO);  
#endif
//==============================================================================================================================

  /* Set PHY IO functions */
  LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);

  /* Initialize the LAN8742 ETH PHY */
  LAN8742_Init(&LAN8742);

  PHYLinkState = LAN8742_GetLinkState(&LAN8742);

  /* Get link state */  
  if(PHYLinkState <= LAN8742_STATUS_LINK_DOWN)
  {
    netif_is_link_up = 0;
#ifdef ALT_INICHE
    ifp->n_mib->ifAdminStatus = NI_DOWN; /* status = down */
    ifp->n_mib->ifOperStatus = NI_DOWN;  /* status = down */
    ifp->n_mib->ifLastChange = cticks * (100 / TPS);
#endif
    printf("Init ENET Close ");
  }
  else
  {
    switch (PHYLinkState)
    {
    case LAN8742_STATUS_100MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;
    case LAN8742_STATUS_100MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;
    case LAN8742_STATUS_10MBITS_FULLDUPLEX:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      break;
    case LAN8742_STATUS_10MBITS_HALFDUPLEX:
      duplex = ETH_HALFDUPLEX_MODE;
      speed = ETH_SPEED_10M;
      break;
    default:
      duplex = ETH_FULLDUPLEX_MODE;
      speed = ETH_SPEED_100M;
      break;      
    }

    /* Get MAC Config MAC */
    HAL_ETH_GetMACConfig(&EthHandle, &MACConf);
    MACConf.DuplexMode = duplex;
    MACConf.Speed = speed;
    HAL_ETH_SetMACConfig(&EthHandle, &MACConf);
    HAL_ETH_Start_IT(&EthHandle);
    netif_is_link_up = 1;
#ifdef ALT_INICHE
    ifp->n_mib->ifAdminStatus = NI_UP; /* status = UP */
    ifp->n_mib->ifOperStatus = NI_UP;
    ifp->n_mib->ifLastChange = cticks * (100/TPS);
#endif
    printf("Init ENET Open ");
  }
}



跟官方协议栈不同的地方,官方协议栈,网络 HEAP 使用的是 SRAM3 就是发送函数传入的地址在 SDRAM 3 我的在 SDRAM2,

原子哥在教程上说
注意! 对于 H7芯片 而言, 而言, DMARxDscrTab和DMATxDscrTab的内存一定要放到 SRAM3区域否则网络会出问题 !
注意 ,如果 使用 H7芯片 的话 Rx_Buff和 Tx_Buff的内存也一定要放到 SRAM3 中否则网络也 会出问题的
但是我看例程 TXBUF 也没在 SRAM3 区域,我也试过拷贝到 SRAM3区域,但是没用,现在是 接收总是慢两拍。这是为什么?


对于我发五个包,发完最后一个时候才接收到第三个包。CPU 把他放在了什么地方?抓包显示pin g 测试软件确实发出去了












友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。