STM32H755+CubeMX6.10.0+LWIP以太网通信+AC6编译器

话不多说,开搞。

        首先是CubeMX配置,我们打开软件后,选择自己所需要的单片机型号(我的STM32H755ZIT6),我用的是官方开发板(NUCLEO-H755ZI-Q),然后就可以开始我们的配置了,如下图所示,针对H7系列多了一个L1 cache ,故我们需要先配置下MPU:

详解:1,使能MPU,使能ICache   DCache;

           2,设置地址为0x30000000,即D2域的SRAM1的起始地址;

           3,访问权限,全部允许  ALL ACCESS PERMITTED

            4,MPU性能配置为 :

                TEX:0;

                memory type:device;

                cacheable :disable;

                bufferable:enable;

                sharable:enable;

这样可以充分发挥缓存的性能,这里我也不是特别明白,大家也可以根据自己的需要配置,如下图:

然后我们需要配置下时钟晶振,由于我的开发板上没有外部晶振,所以我选择了内部高速时钟HSI:

详解:1,针对我的H755开发板,这里必须选择SMPS直接供电(否则会导致单片机自锁),大家可以根据自己的硬件电路设计选择LDO供电,不过还是推荐大家设计成内部SMPS供电方式,可以大大提高性能;

            2,供电范围选择 scale1,这样可以配置更高的时钟频率,我这里配置为400MHz,如下图:

然后就可以配置我们的以太网了,如下图:

详解:RX描述符地址我们配置为0x300000000,TX描述符地址我们配置为0x30000080,描述符长度为4,RX缓冲区长度为1524;

这里需要特别注意的是:对于CubeMX6.10.0版本,这里没有了RX接收缓冲区地址的配置,而且在代码中也未找到对该缓冲区地址的定义,所以可能是系统自动分配的,如果我们采用默认的RAM地址0x20000000,可能会把RX接收缓冲区的地址分配到0x20000000位置下,然而这个空间属于DI域,ETH是无法访问的,所以在生成代码后我们需要修改一下RAM的地址,如下图(选中RAM2改为0x24000000,SIZE改为0x80000):

然后选择linker选项卡,勾选use memory layout from target dialog,大家也可以尝试下修改sct文件,配置下RAM的地址:

上面两张图片只针对M7核,cortexM4可以不做修改。

由于我们时钟频率配置为400MHz,所以对于ETH的通信管脚,我们都配置为very high,否则可能会导致ping不通。

接下来我们配置LWIP,如下图:

详解:

这里我们选择了静态IP的方式,需要保证单片机和自己的电脑配置在一个网段内,其他保持默认即可;

然后是key option 选项卡,如下图:

详解:

        这里MEM_SIZE我们配置为10k大小

        LWIP_RAM_HEAP_POINTER地址配置为0x30002000

这里也可以根据自己的需要来配置SIZE大小和RAM_HEAP的地址

接下是我们使能LWIP_NETIF_STATUS_CALLBACK回调函数:

然后配置下PHY芯片:

配置一个LED灯方便我们调试:

打开project manager 选项卡,把M7和的堆栈大小改一下:

现在点击generate code  来生成代码,生成代码后我们还需要做一些必要的修改:(只针对AC6编译器)

首先点击魔术棒,选择编译器为AC6,修改RAM地址,上文已讲过;

然后打开cc.h文件,修改下列两行代码(大概在45,46行),屏蔽掉do后面的语句(大概82行,这样就不需要勾选微库了)

#define LWIP_TIMEVAL_PRIVATE 1
//#include <sys/time.h>

#define LWIP_PLATFORM_ASSERT(x) //do {printf("Assertion \"%s\" failed at line %d in %s\n", \
                                     x, __LINE__, __FILE__); } while(0)

打开ethernetif.c文件,修改编译部分的代码:

#if defined ( __ICCARM__ ) /*!< IAR Compiler */

#pragma location=0x30000000
ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
#pragma location=0x30000080
ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */

#elif defined ( __CC_ARM )  /* MDK ARM Compiler */

__attribute__((at(0x30000000))) ETH_DMADescTypeDef  DMARxDscrTab[ETH_RX_DESC_CNT]; /* Ethernet Rx DMA Descriptors */
__attribute__((at(0x30000080))) ETH_DMADescTypeDef  DMATxDscrTab[ETH_TX_DESC_CNT]; /* Ethernet Tx DMA Descriptors */

#elif defined ( __GNUC__ ) /* GNU Compiler */

//ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
//ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection")));   /* Ethernet Tx DMA Descriptors */
#if !((__ARMCC_VERSION >= 6010050))
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".RxDecripSection"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".TxDecripSection")));   /* Ethernet Tx DMA Descriptors */
#else
ETH_DMADescTypeDef DMARxDscrTab[ETH_RX_DESC_CNT] __attribute__((section(".bss.ARM.__at_0x30000000"))); /* Ethernet Rx DMA Descriptors */
ETH_DMADescTypeDef DMATxDscrTab[ETH_TX_DESC_CNT] __attribute__((section(".bss.ARM.__at_0x30000080")));   /* Ethernet Tx DMA Descriptors */
#endif
#endif

在low_level_output函数中发送之前添加SCB_CleanInvalidateDCache();函数:

static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
  uint32_t i = 0U;
  struct pbuf *q = NULL;
  err_t errval = ERR_OK;
  ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT] = {0};

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

  for(q = p; q != NULL; q = q->next)
  {
    if(i >= ETH_TX_DESC_CNT)
      return ERR_IF;

    Txbuffer[i].buffer = q->payload;
    Txbuffer[i].len = q->len;

    if(i>0)
    {
      Txbuffer[i-1].next = &Txbuffer[i];
    }

    if(q->next == NULL)
    {
      Txbuffer[i].next = NULL;
    }

    i++;
  }

  TxConfig.Length = p->tot_len;
  TxConfig.TxBuffer = Txbuffer;
  TxConfig.pData = p;
	SCB_CleanInvalidateDCache();
  HAL_ETH_Transmit(&heth, &TxConfig, ETH_DMA_TRANSMIT_TIMEOUT);

  return errval;
}

由于我的开发板PHY芯片的复位信号和单片机的复位信号是连接在一起的,所以在main函数中LWIP初始化之前我们加一段100ms的延时,等PHY复位稳定后,再进行PHY芯片的初始化操作,在while循环中添加下列测试代码:

 while (1)
  {
		MX_LWIP_Process();
		HAL_GPIO_TogglePin(LED3_GPIO_Port,LED3_Pin);
		HAL_Delay(200);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

然后编译下载程序后运行,我们打开cmd命令窗口ping下:

最后,说一下我采用的驱动库版本是STM32Cube FW_H7 V1.11.2,LWIP版本是 V2.1.2,不同的版本库文件可能会有区别,请大家仔细甄别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值