Présentation du Texas Instrument MSP432

| 20 minutes read

Nouvel article, nouvelle présentation hardware. Cette fois-ci, nous allons quitter le monde Arduino, et nous aventurer sur les terres de Texas Instrument, avec le micro-contrôleur MSP432.

Le MSP432

LaunchPad MSP432

LaunchPad MSP432

Le MSP432 est un micro-contrôleur de Texas Instrument, basé sur processeur ARM Cortex-M4F. Pour rappel, rapport à cette dénomination :

  • ARM est une société développant des architectures de processeurs (mobiles pour la plupart), mais qui ne les produit pas directement. Elle revend sous licence les designs à des fondeurs, qui peuvent ensuite adapter le design de base à leurs besoins. Regardez votre smartphone, un processeur à base ARM l’anime.
  • Cortex-Mx : la gamme micro-contrôleur d’ARM.
  • M4F : Le modèle M4, doté d’une unité de calcul en virgule flottante (suffixe F).

Le MSP432 est un micro-contrôleur orienté basse consommation (95µA/MHz en mode actif, soit 4,56 mA à 48 MHz; 0,00085 mA en veille profonde).

Sur la photo ci-dessus, le MSP432 est la grosse puce carrée située sur la partie gauche.

La traditionnelle comparaison avec Arduino Uno s’impose.

Arduino UnoMSP432

Micro-contrôleur

ATmel ATmega328pARM Cortex-M4F

Espace d'adressage

8bits32bits

Fréquence d'horloge

16 MHz48 MHz

Mémoire flash

32 ko 256 ko

Mémoire RAM

2 ko 64 ko

E/S numérique

18 (5V) dont 6 capables de PWM78 (3,3V) dont 22 capables de PWM

Entrées analogiques

5 (10 bits)24 (14 bits)

Communication

1x UART;1x I2C; 1x SPI4x UART;4x I2C; 8x SPI

Le LaunchPad

La photo en début d’article en elle-même représente ce que Texas Instrument appelle un LaunchPad. Autant du côté Arduino, la partie importante est le micro-contrôleur, la carte autour étant là pour faciliter sa manipulation, autant dans le cas du LaunchPad, il s’agit de la même chose.

Grosso modo, la partie gauche du LaunchPad (celle avec le MSP432) propose un ensemble de broches donnant accès aux E/S du micro-contrôleur, ainsi que deux LEDs et deux boutons utilisateurs. La partie droite, quant à elle (celle avec l’autre grosse puce carrée, et séparée par les pointillés sur la carte) est la partie s’occupant de la connexion et communication avec l’ordinateur, de la programmation du MSP432, de la surveillance de la consommation énergétique et de l’interface de déboggage.

Tout comme le monde Arduino possède les shields, cartes filles permettant d’ajouter facilement des fonctionnalités, la même chose existe du côté Texas Instrument avec les Booster Packs. Là aussi, on retrouve les fonctionnalités habituelles : WIFI, pilotage de moteurs, écrans LCD, etc.

Environnements de développement

Si vous souhaitez développer pour le MSP432, vous avez l’embarras du choix en matière d’environnements de développement. Les principaux sont les trois suivants :

Code Composer Studio

