你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】基于RT-Thread在STM32H7上移植LWIP(一)

[复制链接]
STMCU小助手 发布时间:2021-12-25 11:17
一,写在前面" |0 [& M/ I+ l+ e7 @, [
STM32H7目前还是一个比较新的MCU,网上的资料相对于F1 F4系列相对来说就很少了,我自己在移植这个LWIP的时候走了不少弯路,得到了不少人帮助。写这篇文章也是对我自己移植的一个总结,也是希望后来人能少走弯路。
8 I( o* C: ~: E4 t9 w* @) q6 Q4 p这篇文章有由个人编辑并整理,如有错误,欢迎拍砖。
: z6 j/ ]; _4 g- r" r
; l" V* Z- X- h7 ?) |& W二,RT-Thread,STM32H7,LWIP简介
+ @$ h( c. D  I) M! }2 ?- TRT-Thread是一个来自中国的开源物联网操作系统,它提供了非常强的可伸缩能力:从一个可以运行在ARM Cortex-M0芯片上的极小内核,到中等的ARM Cortex-M3/4/7系统,甚至是运行于MIPS32、ARM Cortex-A系列处理器上功能丰富系统。
" }' p: K' Q  y* [0 G* {" F- o. |! ~
8 j" c1 Z& m* O) A4 K( {2 {STM32H7是ST意法半导体Cortex_M系列最高性能处理器。主频高达400M,FLASH高达2Mbytes,SRAM高达1Mbytes,采用六级流水线,自带 指令 和数据 Cache、集成 JPEG编解码器、编解码器、集成 双精度硬件浮点计算单元( DPFPU)和 DSP指令。! ]9 h: t+ m, c, B7 C* m/ o4 F
1 N" w, E/ a& Y! J! l! y; K  u
LWIP是瑞典计算机科学院(SICS)的Adam Dunkels开发的一个小型开源的TCP/IP协议栈。; p% g8 B/ P0 ]! x$ q' e" v& }

) X2 `* l. l# @/ p+ p9 a三,STM32H7的特殊性
9 H  P% R; m. [0 ?9 {8 O2 H这里的特殊性,仅仅只是对比F1 F4系列:
; s- u5 x: \9 j
- d3 n' f$ [) A" ?. |RAM
3 Z7 d$ a1 [# b/ d$ A  yF1 F4系列只有一块RAM,在使用RTOS的时候直接分配给RTOS做堆就可以了。7 }* f+ @) H- y5 r: [# e
H7的RAM构成看下表:# Y) |* d8 m1 n; M' u* A" u: }
20190504165951455.png

6 n' `) s  i: O! ]) \
! ]9 f9 Q( j# N% H2 z6 Q3 V5 VDTCM的速度是400M,但是DMA无法进行访问。" u- x) B6 z5 b3 e2 E/ C/ Y4 M, ~: f
AXI SRAM的速度是200M,DMA可以进行访问。
  C( f, e! ]4 }" C4 ]! p* K5 ?2 mSRAM3是以太网和USB的缓冲区。
