一,写在前面
, h% ^2 Z" v+ K( \3 T- E" r+ GSTM32H7目前还是一个比较新的MCU,网上的资料相对于F1 F4系列相对来说就很少了,我自己在移植这个LWIP的时候走了不少弯路,得到了不少人帮助。写这篇文章也是对我自己移植的一个总结,也是希望后来人能少走弯路。1 B, _3 v2 ?' m* p4 M
这篇文章有由个人编辑并整理,如有错误,欢迎拍砖。
6 e/ r; t& c2 S5 i
+ _8 p! ?' {2 P/ @二,RT-Thread,STM32H7,LWIP简介
/ N; K' o5 D5 G! o0 m! \2 N& j7 p1 i2 iRT-Thread是一个来自中国的开源物联网操作系统,它提供了非常强的可伸缩能力:从一个可以运行在ARM Cortex-M0芯片上的极小内核,到中等的ARM Cortex-M3/4/7系统,甚至是运行于MIPS32、ARM Cortex-A系列处理器上功能丰富系统。. g# ^: |# \! X/ O, U$ V
5 P, g, m3 F' B* I* z- w; V3 _) H' v
STM32H7是ST意法半导体Cortex_M系列最高性能处理器。主频高达400M,FLASH高达2Mbytes,SRAM高达1Mbytes,采用六级流水线,自带 指令 和数据 Cache、集成 JPEG编解码器、编解码器、集成 双精度硬件浮点计算单元( DPFPU)和 DSP指令。" V$ X4 M3 @8 U% t1 P" }8 h* r; }7 @
$ P9 C& \! b) `) g' k) aLWIP是瑞典计算机科学院(SICS)的Adam Dunkels开发的一个小型开源的TCP/IP协议栈。
8 z/ l% T. @ U" ?+ W3 Z# [9 F- r% ^% J$ y+ q% ?! Z- U3 k2 v4 W9 ~% Q
三,STM32H7的特殊性7 d: G; o* ^ R% j1 |+ C
这里的特殊性,仅仅只是对比F1 F4系列:0 q) ^5 E& D* a( Q/ K
4 t4 d+ I' n9 S$ r8 s5 x
RAM% s5 u% J) z3 Z& U$ @
F1 F4系列只有一块RAM,在使用RTOS的时候直接分配给RTOS做堆就可以了。# b5 z9 A3 q* F; q' p `
H7的RAM构成看下表:
$ @0 y3 k& Q. L$ X( P0 r% O* G7 P
% Y+ r; B& U3 T/ c! X7 ]' X" a* u
DTCM的速度是400M,但是DMA无法进行访问。
- S8 B4 C! H3 k" e0 i- TAXI SRAM的速度是200M,DMA可以进行访问。
7 u5 {8 z. A, S5 I. G DSRAM3是以太网和USB的缓冲区。3 \7 ]- W- q( m l9 Y1 Z. Q9 i2 b7 u
8 P5 u2 q% O; Z2 i) {& n
CACHE
1 o. s9 B& P1 \: M5 C& M, c5 ]H7比F1 F4多了一个L1 CACHE一级缓存,这个缓存在为低速存储器带来加速的同时,也为程序带 来了一些问题,其中最为主要的时数据一致性的问题。4 p2 \8 r$ A/ U$ z: w
; Q/ y- n- l0 |* `DMA9 Z: {7 ?* @* B0 Q/ `. U0 x1 v
H7的DAM分为DMA1,DAM2,BDMA,MDMA。其中SDIO和ETH的DMA又是独立的,就是说他们有专用的DMA和其他的DAM之间使用不冲突,无须额外使能,只需要开启中断就默认使用DMA模式。
1 N2 B% L* ]2 ]" S# ?& B% M# A2 L6 D$ n( [4 Z+ }8 v
6 q" M6 R' A) D% }# Y. S
0 x3 f* x% R; ]7 F: K四 ,移植前的准备工作
( K- v; a3 D; n7 q2 I& I确保有一个可以在开发板上能正常运行RT_Thread的工程,目前RT_Thread已经有了正点原子H743的BSP,通过ENV工具使用scons --dist来把这个工程拿出来,复制出dist文件夹下的工程就可以直接使用了;+ i3 b4 G2 U! i8 ]# G( Q
使用ENV工具,开启软件模拟IIC,因为正点原子的开发板的PHY复位接到了pcf8574的7号引脚,然后生成工程肯定会报错,这个时候从别的BSP目录下拷贝出pcf8574.c pcf8574.h phy_reset.c,放到工程里,然后在rtconfig.h加入以下代码来启用模拟IIC
' w. f+ f9 p. ^ u: m$ e2 W- #define BSP_USING_I2C26 O5 w5 E* q7 m& y
" m5 J( ]' ?' ^! I- #define BSP_I2C2_SCL_PIN 1169 R/ c9 w y6 T1 v: Y
- #define BSP_I2C2_SDA_PIN 117
复制代码 % h, }& ~5 b+ }% i+ _; Y
这里的引脚号由硬件决定,如果不是原子的开发板可以省略这一步
& s% g) ?: [+ D5 v
5 T, \( ?0 H, H/ K, ~因为RT-Thread目录下的STM32BSP是依赖CUBEMX,所以还需要在CUBEMX里面开启ETH的引脚,这个请和自己的板子一致;
/ V% x7 T ^+ H l6 |1 B2 m" A9 K
4 ~* E; |! b5 ~9 g! f: F. l. q' A% p/ a( _; P2 d. H# X
开启RMII模式,注意这里的PC1引脚无法选择成高电平,需要在生成的使msp.c里面自己修改为高电平,并开启中断。
) c6 \, [+ _" Z" l/ |% j* d3 q& {) y: _: Q
检查是否开启了I_CACHE和D_CACHE% R$ z$ N, N# q% |- c& Y
6 f# s" s6 c; X: i* b
: K# @. V/ P4 W( M: k4 A: w8 z& t8 g! r2 e G' E a0 d: b- D
这里一定要开启,里面由依赖关系,不然会导致cache无法正确运行。
( @& I8 h l2 C8 C6 l" i! r( D, R' U
) \7 z0 L& h" K2 B8 d6 n然后通过CUBEMX生成工程并把时钟初始化部分拷贝出来复制到board.c中" ?0 O- H9 H% l V
, z9 @& r& H; W4 q v在drv_mpu.c中加入MPU配置
8 s. a0 Q c9 _" F! a以太网DMA描述符区,只能配置为Strongly - order或者Device。9 [4 k" V& A% S" j/ J3 E" ]. u
- MPU_Region_InitTypeDef MPU_InitStruct;3 w* `, Z' q: _: I1 b
- F( w/ H9 ~3 A- /* Disable the MPU */
( `5 Y/ a: H8 ~& a3 F. \/ g - HAL_MPU_Disable();+ T( W# ?8 G6 d
- ( {. G0 f$ R% G B
- /* Configure the MPU attributes as Device not cacheable $ p* a* j Z) K& Y, s
- for ETH DMA descriptors */
; U- V% t& O, ~) I1 x7 |4 @ - MPU_InitStruct.Enable = MPU_REGION_ENABLE;( v; b: C2 C9 T5 K5 |
- MPU_InitStruct.BaseAddress = 0x30040000;
. y' }& z0 n8 _4 j, [1 O - MPU_InitStruct.Size = MPU_REGION_SIZE_256B;7 f2 J- p8 b5 n- I
- MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;0 j: [6 V' `" H" e9 w6 b
- MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;4 s$ T0 |8 a7 E- E
- MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;/ U; [1 Z6 R% J& ] z" |" f
- MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
( P- t$ [4 L1 a- X/ s+ o - MPU_InitStruct.Number = MPU_REGION_NUMBER0;$ a7 Q; `3 Z/ Y% y- C3 p6 [2 H
- MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0; Q: |! `' O" f, b9 V) C, U/ i1 ?
- MPU_InitStruct.SubRegionDisable = 0x00;) W$ W/ [8 G5 m5 d1 ^3 b6 ]
- MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE; B/ [5 T' |' S$ _) T( p: ~6 @
: |! V$ K5 W" R- HAL_MPU_ConfigRegion(&MPU_InitStruct);
# s9 l, ^+ G1 }5 O# O - ! \: t" }4 Q6 g. ?6 f
- /* Configure the MPU attributes as Cacheable write through + z+ |1 y8 ^- O% W2 ?( d
- for LwIP RAM heap which contains the Tx buffers *// d. g. n% I! f
- MPU_InitStruct.Enable = MPU_REGION_ENABLE;% l0 I$ f6 c3 ` l" H$ L6 S
- MPU_InitStruct.BaseAddress = 0x30044000;
5 L. x: s& x8 v% G5 S ~ - MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
4 m$ S: j8 @! _7 |- t. F: \9 L - MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
: ^: c- f# v/ Y- N$ k6 A5 G0 q& a2 V - MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
( b* l/ p+ h% u1 Z - MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
3 _; ]7 r6 h1 Y. k+ U5 N2 l - MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
o: e6 ?. S& ` - MPU_InitStruct.Number = MPU_REGION_NUMBER1; t' B7 V8 V3 R$ g
- MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
# S& R4 u% O" r) ?# B$ w+ ~ - MPU_InitStruct.SubRegionDisable = 0x00;
9 c# s& E: g" _" p) S1 f - MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;' Y6 x, m4 L9 M* o' n
- % o7 k6 P, {5 u' D7 h
- HAL_MPU_ConfigRegion(&MPU_InitStruct);
) R; W Q a" ?" `( w# T- K
: _; C: G) a4 _" n9 l- /* Enable the MPU */
! f" R8 w( T+ p: {9 d- \ g - HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
* z1 f4 H5 S! E# P
复制代码
. a% X1 |' V# z. f) G1 X在工程中添加ETH库函数,stm32h7xx_hal_eth.c和stm32h7xx_hal_eth_ex.c% E6 E8 |- m3 ?3 E% C9 X
$ p% T# ?; {2 u+ b( ]0 a2 E# c五,LWIP协议栈的移植
8 a6 O3 Q- {" l该移植参考思路,移植也可以通过git log的方式参考这个移植步骤,但是这里移植里面有几处错误后文会提出。后来发现这个移植与STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Projects\STM32H743ZI-Nucleo\Applications\LwIP,基本一致。
* E+ ^# {4 u" V: g- g* y
( c* K& `% u: ~, T& HLWIP协议栈的源码& H5 N* U0 o3 _' d$ T, ^, z
如果你有安装CUBEMX,那么直接从STM32Cube\Repository\STM32Cube_FW_H7_V1.3.2\Middlewares\Third_Party\LwIPP的目录下把LWIP的源码拷贝出来就可以了。或者下载参考思路里面的链接把LWIP源码拷贝出来。$ n- X8 r- w; M* P
工程中添加新的文件夹
; j: ]9 L/ P9 Q% z; I7 F5 [0 W
/ h+ [" p) u) Z& nlwip/api:添加LwIP\src\api目录下的所有文件3 ]' T( _5 U% Q+ v6 k6 v
3 q" p- M2 V' H% V
' D, E5 D: Q% j( z. s- w2 g z- s
( z) n( ~+ {$ b5 q# [9 c" e! klwip/core:添加LwIP\src\core目录下的文件,并包括ipv4文件夹下的文件
" ~$ M; U" G2 v! _& {& p2 F
. A. Q# b. _: b* v9 W
; B7 d+ i: b" Q) A& V' h
7 @- J( U1 i- slwip/netif:添加ethernet.c,sysarch.c% E u- q, [6 Y
/ M' k0 [; O1 X; [- `8 \
u0 m( ^ T5 [- |) r+ U: p- L5 z3 l# B6 s* v
lwip/port:添加ethernetif.c,lan8742.c(lan8720也可以用)
- O- K& R+ b+ q- m1 o. Y) T+ ~: ]
6 g+ j6 o$ j8 B9 h W9 t# _
" s# S! g8 Z, q$ l$ |- T9 R _9 y$ a; d4 L, {+ Q0 i2 F
移植准备工作就全部做完了,下一节修改工程报错
- ]9 w' a# C7 y4 A3 d' F
5 i6 c7 [ g9 Z4 [) J: Y3 M
! L. ?" a7 }+ y/ Y; ?7 \% g7 H( @6 e+ \; ? i9 I: l: m+ p
|