Linux Embedded

Le blog des technologies libres et embarquées

Construire un micrologiciel M4 pour l'iMX8 depuis Yocto

​Construire un micrologiciel M4 pour l’iMX8 depuis Yocto

Dans le contexte de mon stage de fin d'études au sein de la société Smile ECS, j’ai été amené à travailler sur un projet nécessitant la communication entre un microcontrôleur et un processeur d’application sur une carte Boundary Devices Nitrogen8M Mini.

Le microcontrôleur en question est un Cortex-M4F intégré à l’iMX8M Mini de NXP qui est cadencé à 400MHz. Ce microcontrôleur est utilisé pour des applications temps réel et est capable de communiquer avec le processeur d’application via diverses “mailbox” implémentées dans le SoC. Le micrologiciel du microcontrôleur doit être compilé avec un compilateur croisé fourni avec le kit de développement logiciel MCUXpresso fourni par NXP.

Un problème récurrent lors du développement d’un micrologiciel est la compilation de celui-ci. En effet, il est nécessaire de compiler le micrologiciel avec un compilateur croisé, ce qui peut être problématique lorsque l’on souhaite utiliser des bibliothèques externes. De plus, peu de documentation est disponible sur le sujet.

La manière la plus classique est de compiler ce logiciel sur un système Linux et d’intégrer l’exécutable final dans une recette Yocto. Cependant, cette méthode est peu pratique et nécessite de recompiler le micrologiciel à chaque modification et de le réintégrer dans la recette Yocto. Il est également nécessaire de reproduire le même environnement de compilation si un autre développeur souhaite travailler sur le micrologiciel, ce qui n’est pas acceptable pour un projet qui doit être reproductible.

Dans ce post, nous allons voir comment compiler un micrologiciel pour la cible Cortex-M4F depuis Yocto, en utilisant un compilateur croisé et en utilisant le SDK fourni par NXP. Nous verrons également comment intégrer ces recettes dans un SDK généré par Yocto pour une utilisation externe.

Prérequis

Pour suivre ce tutoriel, il est nécessaire d’avoir un système Linux et de disposer d’un environnement Yocto fonctionnel. On se focalisera sur la carte Boundary Devices Nitrogen8M Mini.

Tout les layers ont été réalisés avec la version Kirkstone (4.0) de Yocto et MCUxpresso 2.3.0.

Création d’un layer

La première étape est de créer un layer Yocto pour notre projet. Pour cela, on crée un dossier meta-mcuxpresso dans le dossier layers de notre environnement :

$ cd <chemin vers l'environnement Yocto>
$ mkdir layers
$ bitbake-layers create-layer meta-mcuexpresso
$ bitbake-layers add-layer meta-mcuexpresso

Le découpage de notre layer sera le suivant:

meta-mcuxpresso
├── conf
│   └── layer.conf
├── recipes-devtools
│    ├── recipes-core
│    |  └── packagegroups
│    |       └── nativesdk-packagegroup-sdk-host.bbappend
|    └── external-arm-toolchain
│       ├── arm-binary-toolchain.inc
│       └── gcc-arm-none-eabi_10.3-2021.10.bb
│── recipes-mcuxpresso
│    └── mcuxpresso
│        ├── files
│        │   └── mcuxpresso.sh
│        └── mcuxpresso_2.3.0.bb
└──  recipes-mcuxhelloworld
     └── mcuxhelloworld
         ├── files
         │   └── *.c *.h *.ld *.cmake
         └── mcuxhelloworld_1.0.bb

La recette devtools permet d’installer le SDK de NXP sur la machine hôte, la recette mcuxpresso permet d’installer le SDK sur la cible et la recette mcuxhelloworld est un exemple d’application utilisant le SDK.

Ajout du compilateur croisé

Pour compiler notre logiciel, nous allons utiliser le compilateur croisé GCC 10.3 recommandé par NXP. Pour cela, nous allons utiliser un dérivé de la layer meta-arm, qui contient déjà des recettes pour l’intégration de GCC dans Yocto. Il est possible de ne pas utiliser notre recette et d’utiliser directement les recettes de meta-arm, mais nous avons choisi de créer notre propre recette pour plus de clarté et de reproductibilité.