5 I# d' L5 z$ C" J1 {9 J. [8 `" E$ V, _6 h, s5 R+ w5 p( |
CACHE9 }+ \% Y* @4 C) }
H7比F1 F4多了一个L1 CACHE一级缓存,这个缓存在为低速存储器带来加速的同时,也为程序带 来了一些问题,其中最为主要的时数据一致性的问题。
7 w! N) L8 d$ \) g$ Y) v1 J: y! R$ K  ?3 j/ Y6 ~
DMA& L, y2 {" ^0 T8 Z9 \5 ~" r5 z
H7的DAM分为DMA1,DAM2,BDMA,MDMA。其中SDIO和ETH的DMA又是独立的,就是说他们有专用的DMA和其他的DAM之间使用不冲突,无须额外使能,只需要开启中断就默认使用DMA模式。' S8 ^5 ~0 p! `0 n3 i7 d, p

2 l. q) i! W: t) [4 P1 k
20190504172355726.png
/ S, |* o2 w8 y8 m/ l

" }+ f1 ?4 d4 Z( k4 R! L四 ,移植前的准备工作
1 X& R3 m: _$ ^8 I( n# j- v确保有一个可以在开发板上能正常运行RT_Thread的工程,目前RT_Thread已经有了正点原子H743的BSP,通过ENV工具使用scons --dist来把这个工程拿出来,复制出dist文件夹下的工程就可以直接使用了;* q& S5 U* Q8 Y" \" Q* `2 i( a, l- a
使用ENV工具,开启软件模拟IIC,因为正点原子的开发板的PHY复位接到了pcf8574的7号引脚,然后生成工程肯定会报错,这个时候从别的BSP目录下拷贝出pcf8574.c pcf8574.h phy_reset.c,放到工程里,然后在rtconfig.h加入以下代码来启用模拟IIC
: K; E8 e+ L) m7 r5 N
  1. #define BSP_USING_I2C2
    # H* ?5 A7 L/ R" R  L

  2. 0 J/ h4 @, N# C
  3. #define BSP_I2C2_SCL_PIN 116
    / `* f( j/ F; Q5 O5 M# {1 m6 V2 W
  4. #define BSP_I2C2_SDA_PIN 117
复制代码

" Q3 w; s0 F+ O( K) i( Z9 ?% x4 Y这里的引脚号由硬件决定,如果不是原子的开发板可以省略这一步( V8 a2 r3 i- K: H" R  P

0 u# @( j" ^/ N% Q/ B因为RT-Thread目录下的STM32BSP是依赖CUBEMX,所以还需要在CUBEMX里面开启ETH的引脚,这个请和自己的板子一致;( {" _1 l3 k: J9 ?4 s! d
+ s3 v* k& W# V4 `* F: m8 n* Q4 `
20190504230500122.png
9 b, a+ F! \  Q8 B1 F/ S- ^
3 t' W4 H; A; f( E! ~4 b$ \
开启RMII模式,注意这里的PC1引脚无法选择成高电平,需要在生成的使msp.c里面自己修改为高电平,并开启中断。
7 k* N$ y# o6 ?" Y7 H
  j: H  A$ X) [# g0 W. r0 w9 Z检查是否开启了I_CACHE和D_CACHE9 T4 D9 Z7 B9 ^7 `+ ~$ f! k- N1 k

: e+ F) m: K' Y% r& @+ J/ ?2 p
20190504230946919.png

' I" k$ w& @4 H6 u& u- u0 }, Q7 e8 ?3 o; @- W, _/ E
这里一定要开启,里面由依赖关系,不然会导致cache无法正确运行。& e9 }4 }' X( d
) a9 D8 R, K* J) z1 o
然后通过CUBEMX生成工程并把时钟初始化部分拷贝出来复制到board.c中
' s# \2 F7 j8 t: Z1 ~8 S/ J7 C6 O2 D* c9 _9 o; ]+ N8 n6 o, f. C+ c
在drv_mpu.c中加入MPU配置4 k/ a+ K# S9 g  C  a5 [
以太网DMA描述符区,只能配置为Strongly - order或者Device。! \% O: i* G* P" M
  1.   MPU_Region_InitTypeDef MPU_InitStruct;
    / t8 Z7 d- `9 I# W; q
  2. : C. ?4 a4 t. d* N
  3.   /* Disable the MPU */
      y: a) X- ?. g" S: B) v' k& D: v0 p
  4.   HAL_MPU_Disable();
    / g& N1 V+ _- w- t- b; o
  5. 9 m5 F6 N' H0 x* }1 ]. J1 o
  6.   /* Configure the MPU attributes as Device not cacheable   ~, R& U8 T, G2 _& t: ~3 J
  7.      for ETH DMA descriptors */& E/ \2 ?- Z" l% b) h( e
  8.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    , t; h& O; u( P9 U  d9 ^. F5 E
  9.   MPU_InitStruct.BaseAddress = 0x30040000;
    + r# u  e% U9 A  E" o- ?
  10.   MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
    0 W& y7 f& y$ x" K% |# k+ [' ~: G
  11.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    / p6 @# l" {$ I  T9 O
  12.   MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
    2 P+ X# w3 ~4 S, a& X1 S
  13.   MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;# V- i5 g# D5 n9 Z
  14.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;9 {4 g6 f! K, p+ T6 o
  15.   MPU_InitStruct.Number = MPU_REGION_NUMBER0;
    & m2 ?% {6 V' D
  16.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;' d: J6 P3 }8 g
  17.   MPU_InitStruct.SubRegionDisable = 0x00;
    1 B5 x# y+ a: ]- `4 n3 O
  18.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
    ( H9 ^1 a  z- e$ K3 x" G6 P1 ?  ~

  19. 1 m  ^0 C: w3 h: ]9 z" V8 |
  20.   HAL_MPU_ConfigRegion(&MPU_InitStruct);, o5 v* u' X& [1 o5 l# U( w  U

  21. : R6 D  s. Y, t# Q9 J
  22.   /* Configure the MPU attributes as Cacheable write through 4 H! x3 ?! a2 W+ @- @3 s0 L) a
  23.      for LwIP RAM heap which contains the Tx buffers */% H: Q4 r- U5 y/ @- U8 Z! {
  24.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;; S- x/ k, i9 q  |1 ?
  25.   MPU_InitStruct.BaseAddress = 0x30044000;
    7 @4 T) x& Z4 z2 b
  26.   MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;6 r+ K8 z$ |9 X+ n8 l7 y2 o
  27.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    : i+ ~6 L8 G2 e' N! {
  28.   MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
    ) ]  K4 A9 ^/ E3 v- u, J+ `  V; d
  29.   MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
    " v. x% b# {* p  X
  30.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;1 r5 z! p( \9 Y2 e9 D
  31.   MPU_InitStruct.Number = MPU_REGION_NUMBER1;
    : b8 b% w' k  ~
  32.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
      [. C. I  N6 Q
  33.   MPU_InitStruct.SubRegionDisable = 0x00;; Z1 q( ~: ^& L) z6 h
  34.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;3 w3 I, @; U+ u" Z7 F) |2 |
  35. , K% G; C- a5 H2 [6 Q3 \% T
  36.   HAL_MPU_ConfigRegion(&MPU_InitStruct);
    - x" G/ ~9 S; l

  37. 3 _" ^. p7 `: W$ t8 [
  38.   /* Enable the MPU */
    + P& \) j* q% n6 B9 L
  39.   HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);( _8 |+ W: p+ R8 a6 J" r
复制代码

- X  h  T) `- Q3 `$ s在工程中添加ETH库函数,stm32h7xx_hal_eth.c和stm32h7xx_hal_eth_ex.c$ L5 M- o" }6 e; w# p& a
" Q; o% @$ m7 E+ W1 M* G
五,LWIP协议栈的移植

