Fonction millis() ,boucle "for"

Bonjour à tous

Le mystère persiste avec un autre problème ou piège plus exactement.
J’ai tenté le nbr de boucle max soit 2^32-1 , et la aucun résultat !

En fait on pourrait penser que la boucle s’effectue jusqu’au débordement, mais non aucune boucle ne s’effectue
La toute dernière boucle serait pour i=2^32-1, mais i++ est incrémente et déborde ! On ne peut donc faire que 2^32-2 boucles

Mais le plus surprenant est que ces quelques 4 milliards d’opérations sont faites en un temps record, invisible !!!

Je n’ai pas vérifier la fréquence d’horloge de l’Atmega ni le nbr d’opérations par cycle d’horloge, mais même à 1 opération élémentaire par cycle à 40Mhz , la sortie de boucle devrait se faire en gros après 100 secondes .
Ils sont forts ces chinois ils ont réussi à faire tourner l’Arduino Nano à plus de 1Ghz !!! ???
Trèfle de plaisanterie je suis preneur d’explications …

unsigned long Temp;
unsigned long Data;
unsigned long MaxLong =pow(2,32)-1; 
void setup() {
Serial.begin(9600);
 Serial.println("Debut");
}

void loop() {
 
  Temp=millis();  
  Data=0;
      for(unsigned long i=1 ; i <= MaxLong-1; i++){    // j'ai mis le paquet de CHEZ PAQUET
        Data= Data+1;
        
       }

Serial.println(Data);

delay(500);
}

.....suite ma version IDE Arduino = 1.8.8 Arduino Nano aux yeux bridés Windows 10 Super PC ASUS bête de course

Bonjour ATOS__VQ

ATOS_VQ: Bonjour à tous

Le mystère persiste avec un autre problème ou piège plus exactement.

Il n'y a aucun mystère. Voir le post #2.

Remplacez "Data= Data+1;" par des instructions no-op.

Cordialement, bidouilleelec

Merci bidouillelec

Je n'ai pas trouve cette instruction no-op qui est refusée par le compilateur et je ne l'ai pas trouvée dans les références Arduino, peux tu me donner la bonne syntaxe , merci beaucoup

Comme Data ne sert nulle part, l'optimiseur, s'il fait bien son travail, va retirer la ligne (si j'ose dire) Data++; La boucle ne servant plus à rien, l'optimiseur zélé va la retirer aussi, (et le stockage et le temps de calcul seront améliorés). Deux solutions sont possibles: a) Déclarer Data comme "volatile", pour ... éviter que l'optimiseur ne la volatilise. b) forcer des instructions assembleurs (NOP ne fait rien) dans cette boucle cf https://www.nongnu.org/avr-libc/user-manual/inline_asm.html et ... les déclarer comme volatiles.

ATOS_VQ: Merci bidouillelec

Je n'ai pas trouve cette instruction no-op qui est refusée par le compilateur et je ne l'ai pas trouvée dans les références Arduino, peux tu me donner la bonne syntaxe , merci beaucoup

Je parlais de votre 1er code.

Dans le cas de votre second code : "Serial.println(Data);" rend la donnée Data fonctionnelle. Elle est utile à une sortie. Et donc la boucle for devient effective et prise en compte..

A vous de voir la structure de votre second programme. (au passage : la compilation comporte un warning, au moins sur IDE 1.8.8 ) .

no-op : ( instruction no operation) https://whatis.techtarget.com/definition/no-op-no-operation https://whatis.techtarget.com/definition/no-op-no-operation

Cordialement, bidouilleelec

dbrion06: Deux solutions sont possibles: a) Déclarer Data comme "volatile", pour ... éviter que l'optimiseur ne la volatilise.

Bah! non

Bonjour dbrion06

bidouilleelec: Bah! non

J'ai écris une bêtise : "" Déclarer Data comme "volatile" "" règle effectivement le problème.

Cordialement, bidouilleelec

