编写不易,转载请注明出处。
介绍两种移植方法
第一种:AFboot + Linux4.13.12 + Stm32_mini_rootfs.cpio.bz2
第二种:u-boot-2016.03 + Linux4.13.12 + Stm32_mini_rootfs.cpio.bz2
硬件平台:stm32f429-discovery
软件平台:ubuntu-12.04
1.交叉编译器下载
下载地址:https://launchpad.net/gcc-arm-embedded/+download
我下载的是gcc-arm-none-eabi-5_4-2016q3-20160926-linux.tar.bz2
安装交叉编译器。
2.下载linux4.13.12源码
下载地址:https://mirrors.edge.kernel.org/pub/linux/kernel/
下载Linux-4.13.12.tar.xz
3.下载uboot
下载地址:http://ftp.denx.de/pub/u-boot/
下载u-boot-2016.03.tar.bz2
4.下载afboot
下载地址:https://github.com/mcoquelin-stm32/afboot-stm32.git
下载afboot-stm32-master.zip
5.下载rootfs
下载地址:https://elinux.org/File:Stm32_mini_rootfs.cpio.bz2
下载Stm32_mini_rootfs.cpio.bz2
AFboot + Linux4.13.12+ Stm32_mini_rootfs.cpio.bz2
打开afboot的Makefile,可以看到kernel和dtb在FLASH中的位置
KERNEL_ADDR?=0x08008000
DTB_ADDR?=0x08004000
编译afboot:make stm32f429i-disco
得到stm32f429i-disco.bin。
文件系统使用initramfs,将下载的Stm32_mini_rootfs.cpio.bz2解压
先解压成cpio文件:bzip2 -d Stm32_mini_rootfs.cpio.bz2
创建文件夹rootfs:mkdir rootfs
将文件解压到rootfs文件夹中:cpio -idmv < ../Stm32_mini_rootfs.cpio
看看dev中是否有null,tty0,console节点,没有的话需要在dev文件夹中创建这三个节点。
sudo mknod console c 5 1
sudo mknod null c 1 3
sudo mknod tty0 c 204 64
在rootfs文件夹下面添加init文件,文件中添加下面的内容
#!/bin/sh
# devtmpfs does not get automounted for initramfs
/bin/mount -t devtmpfs devtmpfs /dev
exec 0</dev/console
exec 1>/dev/console
exec 2>/dev/console
exec /sbin/init $
配置Linux4.9内核:make stm32_defconfig
在menuconfig中添加rootfs文件的文件的路径
[*] Initial RAM filesystem and RAM disk (initramfs/initrd) support
(/work/system/my-linux/rootfs) Initramfs source file(s)
编译内核:make
生成的内核的路径:arch/arm/boot/xipImage
生成的设备树路径:arch/arm/boot/dts/stm32f429-disco.dtb
直接给xipImage和stm32f429-disco.dtb添加后缀名.bin,这样才可以通过j-flash或者st-link烧写到flash中。
烧写系统
stm32f429i-disco.bin烧写到0x08000000
stm32f429-disco.dtb.bin烧写到0x08004000
xipImage.bin烧写到0x08008000
.[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.13.12 (lyd@ubuntu) (gcc version 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496] (GNU Tools for ARM Embedded Processors)) #8 PREEMPT Thu Aug 9 02:55:36 PDT 2018
[ 0.000000] CPU: ARMv7-M [410fc241] revision 1 (ARMv7M), cr=00000000
[ 0.000000] CPU: unknown data cache, unknown instruction cache
[ 0.000000] OF: fdt: Machine model: STMicroelectronics STM32F429i-DISCO board
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping off. Total pages: 2032
[ 0.000000] Kernel command line: root=/dev/ram rdinit=/linuxrc
[ 0.000000] PID hash table entries: 32 (order: -5, 128 bytes)
[ 0.000000] Dentry cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.000000] Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.000000] Memory: 7772K/8192K available (1147K kernel code, 130K rwdata, 392K rodata, 61K init, 114K bss, 420K reserved, 0K cma-reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0x00000000 - 0x00001000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0x00000000 - 0xffffffff (4095 MB)
[ 0.000000] lowmem : 0x90000000 - 0x90800000 ( 8 MB)
[ 0.000000] .text : 0x08008000 - 0x08188fec (1540 kB)
[ 0.000000] .init : 0x9000a000 - 0x9000d000 ( 12 kB)
[ 0.000000] .data : 0x90008000 - 0x9002ba60 ( 143 kB)
[ 0.000000] .bss : 0x9002ba60 - 0x90048264 ( 115 kB)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[ 0.000000] /soc/interrupt-controller@40013c00: 23 External IRQs detected
[ 0.000000] clocksource: arm_system_timer: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 355517175 ns
[ 0.000000] ARM System timer initialized as clocksource
[ 0.000000] /soc/timer@40000c00: STM32 clockevent driver initialized (32 bits)
[ 0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns
[ 0.010000] Calibrating delay loop... 110.48 BogoMIPS (lpj=552448)
[ 0.100000] pid_max: default: 4096 minimum: 301
[ 0.100000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.100000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.100000] Hierarchical SRCU implementation.
[ 0.110000] devtmpfs: initialized
[ 0.160000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.160000] pinctrl core: initialized pinctrl subsystem
[ 0.200000] stm32f429-pinctrl soc:pin-controller: GPIOA bank added
[ 0.200000] stm32f429-pinctrl soc:pin-controller: GPIOB bank added
[ 0.200000] stm32f429-pinctrl soc:pin-controller: GPIOC bank added
[ 0.200000] stm32f429-pinctrl soc:pin-controller: GPIOD bank added
[ 0.200000] stm32f429-pinctrl soc:pin-controller: GPIOE bank added
[ 0.210000] stm32f429-pinctrl soc:pin-controller: GPIOF bank added
[ 0.210000] stm32f429-pinctrl soc:pin-controller: GPIOG bank added
[ 0.210000] stm32f429-pinctrl soc:pin-controller: GPIOH bank added
[ 0.210000] stm32f429-pinctrl soc:pin-controller: GPIOI bank added
[ 0.210000] stm32f429-pinctrl soc:pin-controller: GPIOJ bank added
[ 0.220000] stm32f429-pinctrl soc:pin-controller: GPIOK bank added
[ 0.220000] stm32f429-pinctrl soc:pin-controller: Pinctrl STM32 initialized
[ 0.290000] stm32-dma 40026000.dma-controller: STM32 DMA driver registered
[ 0.300000] stm32-dma 40026400.dma-controller: STM32 DMA driver registered
[ 0.300000] clocksource: Switched to clocksource arm_system_timer
[ 0.500000] workingset: timestamp_bits=30 max_order=11 bucket_order=0
[ 0.560000] random: fast init done
[ 0.600000] io scheduler noop registered (default)
[ 0.600000] io scheduler mq-deadline registered
[ 0.600000] io scheduler kyber registered
[ 0.600000] STM32 USART driver initialized
[ 0.600000] 40011000.serial: ttyS0 at MMIO 0x40011000 (irq = 32, base_baud = 5250000) is a stm32-usart
[ 0.980000] console [ttyS0] enabled
[ 0.990000] stm32_rtc 40002800.rtc: rtc core: registered 40002800.rtc as rtc0
[ 1.000000] stm32_rtc 40002800.rtc: Date/Time must be initialized
[ 1.010000] i2c /dev entries driver
[ 1.030000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
[ 1.040000] stm32_rtc 40002800.rtc: setting system clock to 2000-01-01 01:58:22 UTC (946691902)
[ 1.050000] Freeing unused kernel memory: 12K
[ 1.060000] This architecture does not have kernel memory protection.
/ # ls
bin dev etc init linuxrc proc sbin sys usr
/ #
u-boot-2016.03+ Linux4.13.12+ Stm32_mini_rootfs.cpio.bz2
配置uboot:make stm32f429-discovery_defconfig
编译uboot:make
生成uboot.bin
rootfs在按照前面讲的移植。
编译linux
有几个地方需要修改一下:
arch/arm/configs/stm32_defconfig中的CONFIG_DRAM_BASE改为0xD0000000.
arch/arm/boot/dts/stm32f429-disco.dts中的 reg = <0x90000000 0x800000>改为
reg = <0xD0000000 0x800000>。
还有一个地方,我在这卡了好久,一直都卡在start kernel。。。,后来使用emcraft提供的内核,发现可以正常运行,对比发现我移植的内核entey point和load address相同,而emcraft提供的内核entry point比load address大1,我按照emcraft的修改内核,发现linux13.12可以正常使用。具体的修改:scripts/Makefile.lib中修改UIMAGE_ENTRYADDR,如下所示
UIMAGE_LOADADDR ?= arch_must_set_this
UIMAGE_ENTRYADDR =$(shell echo $(UIMAGE_LOADADDR) | sed -e "s/..$$/01/")
UIMAGE_NAME ?= 'Linux-$(KERNELRELEASE)'
编译内核:make uImage LOADADDR=0xD0008000,生成uImage文件
编译设备树:make dtbs,生成stm32f429-disco.dtb
烧写系统
将uboot烧写到起始地址为0x08000000的flash中,使用uboot的命令loadb,将uImage传输到SDRAM中,地址为0xD0100000,将stm32f429-disco.dtb传输到0xD0300000位置。
bootm D0100000 - D0300000 启动Linux系统
U-Boot 2016.03 (Aug 10 2018 - 03:41:25 -0700)
DRAM: 8 MiB
WARNING: Caches not enabled
Flash: 2 MiB
*** Warning - bad CRC, using default environment
In: serial_stm32
Out: serial_stm32
Err: serial_stm32
Net: Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot: 0
U-Boot > loadb d0100000
## Ready for binary (kermit) download to 0xD0100000 at 115200 bps...
Starting kermit transfer. Press Ctrl+C to cancel.
Transferring uImage...
100% 1136 KB 8 KB/sec 00:02:07 0 Errors
## Total Size = 0x0011c080 = 1163392 Bytes
## Start Addr = 0xD0100000
U-Boot > loadb d0300000
## Ready for binary (kermit) download to 0xD0300000 at 115200 bps...
Starting kermit transfer. Press Ctrl+C to cancel.
Transferring stm32f429-disco.dtb...
100% 15 KB 15 KB/sec 00:00:01 0 Errors
## Total Size = 0x00003cbc = 15548 Bytes
## Start Addr = 0xD0300000
U-Boot > bootm d0100000 - d0300000
## Booting kernel from Legacy Image at d0100000 ...
Image Name: Linux-4.13.12
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1163328 Bytes = 1.1 MiB
Load Address: d0008000
Entry Point: d0008001
Verifying Checksum ... OK
## Flattened Device Tree blob at d0300000
Booting using the fdt blob at 0xd0300000
Loading Kernel Image ... OK
Loading Device Tree to d05cf000, end d05d5cbb ... OK
Starting kernel ...
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.13.12 (lyd@ubuntu) (gcc version 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496] (GNU Tools for ARM Embedded Processors)) #1 PREEMPT Fri Aug 10 20:52:19 PDT 2018
[ 0.000000] CPU: ARMv7-M [410fc241] revision 1 (ARMv7M), cr=00000000
[ 0.000000] CPU: unknown data cache, unknown instruction cache
[ 0.000000] OF: fdt: Machine model: STMicroelectronics STM32F429i-DISCO board
[ 0.000000] debug: ignoring loglevel setting.
[ 0.000000] On node 0 totalpages: 2048
[ 0.000000] free_area_init_node: node 0, pgdat d01d93e0, node_mem_map d07f0000
[ 0.000000] Normal zone: 16 pages used for memmap
[ 0.000000] Normal zone: 0 pages reserved
[ 0.000000] Normal zone: 2048 pages, LIFO batch:0
[ 0.000000] pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768
[ 0.000000] pcpu-alloc: [0] 0
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping off. Total pages: 2032
[ 0.000000] Kernel command line: console=ttyS0,115200 earlyprintk consoleblank=0 ignore_loglevel
[ 0.000000] PID hash table entries: 32 (order: -5, 128 bytes)
[ 0.000000] Dentry cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.000000] Inode-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.000000] Memory: 6036K/8192K available (1074K kernel code, 126K rwdata, 376K rodata, 212K init, 114K bss, 2156K reserved, 0K cma-reserved)
[ 0.000000] Virtual kernel memory layout:
[ 0.000000] vector : 0x00000000 - 0x00001000 ( 4 kB)
[ 0.000000] fixmap : 0xffc00000 - 0xfff00000 (3072 kB)
[ 0.000000] vmalloc : 0x00000000 - 0xffffffff (4095 MB)
[ 0.000000] lowmem : 0xd0000000 - 0xd0800000 ( 8 MB)
[ 0.000000] .text : 0xd0008000 - 0xd0114940 (1075 kB)
[ 0.000000] .init : 0xd0185000 - 0xd01ba000 ( 212 kB)
[ 0.000000] .data : 0xd01ba000 - 0xd01d9a60 ( 127 kB)
[ 0.000000] .bss : 0xd01d9a60 - 0xd01f6264 ( 115 kB)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[ 0.000000] /soc/interrupt-controller@40013c00: 23 External IRQs detected
[ 0.000000] clocksource: arm_system_timer: mask: 0xffffff max_cycles: 0xffffff, max_idle_ns: 331816030 ns
[ 0.000000] ARM System timer initialized as clocksource
[ 0.000000] /soc/timer@40000c00: STM32 clockevent driver initialized (32 bits)
[ 0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns
[ 0.010000] Calibrating delay loop... 14.25 BogoMIPS (lpj=71296)
[ 0.120000] pid_max: default: 4096 minimum: 301
[ 0.120000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.120000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.140000] Hierarchical SRCU implementation.
[ 0.160000] devtmpfs: initialized
[ 0.310000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.310000] pinctrl core: initialized pinctrl subsystem
[ 0.410000] stm32f429-pinctrl soc:pin-controller: GPIOA bank added
[ 0.420000] stm32f429-pinctrl soc:pin-controller: GPIOB bank added
[ 0.420000] stm32f429-pinctrl soc:pin-controller: GPIOC bank added
[ 0.430000] stm32f429-pinctrl soc:pin-controller: GPIOD bank added
[ 0.440000] stm32f429-pinctrl soc:pin-controller: GPIOE bank added
[ 0.440000] stm32f429-pinctrl soc:pin-controller: GPIOF bank added
[ 0.450000] stm32f429-pinctrl soc:pin-controller: GPIOG bank added
[ 0.450000] stm32f429-pinctrl soc:pin-controller: GPIOH bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOI bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOJ bank added
[ 0.470000] stm32f429-pinctrl soc:pin-controller: GPIOK bank added
[ 0.470000] stm32f429-pinctrl soc:pin-controller: Pinctrl STM32 initialized
[ 0.690000] stm32-dma 40026000.dma-controller: STM32 DMA driver registered
[ 0.730000] stm32-dma 40026400.dma-controller: STM32 DMA driver registered
[ 0.750000] clocksource: Switched to clocksource arm_system_timer
[ 1.280000] workingset: timestamp_bits=30 max_order=11 bucket_order=0
[ 1.460000] random: fast init done
[ 1.580000] io scheduler noop registered (default)
[ 1.580000] io scheduler mq-deadline registered
[ 1.580000] io scheduler kyber registered
[ 1.590000] STM32 USART driver initialized
[ 1.590000] 40011000.serial: ttyS0 at MMIO 0x40011000 (irq = 32, base_baud = 5625000) is a stm32-usart
[ 2.020000] console [ttyS0] enabled
[ 2.050000] stm32_rtc 40002800.rtc: rtc core: registered 40002800.rtc as rtc0
[ 2.060000] stm32_rtc 40002800.rtc: Date/Time must be initialized
[ 2.070000] i2c /dev entries driver
[ 2.120000] input: gpio_keys as /devices/platform/gpio_keys/input/input0
[ 2.130000] stm32_rtc 40002800.rtc: setting system clock to 2000-01-01 02:19:54 UTC (946693194)
[ 2.170000] Freeing unused kernel memory: 212K
[ 2.170000] This architecture does not have kernel memory protection.
/ # ls
bin dev etc init linuxrc proc sbin sys usr
/ #
我还试了linux4.9和linux4,17,其中linux4.9可以正常使用,linux4.17还有点问题。移植的问题搞定了,下可以漫长的驱动搬砖了。
这里了可以下载可执行文件,想偷懒的可以直接下载
https://download.csdn.net/download/u011371090/10597526
参考了下面这些文档,感谢编写这些资料的大神们
https://stackoverflow.com/questions/41321971/running-linux-4-9-on-cortex-m4-stm32f4-29i-disc1
https://blog.csdn.net/u010444107/article/details/78580947
https://blog.csdn.net/sinat_20006769/article/details/79059304