Go Down

Topic: ESP-IDF: main() ou app_main() (Read 221 times) previous topic - next topic

68tjs

Jan 15, 2020, 01:06 pm Last Edit: Jan 15, 2020, 01:07 pm by 68tjs
Bonjour,

Dans mes recherches sur l'ESP32 je regarde du coté d'ESP-IDF et je vois que dans les exemples en C/C++ on n'utilise pas main() mais app_main()

Je n'ai jamais entendu parler d' "app_main" qu'elle est la différence avec "main" ?

Bonne journée.

hbachetti

main() n'est qu'une convention.

Si le point d'entrée s'appelle app_main() c'est que le startup appelle cette fonction au lieu de main().
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

68tjs

Merci.
Je pensais que le terme "main" était normalisé en langage C ou C++, donc obligatoire, et que c'était la fonction qui se lançait automatiquement en premier.
D'un autre coté je ne sais pas ce qu'est un "startup" et je pense qu'il faut être réaliste : j'atteins mes limites.

hbachetti

Le startup initialise les variables globales et appelle les constructeurs des objets globaux. Il crée aussi la pile et le tas.

Il configure aussi les périphériques principaux du micro-contrôleur :
- les accès à la mémoire (chip select, wait states, etc)
- l'horloge
- le watchdog
- etc.

Ensuite il appelle main().
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

68tjs

C'est particulier aux microcontrôleur ?

Avec les avr j'avais suivi. J'avais trouvé le vrai fichier C++ avec sa fonction main() qui appellait une fonction init() qui configurait le micro à la sauce arduino.

Avec les avr j'avais l'impression que j'avais prise sur le logiciel arduino et que je pouvais m'en écarter, avec le circuit Xtensa terminé par Espressif je découvre  qu'il existe des mécanismes dont j'ignore l'existence.
Cela devient vraiment une boîte noire dans laquelle on ne peut plus entrer, c'est dommage mais c'est la rançon de la performance.

J'ai toujours aimé comprendre ce que je ne connais pas encore mais là je crains que cela tourne au masochisme.


hbachetti


Vrai. Sur Arduino c'est différent.
Le point d'entrée est main() et il appelle une fonction init(). Init() ne fait pas grand chose à part initialiser timers et ADC.
Init() n'est pas le startup.
Le vrai startup est planqué dans la librairie libgcc, livrée sous forme binaire dans ARDUINO.

Les sources : probablement ici : https://github.com/gcc-mirror/gcc/tree/master/libgcc

Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

68tjs

Le choix se "ferait" au niveau de la conception du  compilateur ou du linker ?
app_main serait normalisé dans le C et/ou C++ ?

Il faut bien un mécanisme qui fixe la première fonction appellée au démarage d'un programme.
Admettons que le choix d'appeler app_main ou main soit fait dans la conception du complilateur ou du linker, je ne m'étais jamais posé la question de savoir où ce choix est fait. Pour moi c'était un choix des concepteurs du langage.

Dans tous les tuto de C que j'ai parcouru  j'ai toujours vu la fonction main et jamais app_main.


Mais pourquoi cette double (ou plus ?) possibilité app_main et main.
Derrière les noms il se cache bien des comportements différents, des avantages et des inconvénients.

En fonctionnement "normal" app_main appelerait-elle directement main ?
Avec les micros (contrôleur ou processeurs) app_main permettrait-elle de faire des actions suplémentaires ?
ou dit autrement app_main est-il réservé aux systèmes d'exploitation ou équivalents, et main pour les programmes qui tournent à l'intérieur d'un système d'exploitation ?

Merci pour ta patience.

.

hbachetti

#7
Jan 16, 2020, 10:14 am Last Edit: Jan 16, 2020, 11:53 am by hbachetti
Quote
Le choix se "ferait" au niveau de la conception du  compilateur ou du linker ?
Non, le choix se fait au niveau de la librairie C.

Quote
Il faut bien un mécanisme qui fixe la première fonction appellée au démarage d'un programme.
Oui, le vecteur de RESET.

Dans le fichier de lien on peut fixer l'adresse de certaines variables ou fonctions.
L'adresse des vecteurs d'interruption est fixée ainsi.
Le vecteur de reset contient l'adresse du startup.
Que le startup appelle main(), app_main() ou toto() importe peu.
main() est simplement un standard, une convention, mais cela dépend totalement de la librairie C.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

al1fch

#8
Jan 16, 2020, 11:24 am Last Edit: Jan 16, 2020, 12:00 pm by al1fch
Bonjour

pour moi le code machine exécuté à la mise sous tension est enfoui dans la ROM de l'ESP32

Il configure certaines ressources (horloges..RAM, UART, SPI...)  en tenant compte de l'état de 'fusibles' (efuses)

Ceci fait il examine l'état de plusieurs GPIO (0, 2....)  et ensuite selon leur combinaison fixe le comportement du bootloader matériel (ROM) , bootloader de premier niveau

