Informatique embarqu´ee3/12

J.-M Friedt

Informatique embarqu´ee3/12

J.-M Friedt

FEMTO-ST/´epartement temps-fr´equence

[email protected]

transparents `a jmfriedt.free.fr

24 janvier 2015

1 / 15 Informatique embarqu´ee3/12 J.-M Friedt Exploitation d’une biblioth`eque

1 dangers d’une biblioth`eque 2 utilit´ed’une biblioth`eque

Les ressources additionnelles ne se justifient que sur microcontrˆoleur haut de gamme (> 16 bits)

Diverses impl´ementations libres des biblioth`equesstandard du : • glibc (http://www.gnu.org/software/libc/, utilis´eepar le noyau ) ... • ... et eglibc (embedded glibc, http://www.eglibc.org/home) ont fusionn´e, • uClibc (http://www.uclibc.org/, utilis´eepar uClinux), • ...

2 / 15 Informatique embarqu´ee3/12 J.-M Friedt Exploitation d’une biblioth`eque–

Newlib : impl´ementationde libc r´epondant `atoutes les exigences d’un OS ⇒ complet, mais complexe et lourd L’utilisation de printf et du calcul flottant n’est pas `aprendre `ala l´eg`ere:

avec stdio 80336 Taille du fichier .hex intel 1 : 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 `abase de cœur ARM7 sous GNU/Linux, GNU/Linux Magazine France 117 (Juin 2009), pp.40-59 3 / 15 Informatique embarqu´ee3/12 J.-M Friedt Le probl`eme... Dans un programme en C, l’appel `a malloc() se traduit par une erreur `al’´editionde 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’

4 / 15 Informatique embarqu´ee3/12 J.-M Friedt Exploitation d’une biblioth`eque– newlib https://sourceware.org/newlib/libc.html#Stubs : 17 stubs, colle entre newlib et nos programmes 2.

• exit : quitter un programme • lseek : sans fermer les fichiers ouverts • open : • environ : • read : lire depuis un fichier • execve : • sbrk : utilis´epar malloc • fork : • stat : • fstat : • times : • getpid : • unlink : • isatty : • wait : • kill : • write : ´ecriredans un fichier, • link : incluant stdout

2. http://wiki.osdev.org/Porting_Newlib 5 / 15 Informatique embarqu´ee3/12 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 (struct r e e n t ∗r , int file, void ∗ptr , s i z e t l e n ) {c h a r c; int i; unsigned char ∗p ; p = (unsigned char ∗) p t r ; f o r (i=0; i < l e n ; i ++) {w h i l e ( global i n d e x == 0) {} //!uart0 k b h i t()); c = g l o b a l tab [0]; global i n d e x =0; //(char) uart0 g e t c(); i f (c == 0x0D) {∗p=’\0’ ;break; } ∗p++ = c ; j m f putchar(c,NULL,0 ,0) ; } r e t u r n len − i ; }

s s i z e t w r i t e r ( struct r e e n t ∗r , int file, const void ∗ptr , s i z e t l e n ) { i n t i; const unsigned char ∗p ; p = (const unsigned char ∗) 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 len; }

v o i d jmf p u t c h a r (int a,char ∗chaine , int ∗ c h a i n e i n d e x ,int USARTx) { i f (chaine != 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 (usart p o r t ==1) {USART SendData (USART1, a); w h i l e(USART GetFlagStatus(USART1, USART FLAG TC) == RESET) { ; } } e l s e {USART SendData (USART2, a); w h i l e(USART GetFlagStatus(USART2, USART FLAG TC) == RESET) { ; } } } } 6 / 15 Informatique embarqu´ee3/12 J.-M Friedt D´emonstration

#ifdef use 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" ,(int)mf);

t =(char ∗)malloc(200); // malloc requiert s b r k p r i n t f ( "^%x\n^%x\n" ,(int)t[0],t[199]); memset(t ,0x55,200) ; p r i n t f ( "^%x\n^%x\n" ,(int)t[0],t[199]); #endif

w h i l e (1) { #ifndef use s t d i o p u t chars(welcome); #else p r i n t f ( "%s" , welcome ) ; #endif i f (i <10) p u t c h a r (USART1 , i+’0’ ); e l s e put c h a r (USART1 , i+’A’ −10) ; i ++;if (i==16) i=0; ...

7 / 15 Informatique embarqu´ee3/12 J.-M Friedt D´emonstration

Compromis entre temps de d´eveloppement, fonctionnalit´eset occupation de ressources

3240 main.bin 31824 main_stdio.bin

Ici, affichage par printf(), allocation de m´emoirepar malloc(), calculs flottants

Un ´emulateurpour 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´eanmoinsune impl´ementation“correcte” des p´eriph´eriques.

8 / 15 Informatique embarqu´ee3/12 J.-M Friedt M´ethodes de d´everminagede code embarqu´e

1 la partie algorithmique du code est portable et se compile sur PC ⇒ bien s´eparer les parties algorithmiques et acc`esau mat´eriel + donne acc`esaux outils de profilage et anayse du PC 2 l’´emulateur(plus souple que le mat´eriel,et permet de sonder la machine `a´etatsqu’est le processeur) 3 sonde JTAG et gdb (si disponible) : ex´ecutionsur le “vrai” mat´eriel avec points d’arrˆetet avance pas `apas.

9 / 15 Informatique embarqu´ee3/12 J.-M Friedt Compilation s´epar´eepour qualifier un logiciel

• tester des conditions de fonctionnement impr´evuesou rarement accessibles exp´erimentalement • exploiter des outils de d´everminage (valgrind) ou de profilage • test unitaire Programme principal, biblioth`eque i n t main() { initialisation(); w h i l e (1) { interroge();traitements();} } Programme pour microcontrˆoleur u n s i g n e d short interroge (unsigned int freq) { GPIO SetBits(GPIOB, GPIO Pin 1 ) ; v = readADC1 (ADC Channel 8 ) ; GPIO ResetBits (GPIOB,GPIO Pin 1 ) ; ... r e t u r n (v); }

