在之前的博文 Linux Kernel 之一 完整嵌入式 Linux 环境、构建工具、编译工具链、CPU 体系架构 中说了要一步步搭建整个嵌入式 Linux 运行环境,今天主要学习一下将 Linux 内核适配 STM32F769I-EVAL 开发板。
文中涉及的源代码均放到了我个人的 Github 上:https://github.com/ZCShou/BOARD-STM32F769I-EVAL
。这个仓库中包含了要搭建的完整嵌入式 Linux 环境的所有源代码,后续博文均以该仓库中的源码为基础来学习!
我这里使用的基本开发环境依旧是在之前博文中多次说明的 Ubuntu 22.04.1 LTS + Arm GNU Toolchain 11.3.Rel1,对应的 J-link 也依旧是 J-Link_Linux_V764e_x86_64.deb。该环境下需要注意的问题说明如下:
arm-none-eabi-gdb
报错如下:sudo add-apt-repository ppa:deadsnakes/ppa -y
sudo apt install python3.8
我使用的是 VSCode 来查看 U-Boot + Kernel 源代码,为了查看方便,我把不需要的文件进行了隐藏,通过将不需要的文件排除在外,加快搜索等操作的执行,也避免了过多无用结果。以下是我的 VSCode 配置:
{
"files.exclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"u-boot-v2021.10":true,
// arch
"**/mips": true,
"**/powerpc": true,
"**/riscv": true,
"**/ti": true,
"**/x86": true,
"**/sandbox": true,
"**/arch/{arc,m68k,microblaze,mips,nios2,powerpc,riscv,sandbox,sh,x86,xtensa,um,sparc,s390,parisc,openrisc,nds32,ia64,hexagon,h8300,csky,arm64,alpha}": true,
// cpu
"**/arch/arm/cpu/{arm11,arm720t,arm920t,arm926ejs,arm946es,arm1136,arm1176,armv7,armv8}": true,
// machine
"**/arch/arm/mach-[^s]*": true,
"**/arch/arm/mach-s[^t]*": true,
"**/arch/arm/mach-st[^m]*": true,
"**/arch/arm/mach-stm32[$^m]*": true,
// dts
"**/dts/[^s|^M|^i|^a|^d|^.]*": true,
"**/dts/d[^t]*": true,
"**/dts/i[^n]*": true,
"**/dts/in[^c]*": true,
"**/dts/a[^r]*": true,
"**/dts/ar[^m]*": true,
"**/dts/arm[^v]*": true,
"**/dts/s[^t]*": true,
"**/dts/st[^m|^-]*": true,
"**/dts/stm32[^f]*": true,
"**/dts/stm32f[^7]*": true,
"**/dts/stm32f7[^6|4|^-]*": true,
"**/dts/stm32f769-[^e|d|p]*": true,
// configs
"**/configs/[^s]*": true,
"**/configs/s[^t]*": true,
"**/configs/st[^m]*": true,
"**/configs/stm[^3]*": true,
// "**/configs/stm3[^2]*": true,
"**/configs/stm32[^f|^_]*": true,
"**/configs/stm32f[^7]*": true,
// "**/configs/stm32f7[^6|^4]*": true,
// "**/configs/stm32f769-[^e]*": true,
// board
"**/board/[^s]*": true,
"**/board/s[^t]*": true,
"**/board/ste": true,
"**/board/sto*": true,
"**/board/st/st[^m]*": true,
"**/board/st/stm32[^f]*": true,
// "**/board/st/stm32f[^7]*": true,
// "**/board/st/stm32f7[^6|^4]*": true,
},
"editor.insertSpaces": false
}
我使用的嵌入式环境是 STM32F769I-EVAL 板子。STM32F769I-EVAL 板子使用的 STM32F769NI 这个 MCU,STM32F769NI 这款 MCU 采用的是 ARM Cortex-M7 的核心,指令集架构是 ARMv7m。此外,还需要注意,这个板子上的的串口的 RX 默认是断开,需要用短路帽连接起来。
Linux 内核本身提供了对于 STM32 的支持,不过并没有提供 STM32F769I-EVAL 板子对应的设备树文件。配置文件是 ./arch/arm/configs/stm32_defconfig
。不过,这个文件更像是一个 DEMO,其中的有些内容并不符合我们的 STM32F769I-EVAL 开发板,本篇博文的移植主要就是添加对于 STM32F769I-EVAL 板子的支持。
绝大多数情况下,移植工作都不是从零开始。Linux Kernel 中默认提供了对于 STM32F769-disco 的支持,STM32F769I-EVAL 的移植完全可以参考它来进行。此外,在博文 U-Boot 之二 移植过程详解、 STM32F769I-EVAL 开发板适配 已经将学习过设备树相关的适配,而 U-Boot 的设备数文件和 Linux 内核中的是基本一致的。
增加 STM32F769-eval 设备树文件:./arch/arm/boot/dts/stm32f769.dtsi
和 ./arch/arm/boot/dts/stm32f769-eval.dts
。stm32f769.dtsi
是直接复制的 stm32f746.dtsi
然后更名的,没有任何修改;stm32f769-pinctrl.dtsi
原来就存在,不需要改动;stm32f769-eval.dts
是直接复制的 stm32f769-disco.dts
,然后做了如下更改:
将新增的 stm32f769-eval.dts
添加到 ./arch/arm/boot/dts/Makefile
中,否则编译系统不会编译我们新增的设备树文件。
编辑 ./arch/arm/mach-stm32/board-dt.c
,在其中增加自己的 MCU 。由于 Linux 本身提供了对于 STM32F769-disco 开发板的支持,因此这里面已经有了 STM32F769
,因此,我们 board-dt.c
不要更改。
此外,还需要在 MCU 这一级的 Kconfig 文件 ./arch/arm/mach-stm32/Kconfig
中添加我们的 MCU。同样,由于 Kconfig 中已经存在 MAC_STM32F769
了,这里我也不需要更改。此外,这里默认选择了全部 MCU,我修改为只选中 STM32F769
。也可以后面在 menuconfig 中手动更改,效果是一样的。
将 STM32 的配置添加到 ARM 架构这一级的 ./arch/arm/Kconfig
配置系统中。同样,由于 Linux 本身提供了对于 STM32F769-disco 开发板的支持,因此这里面已经有了 ./arch/arm/mach-stm32/Kconfig
,因此,不需要更改。
这里需要注意,我们的 STM32F769 是没有 mmu 的,因此,实际在 ./arch/arm/Kconfig-nommu
文件中有很多真多我们的 MCU 的默认配置,这里不需要修改,后面可以直接使用 stm32_deconfig
文件中的配置覆盖这些默认配置。
将 ARM 架构添加到架构一级的总的 Kconfig 系统 ./arch/Kconfig
中。同样,由于 Linux 本身提供了对于 STM32 的支持,这里不需要改动。
修改默认的配置文件:./arch/arm/configs/stm32_defconfig
。在 Linux Kernel 中,所有 STM32 共用这一个配置文件,这个文件中的部分内容并不能适合我们的开发板。如果不想修改这个文件,我们可以直接新建一个 stm32f769_defconfig
,主要修改如下:
之所以在这个配置文件中修改配置是为了不用每次编译都在 ARCH=arm CROSS_COMPILE=arm-none-eabi- make O=build_stm32 menuconfig
进行修改,一劳永逸!
上面的移植仅仅是在 Linux Kernel 中添加了 STM32F769I-EVAL 的支持,接下来还需要根据 STM32F769I-EVAL 的手册修改移植的文件内容,使其完全符合 STM32F769I-EVAL 中各种资源的定义。
注意,Linux Kernel 中的设备树与 U-Boot 中的基本是一致的(U-Boot 的文件就来自于 Linux Kernel),因此,完全可以直接参照在 在博文 U-Boot 之二 移植过程详解、 STM32F769I-EVAL 开发板适配 中的适配过程。甚至直接对比文件复制相关改动即可。
根据 STM32F769I-EVAL 手册说明,DRAM 应该是 32MB,这里显示是 16 MiB,显然是不对的。
STM32F769I-EVAL 手册中说 DRAM 芯片是 IS42S32800G-6BLI,我们需要根据手册,修改 FMC 在设备树文件中有描述。
STM32F769-EVAL 开发板上是有 SD 卡的。但是这里显示没有卡。不出意外的话,这里是由于 STM32F769-Disco 与 STM32F769-EVAL 在这方面配置不同导致。下图是两款开发板关于 SD 卡的说明:
从中我们可以看出,两款开发板使用的 SDMMC 并不相同!EVAL 开发板有两个 SD 卡插槽:SD1 -> SDMMC1
,SD2 -> SDMMC2
。而 Discovery 板子只有一个 SD卡插槽:SD -> SDMMC2
。关键在于 SDMMC2 的管脚使用是不一样的!