Bonjour à tous,
Je vous présente mon projet HWA (HardWare Advanced), qui vise à établir une syntaxe élégante pour programmer des microcontrôleurs ou des périphériques en langage C.
Il ne s'agit pas d'une bibliothèque d'abstraction mais d'un ensemble de macros qui produisent un code C qui sera correctement optimisé par le compilateur. Il n'y a donc aucun coût en termes de vitesse d'exécution ou de consommation mémoire et besoin de rien d'autre qu'une chaîne de compilation C (C11).
Un court exemple pour un STM32 :
Code C : Sélectionner tout - Visualiser dans une fenêtre à part
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 #include <hwa/stm32f103rbt6.h> #define AHBHZ HW_DEVICE_HSIHZ // AHB frequency #define COUNTER counter2 #define PERIOD 0.25 // Blinking period #define LED1 pa2 /* Service counter IRQ: toggle the LED. */ HW_ISR( COUNTER ) { hw( clear, irq(COUNTER) ); hw( toggle, LED1 ); } int main ( ) { hwa( begin_from_reset ); /* Power the controllers we use */ hwa( power, (LED1,port), on ); hwa( power, COUNTER, on ); hwa( commit ); /* Configure GPIOs */ hwa( configure, LED1, mode, digital_output, frequency, lowest ); /* Configure the counter */ hwa( configure, COUNTER, mode, counter, clock, from_apb1_psc, direction, up_loop, prescaler, AHBHZ*0.001 - 1, // 1 ms clock period reload, PERIOD/2 / 0.001 - 1, run, yes ); hwa( commit ); hw( turn, (COUNTER,nvic), on ); hw( enable, irq(COUNTER) ); /* Sleep between interrupts */ for(;;) { hw( sleep_until_irq ); // sleep_until_event is OK too. } }
En bref, HWA fournit un ensemble d'objets prédéfinis, qui représentent le contenu du microcontrôleur, et deux instructions génériques :
- 'hw(...)' qui effectue immédiatement une action sur un objet ;
- 'hwa(...)' qui enregistre une action dans une transaction qui sera exécutée par 'hwa(commit)'.
Ces instructions acceptent un nombre variable d'arguments. Typiquement, un nom d'action, un objet, une liste de paires argument/valeur qui peuvent être obligatoires ou optionnels.
Les objets sont désignés par leur nom ou par un chemin constitué d'une suite de noms d'objets. Par exemple '(LED1,port)' désigne l'objet 'port' qui gère la broche LED1.
J'ai porté une attention particulière à la gestion des erreurs qui peut rapidement devenir pénible avec les macros. Normalement, en cas de problème, le compilateur affiche un message éclairant, par exemple pour rappeler la syntaxe d'une action ou les valeurs acceptables pour un argument.
Ce projet est en développement (chaotique !) depuis des années mais je pense que ses fondations commencent à bien se stabiliser.
Le code est hébergé sur Github ici, une documentation avec des exemples : là.
L'objectif de mon intervention ici est d'évaluer l'intérêt que ce projet suscite et de récolter des idées, des remarques qui pourraient me guider pour la suite. Je réponds aux questions s'il y en a !
Partager