Aller au contenu

TP01 - Installation de l’environnement et « Hello World »

Objectifs du TP

Ce premier TP a pour but de configurer votre environnement de travail et de réaliser un premier projet avec le système embarqué que nous utiliserons cette année. À la fin de ce TP, les étudiants :

  • auront installé leur PC pour réaliser les TPs ;
  • sauront utiliser les outils de développement ;
  • sauront utiliser le CI/CD de gitlab pour vérifier le code ;
  • auront rédigé un journal de travail et déposé le PDF dans le dépôt git.

Les livrables sont :

  • le code complet de votre solution (avec les programmes de test) dans le projet gitlab qui vous a été attribué
  • un journal de travail déposé sur gitlab.

Temps accordé : 3 périodes de 45 minutes en classe + travail personnel à la maison

Délai

Le TPs doit être rendu au plus tard 6 jours après la séance en classe. Si vous avez le TP le mardi, vous devez le rendre au plus tard le lundi de la semaine suivante à 23:59.

Configuration minimale

Pour faire les TPs, vous avez besoin d’une machine bien configurée. Vous pouvez utiliser une machine Windows récente (de préférence Windows 10 ou 11), une machine Apple, ou une machine Linux.

Assurez-vous d’avoir une version récente de Git et de Python. Pour bénéficier des avantages de Linux, nous vous recommandons d’installer Windows Terminal, wsl2, ainsi qu’une distribution moderne telle qu’Ubuntu. Les deux derniers points sont facultatifs car pas utilisés dans ce cours. Cependant, ils font partie d’une configuration de développement moderne.

Nous vous recommandons un terminal récent tel que iTerm2 ou Warp. Nous recommandons aussi Homebrew pour facilement installer de nombreux logiciels utiles.

En principe, votre Linux devrait être configuré correctement. Assurez-vous quad même d’avoir une version récente de git et de python3.

La configuration de J. Supcik

Sur ma machine, j’utilise le shell zsh avec l’extension oh my zsh et le thème Powerlevel10k. Libre à vous de vous en inspirer et l’adapter selon vous goûts. Même si vous êtes sous Windows, dans WSL, vous pourrez très bien aussi profiter du comfort d’une telle configuration 😉.

Installation de Visual Studio Code (VS Code)

Note pour utilisateurs avancés (et rebelles 😄)

Vous n’êtes pas obligé d’utiliser Visual Studio Code. Si vous préférez utiliser Atom, CLion, Emacs ou vim, vous pouvez le faire. Mais ce n’est pas sûr que l’enseignant(e) puisse vous aider en cas de problème.

Si vous ne l’avez pas déjà fait, téléchargez et installez Visual Studio Code sur votre ordinateur personnel. Si vous avez des problèmes pour l’installation, étudiez la procédure relative à votre système.

Windows (y compris Windows 11) a besoin de drivers pour dialoguer avec la cible. Vous pouvez les télécharger sur le site de ST en suivant ce lien

Le logiciel est gratuit, mais vous devez avoir un compte sur le site de st.com pour pouvoir le télécharger. Suivez les instructions données par le site.

Avec macOS, vous devrez probablement accorder quelques permissions supplémentaires pour installer les logiciels, mais aucun driver spécifique n’est nécessaire.

Si vous utilisez Linux, assurez-vous d’avoir installé stlink-tools (en appliquant les règles udev correspondantes - sudo systemctl restart udev) et d’avoir les permissions suffisantes pour utiliser le port USB (/dev/ttyACM0).

Il y a plusieurs moyens d’obtenir les permissions, mais la plus simple est d’ajouter votre username au groupe dialout.

sudo gpasswd -a $USER dialout

Redémarez votre session pour activer ce changement.

Installation de PlatformIO IDE

Installez PlatformIO IDE en tant qu’extension de Visual Studio Code. Suivez les instructions décrites sur Internet.

Familiarisez-vous avec l‘interface de PlatformIO.