Pour ce qui nous concerne cela va donner soit :
-l'activation du téléchargement d'un code par UART et son stockage en memoire Flash SPI
-l'activation directe  du code présent en mémoire Flash SPI avec des points d'entrée définis

Un bootloader logiciel , bootloader de second niveau,  ( téléchargé auparavant par UART avec l'application et nombre de fonctions) entre alors en scène.
Il est  en partie configurable  par la chaine de développement  en application de règles définies  par Xtensa. Une ligne bootloader config apparait dans le menu de configuration de l'IDF.

sources :
boot : https://github.com/espressif/esptool/wiki/ESP32-Boot-Mode-Selection
efuses : https://github.com/espressif/esptool/wiki/espefuse
bootloader logiciel : https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/bootloader.html

Les engagements de confidentialité et non divulgation ne permettent pas à Espressif de documenter en profondeur certaines fonctionnalités de l'ESP32 et Cadence  de répond pas  aux demandes d'utilisateurs Lambda.  Cette situation a déjà été évoquée sur les forums d'Espressif.


al1fch

#9
Jan 16, 2020, 12:06 pm Last Edit: Jan 16, 2020, 12:25 pm by al1fch
pour revenir à  app_main()   il semble d'après cet échange qu'il y ait un rapport avec la désignation 'historique'  des deux coeurs APP et PRO   puis  cpu1 et cpu2

https://esp32.com/viewtopic.php?t=3180

fichier 'startup' pour mega328  ? d'après le nom je verrai bien le fichier objet 'run time'  "crtatmega328.o"

hbachetti

Oui tout à fait. Dans le fichier map on voit bien ceci :
Code: [Select]
.text           0x0000000000000000     0x30de
 *(.vectors)
 .vectors       0x0000000000000000       0x68 /mnt/sdc1/riton/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr5/crtatmega328p.o
                0x0000000000000000                __vectors
                0x0000000000000000                __vector_default
 *(.vectors)
 *(.progmem.gcc*)
                0x0000000000000068                . = ALIGN (0x2)
                0x0000000000000068                __trampolines_start = .
 *(.trampolines)
 .trampolines   0x0000000000000068        0x0 linker stubs
 *(.trampolines*)
                0x0000000000000068                __trampolines_end = .
 *libprintf_flt.a:*(.progmem.data)
 *libc.a:*(.progmem.data)
 *(.progmem*)
 .progmem.data  0x0000000000000068       0x3c /tmp/ccj26h77.ltrans1.ltrans.o
                0x0000000000000068                port_to_output_PGM
                0x0000000000000072                port_to_mode_PGM
                0x000000000000007c                digital_pin_to_port_PGM
                0x0000000000000090                digital_pin_to_bit_mask_PGM
 .progmem.data  0x00000000000000a4       0x14 /tmp/ccj26h77.ltrans2.ltrans.o
                0x00000000000000b8                . = ALIGN (0x2)
 *(.jumptables)
 *(.jumptables*)
 *(.lowtext)
 *(.lowtext*)
                0x00000000000000b8                __ctors_start = .
 *(.ctors)
 .ctors         0x00000000000000b8        0x2 /tmp/ccj26h77.ltrans1.ltrans.o
                0x00000000000000ba                __ctors_end = .
                0x00000000000000ba                __dtors_start = .
 *(.dtors)
                0x00000000000000ba                __dtors_end = .
 SORT(*)(.ctors)
 SORT(*)(.dtors)
 *(.init0)
 .init0         0x00000000000000ba        0x0 /mnt/sdc1/riton/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr5/crtatmega328p.o
                0x00000000000000ba                __init
 *(.init0)
 *(.init1)
 *(.init1)
 *(.init2)
 .init2         0x00000000000000ba        0xc /mnt/sdc1/riton/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr5/crtatmega328p.o
 *(.init2)
 *(.init3)
 *(.init3)
 *(.init4)
 .init4         0x00000000000000c6       0x16 /mnt/sdc1/riton/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/../lib/gcc/avr/5.4.0/avr5/libgcc.a(_copy_data.o)
                0x00000000000000c6                __do_copy_data
 .init4         0x00000000000000dc       0x10 /mnt/sdc1/riton/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/../lib/gcc/avr/5.4.0/avr5/libgcc.a(_clear_bss.o)
                0x00000000000000dc                __do_clear_bss
 *(.init4)
 *(.init5)
 *(.init5)
 *(.init6)
 .init6         0x00000000000000ec       0x16 /mnt/sdc1/riton/.arduino15/packages/arduino/tools/avr-gcc/5.4.0-atmel3.6.1-arduino2/bin/../lib/gcc/avr/5.4.0/avr5/libgcc.a(_ctors.o)
                0x00000000000000ec                __do_global_ctors


__init, __do_copy_data, __do_clear_bss, __do_global_ctors font bien penser à un startup.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

hbachetti

Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

Go Up