Le processeur STM32MP157 de STMicroelectronics, basé sur une architecture hétérogène double cœur Cortex-A7 et un cœur Cortex-M4, nécessite une phase de portage spécifique du chargeur d'amorçage U-Boot pour s'adapter aux différentes configurations matérielles. Cette procédure détaille l'adaptation du code source officiel pour un système embarqué personnalisé doté de 1 Go de RAM et d'un stockage eMMC.
1. Préparation du code source et application des patchs
Après avoir extrait l'archive du code source d'U-Boot (version 2020.01), il est indispensable d'appliquer les correctifs fournis par le constructeur pour garantir la compatibilité avec l'architecture STM32MP1. Utilisez la commande suivante pour intégrer tous les fichiers de patch situés dans le répertoire parent :
find ../ -name "*.patch" -type f -exec patch -p1 -i {} \;
2. Création d'une configuration de plateforme personanlisée
Pour ne pas altérer les fichiers génériques, nous créons une configuration spécifique à notre carte en nous basant sur le profil "trusted" de ST :
cp configs/stm32mp15_trusted_defconfig configs/stm32mp15_custom_defconfig
L'étape suivante consiste à adapter l'arbre de périphériques (Device Tree). Les fichiers DTS doivent être dupliqués et renommés :
cp arch/arm/dts/stm32mp15xx-dkx.dtsi arch/arm/dts/stm32mp15xx-custom.dtsicp arch/arm/dts/stm32mp157a-dk1.dts arch/arm/dts/stm32mp157a-custom.dtscp arch/arm/dts/stm32mp157a-dk1-u-boot.dtsi arch/arm/dts/stm32mp157a-custom-u-boot.dtsi
Dans stm32mp157a-custom.dts, mettez à jour l'inclusion du fichier d'en-tête pour pointer vers votre nouveau fichier .dtsi et modifiez la propriété model.
Dans le fichier stm32mp15xx-custom.dtsi, il est crucial d'ajuster la capacité de la mémoire vive si elle diffère du modèle de référence (512 Mo). Pour 1 Go de RAM, modifiez le nœud memory comme suit :
memory@c0000000 {
device_type = "memory";
reg = <0xc0000000 0x40000000>; /* 1 Go de RAM */
};
Enfin, mettez à jour le Makefile dans arch/arm/dts/ pour inclure votre nouveau binaire d'arbre de périphériques (stm32mp157a-custom.dtb) dans la liste de compilation.
3. Configuration de l'environnement de compilation
Modifiez le Makefile principal à la racine du projet pour définir l'architecture et le préfixe de la chaîne de compilation croisée :
ARCH = arm
CROSS_COMPILE = arm-none-linux-gnueabihf-
Dans le fichier Makefile.sdk situé au niveau supérieur, spécifiez l'arbre de périphériques cible :
DEVICE_TREE ?= stm32mp157a-custom
4. Ajustements du code source pour le déploiement
Pour autoriser le flashage via USB OTG sans restriction, il est parfois nécessaire de modifier board/st/stm32mp1/stm32mp1.c en commentant les lignes forçant certains modes de démarrage spécifiques (comme BOOT_FASTBOOT ou BOOT_STM32PROG).
Créez un script nommé build_uboot.sh pour automatiser le processus :
#!/bin/bash
make stm32mp15_custom_defconfig
cp .config ../build-output/
make distclean
make -f $PWD/../Makefile.sdk all UBOOT_CONFIGS=stm32mp15_custom_defconfig,trusted,u-boot.stm32
5. Adaptation des périphériques : ADC et Ethernet
Désactivation de l'ADC
Le firwmare officiel tente parfois de vérifier le courant d'entrée via l'ADC. Si votre circuit d'alimentation diffère, cela peut bloquer le démarrage. Désactivez l'ADC via make menuconfig :
- Désélectionner :
Command line interface > Device access commands > adc - Désélectionner :
Device Drivers > Enable ADC drivers
Configuraton du contrôleur Ethernet (PHY AR8031)
Si vous utilisez un contrôleur PHY Atheros AR8031, des registres spécifiques doivent être configurés dans drivers/net/phy/phy.c au sein de la fonction phy_probe pour stabiliser le lien et activer l'horloge 125 MHz :
/* Configuration spécifique AR8031 */
u16 reg_val;
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0003);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x805d);
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4003);
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, reg_val & ~(1 << 8)); /* Désactivation SmartEEE */
/* Activation sortie CLK 125MHz */
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x0007);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, 0x8016);
phy_write(phydev, MDIO_DEVAD_NONE, 0xd, 0x4007);
reg_val = phy_read(phydev, MDIO_DEVAD_NONE, 0xe);
phy_write(phydev, MDIO_DEVAD_NONE, 0xe, (reg_val & 0xffe3) | 0x0018);
6. Support de l'eMMC et démarrage final
Pour activer le stockage eMMC sur l'interface SDMMC2, ajoutez le nœud suivant dans votre fichier .dtsi :
&sdmmc2 {
pinctrl-names = "default", "opendrain", "sleep";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
non-removable;
no-sd;
no-sdio;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&vdd>;
status = "okay";
};
Une fois compilé et flashé, vous pouvez définir les variables d'environnement dans la console U-Boot pour charger le noyau Linux depuis l'eMMC (périphérique 1) :
setenv bootargs 'console=ttySTM0,115200 root=/dev/mmcblk1p3 rootwait rw'
setenv bootcmd 'ext4load mmc 1:2 0xc2000000 uImage; ext4load mmc 1:2 0xc4000000 custom.dtb; bootm 0xc2000000 - 0xc4000000'
saveenv
reset