embarqu´ee 4/16 J.-M Friedt
Informatique embarqu´ ee 4/16
J.-M Friedt
FEMTO-ST/d´epartement temps-fr´equence jmfriedt@femto-st.fr
transparents `ajmfriedt.free.fr
5 f´evrier 2018
1 / 23
embarqu´ee 4/16
J.-M Friedt
Exploitation d’une biblioth` eque
1 dangers d’une biblioth`eque
2 utilit´e d’une biblioth`eque
Les ressources additionnelles ne se justifient que sur microcontrˆoleur haut de gamme (>16 bits)
Diverses impl´ementations libres des biblioth`eques standard du C :
• glibc (http://www.gnu.org/software/libc/, utilis´ee par le noyau Linux) ...
• ... et eglibc (embeddedglibc,http://www.eglibc.org/home) ont fusionn´e,
• uClibc (http://www.uclibc.org/, utilis´ee par uClinux),
• ...
2 / 23
embarqu´ee 4/16
J.-M Friedt
Exploitation d’une biblioth` eque –
newlib
Newlib: impl´ementation delibcr´epondant `a toutes les exigences d’un OS ⇒complet, mais complexe et lourd
L’utilisation de printfet du calcul flottant n’est pas `a prendre `a la l´eg`ere :
Taille du fichier .hex intel1: avec stdio 80336 sans stdio 4048 sans stdio, avec une division flottante 12950 sans stdio, avec atan sur flottant 17090 avec stdio, avec une division flottante 80397 avec stdio, avec atan sur flottant 80397
1. J.-M Friedt, ´E. Carry,D´eveloppement sur processeur `a base de cœur ARM7 sous GNU/Linux, GNU/Linux Magazine France117(Juin 2009), pp.40-59
3 / 23
embarqu´ee 4/16
J.-M Friedt
Le probl` eme ...
Dans un programme en C, l’appel `amalloc()se traduit par une erreur
`
a l’´edition de liens
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-sbrkr.o): In function ‘_sbrk_r’:
newlib/libc/reent/sbrkr.c:58: undefined reference to ‘_sbrk’
Idem pourprintf()
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-sbrkr.o): In function ‘_sbrk_r’:
newlib/libc/reent/sbrkr.c:58: undefined reference to ‘_sbrk’
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-writer.o): In function ‘_write_r’:
newlib/libc/reent/writer.c:58: undefined reference to ‘_write’
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-closer.o): In function ‘_close_r’:
newlib/libc/reent/closer.c:53: undefined reference to ‘_close’
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-fstatr.o): In function ‘_fstat_r’:
newlib/libc/reent/fstatr.c:62: undefined reference to ‘_fstat’
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-isattyr.o): In function ‘_isatty_r’:
newlib/libc/reent/isattyr.c:58: undefined reference to ‘_isatty’
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-lseekr.o): In function ‘_lseek_r’:
newlib/libc/reent/lseekr.c:58: undefined reference to ‘_lseek’
arm-none-eabi/lib/thumb/cortex-m3/libc.a(lib_a-readr.o): In function ‘_read_r’:
newlib/libc/reent/readr.c:58: undefined reference to ‘_read’
4 / 23
embarqu´ee 4/16
J.-M Friedt
Exploitation d’une biblioth` eque –
newlib
https://sourceware.org/newlib/libc.html#Stubs: 17 stubs, colle entrenewlibet nos programmes2.
• exit: quitter un programme sans fermer les fichiers ouverts
• environ :
• execve :
• fork :
• fstat :
• getpid :
• isatty :
• kill :
• link :
• lseek :
• open :
• read : lire depuis un fichier
• sbrk :utilis´e parmalloc
• stat :
• times :
• unlink :
• wait :
• write : ´ecrire dans un fichier, incluant stdout
2. http://wiki.osdev.org/Porting_Newlib
5 / 23
embarqu´ee 4/16
J.-M Friedt
Exploitation d’une biblioth` eque –
newlib
Exemple d’impl´ementation (envoyerstdiosur port s´erie)
s s i z e t r e a d r (s t r u c t r e e n t ∗r , i n t f i l e , v o i d∗p t r , s i z e t l e n ) {c h a r c ; i n t i ; u n s i g n e d c h a r ∗p ;
p = (u n s i g n e d c h a r∗) p t r ; f o r ( i = 0 ; i<l e n ; i ++)
{w h i l e ( g l o b a l i n d e x == 0 ){}// ! u a r t 0 k b h i t ( ) ) ; c = g l o b a l t a b [ 0 ] ; g l o b a l i n d e x =0; // ( c h a r ) u a r t 0 g e t c ( ) ; i f ( c == 0x0D ){∗p=’ \0 ’;b r e a k;}
∗p++ = c ; j m f p u t c h a r ( c , NULL , 0 , 0 ) ; }
r e t u r n l e n−i ; }
s s i z e t w r i t e r ( s t r u c t r e e n t ∗r , i n t f i l e , c o n s t v o i d∗p t r , s i z e t l e n ) {i n t i ; c o n s t u n s i g n e d c h a r∗p ;
p = (c o n s t u n s i g n e d c h a r∗) p t r ; f o r ( i = 0 ; i<l e n ; i ++)
{i f (∗p ==’ \ n ’ ) j m f p u t c h a r (’ \ r ’, NULL , 0 , 0 ) ; j m f p u t c h a r (∗p++,NULL , 0 , 0 ) ;
} r e t u r n l e n ; }
v o i d j m f p u t c h a r (i n t a ,c h a r∗c h a i n e , i n t∗c h a i n e i n d e x ,i n t USARTx )
{ i f ( c h a i n e != NULL ){c h a i n e [∗c h a i n e i n d e x ]= a ;∗c h a i n e i n d e x=∗c h a i n e i n d e x +1;}
e l s e {i f ( u s a r t p o r t ==1)
{USART SendData ( USART1 , a ) ;
w h i l e( U S A R T G e t F l a g S t a t u s ( USART1 , USART FLAG TC ) == RESET ){; } }
e l s e
{USART SendData ( USART2 , a ) ;
w h i l e( U S A R T G e t F l a g S t a t u s ( USART2 , USART FLAG TC ) == RESET ){; } }
}
} 6 / 23
embarqu´ee 4/16
J.-M Friedt
D´ emonstration
#i f d e f u s e s t d i o
f o r ( tempe =1; tempe<10; tempe++) {mf=mf∗l f ;}
p r i n t f (" \ n + mf =% d \ n ", (i n t) mf ) ;
t =(c h a r∗) m a l l o c ( 2 0 0 ) ; // m a l l o c r e q u i e r t s b r k p r i n t f (" ^% x \ n ^% x \ n ", (i n t) t [ 0 ] , t [ 1 9 9 ] ) ;
memset ( t , 0 x55 , 2 0 0 ) ;
p r i n t f (" ^% x \ n ^% x \ n ", (i n t) t [ 0 ] , t [ 1 9 9 ] ) ;
#e n d i f w h i l e ( 1 ) {
#i f n d e f u s e s t d i o p u t c h a r s ( welcome ) ;
#e l s e
p r i n t f (" % s ", welcome ) ;
#e n d i f
i f ( i<10) p u t c h a r ( USART1 , i +’ 0 ’) ;
e l s e p u t c h a r ( USART1 , i +’ A ’−10) ; i ++;i f ( i ==16) i =0;
. . .
7 / 23
embarqu´ee 4/16
J.-M Friedt
D´ emonstration
Compromis entre temps de d´eveloppement, fonctionnalit´es et occupation de ressources
3240 main.bin 31824 main_stdio.bin
Ici, affichage parprintf(), allocation de m´emoire parmalloc(), calculs flottants
Un ´emulateur pour tester ses programmes en l’absence du mat´eriel : https://github.com/beckus/qemu_stm32
qemu-system-arm -M stm32-p103 -serial stdio -serial stdio -kernel main.bin suppose n´eanmoins une impl´ementation “correcte” des p´eriph´eriques.
8 / 23
embarqu´ee 4/16
J.-M Friedt
Probl` eme de la coh´ erence de la
chaˆıne de compilation
• Les biblioth`eques doivent suivre le mˆeme mod`ele de binaire que ceux g´en´er´es par le compilateur (EABI)
• ... et ˆetre compil´ees avec les mˆemes options (e.g. hard float v.s soft float).
• Recompiler ses outils pour garantir la coh´erence :
https://github.com/jmfriedt/summon-arm-toolchainqui se charge de configurer tous les outils de la mˆeme fa¸con
TARGET=arm-none-eabi PREFIX=${HOME}/sat
./configure --target=${TARGET} --prefix=${PREFIX} --enable-multilib ...
9 / 23
embarqu´ee 4/16
J.-M Friedt
Conception de logiciels
1 S´eparer le code li´e au mat´eriel (initialisation et acc`es aux ressources mat´erielles) de l’algorithmique
2 Compilation s´epar´ee : choisir une impl´ementation du mat´eriel ou une
´
emulation logicielle (gccsupporte une multitude de plateformes)
3 Permet de tester son code sur PC avant de le porter au
microcontrˆoleur (simulation de diverses conditions mat´erielles) – test automatique, en particulier de cas pathologiques
4 Exploitation d’un simulateur pour connaˆıtre l’´etat interne de la machine qui s´equence le code
5 qemupour un grand nombre de plateformes, simavrpour Atmega32U2
unsigned short interroge (unsigned short puissance, unsigned int freq,unsigned int offset,unsigned char chan) { unsigned int v12;
FTW0[1] = (freq & 0xFF000000) >> 24;
FTW0[2] = (freq & 0xFF0000) >> 16;
FTW0[3] = (freq & 0xFF00) >> 8;
FTW0[4] = (freq & 0xFF);
[...]
v12 = readADC12 ();
readerF2_CLR; // coupe reception
TIM_ITConfig (TIM3, TIM_IT_Update, ENABLE);
return (v&0x03F);
}
10 / 23
embarqu´ee 4/16
J.-M Friedt
Conception de logiciels
1 S´eparer le code li´e au mat´eriel (initialisation et acc`es aux ressources mat´erielles) de l’algorithmique
2 Compilation s´epar´ee : choisir une impl´ementation du mat´eriel ou une
´
emulation logicielle (gccsupporte une multitude de plateformes)
3 Permet de tester son code sur PC avant de le porter au
microcontrˆoleur (simulation de diverses conditions mat´erielles) – test automatique, en particulier de cas pathologiques
4 Exploitation d’un simulateur pour connaˆıtre l’´etat interne de la machine qui s´equence le code
5 qemupour un grand nombre de plateformes, simavrpour Atmega32U2
unsigned short interroge(unsigned short puissance,unsigned int freq, \
__attribute__((unused))unsigned int offset,__attribute__((unused))unsigned char chan) {float reponse;
reponse =exp(-(((float)freq-f01)/df)*(((float)freq-f01)/df))*3100.;
reponse+=exp(-(((float)freq-f02)/df)*(((float)freq-f02)/df))*3100.;
reponse+=(float)((rand()-RAND_MAX/2)/bruit); // ajout du bruit;
if (reponse<0.) reponse=0.;
if (reponse>4095.) reponse=4095.;
usleep(60);
return((unsigned short)reponse);
} 11 / 23
embarqu´ee 4/16
J.-M Friedt
Cas des interruptions
Version PC
v o i d h a n d l e a l a r m (i n t x x x )
{// p r i n t f ( ”RTC : %d %d %d\n ” , s e c o n d e ,→
,→m i n u t e , h e u r e ) ; t i m 0 +=10;
s e c o n d e +=10;
i f ( s e c o n d e>600){m i n u t e ++; s e c o n d e =0;}
i f ( m i n u t e>60){h e u r e ++; m i n u t e =0;}
a l a r m ( 1 ) ; }
v o i d h a n d l e i o (i n t x x x ) {// i o h a p p e n e d =1;
g l o b a l t a b [ g l o b a l i n d e x ] = g e t c h a r ( ) ; i f ( g l o b a l i n d e x<( NB CHARS−1 ) )
g l o b a l i n d e x ++;
}
i n t main ( ){
s i g n a l ( SIGALRM , h a n d l e a l a r m ) ; i o h a p p e n e d =0;
s t r u c t t e r m i o s b u f ; t c g e t a t t r ( 0 , &b u f ) ;
b u f . c l f l a g &= ˜ (ECHO| ICANON ) ; b u f . c c c [ VMIN ] = 1 ;
b u f . c c c [ VTIME ] = 0 ;
t c s e t a t t r ( 0 , TCSAFLUSH , &b u f ) ; s i g n a l ( SIGIO , h a n d l e i o ) ;
i n t s a v e d f l a g s= f c n t l ( 0 , F GETFL , 0 ) ; f c n t l ( 0 , F SETFL , s a v e d f l a g s |O ASYNC| →
,→O NONBLOCK ) ; f c n t l ( 0 , F SETOWN , g e t p i d ( ) ) ;
a l a r m ( 1 ) ; // s i on v e u t s i m u l e r l e t i m e o u t }
Version microcontroleur
v o i d t i m 3 i s r (v o i d) // VERSION LIBOPENCM3 {
i f ( T I M G e t I T S t a t u s ( TIM3 , T I M I T U p d a t e ) !=→
,→RESET )
{T I M C l e a r I T P e n d i n g B i t ( TIM3 , T I M I T U p d a t e ) ; t i m 0 ++;
s e c o n d e ++; // s e c o n d e en 1/10→ ,→s e c o n d e
i f ( s e c o n d e>6 0 0 ) {s e c o n d e = 0 ; m i n u t e++;}
i f ( m i n u t e>6 0 ) {m i n u t e = 0 ; h e u r e ++;}
i f ( h e u r e>2 4 ) {h e u r e = 0;}
} }
v o i d u s a r t 1 i s r (v o i d) {
i f( U S A R T G e t I T S t a t u s ( USART1 , USART IT RXNE→
,→) )
{U S A R T C l e a r I T P e n d i n g B i t ( USART1 ,→
,→USART IT RXNE ) ;
U S A R T C l e a r F l a g ( USART1 , USART IT RXNE ) ; {
g l o b a l t a b [ g l o b a l i n d e x ]=→
,→USART ReceiveData ( USART1 ) ; i f ( g l o b a l i n d e x<(NB CHARS−1))→
,→g l o b a l i n d e x ++;
} } }
12 / 23
embarqu´ee 4/16
J.-M Friedt
Profiter des outils d’analyse de
code
valgrindpour ´etudier les fuites de m´emoire
i n t main ( ) {i n t i [ 3 ] , k ;
f o r ( k =0; k<10;k++){i [ k ]= k ; p r i n t f (" % d ", i [ k ] ) ;}
}
qui s’ex´ecute pour donnerSegmentation fault ...
... est analys´e parvalgrind -q ./mon programmeet donne
==7410== Access not within mapped region at address 0x2
==7410== at 0x8048448: main (demo_valgrind.c:5)
(noter la diff´erence de comportement en ajoutantfflush(stdout)ou\n !)
13 / 23
embarqu´ee 4/16
J.-M Friedt
Profiter des outils d’analyse de
code
gprofpour ´etudier le temps d’ex´ecution de chaque fonction
v o i d f o n c t i o n 1 s ( ) {v o l a t i l e i n t k ;f o r ( k =0; k<0x 1 0 0 0 0 0 0 ; k++){};}
v o i d f o n c t i o n 2 s ( ) {v o l a t i l e i n t k ;f o r ( k =0; k<0x 2 0 0 0 0 0 0 ; k++){};}
v o i d f o n c t i o n 3 s ( ) {v o l a t i l e i n t k ;f o r ( k =0; k<0x 3 0 0 0 0 0 0 ; k++){};}
i n t main ( ) {f o n c t i o n 1 s ( ) ;
f o n c t i o n 2 s ( ) ; f o n c t i o n 3 s ( ) ; }
qui se compile avec l’option-pgpour g´en´erer `a l’ex´ecutiongmon.out...
... qui s’analyse pargprof -bp ./mon programmeet donne
% cumulative self self total
time seconds seconds calls ms/call ms/call name 55.56 0.10 0.10 1 100.00 100.00 fonction3s
33.33 0.16 0.06 1 60.00 60.00 fonction2s
11.11 0.18 0.02 1 20.00 20.00 fonction1s
14 / 23
embarqu´ee 4/16
J.-M Friedt
Simulateur
1 Exploitation d’un simulateur pour connaˆıtre l’´etat interne de la machine qui s´equence le code
2 qemupour un grand nombre de plateformes, simavrpour Atmega32U2
Capture d’´ecran degtkwaveutilis´e pour afficher l’´evolution du port C.
Pr´efixer son programme des d´eclarations de simulations :
#i n c l u d e " a v r _ m c u _ s e c t i o n . h "
AVR MCU( F CPU , " a t m e g a 3 2 ") ;
c o n s t s t r u c t a v r m m c u v c d t r a c e t m y t r a c e [ ] MMCU = { {AVR MCU VCD SYMBOL(" P O R T B ") , . what = (v o i d∗)&PORTB,}, };
i n t main {DDRB |=1<<PORTB5 ; w h i l e ( 1 ){PORTBˆ=1<<PORTB5 ;→
,→ d e l a y m s ( 1 0 0 0 ) ;} }
15 / 23
embarqu´ee 4/16
J.-M Friedt
Simulateur
1 Exploitation d’un simulateur pour connaˆıtre l’´etat interne de la machine qui s´equence le code
2 qemupour un grand nombre de plateformes, simavrpour Atmega32U2
Capture d’´ecran degtkwaveutilis´e pour afficher l’´evolution de la pile.
Pr´efixer son programme des d´eclarations de simulations :
#i n c l u d e " a v r _ m c u _ s e c t i o n . h "
AVR MCU( F CPU , " a t m e g a 3 2 ") ;
c o n s t s t r u c t a v r m m c u v c d t r a c e t m y t r a c e [ ] MMCU ={
{AVR MCU VCD SYMBOL(" P O R T C ") , . what = (v o i d∗) ( 0 x 2 8 ) , }, // &PORTC
{AVR MCU VCD SYMBOL(" S T A C K L ") , . what = (v o i d∗) ( 0 x5D ) , }, // s t a c k =0x3{DE}+0x 2 0 {AVR MCU VCD SYMBOL(" S T A C K H ") , . what = (v o i d∗) ( 0 x5E ) , }, // s t a c k =0x3{DE}+0x 2 0
};
16 / 23
embarqu´ee 4/16
J.-M Friedt
Virgule fixe/virgule flottante
• Repr´esentation d’un nombre en virgule flottante :
• mantisse/exposant (mantisse∈[0,1−1[), similaire `a la notation scientifique 0,1234×103
• supporte une large gamme de valeurs, au d´etriment de la pr´ecision (codage de la position de la virgule)
• exposant 8 bits-mantisse 23 bits (float), 11-52 (double) qui code donc 2±1024'10±308 sur 15 d´ecimales (252'4×1015)
• ⇒arithm´etique complexe, addition passe par la d´enormalisation pour avoir le mˆeme exposant (donc des 0 en d´ebut de mantisse du nombre le plus petit), multiplication ais´ee
• impl´ementation mat´erielle sur processeurs haut de gamme (FPU)
• Repr´esentation en virgule fixe : homoth´etie pour se ramener `a des calculs sur des entiers.
• on note Qm.n pour repr´esenter la partie enti`ere sur m bits et la partie fractionnaire sur n bits3 (notation en compl´ement `a deux, donc inclut un bit de signe)
3. Maxim, Application Note 3722 : Developing FFT Applications with Low-Power Microcontrollers (2006)
17 / 23
embarqu´ee 4/16
J.-M Friedt
Op´ erations sur les flottants
• flottant = mantisse·2exposant
• ⇒multiplication somme les exposants et multiplie les mantisses (probl`eme de pr´ecision)
• ⇒sommer n´ecessite d’aligner les mantisses en ajustant les exposants
• en l’absence de FPU, op´erations logicielles gourmandes en ressources
Exemple sur STM32F1 (pas de FPU)4:
Op´eration dur´ee (µs)
ADC →entier 1,73
ADC→flottant 3,36
entier×106/106 1,08 entier (<<20)(>>20) 0,83 IIR `a 2 coefficients flottants 30
IIR `a 2 coefficients entiers 3
4. donn´ees acquises par G. Matten, LMA, FEMTO-ST
18 / 23
embarqu´ee 4/16
J.-M Friedt
Cas de la fonction affine
1 Un microcontrˆoleur manipule une donn´ee dans sa repr´esentation : une fr´equence de DDS est comprise entre 0 etfCK, repr´esent´ee par [0..2N−1],
2 un humain veut connaˆıtre une fr´eqeunce en Hz fHz =mot
2N ·fCK 3 application num´erique,fCK = 70 MHz etN= 28
⇒70·106/228= 0.260770320892334
4 GNU/Octave (Matlab) :rats(0.260770320892334,5)=6/23et rats(0.260770320892334,8)=914/3505
5 mot∈[0..228]⇒mot×914 sur 38 bits
6 mais si la bande de fr´equence est connue (e.g. 8-10 MHz), bits de poids fort peuvent ˆetre ´elimin´es
(mot&0x003fffff)*914/3505sera exacte, tandis que
0x00400000*914/3505 est pr´ecalcul´e (bits de poids forts connus)
7 si la fr´equence est impr´ecise, bits de poids faible peuvent ˆetre
´
elimin´es : (mot>>8)*914/3505perd les 100 derniers Hz
19 / 23
embarqu´ee 4/16
J.-M Friedt
Exemple de capteur
• soit une mesure de fr´equencef issue d’un capteur oscillant, dont la fr´equence de vibration change avec la temp´eratureT
• sachant quef '1 MHz avec une pr´ecision de 10 Hz, on veut obtenir la temp´erature `a 0,1 K pr`es :
300000 400000 500000 600000 700000 800000 900000 1e+06
-200 -150 -100 -50 0 50 100 150
frequence (Hz)
temperature (degC)
-40 -20 0 20 40 60 80
700000 750000 800000 850000 900000 950000 1e+06
temperature (degC)
frequence (Hz)
f =−6,6667×T2+ 2000×T+ 916670 T=−150 +√
160000−0,15×f
Exprimer cette loi d’´etalonnage avec des coefficients entiers Rappel : la suitexn+1= 12
xn+xy
n
converge vers√ y
(m´ethode de Newton surx2−y= 0 avecxn+1 =xn−f/f0)
20 / 23
embarqu´ee 4/16
J.-M Friedt
Application des coefficients
d’´ etalonnage
T =A+√
B+C·f Hypoth`eses :
• f '106(1 MHz)
• f `a 10 Hz pr`es
• A'100
• C '0,1
• T `a 0,1 K pr`es
21 / 23
embarqu´ee 4/16
J.-M Friedt
Application des coefficients
d’´ etalonnage
Exemple de calcul en virgule fixe compte tenu de la pr´ecision recherch´ee :
1 la loi liant fr´equence et temp´erature est du type f =αT2+βT +γ⇒T =A±√
B+Cf
2 alors (T−A)2=B+C×f donc 2(T−A)dT−2(T −A)dA= dB+dC ×f ⇒ |dT|=
dB 2(T−A)
+
dC×f 2(T−A)
+|dA|
3 on doit donc travailler avec chacun de ces termes inf´erieurs `a 0,1.
4 Application num´erique : par conception,T −A≥100 etf ≤106 doncdB≤10,dA≤0,1 et dC ≤10−5
5 on va donc travailler surA×10 etC×105 pour respecter la r´esolution recherch´ee
6 cependant,C '0,1 doncC×105×f '1010 qui n´ecessite 34 bits,
7 maisf `a 10 Hz donc on peut travailler sur C×105×(f/10)'109 qui ne n´ecessite que 30 bits
Conclusion : 10·A, 104·B et 105·C pr´e- calcul´es
10×T = 10×A+ 10√
B+C·f 10×A+ 10√
B·104+C·f ·104/100 10×A+p
B×104+ (105C) (f/10)/10
22 / 23
embarqu´ee 4/16
J.-M Friedt
Mise en pratique
Nous quittons l’AVR qui a choisi de d´evelopper sa propre libc, pour passer au STM32
• processeur 32 bits capable d’embarquer des biblioth`eques (puis environnements ex´ecutifs)
• summon-arm-toolchainfournit un script pour g´en´erer un ensemble “coh´erent” d’outils – explication de sa compilation `a http://jmfriedt.free.fr/summon_arm.pdf
• le processeur se d´ecline en une multitude de classes :linker script appropri´e.
• Emulateur pour STM32 :´ qemu pour ARM compl´et´e de l’´emulation de p´eriph´eriques –https://github.com/beckus/qemu_stm32.
Les divers outils de compilation :Makefile,configure,cmake Les divers outils d’archivage :svn,git,hg(mercurial)
23 / 23