Installation d’autres extensions de Visual Studio Code

Installez encore les extensions suivantes :

Optionnel

Vous pouvez aussi jeter un coup d’œil au paquet d’extensions VSCode Essentials et décider si vous souhaitez les installer.

Préparation du matériel (cible)

Pour tous les TPs, nous utilisons la cible STM32F412 Discovery kit. Cette cible a deux ports USB, mais pour programmer la cible, il faut obligatoirement utiliser le port noté ST-LINK/V2-1 et non le port USB USER. Il est probable que vous ne verrez l’indication ST-LINK/V2-1, car elle est cachée par la carte d’extension montée sur la carte de base.

Autrement dit, connectez le câble USB du côté de la carte d’extension comme ceci :

Cible

et connectez l’autre bout du câble dans une prise USB de votre ordinateur. C’est le seul câblage que vous devez faire.

Mise à jour du firmware de la cible (facultatif)

Pour programmer le microcontrôleur, la cible inclut une interface ST-LINK/V2. Si la cible est neuve (ou trop vieille), il est recommandé de mettre à jour le firmware de cette interface.

Info pour machine Apple avec Apple Silicon

La version actuelle (3.10.3) du logiciel de mise à jour du firmware est un programme Java prévu pour fonctionner sur une architecture Intel. Pour les utilisateurs d’ordinateurs Apple avec le microprocesseur Apple Silicon, vous pouvez faire la mise à jour en téléchargeant une version de Java pour Intel (tel que Azul LTS LTS) et en utilisant le système Rosetta 2. Lancez le programme en donnant le chemin complet d’un Java X86 présent sur votre machine - vous trouverez un exemple ci-dessous. De plus, rappelez-vous de modifier les paramètres de sécurité pour que le programme puisse être exécuté (sous “Préférences Système” -> “Sécurité et confidentialité” après avoir lancé une fois le logiciel).

"/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" -jar STLinkUpgrade.jar
  • Téléchargez le logiciel de mise à jour (STSW-LINK007) sur le site de ST.
  • Vérifiez que le câble USB est bien connecté sur le bon connecteur (comme expliqué ci-dessus)
  • « Désarchivez » le fichier que vous venez de télécharger, lisez le readme.txt et démarrez le programme.
  • Vous devriez voir ceci : ST-Link Upgrade 1
  • Cliquez sur Open in update mode
  • Par défaut, l’interface ST-LINK/V2 de votre carte implémente un disque USB. Ça peut être pratique dans certains cas, mais pour nous, c’est plutôt dérangeant, car votre système d’exploitation vous indiquera que vous n’avez pas éjecté ce disque correctement à chaque fois que vous déconnecterez la carte. C’est pourquoi nous vous conseillons de désactiver cette option en cliquant sur Change Type et en sélectionnant l’option sans Mass storage : ST-Link Upgrade 1
  • Cliquez pour terminer sur _Upgrade :
  • À la fin de la procédure, le programme indique Upgrade successful et vous pouvez alors quitter le programme.

Attention

Il est possible que certains logiciels nécessitent l’option Mass storage. C’est principalement le cas avec les outils stlink sous Linux. Si vous constatez que vos outils ne fonctionnent pas correctement, réactivez l’option Mass storage et voyez si ça résout le problème.

Création du projet sur votre machine

Pour ce TP, vous travaillerez en groupe de 2 ou 3 étudiants. Vous avez reçu un e-mail vous invitant à rejoindre un projet tp01-<x> sur gitlab. Acceptez cette invitation.

Chaque étudiant doit maintenant « cloner » ce projet sur sa machine. Sur votre machine, vous pouvez nommer le projet comme vous voulez. Vous pouvez garder le nom complet (tp01-<x>), vous pouvez le nommer simplement tp01ou vous pouvez choisir n’importe quel nom qui vous fait plaisir.

