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

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

[复制链接]
STMCU小助手 发布时间:2021-12-25 11:17
一,写在前面& J. |8 H# Q6 Z" X" Z! B
STM32H7目前还是一个比较新的MCU,网上的资料相对于F1 F4系列相对来说就很少了,我自己在移植这个LWIP的时候走了不少弯路,得到了不少人帮助。写这篇文章也是对我自己移植的一个总结,也是希望后来人能少走弯路。
1 i! f. y) {  k; }2 x这篇文章有由个人编辑并整理,如有错误,欢迎拍砖。& L* i; \1 ~# r5 ]+ ?7 Z' r- O
# s: [0 d1 }/ C+ y3 O; `+ `/ n
二,RT-Thread,STM32H7,LWIP简介
# C1 }* N/ G/ DRT-Thread是一个来自中国的开源物联网操作系统,它提供了非常强的可伸缩能力:从一个可以运行在ARM Cortex-M0芯片上的极小内核,到中等的ARM Cortex-M3/4/7系统,甚至是运行于MIPS32、ARM Cortex-A系列处理器上功能丰富系统。
( a5 u" d& A9 W3 W5 M% V: {0 ~
! B; k& A. _/ Z+ E8 s- L  s  L& XSTM32H7是ST意法半导体Cortex_M系列最高性能处理器。主频高达400M,FLASH高达2Mbytes,SRAM高达1Mbytes,采用六级流水线,自带 指令 和数据 Cache、集成 JPEG编解码器、编解码器、集成 双精度硬件浮点计算单元( DPFPU)和 DSP指令。  E& a) X. s0 H; r# T* A# ~

) n( B8 A. F" f+ P/ I, eLWIP是瑞典计算机科学院(SICS)的Adam Dunkels开发的一个小型开源的TCP/IP协议栈。: ]# ]0 q0 y8 Z. X8 n
% f& B( }: w' ]2 E5 Q! [
三,STM32H7的特殊性. p$ ^1 `% V" l! z- T+ R6 l, m
这里的特殊性,仅仅只是对比F1 F4系列:
( _1 H9 b$ ~+ R5 y* e- N* b% B+ U  |$ S# w
RAM
8 l9 a: m" }- K) hF1 F4系列只有一块RAM,在使用RTOS的时候直接分配给RTOS做堆就可以了。# f7 K& P+ e- Z8 v
H7的RAM构成看下表:
' W+ s4 b5 Y; Z
20190504165951455.png
& I) _. D4 Y& m

/ z" n- D8 S* r1 r! g" NDTCM的速度是400M,但是DMA无法进行访问。4 h5 Q9 h. U# J. {1 l+ v* R, }5 e3 ^
AXI SRAM的速度是200M,DMA可以进行访问。" L% x: W0 m3 R" T1 h
SRAM3是以太网和USB的缓冲区。' E' S! s- f  U" x1 b* a, |0 [3 b
2 K! x  n+ G4 f  k
CACHE, i! k/ V1 p. v6 ~. p( z
H7比F1 F4多了一个L1 CACHE一级缓存,这个缓存在为低速存储器带来加速的同时,也为程序带 来了一些问题,其中最为主要的时数据一致性的问题。6 i& Y' n/ r  ]% e# x( q, W
. z9 N5 D% o9 m
DMA  b+ ]9 p! u) ~6 p8 @. G
H7的DAM分为DMA1,DAM2,BDMA,MDMA。其中SDIO和ETH的DMA又是独立的,就是说他们有专用的DMA和其他的DAM之间使用不冲突,无须额外使能,只需要开启中断就默认使用DMA模式。
. `! u6 n5 H$ z( j) `7 N
) _. o; P; N- a8 S
20190504172355726.png
' |8 T) W. B; N6 a. m7 c8 L

, m& w- N: G7 h四 ,移植前的准备工作
! u3 H' X9 V  [" P9 d. p3 [& \( _确保有一个可以在开发板上能正常运行RT_Thread的工程,目前RT_Thread已经有了正点原子H743的BSP,通过ENV工具使用scons --dist来把这个工程拿出来,复制出dist文件夹下的工程就可以直接使用了;/ ?  u, c4 {+ r# k! ~
使用ENV工具,开启软件模拟IIC,因为正点原子的开发板的PHY复位接到了pcf8574的7号引脚,然后生成工程肯定会报错,这个时候从别的BSP目录下拷贝出pcf8574.c pcf8574.h phy_reset.c,放到工程里,然后在rtconfig.h加入以下代码来启用模拟IIC5 s5 P) g, Z8 m0 ?2 q4 e2 E
  1. #define BSP_USING_I2C2
    % U7 J3 v1 q: V! C. `( a1 p

  2. 6 u( Y6 |! w6 U1 K* X* Y1 [- V
  3. #define BSP_I2C2_SCL_PIN 116
    % W* F- u( @! Q
  4. #define BSP_I2C2_SDA_PIN 117
复制代码

+ a# Z: s$ V: W6 \  }这里的引脚号由硬件决定,如果不是原子的开发板可以省略这一步
! C3 \% `# m* G  U' j' p' i  i2 }- Z- ]7 V
因为RT-Thread目录下的STM32BSP是依赖CUBEMX,所以还需要在CUBEMX里面开启ETH的引脚,这个请和自己的板子一致;
% ^" F$ U( \5 F" e& x3 ?  A. t5 I! u; W( U$ A0 \- t
20190504230500122.png
0 ~) p8 L8 ]2 G# H6 E, N4 u
8 u/ }6 z6 d. x( R3 B: D1 p
开启RMII模式,注意这里的PC1引脚无法选择成高电平,需要在生成的使msp.c里面自己修改为高电平,并开启中断。9 `9 [6 C/ v8 z6 ^" O) x- g

' o9 `% j1 K& [9 p1 a2 p检查是否开启了I_CACHE和D_CACHE
0 y2 Z/ ?# g3 `+ ~
" ^3 a: K) \+ }8 `! i
20190504230946919.png

0 F- |- N: ~! x; W: N& }9 ^  ~. f! e8 m2 b/ N, m: `& L5 M
这里一定要开启,里面由依赖关系,不然会导致cache无法正确运行。' F/ Z1 [7 B) ?) K  b3 u$ s
" i9 o$ D* a; D( F, ~
然后通过CUBEMX生成工程并把时钟初始化部分拷贝出来复制到board.c中+ E- {8 r8 i4 ]& [/ K3 F8 y3 i( w0 ^

$ u4 I. V9 Q+ Z6 Y( Z在drv_mpu.c中加入MPU配置0 x% h& `! L5 r1 x  [* i( v, Y
以太网DMA描述符区,只能配置为Strongly - order或者Device。- o1 z, s% R' G9 D0 P2 F$ j3 K9 M
  1.   MPU_Region_InitTypeDef MPU_InitStruct;
    ; u6 Q7 [. V( t  a, m8 W$ a
  2. 0 M& V) o: j/ `, ]; O3 O  l* _
  3.   /* Disable the MPU */% M7 p! w0 k* O
  4.   HAL_MPU_Disable();
    7 z' k& X/ @* W8 n
  5. " S& s% R1 `/ |) s/ D& }/ j1 H* F) W/ G
  6.   /* Configure the MPU attributes as Device not cacheable , E4 O" V% l% S2 _/ e$ a. t
  7.      for ETH DMA descriptors */9 R8 {1 u% R4 {; ], ]6 I
  8.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    6 Q- X; q& r3 P- ~) i9 L
  9.   MPU_InitStruct.BaseAddress = 0x30040000;
    $ e9 }, r) T* b9 S8 t
  10.   MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
    ( [' j2 M+ p2 G
  11.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    3 W" d& u$ o" s/ a, L" ?% e. Z
  12.   MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
    ' t8 c2 ^6 M; q! w; S
  13.   MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;. U$ R) d; X; W8 ^7 C+ x
  14.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
    : h/ A5 G! T! J7 d8 R
  15.   MPU_InitStruct.Number = MPU_REGION_NUMBER0;( i8 I2 A6 O# K! v' L) e
  16.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;+ Q( Z! S" h4 q& o" L( b
  17.   MPU_InitStruct.SubRegionDisable = 0x00;. N. F8 G/ O* V1 Z. u9 M' X. J
  18.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;; g- E' @" e) i7 k5 D: E2 R' {

  19. 0 p$ c% U3 s% N6 N3 N
  20.   HAL_MPU_ConfigRegion(&MPU_InitStruct);- m4 ]; w; Y+ C& [- V  \

  21. 1 ]1 S! j" a9 P- Q
  22.   /* Configure the MPU attributes as Cacheable write through
    * w& v! e, m4 |0 z7 \  t
  23.      for LwIP RAM heap which contains the Tx buffers */
    2 m; r2 ^) b0 a5 C
  24.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    8 h% p% H- k* g) E' o8 ?
  25.   MPU_InitStruct.BaseAddress = 0x30044000;4 j% m  _: J) R9 [$ ]: y
  26.   MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;6 R# U# x- s5 |) h! H1 b
  27.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;- e% H4 S, \3 I4 A) \6 O# S& o
  28.   MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;* b, F$ E' m0 _; k9 @9 ^
  29.   MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
    ' J7 R: j8 C; B9 m' h5 F0 z
  30.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
      h& x% ?: @9 a0 q" E
  31.   MPU_InitStruct.Number = MPU_REGION_NUMBER1;3 O3 K# s( T) {- ]6 v1 E5 @
  32.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;# X8 B, U' x- \* k# I8 d4 \
  33.   MPU_InitStruct.SubRegionDisable = 0x00;
    & \; D" \6 u3 M% k1 [, A1 |2 i
  34.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;& k' |" s5 x3 D8 U2 {# D, p, b

  35. 7 y: T- Q3 x5 Q6 _6 x+ Q
  36.   HAL_MPU_ConfigRegion(&MPU_InitStruct);% R' l# k! S4 K  b0 S8 \

  37. " Z9 \& {3 D& X; P" K% C7 Q
  38.   /* Enable the MPU */
    9 d+ q) \! c" P9 U2 r  g' ]
  39.   HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
    ; x, o. w5 v+ p# L. N$ w
复制代码

1 Y8 l* N  v, |2 O& B在工程中添加ETH库函数,stm32h7xx_hal_eth.c和stm32h7xx_hal_eth_ex.c
2 Q' h- P$ u! q9 p$ H9 k- I6 [( K
五,LWIP协议栈的移植
1 |) s8 n! a, h2 B
该移植参考思路,移植也可以通过git log的方式参考这个移植步骤,但是这里移植里面有几处错误后文会提出。后来发现这个移植与STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Projects\STM32H743ZI-Nucleo\Applications\LwIP,基本一致。
4 o8 y, I8 _9 n; {* L; F  W. w. T* i4 L  C
LWIP协议栈的源码1 K& V. [+ H/ Y" ?# }  q6 t
如果你有安装CUBEMX,那么直接从STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Middlewares\Third_Party\LwIPP的目录下把LWIP的源码拷贝出来就可以了。或者下载参考思路里面的链接把LWIP源码拷贝出来。$ H) [5 l2 l  g, T
工程中添加新的文件夹" _. z: P# X0 ^/ x* O3 G: i, P. m
9 k" i. h; H( S; x8 a0 O) V
lwip/api:添加LwIP\src\api目录下的所有文件# L% _; Q4 b/ a: t& c' L

* {$ A# b# f% y: `8 P
20190505093456906.png

' `  V, A; y! C* l8 s4 K
6 w# }( P7 n! [) s/ nlwip/core:添加LwIP\src\core目录下的文件,并包括ipv4文件夹下的文件
" ~' {0 [) t1 g0 Y9 u$ T4 S- `8 G9 t4 `! ^; z' D) W  p
2019050509354914.png
: O, v9 u( C4 v5 x* ?7 y+ m* u
* S/ \/ _  z2 l
lwip/netif:添加ethernet.c,sysarch.c8 ]( a4 \! \. g, [  v

4 I- Q# h* @& W4 S; y7 b( F
20190505093617351.png
: X; F3 W, j% E* ]
; p/ D1 a/ N2 R& Y7 G
lwip/port:添加ethernetif.c,lan8742.c(lan8720也可以用)
) ~, S: \* j  [5 o+ U( M7 d$ e; O9 K
20190505093754704.png
4 T' L9 o+ V/ K2 `
0 K# W' C) R: q, r$ ~7 X0 S
移植准备工作就全部做完了,下一节修改工程报错- C5 V1 |; R* A! o4 T
4 `+ Y9 G( Y8 i* g4 c6 W

; i3 x0 s  W% {) L' K/ S
1 M) T5 K3 Z$ [0 x  u
收藏 评论0 发布时间:2021-12-25 11:17

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版