这是一款比较新的Cortex-M7内核的MCU,因为项目原因,需要一款RAM大(1024KB),主频高(480M)的芯片,我司的硬件工程师选择了他。
需要注意的是为什么不使用标准库,而选用大多数嵌入式工程师不是很熟悉的STM32CUBEMX生成的HAL库(完全是因为找不到标准库啊!啊!啊!,当然也有学习新开发工具的想法)
我使用的是STM32CUBEMX_V5.6.1
1.首先选择芯片(STM32H750VB)
2.配置时钟,选择HSE(根据实际PCB选择)
3.配置HAL库时钟,选择TIM1,因为需要上FreeRTOS系统,而系统的节拍器通常会选择系统滴答定时器systick,所以我们这里选择TIM1作为库定时器而不是systick。
4.使能Cache和MPU内存保护单元
因为H7结构体的特殊,LWIP网络需要使用的RAM要MPU保护,并且地址也是定死的0x30040000开始,和F4随意定义不同
具体为何这么设置得去看H750的用户手册
5.PHY芯片设置,PCB选用的是LAN8720A,虽然STM32CUBEMX选用的是LAN8742,但其实并没有什么很大的区别(即使区别不大,CUBEMX直接生成的程序也并不能让你ping通网络,可能是芯片比较新,好多功能没有得到实际验证,具体如何修改,下面会进行详细描述)。
6.FREERTOS系统设置,需要注意的也就只有TOTAL_HEAP_SIZE,你需要根据实际需要设置大小,其他的就是用什么使能什么,譬如:使用信号量的话就使能SEMAPHORE 等等。
7.LWIP设置,主要设置3个地方,注重注意的就是LWIP_NETIF_LINK_CALLBACK需要使能
通用设置很常规,这里我不要DHCP,就除能设置成了静态IP
使能了LINK_CALLBACK之后,就多了一个网线插拔时会进入的回调函数,你就可以在里面处理一些事情,不做也可以,他会自动deinit-ETH
PHY芯片选择LAN8742A
8.随意设置一个运行灯添加在TASK里面,用来查看程序运行状态就结束可以生成程序了。
因为STM32H750是一款很新的芯片,所以会出现,J-LINK和IAR中都没有这款芯片的情况,这个时候就需要更新IDE和J-LIN了,我更新到了IAR8.32和J-LINK6.84。
这里要吐槽的一点是IAR8.32真的是个垃圾,调试的时候,只是把鼠标放在变量名字上都会闪退,更别说在watch中看数组了。
1.因为我task多,MX_LWIP_Init();这个LWIP初始化函数是在任务中,是开启了系统任务调度之后才初始化的,就导致了PHY芯片初始化没有完成的问题。
解决方法:
ethernetif.c中、
static void low_level_init(struct netif *netif)
/* USER CODE BEGIN PHY_PRE_CONFIG */
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_RESET);
HAL_Delay(50);
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_2,GPIO_PIN_SET); //LAN8720A复位
/* USER CODE END PHY_PRE_CONFIG */
/* Set PHY IO functions */
LAN8742_RegisterBusIO(&LAN8742, &LAN8742_IOCtx);
/* Initialize the LAN8742 ETH PHY */
while(LAN8742_Init(&LAN8742) != LAN8742_STATUS_OK) //需要写一个while确保LAN8742_Init成功
;
添加一个复位功能和while等待初始化完成功能。
2.因为硬件上面没有硬件上拉采用的自动协商,所以在软件中也要完成自动协商,在初始化完成后添加
static void low_level_init(struct netif *netif)
/* USER CODE BEGIN PHY_POST_CONFIG */
LAN8742_StartAutoNego(&LAN8742); //启动自动协商
/* USER CODE END PHY_POST_CONFIG */
2.ETH_RX_BUFFER_SIZE的宏定义是 1536UL
而生成代码
heth.Init.RxBuffLen = 1528;
需要改成
heth.Init.RxBuffLen = ETH_RX_BUFFER_SIZE;
3.清除高速Cache
static err_t low_level_output(struct netif *netif, struct pbuf *p)
TxConfig.Length = framelen;
TxConfig.TxBuffer = Txbuffer;
SCB_CleanInvalidateDCache(); //清除Cache缓冲区
HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);
return errval;
static struct pbuf * low_level_input(struct netif *netif)
if (HAL_ETH_GetRxDataBuffer(&heth, &RxBuff) == HAL_OK)
{
SCB_CleanInvalidateDCache(); //清除Cache缓冲区
HAL_ETH_GetRxDataLength(&heth, &framelength);
/* Build Rx descriptor to be ready for next data reception */
HAL_ETH_BuildRxDescriptors(&heth);
SCB_InvalidateDCache_by_Addr((uint32_t *)Rx_Buff, (ETH_RX_DESC_CNT*ETH_RX_BUFFER_SIZE));
#if !defined(DUAL_CORE) || defined(CORE_CM7)
/* Invalidate data cache for ETH Rx Buffers */
SCB_InvalidateDCache_by_Addr((uint32_t *)RxBuff.buffer, framelength);
#endif
custom_pbuf = (struct pbuf_custom*)LWIP_MEMPOOL_ALLOC(RX_POOL);
custom_pbuf->custom_free_function = pbuf_free_custom;
p = pbuf_alloced_custom(PBUF_RAW, framelength, PBUF_REF, custom_pbuf, RxBuff.buffer, ETH_RX_BUFFER_SIZE);
}
4.系统时钟初始化完成后需要初始化SRAM3的时钟
/* USER CODE BEGIN SysInit */
__HAL_RCC_D2SRAM3_CLK_ENABLE(); //启动SRAM3的时钟
/* USER CODE END SysInit */
这样就差不多了,我会把里面的相关资源上传
J-LINK下载
不带FREERTOS的工程下载地址
IAR8.32由于安装包太大,传不上来