# P+ N, H2 g4 P2 K1 ?该移植参考思路,移植也可以通过git log的方式参考这个移植步骤,但是这里移植里面有几处错误后文会提出。后来发现这个移植与STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Projects\STM32H743ZI-Nucleo\Applications\LwIP,基本一致。, S7 j- c6 I7 c  P8 m- w9 H, D
; @2 D" A! i6 P5 a
LWIP协议栈的源码7 r' }2 M+ Z4 ^* a8 P
如果你有安装CUBEMX,那么直接从STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Middlewares\Third_Party\LwIPP的目录下把LWIP的源码拷贝出来就可以了。或者下载参考思路里面的链接把LWIP源码拷贝出来。$ p$ y) r; W* ~" s( k0 x
工程中添加新的文件夹8 _0 }  m0 \' Q1 n+ g( `* t

, Q% k8 t( R0 U1 s8 jlwip/api:添加LwIP\src\api目录下的所有文件$ q. E* Y( U( ^7 H) `9 z
2 S9 C9 G: z$ j  J+ k9 R: v- p  K/ u$ K
20190505093456906.png
9 b$ E6 u* Q# A0 `

: J) R* V. o6 w; b+ mlwip/core:添加LwIP\src\core目录下的文件,并包括ipv4文件夹下的文件, M( |& r3 h8 l. q

% U' a8 b  B& E8 I
2019050509354914.png
9 q% W  {1 T0 c" [

7 V1 c6 M/ m8 b9 y3 y/ B8 a. vlwip/netif:添加ethernet.c,sysarch.c0 S+ M. Z+ m* _" R. k2 b4 u

1 c$ W+ s! y# W9 t
20190505093617351.png
+ T7 \, K0 A) }

9 C; a, z! X. n9 U# n" F: mlwip/port:添加ethernetif.c,lan8742.c(lan8720也可以用)9 W/ }- A. w1 y/ j
( @" {/ K' C" M, R* t  i1 }* |
20190505093754704.png

( Q8 N" T& _$ N! e# j! h) z" \5 x3 Z$ F4 `6 N( F
移植准备工作就全部做完了,下一节修改工程报错2 M& Z+ X8 ]/ {5 H# p) a
- O2 _7 C, V% y) Y. ]
( }; y8 |( |2 Y1 [

/ k8 i- ?& E: P
赞 收藏 1 评论0 发布时间:2021-12-25 11:17

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版