Effectuez les opérations suivantes :

  • Commencez par ouvrir Visual Studio Code.
  • Cliquez ensuite sur l’icône Source Control dans la barre de gauche (ou pressez Shift+Ctrl+G).
  • Cliquez sur Clone Repository.
  • Entrez l’URL de votre projet et sélectionnez-la.
  • Choisissez ensuite dans quel dossier vous souhaitez créer le projet et cliquez sur Select Repository Location.
  • Cliquez ensuite sur le bouton Open en bas à droite pour ouvrir le projet.
  • Faites confiance au code de ce projet.
  • Initialisez le projet avec PlatformIO. Ouvrez la palette de commande (ou pressez Shift+Ctrl+P ou F1 ou Shift+Cmd+P sur macOS) et choisissez PlatformIO: Open PlatformIO Core CLI.
  • Dans la fenêtre qui s’ouvre en bas à droite de votre éditeur, tapez la commande suivante :

    pio init --board disco_f412zg --ide vscode `
      -O "framework=stm32cube" `
      -O "platform_packages=toolchain-gccarmnoneeabi@>=1.90000.0"
    
    pio init --board disco_f412zg --ide vscode \
      -O "framework=stm32cube" \
      -O "platform_packages=toolchain-gccarmnoneeabi@>=1.90000.0"
    
  • Le système installe les outils nécessaires à la compilation de votre code.

  • Rechargez la fenêtre afin que l’extension PlatformIO utilise les fichiers que vous venez de créer. Vous pouvez le faire avec la commande Developer: Reload Window depuis la palette de commande, ou vous pouvez fermer VS code et le rouvrir.

Configuration du projet

Maintenant que le projet a été créé, il vous faut encore le configurer pour les spécificités de la cible que nous utilisons. Le premier fichier que vous devez modifier est platformio.ini. Ajoutez les lignes 7 à 23 du code ci-dessous au fichier existant :

platformio.ini
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[env:disco_f412zg]
platform = ststm32
board = disco_f412zg
framework = stm32cube
platform_packages = toolchain-gccarmnoneeabi@>=1.90000.0

; ----- begin of ADO specific content -----
board_build.stm32cube.custom_config_header = yes
board_build.stm32cube.variant = STM32412G-Discovery
test_framework = unity
check_tool = cppcheck

build_flags =
    -mfpu=fpv4-sp-d16
    -mfloat-abi=softfp

build_src_flags =
    -Werror

monitor_speed = 115200

lib_deps = https://github.com/heiafr-isc/stm32cube-f412disco-ado.git#main
; ----- end of ADO specific content -----

Le framework que nous utilisons (STM32Cube) doit être configuré pour le projet. Téléchargez le fichier stm32f4xx_hal_conf.h dans le dossier include de votre projet.

Complément

Le fichier stm32f4xx_hal_conf.h ainsi que la plupart des fichiers de la bibliothèque https://github.com/heiafr-isc/stm32cube-f412disco-ado.git ont été générés avec STM32CubeMX. Si ça vous intéresse, vous pouvez télécharger le projet utilisé pour générer ces fichiers et consulter la documentation correspondante.

Le « Hello World » de l’embarqué

Dans la programmation des systèmes embarqués, l’équivalent du « Hello World » de l’informatique, c’est de faire clignoter une LED. Nous allons faire ceci avec la LED bleue de notre cible.

Dans le dossier src, ajoutez un fichier main.cpp avec le contenu suivant :

/**
 ******************************************************************************
 * @file        : main.c
 * @brief       : Main Program for TP01
 * @author      : YOUR NAME <YOUR E-MAIL ADDRESS>
 * @date        : CURRENT DATE
 ******************************************************************************
 * @copyright   : Copyright (c) 2022 HEIA-FR / ISC
 *                Haute école d'ingénierie et d'architecture de Fribourg
 *                Informatique et Systèmes de Communication
 * @attention   : SPDX-License-Identifier: MIT OR Apache-2.0
 ******************************************************************************
 * @details
 * Main Program for TP01
 ******************************************************************************
 */