[http://www.ti.com/tool/ccstudio]

Code Composer Studio

Code Composer Studio

Code Composer Studio (CCS pour les intimes) est l’environnement de développement officiel proposé par Texas Instrument. Il est capable de gérer un grand nombre de processeurs et contrôleurs fournis par TI, dont le MSP432. Il est normalement payant, la licence de base coûtant 445 $. Il est possible de l’essayer gratuitement pendant 180 jours. Au delà, une limitation de la taille du code que l’on peut mettre sur le micro-contrôleur est mise en place (32 ko max dans le cas du MSP432). Les deux avantages principaux de CCS sont la possibilité de debug en temps réel, ainsi que le suivi de la consommation énergétique (voir plus bas).

Le bon :

  • Environnement très complet
  • Debug en temps réel
  • Suivi énergétique (pas besoin de licence payante pour ça)
  • Gestion des projets Energia et de l’API Arduino (voir plus bas)

Le moins bon :

  • Licence payante, et chère, pour un Eclipse rebrandé (et la licence gratuite est trop limitée)
  • C’est du Eclipse, ce n’est donc pas ce qu’il y a de plus léger
  • (OS X uniquement) version beta toute récente
  • (OS X uniquement) la console série ne fonctionne pas

Code Composer Studio Cloud

[https://dev.ti.com/ide]

Code Composer Studio Cloud

Code Composer Studio Cloud

Code Composer Studio Cloud, c’est la même chose que CCS, mais en version web. Concrètement, on doit installer un logiciel sur son ordinateur qui fera l’interface entre le LaunchPad et le navigateur, et une extension sur le navigateur qui fera le lien entre CCS Cloud et le programme installé précédemment. CCS Cloud ne nécessite pas de licence, juste la création d’un compte sur le site de TI.

Le bon :

  • Environnement très complet
  • Debug en temps réel
  • Fonctionne avec tous les navigateurs (OK, pour IE 6 je ne garantis chen)
  • Gestion des projets Energia et de l’API Arduino (voir plus bas)
  • C’est gratuit
  • Le terminal série fonctionne

Le moins bon :

  • C’est mou du genou, vraiment…
  • Pas de suivi énergétique

Energia

[http://energia.nu/]

Energia

Energia

Les habitués d’Arduino ne rêvent pas (et ne sont pas non plus devenus daltoniens) : il s’agit bien de la même interface que le logiciel Arduino, mais en rouge au lieu de vert. Et vous pouvez aussi utiliser l’API Arduino. En effet, Energia est un fork d’Arduino, dédié aux micro-contrôleurs de Texas Instrument. L’API utilisée est quasiment la même (sous réserve de compatibilité matérielle) ce qui ne dépaysera pas les « arduinistes ».

L’avantage d’Arduino, et par extension d’Energia, est que l’API fournie (qui est du C++) simplifie l’accès au matériel. Exemple typique :

Voici comment on fait clignoter une LED avec l’API Arduino / Energia

// most launchpads have a red LED
#define LED RED_LED
 
// the setup routine runs once when you press reset:
void setup() { 
  // initialize the digital pin as an output.
  pinMode(LED, OUTPUT); 
}
 
// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(LED, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000); // wait for a second
  digitalWrite(LED, LOW); // turn the LED off by making the voltage LOW
  delay(1000); // wait for a second
}

Et voici comment on fait clignoter une LED en C++ brut :

#include "msp.h"
 
void main(void)
{
  volatile uint32_t i;
 
  WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
 
  // The following code toggles P1.0 port
  P1DIR |= BIT0; // Configure P1.0 as output
 
  while(1)
  {
    P1OUT ^= BIT0; // Toggle P1.0
    for(i=10000; i>0; i--); // Delay
  }
}

Bien entendu, vous pouvez très bien utiliser le code C++ brut au sein d’Energia, ou bien mélanger C++ brut et API Arduino.

Pour information, le projet Energia est porté par un employé de Texas Instrument.

Le bon :

  • Terrain familier pour les habitués d’Arduino
  • C’est gratuit
  • Pour les gourous du code, vous pouvez aussi programmer à l’ancienne (sans l’API Arduino)

Le moins bon :

  • Pas de debug en temps réel
  • Pas de suivi énergétique
  • (OS X uniquement ?) Java 6 obligatoire ? en 2015 ? sérieusement ?

 

Le multitâche facile

Bon, le MSP432, c’est gentil, mais à part plus de mémoire et d’entrées / sorties, il y a quoi de vraiment différenciant par rapport à un Arduino Uno ? C’est quoi la killer feature ?

C’est le multitâche facile !

Disclaimer : oui, il est possible de faire du multitâche avec un Arduino Uno; non, ce n’est pas out of the box; oui les capacités matérielles du micro-contrôleur de l’Arduino Uno limitent assez vite les possibilités; oui, c’est plus facilement faisable avec des Arduino plus puissants. Là, le mot important dans le titre est celui juste après « multitâche », à savoir « facile ».

Ce que j’entends par multitâche est la possibilité de pouvoir exécuter des bouts de code, potentiellement bloquants, en parallèle.

Prenons un exemple simple : faire clignoter deux LEDs à un rythme différent (exemple : 1000ms pour l’une, 33ms pour l’autre).

Ce problème peut se résoudre relativement facilement avec un Arduino Uno. Exemple de code :

// define LED pins
#define LED1 2
#define LED2 3
 
unsigned long tick = 0;
// the setup routine runs once when you press reset:
 
void setup() {
  // initialize the digital pin as an output.
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
}
 
void loop() {
  if (tick%1000 == 0)
    digitalWrite(LED1, !digitalRead(LED1)); // switch LED1 state
  if (tick%33 == 0)
    digitalWrite(LED2, !digitalRead(LED2)); // switch LED2 state
  tick++;
  delay(1); // wait for 1 ms
}

 

Cette solution part du postulat que, si on découpe la boucle en échelle de temps suffisamment petite, on peut réussir à simuler un multitâche. En revanche, que se passe-t-il si je veux mélanger des tâches dont l’une peut être bloquante ?

Par exemple, je veux faire tourner un moteur pas à pas de 50 pas en avant puis 25 en arrière (et boucler dessus) pendant qu’une LED doit clignoter toutes les 33 ms (pour prévenir que le moteur tourne et que c’est potentiellement dangereux).

Le code pour faire tourner un moteur pas à pas de 50 pas est « motor.step(50) ». Or, fonction « step » est bloquante : tant que l’on n’aura pas tourné de 50 pas, le programme ne passera pas à la ligne de code suivante. Sauf si cette rotation dure moins d’une milliseconde, on va décaler à chaque fois l’allumage / extinction de la LED, et ne pas pouvoir tenir la cadence pour celle-ci.

Une solution de contournement peut être la suivante : faire avancer (ou reculer) le moteur pas à pas d’un unique pas à la fois, garder un compteur de déplacement de ce moteur, et là il pourrait y avoir moyen de s’en sortir. Ajoutez à l’équation une deuxième opération bloquante et non découpable en petits morceaux, et là vous tombez sur un problème insoluble.

C’est là qu’arrive à la rescousse TI-RTOS (Texas Instrument Real Time Operating System). L’idée générale est de créer autant de tâches que nécessaires : dans le cas du moteur pas à pas, une tâche qui fait clignoter une LED toutes les 33 ms et une tâche qui fait avancer le moteur de 50 pas; ou bien, dans le cas du multi-clignotement de LEDs, une tâche qui fait clignoter une LED toutes les 1000 ms, et une tâche qui fait clignoter une LED toutes les 33 ms (cet exemple sera détaillé plus loin). Ensuite, il suffit de lancer ces tâches en parallèle. Plus précisément, TI-RTOS propose un ordonnanceur de tâches qui va basculer très rapidement entre chaque tâche définie pour leur permettre de s’exécuter, et quand une tâche s’exécutera, toutes les autres seront suspendues.

Concrètement, comment ça se présente (la suite va s’appliquer à un projet Energia) ?

Il vous faut créer un projet Energia avec un fichier .ino du nom du projet (exemple, pour le projet « Blinkito », il faut un fichier « Blinkito.ino ») qui peut être vide ou bien déclarer des variables / méthodes qui seront accessibles à l’ensemble des tâches, et un fichier .ino par tâche, chacun avec son couple setupXXXX() / loopXXXX() (XXXX devant être remplacé par un nom unique à chacune des tâches). Dans le cas de Blinkito, ça nous donne :

  • un fichier « Blinkito.ino » vide
  • un fichier « Blinkito1000.ino » (le nom est à votre entière discrétion) contenant
// the setup routine runs once when you press reset:
 
void setup1000() { 
  // initialize the digital pin as an output.
  pinMode(RED_LED, OUTPUT); 
}
 
// the loop routine runs over and over again forever:
void loop1000() {
  digitalWrite(RED_LED, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000); // wait for 1000 ms
  digitalWrite(RED_LED, LOW); // turn the LED off by making the voltage LOW
  delay(1000); // wait for 1000 ms
}
  • un fichier « Blinkito33.ino » (le nom est à votre entière discrétion) contenant
// the setup routine runs once when you press reset:
void setup33() { 
 
// initialize the digital pin as an output.
  pinMode(BLUE_LED, OUTPUT); 
}
// the loop routine runs over and over again forever:
void loop33() {
  digitalWrite(BLUE_LED, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(33); // wait for 33 ms
  digitalWrite(BLUE_LED, LOW); // turn the LED off by making the voltage LOW
  delay(33); // wait for 33 ms
}

Et c’est tout. Si vous compilez et flashez ce programme sur le MSP432, vous verrez les LEDs clignoter chacune à leur rythme. Il aurait bien entendu été possible de remplacer le code de clignotement d’une des LEDs par celui de manipulation d’un moteur pas à pas sans problème, et voir le tout s’animer comme souhaité.

Sous le capot, que se passe-t-il ?

Tout d’abord, tous les fichiers .ino sont fusionnés en un seul fichier .cpp (dans ce cas, Blinkito.cpp)

#line 1 "Blinkito.ino"
#line 1 "Blinkito1000.ino"
// the setup routine runs once when you press reset:
#include "Arduino.h"
void setup1000();
void loop1000();
void setup33();
void loop33();
#line 4
void setup1000() { 
  // initialize the digital pin as an output.
  pinMode(RED_LED, OUTPUT); 
}
// the loop routine runs over and over again forever:
void loop1000() {
  digitalWrite(RED_LED, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(1000); // wait for a second
  digitalWrite(RED_LED, LOW); // turn the LED off by making the voltage LOW
  delay(1000); // wait for a second
}
 
#line 1 "Blinkito33.ino"
// the setup routine runs once when you press reset:
void setup33() { 
  // initialize the digital pin as an output.
  pinMode(BLUE_LED, OUTPUT); 
}
 
// the loop routine runs over and over again forever:
void loop33() {
  digitalWrite(BLUE_LED, HIGH); // turn the LED on (HIGH is the voltage level)
  delay(33); // wait for a second
  digitalWrite(BLUE_LED, LOW); // turn the LED off by making the voltage LOW
  delay(33); // wait for a second
}

Ensuite, le fichier source principal « main.cpp » est créé. Ce fichier s’occupe de déclarer les tâches pour TI-RTOS et de les ajouter à l’ordonnanceur, puis de lancer ledit ordonnanceur.

/*
 * ======== main.cpp ========
 * MT wiring Task framework
 */
#include <stddef.h>
 
/* XDC Header files */
#include <xdc/cfg/global.h>
 
/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/family/arm/m3/Hwi.h>
#include <xdc/runtime/System.h>
#include <ti/drivers/Power.h>
/* Board Support Header files (from configuration closure) */
#include <ti/runtime/wiring/Energia.h>
 
/* magic insertion point 769d20fcd7a0eedaf64270f591438b01 */
extern void setup1000();
extern void loop1000();
extern void setup33();
extern void loop33();
 
#define NUM_SKETCHES 2
void (*func_ptr[NUM_SKETCHES][2])(void) = {
 {setup1000, loop1000},
 {setup33, loop33}
};
const char *taskNames[] = {
 "loop1000",
 "loop33"
};
 
xdc_Void the_task(xdc_UArg _task_setup, xdc_UArg _task_loop);
/* Wiring-specific GPIO HW interrupt vectors */
__extern void Wiring_GPIO_hwiIntFxn(xdc_UArg callbacks);
 
/*
 * ======== main task ========
 */
xdc_Void the_task(xdc_UArg _task_setup, xdc_UArg _task_loop)
{
  /* Call setup once */
  (*(void(*)()) _task_setup)();
 
  /* Call loop repeatedly */
  for(;;) {
    (*(void(*)()) _task_loop)();
    System_flush();
    Task_yield();
  }
}
 
/*
 * ======== main ========
 */
int main()
{
  /* initialize all device/board specific peripherals */
  Board_init(); /* this function is generated as part of TI-RTOS config */
  Power_enablePolicy();
 
  Task_Params taskParams;
 
  /* initialize taskParams and set to default */
  Task_Params_init(&taskParams);
 
  /* All tasks have the same priority */
  taskParams.priority = Task_numPriorities - 2;
  taskParams.stackSize = 0x800;
 
  uint8_t i = 0;
  for(i = 0; i < NUM_SKETCHES; i++) {
    /* Set arg0 to setup() */
    taskParams.arg0 = (xdc_UArg)func_ptr[i][0];
    /* Set ar1 to loop */
    taskParams.arg1 = (xdc_UArg)func_ptr[i][1];
    /* Set the task name */
    taskParams.instance->name = (xdc_String) taskNames[i];
    /* Create the task */
    Task_create(the_task, &taskParams, NULL);
  }
 
  /* does not return */
  BIOS_start();
 
  return (0); /* should never get here, but just in case ... */
}

Le suivi de consommation énergétique

L’autre point intéressant avec le LaunchPad est la possibilité d’avoir un suivi de la consommation énergétique, et dans certains cas, un suivi des états d’activité du micro-contrôleur. Cette technologie, appelée EnergyTrace, n’est pour le moment disponible que depuis Code Composer Studio.

Dans les captures ci-dessous, le code suivant était exécuté :

  • allumage d’une LED
  • attente en mode basse consommation (1000 ms)
  • extinction de la LED
  • attente en mode consommation normale (environ 250 ms)

En mode free run

En mode free run, c’est-à dire quand on se contente de brancher le LaunchPad à l’ordinateur et de lancer EnergyTrace, on a accès aux informations suivantes :

EnergyTrace Free Run Profile

EnergyTrace Free Run Profile

Le résumé de la consommation d’énergie au cours de la mesure (total, moyen, min et max), ainsi qu’une autonomie estimée en fonction du type d’alimentation (piles, batteries, etc.).

EnergyTrace Free Run Power

EnergyTrace Free Run Power

Un graphe de la puissance (en mW) consommée au cours du temps. On voit bien les phases de consommation de la LED.

EnergyTrace Free Run Energy

EnergyTrace Free Run Energy

Un graphe de la consommation d’énergie (en µJ) cumulée au cours du temps. Là aussi, on voir bien les phases de « plateau » où la LED est éteinte, mais où le délai d’attente n’est pas en mode basse consommation.

En mode debug

En mode debug, outre les deux graphes précédents (moins précis dans ce cas) et la perte du résumé énergétique, nous avons les informations suivantes :

EnergyTrace Debug Profile

EnergyTrace Debug Profile

Un résumé des états du processeur, avec la séparation LPM (Low Power Mode) et Active Mode (et pour ce dernier, les fonctions les plus consommatrices)

EnergyTrace Debug CPU States

EnergyTrace Debug CPU States

Un graphe de l’évolution des états du processeur au cours du temps. On y distingue bien les successions d’attente en mode basse consommation ou en mode normal.

Mises bout à bout, toutes ces informations permettent d’optimiser à la fois le montage électronique et le code l’animant.

Remarques diverses

Quelques informations supplémentaires en vrac :

  • Un LaunchPad à base de MSP432 (MSP-EXP432P401R) ne coûte quasiment rien. Pour un peu plus de 16 euros, il peut être à vous. Comparé à un Arduino Uno à 20 euros, ou un Arduino Due (le plus proche en terme d’architecture) à 45 euros, c’est limite donné 🙂
  • Pour les arduinistes habitués à tirer jusqu’à 40 mA par broche d’un Arduino, le MSP432 est limité à environ 6 mA par broche si on ne veut pas voir leur tension trop chuter, environ 2 mA si on veut rester dans des niveaux normaux.
  • En parlant de tension, comme mentionné dans le tableau en début d’article, le MSP432 travaille en 3,3V. En fouillant dans les caractéristiques techniques, il est possible d’appliquer une tension supérieure aux entrées numériques, mais en limitant le courant à 2 mA maximum à l’aide d’une résistance en série. La méthode de calcul de la résistance mininale est la suivante : (Vext – Valim) / 0.002. Soit, dans le cas d’un MSP alimenté en 3,3V, et un périphérique externe en 5V : (5 – 3,3) / 0.002 = 1000 ohms.
  • (Infos valables lors de la rédaction de l’article, changera surement au cours du temps) La partie programmeur du MSP432 possède son propre firmware. Et les outils de programmation sont sensibles à la version de ce firmware. Normalement, un LaunchPad fraîchement acheté aura la version 2.2.4.0 (ou inférieure) du firmware. La première programmation à l’aide de Code Composer Studio passera ce firmware à la version 2.2.4.2, ce qui rendra le LaunchPad incompatible avec les versions 16 et inférieures du logiciel Energia. À la date de rédaction de l’article, Energia 16 est la dernière version disponible, mais la version du code actuellement sur Github (la future version 17 donc) fonctionne parfaitement.

 

Arnaud Boudou Author: Arnaud Boudou

Développeur Java et mobile (iOS) ; enthousiaste des TIC ; photographe amateur (un jour, peut-être…).

Mes hashtags : #j2ee #objc #raspberrypi #inneedforgadgetry

@boudouarnaud sur Twitter

Like it?  Share  it!

Share Button