Go Down

Topic: Fonction millis() ,boucle "for" (Read 760 times) previous topic - next topic

fdufnews

Naïvement je pensais par exemple qu'un digitalwrite aurait fait après compilation ce que j'aurais pu faire en assembleur....mais c'est comme si le langage était interprété , l'instruction digitalwrite est transformé en une succession d'instructions, même si cette instruction a déjà été utilisé ....(?)
digitalWrite(), c'est une fonction issue d'une librairie. Cette librairie a été développée pour être fonctionnelle sur différents processeurs cibles. Elle crée une couche d'abstraction entre l'appellation D0, D1, D2, ... et les ports matériels desdits processeurs. Tu peux utiliser D0 sur un ATmega328, ATmega2560 ou même un processeur ARM SAM3X8E et cela va fonctionner.
Il ne faut pas perdre de vue que le "langage" Arduino n'a pas été développé pour être performant en vitesse d'exécution mais pour être facile à utiliser par des néophytes. Et d'ailleurs cela suffit pour de nombreuses personnes.

Le C permet de manipuler directement les registres du processeur comme l'a proposé hbachetti mais cela nécessite d'avoir mis le nez dans la documentation.
Il y a, comme je l'ai proposé un peu plus haut, la librairie digitalWriteFast qui à une syntaxe similaire à digitalWrite mais qui est plus rapide car l'identification des registres est faite à la compilation au lieu d'être faite à l'exécution. Mais cela impose une contrainte, si un numéro de port est variable à l'exécution on perd cette optimisation.
Code: [Select]
digitalWrite(D2,HIGH); // sera optimisé
for(i= 2;i<8;i++){
    digitalWrite(i,HIGH);  // ne sera pas optimisé et déroulera le code "standard"
}

hbachetti

Et il ne faut pas oublier :

Code: [Select]

  PORTC |= 0x07;
  PORTC &= ~0x07;


Pilotage de plusieurs sorties simultanément.
Ce que ne permet pas digitalWrite().
Intéressant pour piloter un afficheur à 7 segments multiplexé.
Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

dbrion06

" , l'instruction digitalwrite est transformé en une succession d'instructions, même si cette instruction a déjà été utilisé "
Elle verifie que la patte ne sert pas comme pwm.
Elle recalcule le port et la patte (sert si on veut faire un chenillard ou si on veut du code portable).
Toutes ces operations sont nécessaires dans le cas général, même si elles ralentissent d'un facteur 100 l'operation proprement dite.

Si on juge ces étapes de recalcul du port et de la patte, d'inhibition (puis reactivation) des interruptions, et de detection d'un autre usage inutile, le code source est disponible, prêt à être utilisé en C pour les 4 dernières lignes de la fonction....

ATOS_VQ

Super merci pour vos contributions , le site de garretlab est super et permet d'y voir plus clair sur ces instructions

ATOS_VQ

...petit complément concernant la rapidite....

Code: [Select]
void setup() {
pinMode(3,OUTPUT);
}

void loop() {
 digitalWrite(3,HIGH);
digitalWrite(3,LOW);
}


Duree instruction 4.3us

Code: [Select]
void setup() {
DDRD= 0x08;
}

void loop() {
PORTD=0x08;
PORTD =0x00;
}


Duree instruction 187ns (oscillo)

Je n'ai pas trouve les 63 ns de kamill, pourtant c'est lui qui doit avoir raison l'ATMEGA 328 fonctionne à 20MIPS donc 50ns par instruction
Mon Arduino Nano est bride (chinois !)

kamill

#50
Apr 16, 2019, 11:25 am Last Edit: Apr 16, 2019, 11:31 am by kamill
A l'exécution des instructions PORTD=... il faut ajouter le temps du call de la fonction loop(), par contre 187ns ne parait pas beaucoup car le call/ret prend plusieurs cycles d'horloge.
Sur une UNO ou une Mega2560 l'horloge est à 16MHz.

dbrion06

"Je n'ai pas trouve les 63 ns de kamill, pourtant c'est lui qui doit avoir raison l'ATMEGA 328 fonctionne à 20MIPS donc 50ns par instruction"

C'est en fait 62.5 ns sur un arduino à 16Mhz (le temps d'un cycle) ....

ATOS_VQ

J'ai trouvé la faille....les durées incluaient le loop donc revu et corrige la durée est de  62ns environ
le loop prend 2 cycles 125 en gros....pas d'Arduino sous alimente!

dbrion06

" il faut ajouter le temps du call de la fonction loop(), par contre 187ns ne parait pas beaucoup car le call/ret prend plusieurs cycles d'horloge."

loop , normalement, est appelé une fois (dans un while(1==1) , IIRC): l'optimiseur est assez malin pour s'en rendre compte, normalement, et en faire une fonction inline (i.E un copie coller) .

Go Up