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

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

[复制链接]
STMCU小助手 发布时间:2021-12-25 11:17
一,写在前面) v3 M3 y5 r- x* Z
STM32H7目前还是一个比较新的MCU,网上的资料相对于F1 F4系列相对来说就很少了,我自己在移植这个LWIP的时候走了不少弯路,得到了不少人帮助。写这篇文章也是对我自己移植的一个总结,也是希望后来人能少走弯路。, r9 R. u) q4 C* P- w( K. g
这篇文章有由个人编辑并整理,如有错误,欢迎拍砖。! w5 u% C4 F/ R" t5 k
: l3 S9 f, F  h+ n; ?1 l
二,RT-Thread,STM32H7,LWIP简介
$ K4 o8 H/ M: I% K* M7 eRT-Thread是一个来自中国的开源物联网操作系统,它提供了非常强的可伸缩能力:从一个可以运行在ARM Cortex-M0芯片上的极小内核,到中等的ARM Cortex-M3/4/7系统,甚至是运行于MIPS32、ARM Cortex-A系列处理器上功能丰富系统。. D, ^. V  _& y- P
- l( ]: w. Z. v: a
STM32H7是ST意法半导体Cortex_M系列最高性能处理器。主频高达400M,FLASH高达2Mbytes,SRAM高达1Mbytes,采用六级流水线,自带 指令 和数据 Cache、集成 JPEG编解码器、编解码器、集成 双精度硬件浮点计算单元( DPFPU)和 DSP指令。2 u) b) I4 y/ D! f  Q
  w" o, b( I2 i- g# f: t  E
