小弟最近在调试 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 测试软件确实发出去了
一周热门 更多>