10 / 15 Informatique embarqu´ee3/12 J.-M Friedt Compilation s´epar´eepour qualifier un logiciel

• tester des conditions de fonctionnement impr´evuesou rarement accessibles exp´erimentalement • exploiter des outils de d´everminage (valgrind) ou de profilage • test unitaire Programme principale, biblioth`eque i n t main() { initialisation(); w h i l e (1) { interroge();traitements();} } Programme pour PC u n s i g n e d short interroge (unsigned int freq) reponse =exp(−(((float)freq −f 0 1 ) / d f ) ∗(((float)freq −f 0 1 ) / d f ) ) ∗3100.; reponse+=exp(−(((float)freq −f 0 2 ) / d f ) ∗(((float)freq −f 0 2 ) / d f ) ) ∗3100.; r e p o n s e+=(float)((rand() −RAND MAX/2)/bruit ); // ajout du bruit; i f (reponse <0.) reponse=0.; i f (reponse >4095.) reponse=4095.; usleep(60); r e t u r n((unsigned short)reponse);

11 / 15 Informatique embarqu´ee3/12 J.-M Friedt Cas des interruptions Version PC v o i d handle a l a r m (int xxx) Version microcontroleur { // printf(”RTC:%d%d%d \n”,seconde, → v o i d tim3 i s r (void) // VERSION LIBOPENCM3 ,→minute,heure); { tim0 +=10; i f(TIM GetITStatus(TIM3, TIM IT Update ) !=→ seconde+=10; ,→RESET) i f (seconde >600){minute++;seconde=0;} {TIM ClearITPendingBit(TIM3,TIM IT Update ) ; i f (minute >60) {heure++;minute=0;} tim0++; alarm ( 1 ) ; seconde++; // seconde en 1/10 → } ,→seconde i f (seconde > 600) v o i d handle i o (int xxx) {seconde = 0;minute++;} { // io h a p p e n e d=1; i f (minute > 60) g l o b a l t a b [ g l o b a l index] = getchar (); {minute = 0;heure++;} i f (global i n d e x < (NB CHARS − 1) ) i f (heure > 24) g l o b a l i n d e x ++; {h e u r e = 0;} } } } i n t main() { signal(SIGALRM, handle a l a r m ) ; v o i d usart1 i s r (void) { i o happened=0; i f(USART GetITStatus(USART1, USART IT RXNE→ s t r u c t termios buf; ,→)) tcgetattr(0, &buf); {USART ClearITPendingBit(USART1, → buf . c l f l a g &= ˜(ECHO | ICANON) ; ,→USART IT RXNE); buf . c cc [VMIN]=1; USART ClearFlag (USART1,USART IT RXNE); buf . c c c [ VTIME]=0; { tcsetattr (0, TCSAFLUSH, &buf); g l o b a l t a b [ g l o b a l i n d e x ]=→ signal(SIGIO, handle i o ) ; ,→USART ReceiveData(USART1) ; i n t savedflags=fcntl(0, F GETFL , 0) ; i f (global i n d e x <(NB CHARS−1)) → f c n t l ( 0 , F SETFL, savedflags | O ASYNC | → ,→ g l o b a l i n d e x ++; ,→O NONBLOCK ) ; } f c n t l ( 0 , F SETOWN, getpid()); } alarm ( 1 ) ; // si on veut simuler le timeout } }

12 / 15 Informatique embarqu´ee3/12 J.-M Friedt Profiter des outils d’analyse de code

valgrind pour ´etudierles 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;printf( "%d" , i [ k ] ) ;} } qui s’ex´ecutepour donner Segmentation fault ...

... est analys´epar valgrind -q ./mon programme et donne

==7410== Access not within mapped region at address 0x2 ==7410== at 0x8048448: main (demo_valgrind.c:5)

(noter la diff´erencede comportement en ajoutant fflush(stdout) ou \n !)

13 / 15 Informatique embarqu´ee3/12 J.-M Friedt Profiter des outils d’analyse de code

gprof pour ´etudierle temps d’ex´ecutionde chaque fonction

v o i d fonction1s() { v o l a t i l e int k;for (k=0;k <0x1000000 ; k++) {};} v o i d fonction2s() { v o l a t i l e int k;for (k=0;k <0x2000000 ; k++) {};} v o i d fonction3s() { v o l a t i l e int k;for (k=0;k <0x3000000 ; k++) {};}

i n t main() {fonction1s(); fonction2s(); fonction3s(); } qui se compile avec l’option -pg pour g´en´erer`al’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

14 / 15 Informatique embarqu´ee3/12 J.-M Friedt Mise en pratique

Outils pour travailler sur STM32 : • summon-arm-toolchain fournit un script pour g´en´ererun ensemble “coh´erent”d’outils – explication de sa compilation `a http://jmfriedt.free.fr/summon_arm.pdf • le processeur se d´eclineen une multitude de classes : linker script appropri´e. • Emulateur´ pour STM32 : qemu pour ARM compl´et´ede l’´emulation de p´eriph´eriques– https://github.com/beckus/qemu_stm32.

15 / 15