Nous allons créer une recette pour le compilateur croisé dans notre layer Yocto. Pour cela, on crée le dossier recipes-devtools/external-arm-toolchain dans notre layer et le fichier recette gcc-arm-none-eabi_10.3-2021.10.bb:

# Copyright (C) 2019 Garmin Ltd. or its subsidiaries
# Released under the MIT license (see COPYING.MIT for the terms)

require arm-binary-toolchain.inc

COMPATIBLE_HOST = "(x86_64|aarch64).*-linux"

SUMMARY = "Baremetal GCC for ARM-R and ARM-M processors"
LICENSE = "GPL-3.0-with-GCC-exception & GPL-3.0-only"

LIC_FILES_CHKSUM = "file://share/doc/gcc-arm-none-eabi/license.txt;md5=c18349634b740b7b95f2c2159af888f5"

PROVIDES = "virtual/arm-none-eabi-gcc"

SRC_URI = "https://developer.arm.com/-/media/Files/downloads/gnu-rm/${PV}/${BP}-${HOST_ARCH}-linux.tar.bz2;name=gnu-rm-${HOST_ARCH}"
SRC_URI[gnu-rm-aarch64.sha256sum] = "f605b5f23ca898e9b8b665be208510a54a6e9fdd0fa5bfc9592002f6e7431208"
SRC_URI[gnu-rm-x86_64.sha256sum] = "97dbb4f019ad1650b732faffcc881689cedc14e2b7ee863d390e0a41ef16c9a3"

UPSTREAM_CHECK_URI = "https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads"
UPSTREAM_CHECK_REGEX = "${BPN}-(?P<pver>.+)-${HOST_ARCH}-linux\.tar\.\w+"

Pour plus de lisibilité et de maintenabilité, on a choisi de placer les fonctions de la recette dans le fichier arm-binary-toolchain.inc présent dans le même dossier :

INHIBIT_DEFAULT_DEPS = "1"

FILES:${PN} = "${libexecdir} ${bindir}"

BINNAME = "${@d.getVar("BPN").strip("gcc-")}"