Ce n’était pas une bêtise, mais une demi bêtise, à mettre en regard de l’idée brillante de mettre des NOP -prennent 1/16 us chacun sur Arduino- pour tester le temps d’éxécution d’une boucle vide (à soustraire du temps d’éxécution d’une boucle faisant des calculs répétitifs).
Et qu’est une seule -dans le pire des cas- bêtise face au désordre ambient?
Te av baxtalo.

Bonjour Je reviens à la charge pour ce pb de durée instruction,je n'y suis jamais arrivé alors le recours à l'oscilloscope a été salutaire et très décevant,l'extrait du super programme ci dessous génère un signal en crenaux d'une période de 8.5 us !!!(micro seconde) sur Arduino Nano Atmega 328, soit environ 4us par instruction je suis loin des 33ns du dsPic4013 (Je suis débutant en Arduino)

void loop() { digitalWrite(PD_SCK,HIGH); digitalWrite(PD_SCK,LOW);

}

Bonjour,

digitalWrite() ce n'est pas une instruction, mais des dizaines d'instructions.

https://stackoverflow.com/questions/27496873/explanation-of-digitalwrite-in-arduino-toggling-led-of-digital-pin confirme le post de Kamill: l'appel à digitalWrite nécessite de calculer le port (groupe de 8 pattes), le numéro dans le port, et si c'est un timer (ceci fait déjà 3 appels de fonctions ...chaque appel nécessite de stocker/destocker des registres). Il vérifie ensuite que le port est valide, que le numéro dans le port est valide, et que la patte n'est pas impliquée dans un timer ("montre patte blanche"). Alors, il invalide les interruptions, fait effectivement la mise à jour de la patte, revalide les interruptions... Toutes ces précautions sont chronophages...

Il me semble que J-M-L (ou quelqu'un d'autre ?) avait posté sur ce forum une alternative à digitalWrite un peu plus rapide

Si tu veux aller plus vite :

  #define PIN     2

  // pin = D0 à D7
  DDRC |= PIN;      // pinMode(PD_SCK, OUTPUT)
  PORTC |= PIN;     // digitalWrite(PD_SCK, HIGH)
  PORTC &= ~PIN;  // digitalWrite(PD_SCK, LOW)
  // pin = D8 à D13
  DDRD |= PIN;      // pinMode(PD_SCK, OUTPUT)
  PORTD |= PIN;     // digitalWrite(PD_SCK, HIGH)
  PORTD &= ~PIN;  // digitalWrite(PD_SCK, LOW)
  // pin = A0 à A5
  DDRC |= PIN;      // pinMode(PD_SCK, OUTPUT)
  PORTC |= PIN;     // digitalWrite(PD_SCK, HIGH)
  PORTC &= ~PIN;  // digitalWrite(PD_SCK, LOW)

Mais dans ce cas, tu n’est plus indépendant de la plateforme.

Si tu veux aller encore plus vite

 PIND=0x04;  // toggle pin 2

63ns pour inverser une sortie !

Tu veux dire, pour mettre la sortie 2 à HIGH (et les autres de 0 à 7 à LOW): PORTD = 0x04;ouPORTD = B00000100; PIND est en lecture seule, non ?

La méthode d'hbachetti permet de ne pas toucher aux autres IO: PORTD |= 2;ou PORTD |= B00000100;

lesept: PIND est en lecture seule, non ?

Oui, mais c'est une particularité des processeurs AVR: quand tu écris dans PINX ça inverse la (les) sortie(s) correspondante(s). Il faut bien sur qu'elles soient déclarées en sortie.

Cette méthode aussi ne touche pas aux autres bits.

On en apprend tous les jours.

Merci pour vos réponses En fait moi qui tente de voir autre chose que l'assembleur ,je vais être contraint d'y retourner avec Atmega, je pensais innocemment que ce langage plus évolué était plus rapide Merci encore

Pourquoi veux tu retourner à l'assembleur? Quel est ton application?

un programme écrit à la main en assembleur sera plus optimisé qu'un programme en langage C/C++ (bien que les compilateurs actuels soient très performants coté génération de code et optimisation). Par contre c'est au détriment du temps de développement qui est beaucoup plus long en assembleur (écriture et debug), et je ne parle pas de la maintenabilité qui est bien plus facile en C/C++.