uClinux — специальная редакция ядра Linux, способная работать без блока управления памятью [MMU]. ARM Cortex-M MMU не имеют, поэтому на микроконтроллеры на этом ядре, полноценный Linux не поставишь (если только написать эмулятор, как это сделано здесь http://dmitry.gr/index.php?r=05.Projects&proj=07.%20Linux%20on%208bit для AVR).
Значит ставим uCLinux.
Простенькая инструкция по установке.
1. Качаем Linux
uClinux был объединен с основной веткой Linux kernel, поэтому можно брать последнюю стабильную версию ядра — https://www.kernel.org/pub/linux/kernel/ .
Для компиляции ядра у вас должен стоять компилятор ARM — берем отсюда — https://launchpad.net/gcc-arm-embedded .
2. Качаем initramfs
Качаем отсюда — http://elinux.org/images/5/51/Stm32_mini_rootfs.cpio.bz2 — и разархивируем.
mkdir rootfs
cd rootfs
wget http://elinux.org/images/5/51/Stm32_mini_rootfs.cpio.bz2
bzcat ./Stm32_mini_rootfs.cpio.bz2 | sudo cpio -i
rm ./Stm32_mini_rootfs.cpio.bz2
Данный initramfs уже содержит в себе Busybox, скомпилированный для нашей платформы. Поэтому, при компиляции ядра, просто выберем использовать initramfs и укажем путь к нему — см. следующий пункт.
Более подробно про создание initramfs и busybox можно почитать эту статью — https://badembed.ru/qemu-busybox-linux-kernel .
3. Компилируем uClinux
make ARCH=arm CROSS_COMPILE=arm-none-eabi- stm32_defconfig
Далее открываем появившейся файл .config в корне исходников ядра Linux, находим в нем строку CONFIG_INITRAMFS_SOURCE и прописываем путь к нашему initramfs (который вы разархивировали на предыдущем этапе).
CONFIG_INITRAMFS_SOURCE="/home/alex/uclinux_stm32_v2/rootfs"
Далее:
make ARCH=arm CROSS_COMPILE=arm-none-eabi-
На запрос INITRAMFS_ROOT_UID и INITRAMFS_ROOT_GID ставим 0.
4. Качаем и компилируем Bootloader
git clone https://github.com/afaerber/afboot-stm32
cd afboot-stm32
make
5. Заливаем все на STM32F429 DISCO
Заливаем через ST-LINK утилиту — качаем отсюда — https://github.com/texane/stlink
Нужно залить Bootloader, Device Tree и сам kernel
NOTE: Device Tree позволяет конфигурировать оборудовaние во время загрузки при помощи специальных dts-файлов и мeнять установки без пересборки ядра.
st-flash --reset write afboot-stm32/test.bin 0x08000000
st-flash --reset write linux/arch/arm/boot/dts/stm32f429-disco.dtb 0x08004000
st-flash --reset write linux/arch/arm/boot/xipImage 0x08008000
6. Проверяем загрузку Linux на STM32F429 DISCO:
Смотрим linux/arch/arm/boot/dts/stm32f429-disco.dts и определяем на какой USART выведен serial0. В моем случае на USART1:
serial0 = &usart1;
Подключаем к данному USART (USART1 это ножки PA9 PA10) переходник USART<->RS232 или USART<->USB-virtual-com-port, открываем в каком либо serial port терминале (например minicom) serial port этого переходника. Параметры — 115200-8n1.
Перезагружаем STM32F429 DISCO через кнопочку reset на плате и видим:
[ 0.000000] Booting Linux on physical CPU 0x0
[ 0.000000] Linux version 4.8.6 (alex@alex-N56VZ) (gcc version 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496] (GNU Tools for ARM Embedded Processo6
[ 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: 7880K/8192K available (863K kernel code, 63K rwdata, 276K rodata, 56K init, 102K bss, 312K 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 - 0x08124d7c (1140 kB)
[ 0.000000] .init : 0x9000a000 - 0x9000d000 ( 12 kB)
[ 0.000000] .data : 0x90008000 - 0x9001ac40 ( 76 kB)
[ 0.000000] .bss : 0x9001ac40 - 0x90034574 ( 103 kB)
[ 0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[ 0.000000] Preemptible hierarchical RCU implementation.
[ 0.000000] Build-time adjustment of leaf fanout to 32.
[ 0.000000] NR_IRQS:16 nr_irqs:16 16
[ 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... 118.68 BogoMIPS (lpj=593408)
[ 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.110000] devtmpfs: initialized
[ 0.140000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[ 0.140000] pinctrl core: initialized pinctrl subsystem
[ 0.210000] stm32-dma 40026000.dma-controller: STM32 DMA driver registered
[ 0.220000] stm32-dma 40026400.dma-controller: STM32 DMA driver registered
[ 0.220000] clocksource: Switched to clocksource arm_system_timer
[ 0.400000] workingset: timestamp_bits=30 max_order=11 bucket_order=0
[ 0.460000] io scheduler noop registered (default)
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOA bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOB bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOC bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOD bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOE bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOF bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOG bank added
[ 0.460000] stm32f429-pinctrl soc:pin-controller: GPIOH bank added
[ 0.470000] stm32f429-pinctrl soc:pin-controller: GPIOI bank added
[ 0.470000] stm32f429-pinctrl soc:pin-controller: GPIOJ bank added
[ 0.480000] stm32f429-pinctrl soc:pin-controller: GPIOK bank added
[ 0.480000] stm32f429-pinctrl soc:pin-controller: Pinctrl STM32 initialized
[ 0.480000] STM32 USART driver initialized
[ 0.480000] 40011000.serial: ttyS0 at MMIO 0x40011000 (irq = 17, base_baud = 5625000) is a stm32-usart
[ 0.830000] console [ttyS0] enabled
[ 0.850000] Freeing unused kernel memory: 12K (9000a000 - 9000d000)
[ 0.860000] This architecture does not have kernel memory protection.
На этом все.
Также смотрим:
http://elinux.org/STM32
https://github.com/lag-linaro/stm32/blob/master/quickstart.sh
https://en.opensuse.org/openSUSE:ARM_Tech_Symposia_2014/STM32F429
https://github.com/jserv/stm32f429-linux-builder