Electronique´ num´erique J.-M Friedt
Electronique num´ ´ erique
J.-M Friedt
FEMTO-ST/d´ epartement temps-fr´ equence jmfriedt@femto-st.fr
transparents ` a jmfriedt.free.fr
22 novembre 2020
1 / 25
num´erique
J.-M Friedt
Plan des interventions :
7 cours/TP d’introduction au STM32 en C baremetal :
1 Electronique num´ ´ erique et conception du circuit
L3 : aspects analogiques, consommation ´ electrique, lecture de datasheet Survol des divers p´ eriph´ eriques qui seront abord´ es (RS232, SPI, timer, ADC) repr´ esentation des donn´ ees (tailles/encodage), masques, architecture
Rappels sur Atmega32U4 (Makefile, compilation, masques ...)
2 Premiers pas sur le STM32, adresses des p´ eriph´ eriques, architecture
3 Fonctionnement de gcc et optimisations :
pr´ eprocess–compilateur–assembleur–linker, passage C ` a assembleur, pointeurs 4 biblioth` eques et s´ eparation algorithme/mat´ eriel, simulateurs
libopencm3, newlib & stubs, ressources requises par les biblioth` eques 5 Bus de communication s´ erie, synchrone/asynchrone
6 arithm´ etique sur syst` emes embarqu´ es
entiers, flottants, convertir un algorithme exprim´ e en nombres ` a virgules vers des entiers, timers
7 interruptions et acquisition de donn´ ees analogiques, fr´ equence d’´ echantillonnage
vecteurs d’interruption, gestion des horloges du STM32, ADC
2 / 25
Electronique´ num´erique
J.-M Friedt
Compiler son compilateur
Une chaˆıne de compilation n´ ecessite
1 le compilateur (gcc)
2 les outils pour convertir les divers formats de fichiers (binutils)
3 les biblioth` eques (newlib)
+ debugger (gdb) + outils de programmation du microcontrˆ oleur (avrdude, stm32flash, dfu-programmer ...)
configure --target=arm-none-eabi --prefix= $ {HOME}/sat
Automatiser ce processus dans un script pour g´ en´ erer un ensemble
“coh´ erent” d’outils 1 .
1. explication de son utilisation ` a http://jmfriedt.free.fr/summon_arm.pdf
3 / 25
num´erique
J.-M Friedt
newlib
Implication de la biblioth` eque de calculs flottants :
toujours en thumb :
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
Thumb est un sous-ensemble d’instructions pour processeur ARM cod´ e sur 16 bits au lieu de 32 bits
2Diverses impl´ ementations libres des biblioth` eques standard du C :
• glibc (http://www.gnu.org/software/libc/, utilis´ ee par le noyau Linux) ...
• ... et eglibc (embedded glibc, http://www.eglibc.org/home) ont fusionn´ e,
• uClibc (http://www.uclibc.org/, utilis´ ee par uClinux),
2. J.-M Friedt, ´ E. Carry, D´ eveloppement sur processeur ` a base de cœur ARM7 sous GNU/Linux, GNU/Linux Magazine France 117 (Juin 2009), pp.40-59
4 / 25
Electronique´ num´erique
J.-M Friedt
Le probl` eme ...
Dans un programme en C, l’appel ` a malloc() 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 pour printf()
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’
5 / 25
num´erique
J.-M Friedt
Exploitation d’une biblioth` eque –
newlib
https://sourceware.org/newlib/libc.html#Stubs : 17 stubs, colle entre newlib et nos programmes 3 .
• 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 par malloc
• stat :
• times :
• unlink :
• wait :
• write : ´ ecrire dans un fichier, incluant stdout
3. http://wiki.osdev.org/Porting_Newlib
6 / 25
Electronique´ num´erique
J.-M Friedt
Exploitation d’une biblioth` eque –
newlib
Exemple d’impl´ ementation (envoyer stdio sur 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 ){; } }
}
} 7 / 25
num´erique
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;
. . .
8 / 25
Electronique´ num´erique
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 par printf(), allocation de m´ emoire par malloc(), 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.
simavr pour Atmega32U2
9 / 25
num´erique
J.-M Friedt
Stubs
• Un programme principal contient toute l’“intelligence” du code : algorithmique
• Ce programme fait exclusivement appel ` a des fonctions g´ en´ eriques ind´ ependantes du mat´ eriel : stubs
• L’acc` es de ces fonctions au mat´ eriel est impl´ ement´ e dans des fichiers s´ epar´ es
• Algorithmique est li´ e aux appels mat´ eriel par le compilation (compilation s´ epar´ ee)
• Possibilit´ e de passer des arguments par Makefile : variables et tests conditionnels
• Edition de lien g´ ´ en` ere un ex´ ecutable
algorithmique led_on() led_off() communique()
matériel1
GP3DAT |= 0x00070000;
GP3DAT |&= (~0x00070000);
COMTX = a;
matériel2, bibliothèque2 gpio_set (GPIOA, GPIO4);
gpio_clear(GPIOA, GPIO4);
usart_send_blocking (USART1,a)
#include makefile.cortex_AD9958
#include makefile.cortex_XE1203 include makefile.aduc MODBUS = 0
ifeq ($(MODBUS),1) endif
...
matériel2, bibliothèque1
GPIO_SetBits(GPIOC,GPIO_Pin_2);
GPIO_ResetBits(GPIOC,GPIO_Pin_1);
USART_SendData (USART1, a);
Makefile
Edition de liens −> exécutable
→ remplacement “ais´ e” de la plateforme mat´ erielle sans modifier l’algorithme (HAL)
→ “fausses fonctions” sur PC pour ´ emuler les appels : test unitaire
10 / 25
Electronique´ num´erique
J.-M Friedt
HAL : Hardware Abstraction Layer HAL
Android
ST Microelectronics development fra- mework
https://source.android.com/devices/architecture
https://www.st.com/en/embedded-software/x-cube-spn14.html
11 / 25
num´erique
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 (gcc supporte 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 qemu pour grand nombre de plateformes, simavr pour 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);
}
12 / 25Electronique´ num´erique
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 (gcc supporte 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 qemu pour un grand nombre de plateformes, simavr pour 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);
}
13 / 25num´erique
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 ++;
} } }
14 / 25
Electronique´ num´erique
J.-M Friedt
Profiter des outils d’analyse
valgrind pour ´ etudier les fuites de m´ emoire
i n t main ( ) { c h a r ∗ c ;
c =(c h a r ∗ ) m a l l o c ( 1 0 0 ) ; }
est analys´ e par
valgrind --leak-check=full ./programme pour indiquer que
==20235== HEAP SUMMARY:
==20235== in use at exit: 100 bytes in 1 blocks
==20235== total heap usage: 1 allocs, 0 frees, 100 bytes allocated
==20235==
==20235== 100 bytes in 1 blocks are definitely lost in loss record 1 of 1
==20235== at 0x483577F: malloc (vg_replace_malloc.c:309)
==20235== by 0x109146: main (in ...)
==20235==
==20235== LEAK SUMMARY:
==20235== definitely lost: 100 bytes in 1 blocks
valgrind a d´ etect´ e que le tas n’est pas vide en fin d’ex´ ecution
15 / 25
num´erique
J.-M Friedt
Profiter des outils d’analyse
valgrind pour ´ etudier les acc` es ill´ egaux de m´ emoire
i n t main ( ) { c h a r ∗ c ;
c =(c h a r ∗ ) m a l l o c ( 1 0 0 ) ; c [ 1 0 0 ] = 1 0 ;
f r e e ( c ) ; }
est analys´ e par
valgrind -q ./programme pour indiquer que
==21801== Invalid write of size 1
==21801== at 0x109163: main (in ...)
==21801== Address 0x4a490a4 is 0 bytes after a block of size 100 alloc’d
==21801== at 0x483577F: malloc (vg_replace_malloc.c:309)
==21801== by 0x109156: main (in ...) Etrangement, alors que ´
char *c; c=(char*)malloc(100); c[100]=10; free(c);
et
static char c[100]; c[100]=10;
assignent tous deux c sur le tas, seule la premi` ere erreur d’allocation est d´ etect´ ee par valgrind.
16 / 25
Electronique´ num´erique
J.-M Friedt
Profiter des outils d’analyse
valgrind pour ´ etudier acc` es ` a une zone m´ emoire non-allou´ ee (moins ´ evident ` a analyser sur la pile : corruption du compteur de programme au retour de la fonction printf())
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 donner Segmentation fault ...
... est analys´ e par valgrind -q ./mon programme et donne
==22408== Jump to the invalid address stated on the next line
==22408== at 0x700000006: ???
==22408== by 0x900000007: ???
==22408== by 0x48ACBBA: (below main) (libc-start.c:308)
==22408== Address 0x700000006 is not stack’d, malloc’d or (recently) free’d
==22408==
==22408==
==22408== Process terminating with default action of signal 11 (SIGSEGV)
==22408== Access not within mapped region at address 0x700000006
==22408== at 0x700000006: ???
==22408== by 0x900000007: ???
==22408== by 0x48ACBBA: (below main) (libc-start.c:308)
17 / 25
num´erique
J.-M Friedt
Profiter des outils d’analyse
gprof pour ´ 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 -pg pour g´ en´ erer ` a l’ex´ ecution gmon.out ...
... qui s’analyse par gprof -bp ./mon programme et 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
18 / 25
Electronique´ num´erique
J.-M Friedt
Simulateur
1 Exploitation d’un simulateur pour connaˆıtre l’´ etat interne de la machine qui s´ equence le code
2 qemu pour un grand nombre de plateformes, simavr pour Atmega32U2
Capture d’´ ecran de gtkwave utilis´ 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 ) ;}}
19 / 25
num´erique
J.-M Friedt
Simulateur
1 Exploitation d’un simulateur pour connaˆıtre l’´ etat interne de la machine qui s´ equence le code
2 qemu pour grand nombre de plateformes, simavr pour Atmega32U2
1 us + 0A
xx FF FD FC FB DB
Time
STACKH[7:0]=0A STACKL[7:0]=xxPr´ 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 };
20 / 25
Electronique´ num´erique
J.-M Friedt
Emulation des p´ ´ eriph´ eriques
Un ´ emulateur simule le comportement du cœur du processeur, mais comment ´ emuler les p´ eriph´ eriques 4 ?
Exemple du convertisseur analogique-num´ erique du STM32 :
s t a t i c v o i d s t m 3 2 a d c s t a r t c o n v ( Stm32Adc∗s )
{u i n t 6 4 t c u r r t i m e = q e m u c l o c k g e t n s ( QEMU CLOCK VIRTUAL ) ; i n t c h a n n e l n u m b e r=s t m 3 2 A D C g e t c h a n n e l n u m b e r ( s , 1 ) ; i f ( c h a n n e l n u m b e r ==16)
{s−>Vdda=r a n d ( ) %(1200+1) + 2 4 0 0 ; // Vdda b e l o n g s t o t h e i n t e r v a l [ 2 4 0 0 3 6 0 0 ] mv
s−>V r e f=r a n d ( ) %(s−>Vdda−2400+1) + 2 4 0 0 ; // V r e f b e l o n g s t o t h e i n t e r v a l [ 2 4 0 0 Vdda ] mv
s−>ADC DR= s−>Vdda−s−>V r e f ; }
e l s e i f ( c h a n n e l n u m b e r ==17) i
{s−>ADC DR= ( s−>V r e f=r a n d ( ) %(s−>Vdda−2400+1) + 2 4 0 0 ) ; // V r e f [ 2 4 0 0 Vdda ] mv }
e l s e
{s−>ADC DR=((i n t) ( 1 0 2 4 .∗( s i n (2∗M PI∗q e m u c l o c k g e t n s ( QEMU CLOCK VIRTUAL ) /1 e 9 ) + 1 . ) ) &0 x f f f→
,→) ; }
s−>ADC SR&=˜ADC SR EOC ; // i n d i c a t e s o n g o i n g c o n v e r s i o n s−>ADC CR2&=˜ADC CR2 SWSTART ;
// c a l l s c o n v c o m p l e t e when e x p i r e s
t i m e r m o d ( s−>c o n v t i m e r , c u r r t i m e + s t m 3 2 A D C g e t n b r c y c l e p e r s a m p l e ( s , c h a n n e l n u m b e r ) ) ; }
4. https://github.com/beckus/qemu stm32/blob/stm32/hw/arm/stm32 adc.c#L700
21 / 25
num´erique
J.-M Friedt
Communication RS232 5 (32U4)
#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 ") ;
AVR MCU VCD FILE (" t r a c e _ f i l e . vcd ", 1 0 0 0 ) ;
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(" U D R 1 ") , . what = (v o i d∗)&UDR1 , }, };
pour d´ eclarer le registre observ´ e (UDR1), puis
#d e f i n e UART BAUDRATE ( 5 7 6 0 0 ) //#d e f i n e UART BAUDRATE ( 9 6 0 0 ) v o i d i n i t u a r t (v o i d) {u n s i g n e d s h o r t baud ;
UCSR1A = (1<<UDRE1) ; // i m p o r t a n t l y U2X1 = 0
UCSR1B = ( 1<<RXEN1 )|( 1<<TXEN1) ; // e n a b l e r e c e i v e r and t r a n s m i t t e r
UCSR1C = (1<<UCSZ11 )|(1<<UCSZ10 ) ; // 8N1 // UCSR1D = 0 ; // no r t c / c t s baud = ( ( ( ( F CPU / ( UART BAUDRATE∗16UL ) ) )−1 ) ) ;
UBRR1H = (u n s i g n e d c h a r) ( baud>>8);
UBRR1L = (u n s i g n e d c h a r) baud ; }
v o i d u a r t t r a n s m i t (u n s i g n e d c h a r d a t a )
{w h i l e ( ! ( UCSR1A & (1<<UDRE1) ) ) ; // w a i t w h i l e r e g i s t e r i s f r e e
UDR1 = d a t a ; // l o a d d a t a i n t h e r e g i s t e r
}
v o i d s e n d b y t e (u n s i g n e d c h a r c ) {u n s i g n e d c h a r tmp ;
tmp=c>>4; i f ( tmp<10) u a r t t r a n s m i t ( tmp+’ 0 ’) ; e l s e u a r t t r a n s m i t ( tmp+’ A ’−10) ; tmp=( c&0 x 0 f ) ; i f ( tmp<10) u a r t t r a n s m i t ( tmp+’ 0 ’) ; e l s e u a r t t r a n s m i t ( tmp+’ A ’−10) ; }
13 ms
xx 46 39 44 38 30
Time
UDR1[7:0]=440,188 ms
10 ms 20 ms
xx 46 39 44 38 30
Time
UDR1[7:0]=391,234 ms
5. J.-M Friedt, D´ evelopper sur microcontrˆ oleur sans microcontrˆ oleur : les
´
emulateurs, GNU/Linux Magazine France HS 103 (Juillet-Aout 2019)
22 / 25Electronique´ num´erique
J.-M Friedt
Nouvelle architecture : RISC V
#i n c l u d e<s t d i o . h>
i n t main ( ) {l o n g x=0x 1 2 3 4 5 6 7 8 ;
c h a r ∗c =(c h a r∗)&x ;
p r i n t f (" \ n % d \ n ",s i z e o f(l o n g) ) ;
p r i n t f (" % hhx % hhx % hhx % hhx \ n ", c [ 0 ] , c [ 1 ] , c [ 2 ] , c [ 3 ] ) ; }
Rappel : newlib n´ ecessite le stub write() pour afficher
FEMTO=[...]/riscv-probe/
riscv64-unknown-elf-gcc -march=rv32imac -mabi=ilp32 -mcmodel=medany -c h.c riscv64-unknown-elf-gcc -march=rv32imac -mabi=ilp32 -mcmodel=medany \
-nostartfiles -nostdlib -nostdinc -static -lgcc \ -T $(FEMTO)/env/qemu-sifive_e/default.lds \
$(FEMTO)/build/obj/rv32imac/env/qemu-sifive_e/crt.o \
$(FEMTO)/build/obj/rv32imac/env/qemu-sifive_e/setup.o h.o \
$(FEMTO)/build/lib/rv32imac/libfemto.a -o hello32
s’ex´ ecute dans qemu par
$ [...]/riscv-qemu/riscv32-softmmu/qemu-system-riscv32 -M sifive_e \ -nographic -kernel hello32
4
00000078 00000056 00000034 00000012
→ long est cod´ e sur cette architecture 32 bits sur 4 octets
→ 0x78 apparaˆıt en premier, l’octet de poids faible est ` a l’adresse la plus faible : little endian
23 / 25
num´erique
J.-M Friedt
Nouvelle architecture : RISC V
#i n c l u d e<s t d i o . h>
i n t main ( ) {l o n g x=0x 1 2 3 4 5 6 7 8 ;
c h a r ∗c =(c h a r∗)&x ;
p r i n t f (" \ n % d \ n ",s i z e o f(l o n g) ) ;
p r i n t f (" % hhx % hhx % hhx % hhx \ n ", c [ 0 ] , c [ 1 ] , c [ 2 ] , c [ 3 ] ) ; }
Rappel : newlib n´ ecessite le stub write() pour afficher En compilant en 64 bits par (options -march= et -mabi) :
riscv64-unknown-elf-gcc -march=rv64imac -mabi=lp64 -mcmodel=medany -c h.c riscv64-unknown-elf-gcc -march=rv64imac -mabi=lp64 -mcmodel=medany \
-nostartfiles -nostdlib -nostdinc -static -lgcc \ -T $(FEMTO)/env/qemu-sifive_e/default.lds \
$(FEMTO)/build/obj/rv64imac/env/qemu-sifive_e/crt.o \
$(FEMTO)/build/obj/rv64imac/env/qemu-sifive_e/setup.o h.o
$(FEMTO)/build/lib/rv64imac/libfemto.a -o hello64
nous obtenons sous la version 64 bits de qemu le r´ esultat
$ [...]/riscv-qemu/riscv64-softmmu/qemu-system-riscv64 -M sifive_e \ -nographic -kernel hello64
8
00000078 00000056 00000034 00000012
→ long occupe 8 octets (64 bits)
→ toujours little endian
24 / 25
Electronique´ num´erique
J.-M Friedt
Cette s´ eparation permet d’utiliser Conclusion
• outils de profilage et d’analyse de code (lint, valgrind ...)
• outils de test unitaire (cunit)
• un nouveau processeur avec le mˆ eme algorithme de traitement Unique convertisseur analogique- num´ erique : 1×12-bit ` a 2,4 MSPS
v o i d i n i t a d c (v o i d)
{g p i o m o d e s e t u p ( GPIOB , GPIO MODE ANALOG , → ,→GPIO PUPD NONE , GPIO0|GPIO1 ) ; a d c p o w e r o f f (ADC1) ;
a d c d i s a b l e s c a n m o d e (ADC1) ;
// ADCCLOCK<30 MHz, f r o m APB2 =>p r e s c a l e → ,→t q APB2/DIV<30 MHz
a d c s e t c l k p r e s c a l e ( ADC CCR ADCPRE BY4 ) ; a d c s e t s a m p l e t i m e o n a l l c h a n n e l s ( ADC1 , →
,→ADC SMPR SMP 112CYC ) ;
// s i ADCCLOCK = 21 MHz, s a m p l e t i m e = 144 =>→ ,→Tconv = 7 . 4 2 8 6 u s .
a d c p o w e r o n (ADC1) ; }
u n s i g n e d s h o r t r e a d a d c (u n s i g n e d c h a r → ,→c h a n n e l )
{u i n t 8 t c h a n n e l a r r a y [ 1 6 ] ; c h a n n e l a r r a y [ 0 ] = c h a n n e l ; a d c s e t r e g u l a r s e q u e n c e ( ADC1 , 1 ,→
,→c h a n n e l a r r a y ) ; // u s e d c h a n n e l a d c s t a r t c o n v e r s i o n r e g u l a r (ADC1) ; w h i l e ( ! a d c e o c (ADC1) ) ;
r e t u r n( a d c r e a d r e g u l a r (ADC1) ) ; }
25 / 25