LWIP是瑞典计算机科学院(SICS)的Adam Dunkels开发的一个小型开源的TCP/IP协议栈。
; I1 s$ x0 v7 c. E( Q" k% v
/ I; Q+ l, y. u4 d* y* {三,STM32H7的特殊性  R/ Q/ a0 i2 s6 }; J% d  m; {0 g0 S
这里的特殊性,仅仅只是对比F1 F4系列:. U1 j, y" h" t3 \, I/ o
: Q6 |: H6 S: r6 T8 `5 n* B5 S9 p3 i
RAM6 y, W7 l4 |5 ?+ n/ G& y
F1 F4系列只有一块RAM,在使用RTOS的时候直接分配给RTOS做堆就可以了。3 j; C9 S6 U+ y1 T
H7的RAM构成看下表:  \; m* _( G1 Q: I( v. s8 V
20190504165951455.png

& p9 P3 o8 S% q+ H7 l, b4 o1 [0 c  f! G7 ?' G4 {8 u
DTCM的速度是400M,但是DMA无法进行访问。1 Z! v+ ^4 P* o. o" _
AXI SRAM的速度是200M,DMA可以进行访问。, `7 Z+ C* t% A4 q( D8 H+ d
SRAM3是以太网和USB的缓冲区。
  a/ P6 K. ?, N6 Y" b# O2 a# c. A8 R) P: A, z# f
CACHE
. A% `) Q% ?1 ^2 iH7比F1 F4多了一个L1 CACHE一级缓存,这个缓存在为低速存储器带来加速的同时,也为程序带 来了一些问题,其中最为主要的时数据一致性的问题。: c' @2 m# `2 i
7 j3 c( L6 Y6 V& V
DMA' M) e$ R. A* r* _
H7的DAM分为DMA1,DAM2,BDMA,MDMA。其中SDIO和ETH的DMA又是独立的,就是说他们有专用的DMA和其他的DAM之间使用不冲突,无须额外使能,只需要开启中断就默认使用DMA模式。
2 ~  H# P$ _2 V2 ]* z
* n6 v0 t3 ~- K4 z9 |& ~. C( m
20190504172355726.png
$ [( h( V7 |: z' n( K
* O7 i) U+ D: q5 I( B- \# U
四 ,移植前的准备工作
% R) r. H- [0 w! m) o: R' U' I确保有一个可以在开发板上能正常运行RT_Thread的工程,目前RT_Thread已经有了正点原子H743的BSP,通过ENV工具使用scons --dist来把这个工程拿出来,复制出dist文件夹下的工程就可以直接使用了;& z! x4 `: H, w
使用ENV工具,开启软件模拟IIC,因为正点原子的开发板的PHY复位接到了pcf8574的7号引脚,然后生成工程肯定会报错,这个时候从别的BSP目录下拷贝出pcf8574.c pcf8574.h phy_reset.c,放到工程里,然后在rtconfig.h加入以下代码来启用模拟IIC. ~! p- A8 y! T/ U  P8 Y" U' F0 A# \
  1. #define BSP_USING_I2C2
    " f9 ], |- K9 ~% ~( }
  2. # m- v$ i2 s* p) j9 n4 A5 }
  3. #define BSP_I2C2_SCL_PIN 116
    - ]& j( O$ I: e+ f) Q* e
  4. #define BSP_I2C2_SDA_PIN 117
复制代码

2 ?& x7 e  p- [' z: F: u+ Q+ R这里的引脚号由硬件决定,如果不是原子的开发板可以省略这一步. O" [( i! j* v# x

" o1 F3 o+ r$ {0 a因为RT-Thread目录下的STM32BSP是依赖CUBEMX,所以还需要在CUBEMX里面开启ETH的引脚,这个请和自己的板子一致;/ R( Q4 Y! Y# t! w

6 S- i4 L) T: x/ q0 d% p. w
20190504230500122.png

0 w# {9 g4 e/ `/ F' D& l* o
( e" w# q2 }# b; ?7 X" E开启RMII模式,注意这里的PC1引脚无法选择成高电平,需要在生成的使msp.c里面自己修改为高电平,并开启中断。* G1 |! T3 c( H2 f

6 p* F  {3 Y4 A检查是否开启了I_CACHE和D_CACHE/ j' ^3 g* [6 E$ q3 D" T

7 N4 y0 T4 b; i2 P2 Y: d
20190504230946919.png

$ s7 W/ S% T( o! h/ _% ]+ B$ y! c1 V, D6 ?: w
这里一定要开启,里面由依赖关系,不然会导致cache无法正确运行。0 }; g, r* V4 N) f
8 s; P' E; ?! _
然后通过CUBEMX生成工程并把时钟初始化部分拷贝出来复制到board.c中3 b2 a/ y, s' u* j
' j4 X/ k0 q' U3 N7 y
在drv_mpu.c中加入MPU配置
) ~' ]3 t% f* e: x! S% C$ b- Q以太网DMA描述符区,只能配置为Strongly - order或者Device。
8 x8 ]( C" B0 M; L
  1.   MPU_Region_InitTypeDef MPU_InitStruct;  @" y3 O) T  ^6 `+ Y8 V* a

  2. " A! P+ Z, K, c
  3.   /* Disable the MPU */$ k1 f/ K. i9 }) f
  4.   HAL_MPU_Disable();' |$ \# T+ b( a9 Y0 T
  5. 6 n% n4 l/ X6 \/ \, T
  6.   /* Configure the MPU attributes as Device not cacheable
    * [3 x2 Z& }5 M  |, u
  7.      for ETH DMA descriptors */( ?* ^( F- C' z' |1 ~, i
  8.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    # q" A6 j7 E6 q
  9.   MPU_InitStruct.BaseAddress = 0x30040000;3 Q% U: P8 o4 e
  10.   MPU_InitStruct.Size = MPU_REGION_SIZE_256B;2 J2 a+ }7 u4 ?8 [
  11.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    2 Q2 _. r* e6 N" [5 c
  12.   MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
    : Z$ n5 r7 j8 \# Y" {$ p* n$ F
  13.   MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
      c. W! h- Y7 P( ^; S
  14.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;+ }0 R5 |' s9 c: M# A
  15.   MPU_InitStruct.Number = MPU_REGION_NUMBER0;* ]3 g* ?6 u  x. c
  16.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    % f0 a5 w$ l6 w3 P% s
  17.   MPU_InitStruct.SubRegionDisable = 0x00;
    ; T" D5 J+ h# G( ?4 ~% c. m
  18.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;3 H  w' G: t; ?( F' W
  19. ! d/ B& a9 X# `+ m3 m( w$ p: r
  20.   HAL_MPU_ConfigRegion(&MPU_InitStruct);' S! D/ V! R1 T+ r) N
  21. / _7 C; ?" A. n$ G& I5 Z3 J% x$ u9 b- S
  22.   /* Configure the MPU attributes as Cacheable write through
    1 H% M1 o6 M2 T- Z
  23.      for LwIP RAM heap which contains the Tx buffers */
    9 N  T4 x3 J; v9 K  \
  24.   MPU_InitStruct.Enable = MPU_REGION_ENABLE;
    ! t- S, F! K' {; m1 Z' ?
  25.   MPU_InitStruct.BaseAddress = 0x30044000;
      ?$ y5 j9 ^* K1 b( X4 r
  26.   MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;. a! G3 Q& F. d
  27.   MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
    ' D2 `8 Y+ h, @- @
  28.   MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;  _, v# b4 M) W" k9 I- S# N3 P
  29.   MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;" O6 D$ c! u0 z, _+ Q5 M
  30.   MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;4 G" G6 y, [# r
  31.   MPU_InitStruct.Number = MPU_REGION_NUMBER1;$ h8 u. A6 u! K& u( S$ E/ B7 T& n& ?$ D+ J
  32.   MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
    3 J; m& W0 [% @! F. l3 H0 C* Z
  33.   MPU_InitStruct.SubRegionDisable = 0x00;
    . d! k0 ^  @) ?% R. w! Z# }4 \
  34.   MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;# j8 S+ v$ t. O' c4 U& O

  35. " F) J! @; }) K. t4 }) T: K
  36.   HAL_MPU_ConfigRegion(&MPU_InitStruct);8 o7 n0 J. G) d# `" ?, S! P

  37. $ R7 g7 a, {+ h1 u+ w( R( u' _
  38.   /* Enable the MPU */, i  N# L/ M/ `& [) E/ y
  39.   HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);) W( P2 H& {8 t+ \* X  C; n& c
复制代码
) @) [3 F2 ~6 J! r6 ~# @
在工程中添加ETH库函数,stm32h7xx_hal_eth.c和stm32h7xx_hal_eth_ex.c
* O6 M! V* e$ u" ?+ U( f2 g; i7 H" J! `" H1 S9 P
五,LWIP协议栈的移植

$ u- F, h( e4 X' E4 i' i/ I# F该移植参考思路,移植也可以通过git log的方式参考这个移植步骤,但是这里移植里面有几处错误后文会提出。后来发现这个移植与STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Projects\STM32H743ZI-Nucleo\Applications\LwIP,基本一致。
' Q. @" ], V! U& `# B6 E) k% F- c2 Y7 v, e' ?( x) k3 f, d1 l2 [
LWIP协议栈的源码, g2 e  r. N6 ?
如果你有安装CUBEMX,那么直接从STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Middlewares\Third_Party\LwIPP的目录下把LWIP的源码拷贝出来就可以了。或者下载参考思路里面的链接把LWIP源码拷贝出来。
% D3 `' S1 v# q' r0 e; t0 p8 @/ u) E工程中添加新的文件夹1 h* q# q* i% V
8 Q* m& c( C# F
lwip/api:添加LwIP\src\api目录下的所有文件
+ U+ w/ \; H0 Y# C6 U4 |8 G7 B( b& f) o0 t/ p  R3 ], n
20190505093456906.png
$ F9 b5 T9 k; G) g2 B/ n- ~& ~( U
) Z6 u* f6 Z* a8 d2 H4 Q8 U* y
lwip/core:添加LwIP\src\core目录下的文件,并包括ipv4文件夹下的文件* l; b! W. e8 g( D( Z
8 Y9 q  p; C- N5 F- E
2019050509354914.png
% Z1 n! d" ~0 n6 N
* O5 Y2 ~6 n0 ], I; G- ]
lwip/netif:添加ethernet.c,sysarch.c
5 Y# S: n. h  O  l+ v" d3 ?, z0 M& l5 h
20190505093617351.png

: O' E+ e* X; r/ f
$ i5 I4 w+ w4 [5 |lwip/port:添加ethernetif.c,lan8742.c(lan8720也可以用)
# G/ M8 Y; m8 k, |9 L6 z- x/ f, p: o" \! p; ?# r( ]3 n( F% g
20190505093754704.png
+ g& j/ ]! s) l. K# a5 u

8 `8 B% N5 ~! g移植准备工作就全部做完了,下一节修改工程报错' j$ L! W* ~$ J$ g5 V
1 V" [2 V% w, z8 p9 B: S8 {
' \! \+ D0 V! D, m
2 H' \: W' W8 D9 S* F
收藏 评论0 发布时间:2021-12-25 11:17

举报

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