硬汉嵌入式论坛

 找回密码
 立即注册
查看: 506|回复: 5
收起左侧

[ThreadX全家桶] stm32h723zgt6+threadx+netxduo+dp83848i实现tcp服务器

[复制链接]

6

主题

27

回帖

50

积分

初级会员

积分
50
发表于 2025-3-10 17:15:26 | 显示全部楼层 |阅读模式
写在前面:

这篇文章来自去年某个烂尾的项目,今年因为某种需求又重新捡了起来。


还记得去年被h7+netxduo折磨的死去活来,来论坛一通请教也没ping通,今年硬件朋友突然跟我说mdio没有加上拉,加上试试后一下子就通了

因此来分享下心得。

本工程搭建环境是:stm32cubemx+stm32cubeclt+类vscode编辑器(cursor,trae),stm32 vscode extensions插件,ping通之后写了一个tcp服务器的小示例,可将客户端发来的数据加上时间戳后打包原路发回去。各位可用于h7系列的netxduo模板。
先直接上github链接:
https://github.com/newtonltr/stm32h723zgt6-nx-tx


接下来分享一下移植过程以及要点讲解。



1、mpu和cache的配置
用h7的mpu和cache,就要了解它的内存分布,附上cube生成的ld文件的内存分布:
[C] 纯文本查看 复制代码
MEMORY
{
DTCMRAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
RAM (xrw)      : ORIGIN = 0x24000000, LENGTH = 128K
RAM_D2 (xrw)      : ORIGIN = 0x30000000, LENGTH = 32K
RAM_D3 (xrw)      : ORIGIN = 0x38000000, LENGTH = 16K
ITCMRAM (xrw)      : ORIGIN = 0x00000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
}





众所周知,DMA是不能访问DTCM的,因此以太网相关的DMA描述符以及NetXDuo需要的内存池都不能放在这个区域,为了方便和安全最好将以太网的DMA描述符和内存池放在RAM_D2,RAM和DTCM留给普通程序。

因此我们只需要对0x30000000起始的大小为32k的区域进行mpu配置,分为两个区域进行配置,上图:

1.png

2.png

打开dcache和icache,分别为数据和指令的缓存。

mpu control mode设置为允许特定的程序(即内核)访问后台未被mpu配置的内存,对于stm32来说只要是你存在片内的程序都可以访问,并且在出现故障时禁止mpu功能。

首先是对RAM_D2域的全局配置,打开mpu访问权限,打开指令执行访问权限,关闭共享权限(对于多核系统才有影响,普通stm32的话这里全部关闭就行了打开也没影响),打开cache,关闭缓冲区功能。

然后对以太网的dma描述符区域进行单独配置,为什么大小是256B,这里先放eth的配置:

3.png

可见从0x30000000开始大小为256b的ram空间为以太网dma收发描述符所在区域,为了数据一致性,关闭该区域的cache功能。
生成代码后在程序中的体现为:
[C] 纯文本查看 复制代码
void MPU_Config(void)
{
  MPU_Region_InitTypeDef MPU_InitStruct = {0};

  /* Disables the MPU */
  HAL_MPU_Disable();

  /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER0;
  MPU_InitStruct.BaseAddress = 0x30000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_32KB;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);

  /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Number = MPU_REGION_NUMBER1;
  MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}



可见REGION1对REGION0的前256B大小的ram进行了重新配置,覆盖了REGION0的原配置,其他未重新赋值的成员变量则继承REGION0的数值。


2、其他重要cubemx配置
  • 以太网io口速度必须全部设为very high
  • 配置复位引脚
  • 系统时钟时基使用TIM6,其他也可以,用hal库别用systick
  • 取消生成systick和pend sv中断处理函数,因为后面要使用threadx来接管这些中断


到此已经可以点击生成代码了。


3、移植threadx和netxduo

这里只需要注意[color=rgba(0, 0, 0, 0.75)]threadx中tx_initialize_low_level.S文件的修改,system_clock设为cubemx中配置的频率:
[C] 纯文本查看 复制代码
SYSTEM_CLOCK      =   520000000
SYSTICK_CYCLES    =   ((SYSTEM_CLOCK / 1000) -1)


4、编译完成之后测试网络能否ping通以及能否实现转发的功能

4.png

5.png

The End:
之前一直以为stm32h7一定要在使用以太网时配置cache,今天生成工程时忘了配置mpu,结果发现依然能用,cubemx默认关闭mpu和cache,其实只要确保dma描述符区域不在DTCM并且不被缓存就可以了,当然还是有必要给其他区域打开cache的,毕竟这么好的性能不能浪费

评分

参与人数 1金币 +100 收起 理由
eric2013 + 100 很给力!

查看全部评分

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2025-3-11 08:25:09 | 显示全部楼层
谢谢楼主分享。
回复

使用道具 举报

4

主题

1441

回帖

1453

积分

至尊会员

积分
1453
发表于 2025-3-11 14:10:09 | 显示全部楼层
回复

使用道具 举报

4

主题

20

回帖

32

积分

新手上路

积分
32
发表于 2025-4-9 15:14:52 | 显示全部楼层
请问一下楼主,我使用的芯片是跟你相同的,但是外置phy芯片是用的LAN8720A这款,在编写ETH初始化过程中,一直会进入到软件复位超时错误。具体为下述复位无法正常跳出。
[C] 纯文本查看 复制代码
while (READ_BIT(heth->Instance->DMAMR, ETH_DMAMR_SWR) > 0U)
  {

    if (((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT))
    {
      /* Set Error Code */
      heth->ErrorCode = HAL_ETH_ERROR_TIMEOUT;
      /* Set State as Error */
      heth->gState = HAL_ETH_STATE_ERROR;
      /* Return Error */
      printf("go to this ((HAL_GetTick() - tickstart) > ETH_SWRESET_TIMEOUT)\r\n");
      return HAL_ERROR;
    }
  }

请问这个问题你是否有遇到过?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
115434
QQ
发表于 2025-4-10 10:22:18 | 显示全部楼层
Ainit 发表于 2025-4-9 15:14
请问一下楼主,我使用的芯片是跟你相同的,但是外置phy芯片是用的LAN8720A这款,在编写ETH初始化过程中,一 ...

上电后,等待1秒再操作软件软件复位试试。
回复

使用道具 举报

4

主题

20

回帖

32

积分

新手上路

积分
32
发表于 2025-4-10 10:35:51 | 显示全部楼层
eric2013 发表于 2025-4-10 10:22
上电后,等待1秒再操作软件软件复位试试。

感谢感谢,经过我的测试,确实可以初始化成功eth.也能够读取到phy芯片的型号。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-25 21:42 , Processed in 0.376346 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表