#include "f412disco_ado.h"

constexpr Led_TypeDef kMyLed = LED_BLUE;
constexpr int kPeriod = 200;

int main(void) {
    DiscoAdoInit();
    BSP_LED_Init(kMyLed);
    while (true) {
        BSP_LED_Toggle(kMyLed);
        HAL_Delay(kPeriod);
    }
}

Pressez sur la flèche vers la droite dans la barre d’état en bas de l’écran (PlatformIO: Upload)

et la LED bleue devrait clignoter :

Explications du programme

Revenons sur le programme que vous venez d’écrire et expliquons comment il fonctionne :

Les #include

La première ligne (#include) permet d’utiliser les bibliothèques STM32Cube ainsi que les périphériques de votre cible

#include "f412disco_ado.h"

Les constantes

Nous définissons ensuite des constantes. Pour rappel, votre programme doit respecter les 10 commandements et le commandement 6 nous dit :

Tu n’utiliseras aucun « nombre magique » dans ton code.

constexpr Led_TypeDef kMyLed = LED_BLUE;
constexpr int kPeriod = 200;

La première constante indique quelle LED vous souhaitez utiliser. Vous avez le choix entre

  • LED_GREEN
  • LED_ORANGE
  • LED_RED
  • LED_BLUE

Notez le k devant le nom des constantes. Cette pratique émane du Google C++ Style Guide.

La fonction main

Le programme principal appelle la méthode DiscoAdoInit(); qui initialise la cible et appelle ensuite la méthode BSP_LED_Init(kMyLed); qui initialise la LED.

Le reste du programme est une boucle sans fin qui inverse l’état de la LED et qui attend un nombre donné de millisecondes.

int main(void) {
    DiscoAdoInit();
    BSP_LED_Init(kMyLed);
    while (true) {
        BSP_LED_Toggle(kMyLed);
        HAL_Delay(kPeriod);
    }
}

Utilisation du débogueur

Apprendre à se servir du débogueur s’avèrera très pratique pour corriger les erreurs de vos programmes. C’est pourquoi nous allons expérimenter cet outil dès le premier TP.

À faire

Pour débugger votre application, cliquez sur l’icône avec un triangle et un bug dans son coin dans la barre de gauche . Puis cliquez sur le triangle vert à la gauche de PIO Debug en haut à gauche . Expérimentez avec un breakpoint à la ligne qui inverse l’état de la LED et observez ce qui se passe à chaque continue (avec la souris ) ou en pressant F5). Terminez la session de debug avec le carré rouge .

Debug

Le tracing

En plus du débogueur, il est parfois utile de pouvoir laisser des traces pour savoir ce que le programme fait. Nous pouvons pour cela utiliser la fonction printf de la bibliothèque stdio.

  • Modifiez le fichier main.cpp en y ajoutant une ligne au début du programme pour importer la bibliothèque standard stdio :
    #include <stdio.h>
    
    et dans la boucle sans fin, ajouter une instruction printf:
    printf("tic\n");
    
  • Ouvrez le Serial Monitor dans PlatformIO en cliquant sur l’icône correspondant dans la barre d’état au bas de la fenêtre :
    Monitor
  • Recompilez le programme, envoyez-le vers la cible et observez la console.

Dans le TP suivant, vous apprendrez des techniques plus efficaces pour faire du tracing, mais pour l’instant on se contente d’utiliser des printf.

Note

Si vous avez un printf au début de votre programme et que vous avez ouvert le Serial Monitor trop tard, vous pouvez redémarrer le programme de la cible en pressant le bouton RESET :
Reset

Les Tests

Edsger W. Dijkstra

Program testing can be used to show the presence of bugs, but never to show their absence!

Les tests, et en particulier les tests unitaires, sont nécessaires à la qualité des logiciels. Pour tous les TPs de ce cours, vous écrirez des tests unitaires pour valider votre code.

Avec les tests unitaires, nous ne testons pas la fonction main du programme, mais nous testons les fonctions appelées par main.

Avec ce premier TP, mais nous allons valider les fonctions qui manipulent les LEDs.

Commençons par configurer le framework de test de PlatformIO. Dans le dossier test de votre projet, téléchargez les fichiers unity_config.h et unity_config.c.

Toujours dans le dossier test, ajoutez un fichier test_leds.cpp avec le contenu suivant :

/**
 ******************************************************************************
 * @file        : test_main.c
 * @brief       : Basic tests
 * @author      : Jacques Supcik <jacques.supcik@hefr.ch>
 * @date        : 27. July 2022
 ******************************************************************************
 * @copyright   : Copyright (c) 2022 HEIA-FR / ISC
 *                Haute école d'ingénierie et d'architecture de Fribourg
 *                Informatique et Systèmes de Communication
 * @attention   : SPDX-License-Identifier: MIT OR Apache-2.0
 ******************************************************************************
 * @details
 * Basic tests
 ******************************************************************************
 */

#include "stm32412g_discovery.h"
#include "stm32f4xx_hal.h"
#include "system_clock.h"
#include "unity.h"

uint16_t led_pins[LEDn] = {
    LED1_PIN,
    LED2_PIN,
    LED3_PIN,
    LED4_PIN,
};

void setUp(void) {
    BSP_LED_Init(LED_GREEN);
    BSP_LED_Init(LED_ORANGE);
    BSP_LED_Init(LED_RED);
    BSP_LED_Init(LED_BLUE);
    BSP_LED_On(LED_BLUE);
}

void tearDown(void) {
    BSP_LED_DeInit(LED_GREEN);
    BSP_LED_DeInit(LED_ORANGE);
    BSP_LED_DeInit(LED_RED);
    BSP_LED_DeInit(LED_BLUE);
}

void test_led_state_high(void) {
    for (int i = 0; i < LEDn; i++) {
        HAL_GPIO_WritePin(LEDx_GPIO_PORT, led_pins[i], GPIO_PIN_SET);
        TEST_ASSERT_EQUAL(HAL_GPIO_ReadPin(LEDx_GPIO_PORT, led_pins[i]),
                          GPIO_PIN_SET);
    }
    HAL_Delay(500);
}

void test_led_state_low(void) {
    for (int i = 0; i < LEDn; i++) {
        HAL_GPIO_WritePin(LEDx_GPIO_PORT, led_pins[i], GPIO_PIN_RESET);
        TEST_ASSERT_EQUAL(HAL_GPIO_ReadPin(LEDx_GPIO_PORT, led_pins[i]),
                          GPIO_PIN_RESET);
    }
    HAL_Delay(500);
}

int main(void) {
    HAL_Init();
    SystemClock_Config();
    HAL_Delay(2000);  // Mandatory waiting for 2 seconds...
    UNITY_BEGIN();    // Mandatory call to initialize test framework
    for (int i = 0; i < 5; i++) {
        RUN_TEST(test_led_state_high);
        RUN_TEST(test_led_state_low);
    }
    UNITY_END();  // Mandatory call to finalize test framework

    while (1) {
        asm("nop");
    }
}

Ce programme de test initialise le HAL (Hardware Abstraction Layer) et configure l’horloge du système (SystemClock_Config();). Ensuite on attend 2 secondes (nécessaire avec le framework de test de PlatformIO) et on inverse toutes les LEDs 5 fois de suite.

Assurez-vous de bien comprendre ce code et n’hésitez pas à demander des explications à l’enseignant.

Ouvrez la palette de commande de VS Code avec Ctrl+Shift+P avec Windows et Cmd+Shift+P avec macOS, et tapez PlatformIO: Test puis pressez Enter Le résultat devrait ressembler à ça :

Test result

Si votre IDE n’affiche pas les résultats des tests, c’est peut-être que PlatformIO n’arrive pas à déterminer le bon port série et vous devez alors le configurer manuellement. Déterminez le port série utilisé par la cible avec le panneau de configuration de votre OS. Dans le fichier platformio.ini, définissez le paramètre test_port avec le port série correspondant. Si vous avez Windows et que votre cible est sur le port série COM7, la configuration sera :

test_port = COM7

Formatage standard du code

Pour assurer une uniformité du code, nous formatons tous les codes sources avec l’outil clang-format. Pour respecter les conventions de ce cours, ajoutez un fichier .clang-format à la racine de votre projet avec le contenu suivant :

---
BasedOnStyle: Google
IndentWidth: 4
---
Language: Cpp
ColumnLimit: 100
AlignConsecutiveAssignments: true
DerivePointerAlignment: false
PointerAlignment: Left
BinPackArguments: false
BinPackParameters: false

Vous pouvez maintenant reformater vos fichiers avec Shift+Alt+F. Si le système vous demande de préciser l’outil que vous souhaitez utiliser, choisissez C/C++.

L’analyse statique de code

Un autre outil intéressant pour améliorer la qualité du code est l’analyse statique de code. Pour ce TP, ainsi que pour tous les suivants, vous validerez systématiquement vos codes avec les outils suivants :

  • cpplint
  • cppcheck

L’outil cppcheck est intégré à PlatformIO, mais il n’y a pas de raccourci dans l’extension VS Code. Vous pouvez cependant l’utiliser avec le CLI de PlaftormIO. Ouvrez la palette de commande et choisissez PlatformIO: Open PlatformIO Core CLI. Tapez ensuite la commande pio check et vous devriez obtenir le résultat suivant :

Check result

L’autre outil, cpplint, n’est pas intégré à PlatformIO et nous allons l’utiliser au travers de pre-commit. Rendez-vous sur le site pre-commit.com et suivez les instructions d’installation.

Ajoutez le fichier .pre-commit-config.yaml à la racine de votre projet avec le contenu suivant :

repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.3.0
    hooks:
    -   id: check-yaml
        args: [--allow-multiple-documents]
    -   id: end-of-file-fixer
    -   id: trailing-whitespace
  - repo: https://github.com/pre-commit/mirrors-clang-format
    rev: 'v14.0.6'
    hooks:
    -   id: clang-format
  - repo: https://github.com/cpplint/cpplint
    rev: '1.6.0'
    hooks:
    -   id: cpplint

Ajoutez encore le fichier de configuration CPPLINT.cfg à la racine du projet avec le contenu suivant :

CPPLINT.cfg
linelength=100
filter=-build/include_subdir,-readability/casting,-whitespace/indent

Le fichier stm32f4xx_hal_conf.h que vous avez mis dans le dossier include ne répond pas aux exigences de cpplint, mais ce fichier a été généré par STM32CubeMX et plutôt que de le corriger, nous préférons l’exclure de l’analyse statique. Ajoutez donc le fichier CPPLINT.cfg dans le dossier include avec le contenu suivant :

include/CPPLINT.cfg
exclude_files=stm32f4xx_hal_conf.h

Installez le pre-commit hook dans git en tapant la commande :

pre-commit install

À partir de maintenant, les tests seront faits avant chaque commit dans git. Étudiez la documentation de pre-commit pour bien prendre cet outil en main.

Une version « orientée objet » de la LED

Le terme « orienté objet » est peut-être un peu ambitieux, car on ne va pas encore faire d’héritage ou de polymorphisme. Mais nous allons quand même utiliser une classe et des méthodes associées pour offrir une interface simple et élégante au composant LED.

Voici une première version du schéma de la classe que nous souhaitons implémenter :

classe Led

Dans le dossier lib de votre projet, créez un sous-dossier nommé led. Dans ce dossier, créez le fichier led.hpp avec le contenu suivant :

lib/led/led.hpp
/**
 ******************************************************************************
 * @file        : led.hpp
 * @brief       : Class for LEDs
 * @author      : Jacques Supcik <jacques.supcik@hefr.ch>
 * @date        : 27. July 2022
 ******************************************************************************
 * @copyright   : Copyright (c) 2022 HEIA-FR / ISC
 *                Haute école d'ingénierie et d'architecture de Fribourg
 *                Informatique et Systèmes de Communication
 * @attention   : SPDX-License-Identifier: MIT OR Apache-2.0
 ******************************************************************************
 * @details
 * Class for LEDs
 ******************************************************************************
 */

#pragma once

#include "f412disco_ado.h"

class Led {
   public:
    explicit Led(Led_TypeDef led);
    int Read();
    void Write(int value);
    void Toggle();
    void On();
    void Off();
    Led& operator=(int value);
    Led& operator=(const Led& rhs);
    operator int();

   private:
    Led_TypeDef led_;
};

et l’implémentation dans le fichier led.cpp :

lib/led/led.cpp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/**
 ***************************************************************************
 * @file        : led.cpp
 * @brief       : Class for LEDs
 * @author      : Jacques Supcik <jacques.supcik@hefr.ch>
 * @date        : 27. July 2022
 ***************************************************************************
 * @copyright   : Copyright (c) 2022 HEIA-FR / ISC
 *                Haute école d'ingénierie et d'architecture de Fribourg
 *                Informatique et Systèmes de Communication
 * @attention   : SPDX-License-Identifier: MIT OR Apache-2.0
 ***************************************************************************
 * @details
 * Class for LEDs
 ***************************************************************************
 */

#include "led.hpp"

#include "f412disco_ado.h"

static const uint32_t GPIO_PIN[LEDn] = {
    LED1_PIN, LED2_PIN, LED3_PIN, LED4_PIN
};

Led::Led(Led_TypeDef led) : led_{led} { BSP_LED_Init(led); }

int Led::Read() {
    return HAL_GPIO_ReadPin(LEDx_GPIO_PORT, GPIO_PIN[led_]) == GPIO_PIN_RESET;
}

void Led::Write(int value) {
    if (value)
        this->On();
    else
        this->Off();
}

void Led::Toggle() { BSP_LED_Toggle(led_); }

void Led::On() { BSP_LED_On(led_); }

void Led::Off() { BSP_LED_Off(led_); }

Led& Led::operator=(int value) {
    // TODO: Implement this method
}

Led& Led::operator=(const Led& rhs) {
    this->Write(((Led&)rhs).Read());
    return *this;
}

Led::operator int() { return this->Read(); }

Implémentez la surcharge de l’opérateur d’assignation (=) à partir d’un entier (ligne 46) et assurez de bien comprendre toutes les lignes de ce programme. N’hésitez pas à poser des questions à l’enseignant.

Modifiez le programme main pour utiliser cette nouvelle interface. N’oubliez pas d’inclure cette interface avec l’instruction #include :

#include "led.hpp"

Implémentez maintenant des tests unitaires pour toutes les méthodes de la classe Led.

CI/CD (continuous integration / continuous deployment)

Les bienfaits de l’intégration continue ne sont plus à démontrer et nous n’allons pas nous en priver ici. Nous allons donc configurer gitlab pour qu’il vérifie automatiquement notre code lors de chaque push.

Ajoutez un fichier .gitlab-ci.yml à la racine de votre projet tp01 avec le contenu suivant :

.gitlab-ci.yml
image: python:3.10

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
  PLATFORMIO_CACHE_DIR: "$CI_PROJECT_DIR/.platformio-cache"
  PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.pre-commit-cache"

cache:
  paths:
    - .pip-cache/
    - .platformio-cache/
    - .pre-commit-cache/

stages:
 - check
 - test

check-job:
  stage: check
  script:
    - pip install -U platformio
    - pio check --fail-on-defect low
    - pio run
    - pio test --without-uploading --without-testing

precommit-job:
  stage: check
  script:
    - pip install pre-commit
    - pre-commit run --all-files

test-job:
  stage: test
  tags:
    - ado
  script:
    - pip install -U platformio
    - pio test -e disco_f412zg --test-port /dev/ttyACM0

Lors du prochain commit / push, vous verrez une nouvelle entrée dans la rubrique CI/CD / Pipelines de gitlab :

Pipeline

Dès que le bouton devient vert, la tâche est terminée et vous pouvez voir les détails en cliquant le bouton Passed

Pipeline Detail

En cliquant sur les boutons *job, vous pouvez voir les détails de l’exécution avec le résultat de la compilation, de l’analyse statique de code, ou des tests.

Étudiez la sortie des check-job et precommit-job et notez que ces tests ont été faits sur les shared runners de gitlab :

Check Job

Le test-job est exécuté sur des runners dédiées au cours. Il s’agit de 12 Raspberry Pi auxquels nous avons connecté une cible et qui se trouvent en C00.16.

Test Jib

Votre projet passe brillamment tous les tests et vous pouvez fièrement le faire savoir en ajoutant un « badge » à votre projet

Badge 1

Le badge apparaîtra sur la page d’accueil du projet

Badge 1

Prenez pour habitude de toujours soigner les tests et mettez en place des mécanismes de tests automatiques pour tous vos projets.

Voici encore quelques liens utiles :

Mini projet

  • Assurez-vous que tous vos codes sources respectent les 10 commandements. Soignez en particulier les entêtes des codes sources et des commentaires.
  • Validez les changements sur votre dépôt git (commit). Veillez à soigner les commentaires dans vos commits (voir Writing Better Commit Messages et Conventional Commits).
  • Commencez avec la version « orientée objet » de votre programme
  • Dans une nouvelle branche du dépôt, modifiez la vitesse de clignotement.
  • Dans une nouvelle branche, faites clignoter la LED orange à la place de la LED bleue.
  • Dans une nouvelle branche, faites clignoter les 4 LEDs en alternance comme ci-dessous.

  • Fusionnez cette dernière branche dans la branche main de votre projet en utilisant un merge request de gitlab.

  • Synchronisez régulièrement votre dépôt avec GitLab.
  • Rédigez un rapport (journal de travail) avec les indications suivantes :

    • Une page de titre avec au minimum :
      • le nom et le logo officiel de l’école
      • le nom du cours : Architecture des Ordinateurs
      • le titre de votre document : Travail Pratique 1 : Installation de l’environnement et « Hello World »
      • l’URL de votre projet sur gitlab
      • les noms des auteurs (vous) avec la classe dans laquelle vous êtes
      • la date à laquelle vous avez terminé le rapport
      • éventuellement la version du rapport
    • Une introduction pour poser le contexte
    • Un résumé des notions que vous avez apprises pendant ce TP en précisant si c’est
      • non acquis
      • acquis, mais encore à exercer
      • parfaitement acquis
    • Un résumé des points qui vous semblent importants et que vous devez retenir
    • Les réponses aux questions (s’il y en a)
    • Le code source bien formaté et avec du « syntax highlighting » de votre code avec les 4 LEDs qui clignotent en alternance
    • Un chapitre qui décrit le travail au sein de votre groupe (répartition des tâches, contributions de chacun, ambiance …)
    • Une conclusion par laquelle vous donnez vos impressions sur le TP, ce que vous avez aimé, ce que vous avez moins aimé, et éventuellement des suggestions pour des changements. Indiquez également le nombre d’heures que vous avez passées, par personne, en dehors des heures de TP en classe.

    Important

    Déposez votre rapport dans un dossier /docs de votre dépôt git (tp01-x) avec le nom report.pdf (le chemin complet vers votre rapport est donc /docs/report.pdf)