do_install() {
    install -d ${D}${bindir} ${D}${libexecdir}/${BPN}/
    cp -r ${S}/. ${D}${libexecdir}/${BPN}

    # Symlink all executables into bindir
    for f in ${D}${libexecdir}/${BPN}/bin/*; do
        ln -rs $f ${D}${bindir}/$(basename $f)
    done
}

INSANE_SKIP:${PN} = "already-stripped libdir staticdev file-rdeps arch dev-so"

INHIBIT_SYSROOT_STRIP = "1"
INHIBIT_PACKAGE_STRIP = "1"
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"

BBCLASSEXTEND = "native nativesdk"

Cette recette est très simple, elle se contente de télécharger l’archive contenant le compilateur croisé et de l’installer dans le dossier /usr/libexec/gcc/arm-none-eabi/. Enfin, tous les outils sont liés dans le dossier /usr/bin/ où nous pourrons les utiliser directement.

Le compilateur croisé peut maintenant être utilisé en modifiant les variables d'environnement de recette contenant le micrologiciel par exemple.

Ajouter MCUXpresso SDK

Nous avons maintenant un compilateur croisé pour notre micrologiciel, il est maintenant nécessaire d’ajouter le SDK fourni par NXP. Pour cela, nous devons récupérer le SDK depuis le dépôt GitHub de NXP et l’ajouter à notre layer. On crée un dossier recipes-mcuxpresso dans notre layer et on y ajoute le ficher de recette mcuxpresso_2.12.0.bb :

SUMMARY = "MCUXpresso recipe"
DESCRIPTION = "NXP MCUXpresso for Yocto"
LICENSE = "BSD-3-Clause & Apache-2.0"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9 \
                     file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"

PROVIDES = "virtual/mcuxpresso"
BBCLASSEXTEND = "native nativesdk"
DEPENDS += "gcc-arm-none-eabi-native"

S = "${WORKDIR}"

# Clone from git repository and add custom files
SRCREV = "08209840456f5f543b3debc5603c3dbe2b40a2eb"
SRC_URI = "git://github.com/nxp-mcuxpresso/mcux-sdk.git;protocol=https;branch=main \
           "
SRC_URI:append:class-nativesdk = " \
            file://mcuxpresso.sh \
"

# Install the SDK to the sysroot-native in /usr/include/mcuxpresso
do_install() {
    # Create the include directory for the SDK
    install -d ${D}${includedir}
    mkdir -p ${D}${includedir}/mcux-sdk

    # Copy the mcuxpresso SDK root to the include directory
    cp -r ${S}/git/* ${D}${includedir}/mcux-sdk/
}

do_install:append:class-nativesdk() {
    # Create the include directory for the SDK
    install -d ${D}${base_prefix}
    mkdir -p ${D}${base_prefix}/mcux-sdk

    # Copy the mcuxpresso SDK root to the include directory
    cp -r ${S}/git/* ${D}${base_prefix}/mcux-sdk/

    # We want to add the environment-setup.d script to set the environment variables
    mkdir -p ${D}${SDKPATHNATIVE}/environment-setup.d
    install -m 644 ${WORKDIR}/mcuxpresso.sh ${D}${SDKPATHNATIVE}/environment-setup.d/mcuxpresso-setup.sh
}

# The SDK contains binaries for whatever reason
INSANE_SKIP:${PN} += "already-stripped staticdev dev-so ldflags arch"
INSANE_SKIP:${PN}-dev += "already-stripped staticdev dev-so ldflags arch"
INSANE_SKIP:${PN}-dbg += "already-stripped staticdev dev-so ldflags arch"

FILES:${PN} += "${includedir}/mcux-sdk"
FILES:${PN}:append:class-nativesdk = " ${base_prefix}/mcux-sdk ${SDKPATHNATIVE}/environment-setup.d/mcuxpresso-setup.sh"

Dans la création d’un package "native", nous copions le SDK dans le dossier /usr/include/mcux-sdk et nous ajoutons un script environment-setup.d qui sera utilisé lors de l'utilisation du SDK Yocto pour définir les variables d’environnement.

La variable Yocto SDKPATHNATIVE contient le chemin vers le dossier contenant les SDK pour notre machine hôte. Dans notre cas cela correspond à  x86_64-pokysdk-linux vu que nous construisons notre image sur une machine x86_64.

La variable Yocto base_prefix contient le chemin vers la racine du SDK.

Enfin, il reste plus qu’a ajouter les variables d’environnement qui seront utilisées par le SDK dans notre image. Dans notre recette, nous ajoutons au dossier files le fichier mcuxpresso.sh:

export MCUXPRESSO_SDK="$OECORE_NATIVE_SYSROOT/mcux-sdk/"
export MCUXPRESSO_CMAKE_TOOLCHAIN="$MCUXPRESSO_SDK/tools/cmake_toolchain_files/armgcc.cmake"
export ARMGCC_DIR="$OECORE_NATIVE_SYSROOT/usr/"

Ce fichier est copié dans le dossier environment-setup.d du SDK et sera utilisé lors de l'utilisation du SDK pour définir les variables d’environnement que nous aurons besoin pour compiler notre application.

A noté qu'à l’étape de QA, nous devons malheureusement ignorer les erreurs already-stripped, staticdev, dev-so et ldflags car le SDK contient des fichiers pré-compilés pour une autre architecture que la nôtre et celle de l’architecture cible (aarch64 contre armv6/Thumb2).

Créer une application utilisant le compilateur croisé

Bien évidemment, il est inutile d’avoir un compilateur croisé et le SDK de NXP si nous ne l’utilisons pas. Pour cela, nous allons créer une application simple qui utilise le SDK et le compilateur croisé. Il s'agit d'un simple programme affichant “Hello World” sur la console série intégrée au microcontrôleur.

Nous allons partir de l’exemple hello_world fourni par NXP dans le cadre de l’utilisation du SDK et nous allons le modifier pour qu’il utilise notre compilateur croisé et notre intégration de MCUXpresso dans Yocto.

L’exemple d’NXP peut être trouvé ici: Hello World

Pour commencer, nous allons simplifier l’exemple afin qu'il contienne uniquement ce dont nous avons besoin:

$ git clone https://github.com/nxp-mcuxpresso/mcux-sdk-examples.git
# Pour avoir la version utilisée dans ce tutoriel
# $ cd mcux-sdk-examples; git checkout def4ae062c0528e791b4a16a627528438cfa0b15
# On se place dans le dossier contenant l'exemple
$ cd mcux-sdk-examples/evkmimx8mm/demo_apps/hello_world
# On compie les scripts de link
$ mv armgcc/MIMX8MM6xxxxx_cm4_ddr_ram.ld \
  armgcc/MIMX8MM6xxxxx_cm4_flash.ld \
  armgcc/MIMX8MM6xxxxx_cm4_ram.ld .
# On copie la configuration CMake
$ mv config.cmake flags.cmake .
# On peut supprimer les fichiers inutiles dans notre cas
$ rm -rf armgcc/ hello_world_v3_10.xml

Voici l’arborescence de notre dossier de travail final :

$ tree
.
├── empty_rsc_table.c
├── flags.cmake
├── MIMX8MM6xxxxx_cm4_ddr_ram.ld
├── MIMX8MM6xxxxx_cm4_flash.ld
├── MIMX8MM6xxxxx_cm4_ram.ld
├── fsl_iomuxc.h
├── hello_world.c
├── pin_mux.c
├── pin_mux.h
└── readme.txt

Il manque encore le fichier CMakeLists.txt. Nous allons le créer et y ajouter le contenu suivant :

# CROSS COMPILER SETTING
SET(CMAKE_SYSTEM_NAME Generic)
CMAKE_MINIMUM_REQUIRED (VERSION 3.10.0)

# ENABLE ASM
ENABLE_LANGUAGE(ASM)
SET(CMAKE_STATIC_LIBRARY_PREFIX)
SET(CMAKE_STATIC_LIBRARY_SUFFIX)
SET(CMAKE_EXECUTABLE_LIBRARY_PREFIX)
SET(CMAKE_EXECUTABLE_LIBRARY_SUFFIX)

# CURRENT DIRECTORY
SET(ProjDirPath ${CMAKE_CURRENT_SOURCE_DIR})

if (DEFINED ENV{MCUXPRESSO_SDK})
    SET(SdkRootDirPath "$ENV{MCUXPRESSO_SDK}")
else()
    SET(SdkRootDirPath "${ProjDirPath}/../../../../..")
endif()

if (NOT DEFINED SdkRootDirPath)
    SET(SdkRootDirPath ${SdkRootDirPath})
endif()

# Set toolchain file
if (NOT DEFINED CMAKE_TOOLCHAIN_FILE)
    if (DEFINED ENV{MCUXPRESSO_CMAKE_TOOLCHAIN})
        SET(CMAKE_TOOLCHAIN_FILE "$ENV{MCUXPRESSO_CMAKE_TOOLCHAIN}")
    else()
        SET(CMAKE_TOOLCHAIN_FILE ${SdkRootDirPath}/tools/cmake_toolchain_files/armgcc.cmake)
    endif()
endif()

SET(EXECUTABLE_OUTPUT_PATH ${ProjDirPath}/${CMAKE_BUILD_TYPE})
SET(LIBRARY_OUTPUT_PATH ${ProjDirPath}/${CMAKE_BUILD_TYPE})

project(hello_world)
set(MCUX_BUILD_TYPES debug release ddr_debug ddr_release flash_debug flash_release)
set(MCUX_SDK_PROJECT_NAME boot.elf)
if (NOT DEFINED SdkRootDirPath)
    SET(SdkRootDirPath ${SdkRootDirPath})
endif()

include(${ProjDirPath}/flags.cmake)
include(${ProjDirPath}/config.cmake)

add_executable(${MCUX_SDK_PROJECT_NAME}
"${ProjDirPath}/main.c"
"${ProjDirPath}/pin_mux.c"
"${ProjDirPath}/pin_mux.h"
"${SdkRootDirPath}/boards/evkmimx8mm/board.c"
"${SdkRootDirPath}/boards/evkmimx8mm/board.h"
"${SdkRootDirPath}/boards/evkmimx8mm/clock_config.c"
"${SdkRootDirPath}/boards/evkmimx8mm/clock_config.h"
"${ProjDirPath}/fsl_iomuxc.h"
"${ProjDirPath}/empty_rsc_table.c"
)

target_include_directories(${MCUX_SDK_PROJECT_NAME} PUBLIC
    ${ProjDirPath}/
    ${SdkRootDirPath}/boards/evkmimx8mm
)

set(CMAKE_MODULE_PATH
    ${SdkRootDirPath}/utilities
    ${SdkRootDirPath}/utilities/assert
    ${SdkRootDirPath}/devices/MIMX8MM6/drivers
    ${SdkRootDirPath}/drivers/common
    ${SdkRootDirPath}/drivers/rdc
    ${SdkRootDirPath}/devices/MIMX8MM6
    ${SdkRootDirPath}/components/uart
    ${SdkRootDirPath}/components/lists
    ${SdkRootDirPath}/drivers/iuart
    ${SdkRootDirPath}/CMSIS/Core/Include
    ${SdkRootDirPath}/utilities/misc_utilities
    ${SdkRootDirPath}/utilities/debug_console_lite
)

# include modules
include(utility_debug_console_lite)
include(utility_assert_lite)
include(driver_clock)
include(driver_common)
include(driver_rdc)
include(device_CMSIS)
include(component_iuart_adapter)
include(component_lists)
include(driver_iuart)
include(device_startup)
include(CMSIS_Include_core_cm)
include(utilities_misc_utilities_MIMX8MM6)
include(device_system)

IF(NOT DEFINED TARGET_LINK_SYSTEM_LIBRARIES)
    SET(TARGET_LINK_SYSTEM_LIBRARIES "-lm -lc -lgcc -lnosys")
ENDIF()

TARGET_LINK_LIBRARIES(${MCUX_SDK_PROJECT_NAME} PRIVATE -Wl,--start-group)

target_link_libraries(${MCUX_SDK_PROJECT_NAME} PRIVATE ${TARGET_LINK_SYSTEM_LIBRARIES})

TARGET_LINK_LIBRARIES(${MCUX_SDK_PROJECT_NAME} PRIVATE -Wl,--end-group)

ADD_CUSTOM_COMMAND(TARGET ${MCUX_SDK_PROJECT_NAME} POST_BUILD COMMAND ${CMAKE_OBJCOPY}
-Obinary ${EXECUTABLE_OUTPUT_PATH}/${MCUX_SDK_PROJECT_NAME} ${EXECUTABLE_OUTPUT_PATH}/hello_world.bin)

Ce fichier permet de configurer le projet pour que CMake puisse le construire. Il est important de noter que nous utilisons le SDK de NXP défini dans la variable d’environnement MCUXPRESSO_SDK. La variable MCUXPRESSO_CMAKE_TOOLCHAIN permet de définir le fichier de configuration pour le compilateur croisé. Nous utilisons le fichier armgcc.cmake qui le fichier de configuration par défaut du SDK fourni par NXP.

Maintenant, nous avons besoin de la recette pour construire le projet avec Yocto. Pour cela, nous allons créer un fichier mcuxhelloworld_1.0.bb à la racine de notre dossier recipes-mcuxhelloworld:

SUMMARY = "mcuxhelloworld"
DESCRIPTION = "M4 firmware Hello World from Yocto"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

inherit deploy cmake native
DEPENDS += "mcuxpresso-native"
DEPENDS += "gcc-arm-none-eabi-native"
S = "${WORKDIR}"

SRC_URI = " \
        file://CMakeLists.txt \
        file://config.cmake \
        file://empty_rsc_table.c \
        file://flags.cmake \
        file://fsl_iomuxc.h \
        file://main.c \
        file://MIMX8MM6xxxxx_cm4_ddr_ram.ld \
        file://MIMX8MM6xxxxx_cm4_flash.ld \
        file://MIMX8MM6xxxxx_cm4_ram.ld \
        file://pin_mux.c \
        file://pin_mux.h \
        file://readme.txt \
"
# Override the default compiler to use the cross compiler instead
CC = "arm-none-eabi-gcc"
CXX = "arm-none-eabi-g++"
AS = "arm-none-eabi-as"

# Get MCUXPRESSO SDK and CMAKE toolchain file
MCUXPRESSO_SDK = "${STAGING_DIR_NATIVE}/usr/include/mcux-sdk"
MCUXPRESSO_CMAKE_TOOLCHAIN = "${MCUXPRESSO_SDK}/tools/cmake_toolchain_files/armgcc.cmake"

do_configure() {
        export MCUXPRESSO_SDK="${STAGING_DIR_NATIVE}/usr/include/mcux-sdk"
        export ARMGCC_DIR=${STAGING_DIR_NATIVE}/usr

        cmake -DCMAKE_TOOLCHAIN_FILE=${MCUXPRESSO_CMAKE_TOOLCHAIN} \
                -DCMAKE_BUILD_TYPE=release \
                -DCMAKE_C_COMPILER=${CC} \
                -DCMAKE_CXX_COMPILER=${CXX} \
                -DCMAKE_ASM_COMPILER=${AS} \
                -DCMAKE_C_COMPILER_WORKS=false \
                -DCMAKE_MAKE_PROGRAM=${MAKE} \
                ${S}
}

do_install() {
        install -d ${D}/etc/firmware/hello_world.bin
        install -m 0644 ${S}/release/hello_world.bin ${D}/etc/firmware/hello_world.bin
}

# Uboot expects the firmware to be in the deploy directory, it will then
# copy it to the correct location
do_deploy() {
        install -d ${DEPLOYDIR}
        install -m 0644 ${S}/release/hello_world.bin ${DEPLOYDIR}/hello_world.bin
}

addtask deploy after do_install

INSANE_SKIP:${PN} += "arch"
PACKAGES = "${PN}"

FILES:${PN} += "${DEPLOYDIR}/hello_world.bin \
                /etc/firmware/hello_world.bin"

Cette recette est un peu particulière, nous n’utilisons pas le compilateur par défaut de Yocto mais nous utilisons le compilateur croisé fourni que nous avons nous même installé. Nous forçons CMake à utiliser notre nouveau compilateur à l'aide des variables CCCXX et AS et nous définissons le chemin vers le fichier CMake du SDK de NXP que vous venons d'intégrer.

Dans le cas de notre BSP de Boundary Devices, le DEPLOYDIR est un dossier qui se trouve dans la partition /boot de la carte. Le micrologiciel compilé est donc copié dans ce dossier pour que U-Boot puisse le trouver au démarrage. Dans notre cas, il est nécessaire de renommer le fichier hello_world.bin en m4_fw.bin et de définir la variable d’environnement de U-Boot m4enabled à 1.

Une alternative à cette méthode est de charger le micrologiciel depuis Linux grâce à l’utilitaire m4fwloader modifié afin de fonctionner avec l’i.MX8M-Mini. Attention, il est indispensable de charger un micrologiciel au démarrage de la carte (depuis U-Boot) sinon l’utilitaire ne fonctionnera pas.

Une fois que nous avons réalisé cela, nous pouvons construire notre micrologiciel depuis Yocto:

$ bitbake mcuxhelloworld

Test du micrologiciel

Une fois que nous avons construit notre micrologiciel, nous pouvons l’ajouter à notre image Yocto. Il suffit d’ajouter la recette en utilisant la variable IMAGE_INSTALL .

IMAGE_INSTALL += "mcuxhelloworld"

Après d’avoir compilé notre image, nous pouvons la flasher sur notre carte et démarrer le micrologiciel. Nous pouvons le faire depuis U-Boot ou depuis Linux. Afin de tester rapidement, nous allons le faire depuis U-Boot:

=> load mmc 0:1 ${m4loadaddr} hello_world.bin
=> bootaux ${m4loadaddr}

Nous obtenons le résultat suivant dans le port série du microcontrôleur:

Démonstration de Uboot avec hello_world.bin

Ajouter par défaut les paquets dans le SDK

Nous avons maintenant dans Yocto les éléments nécessaires pour construire un micrologiciel pour le microcontrôleur. Nous devons maintenant les ajouter dans le SDK pour qu’un développeur puisse les utiliser sans utiliser Yocto directement.

Pour cela, nous allons surcharger la recette de base Yocto nativesdk-packagegroup-sdk-host.bb utilisée pour construire le SDK Yocto en ajoutant les packages que nous venons d’intégrer. Nous créons donc le fichier nativesdk-packagegroup-sdk-host.bbappend dans le dossier recipes-core/packagegroups/de notre layer et modifions la variable RDEPENDS pour y ajouter les éléments suivants :

RDEPENDS:${PN}:append = " \
    nativesdk-gcc-arm-none-eabi \
    nativesdk-mcuxpresso \
    nativesdk-python \
"

Notre nouveau SDK peut être construit avec la commande populate_sdk 

$ bitbake -c populate_sdk <image>

Utiliser le SDK pour construire un projet

Une fois le SDK construit, nous pouvons le déployer et l’installer sur notre machine de développement:

# Référence: Yocto Cooker
$ cd build/build-<nom_de l'image>/tmp/deploy/sdk
$ ./poky-glibc-x86_64-core-image-minimal-cortexa53-crypto-nitrogen8mm-toolchain-x.x.x.sh

Reprenons notre projet mcuxhelloworld et utilisons le SDK que nous venons de construire :

# Initialisation de l'environnement du SDK
$ . /opt/poky/x.x.x/environment-setup-aarch64-poky-linux
$
$ cd recipes-mcuxhelloworld/mcuxhelloworld/files/
$ mkdir build
$ cd build
$ cmake .. -DCMAKE_TOOLCHAIN_FILE="${MCUXPRESSO_CMAKE_TOOLCHAIN}" -DCMAKE_BUILD_TYPE=release
$ make
[...]
Memory region         Used Size  Region Size  %age Used
    m_interrupts:         576 B        576 B    100.00%
          m_text:        5528 B     130496 B      4.24%
          m_data:        2224 B       128 KB      1.70%
         m_data2:          0 GB        16 MB      0.00%
[100%] Built target boot.elf
$ ls ../release/hello_world.bin
../release/hello_world.bin: data

Nous avons maintenant un micrologiciel compilé avec le SDK que nous avons construit en partageant le même compilateur croisé et le SDK MCUXpresso que celui utilisée lors d'une génération Yocto.

Conclusion

Nous avons maintenant un SDK Yocto qui contient le compilateur croisé et le SDK MCUXpresso. Nous pouvons maintenant construire notre image et notre SDK pour notre microcontrôleur. Nous avons aussi vu comment ajouter des paquets par défaut dans le SDK Yocto pour que des développeurs ne soient pas obligés de deployer Yocto pour construire un micrologiciel adapté à notre carte.

Dans le cadre de ce tutoriel, nous avons utilisé la configuration générique du SDK de NXP. Il est parfaitement possible d’utiliser une configuration spécifique à une autre carte. Il suffit de modifier notre micrologiciel pour qu’il utilise les drivers d’une autre carte.

Le layer meta-mcuxpresso présenté dans cet article est prêt à l’emploi et est disponible sur le Github OpenWide Ingénierie: https://github.com/Openwide-Ingenierie/meta-mcuxpresso

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée.