Go Down

Topic: Bit de controle en attente : Logique et Physique (Read 195 times) previous topic - next topic

huasca

May 18, 2017, 07:23 pm Last Edit: May 19, 2017, 09:44 am by huasca
Bonjour à tous !

En décortiquant le fichier 'main' modifié pour ma carte (BlendMicro) je me suis arreté sur cette fonction :

************************************


1    #if defined(BLEND_MICRO_8MHZ)
2           // As the F_CPU = 8000000UL, the USB core make the PLLCSR = 0x02
3       // But the external xtal is 16000000Hz, so correct it here.
4       PLLCSR |= 0x10;            // Need 16 MHz xtal
5       while (!(PLLCSR & (1<<PLOCK)));      // wait for lock pll


************************************
L'octet PLLCSR se decompose comme ça

 7  6  5  4  3  2  1  0
 0  0  0  ?  0  0  ?  ?

4 = PINDIV ( PLL input prescaler ) divise la frequence par 2 si TRUE
1 = PLLE     ( PLL Enable ) start si TRUE
0 = PLOCK  ( PLL Lock to reference clock ) lock si TRUE

le BIT 0 est le seul des trois à etre en READ ONLY

Donc si je comprends bien ( et c'est ma premiere question < Logique ) :

Ligne 5 : PLLCSR est egal à 0 0 0 1 . 0 0 1 0 tant que le pointeur du bit 0 n'est pas poussé à TRUE ?

et si oui ( ma deuxieme question < Physique ) :

Quelle est la cinematique de validation du bit , autrement dit comment les deux horloges se synchronisent-elles ?

Merci ! :)


" La lumiere du soleil , quand il la deploie , depend de l'organe qui la voit "  W.BLAKE

J-M-L

0x10 Ce n'est pas b00010010....
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

huasca

#2
May 19, 2017, 01:19 am Last Edit: May 19, 2017, 08:40 am by huasca
j'ai oublié de preciser : apres la ligne 4.

c'est le while qui me pose soucis...
" La lumiere du soleil , quand il la deploie , depend de l'organe qui la voit "  W.BLAKE

_pepe_

#3
May 19, 2017, 12:32 pm Last Edit: May 19, 2017, 03:54 pm by _pepe_
Bonjour

Je ne suis pas allé chercher dans le détail de la datasheet, mais d'après ce que je comprends des notations utilisées, l'horloge est produite à l'aide d'une boucle à verrouillage de phase (PLL = phase lock loop).

Une PLL permet de produire des fréquences différentes de l'horloge de référence, en synchronisant un sous-multiple entier de la fréquence d'un oscillateur commandé en tension avec un sous-multiple entier de la fréquence de l'horloge de référence. La tension de commande de l'oscillateur est directement produite par la différence de phase entre ces deux signaux, de sorte que toute différence de fréquence provoque une variation de la tension, jusqu'à ce que le déphasage s'ajuste pour produire la tension correspondant à la fréquence requise.

Le positionnement du bit PINDIV (à ligne 4) permet d'introduire un facteur 2 dans un diviseur du circuit, ce qui impose à la tension de commande de l'oscillateur de retrouver un état d'équilibre différent. Quand cet état d'équilibre sera atteint après un certain délai, le signal de sortie aura atteint la fréquence souhaitée et la PLL sera verrouillée.

Pour garantir que la nouvelle fréquence produite est correcte, toute modification du bit PINDIV impose donc d'attendre que le bit PLOCK, qui indique l'état de verrouillage de la PLL, soit positionné. C'est ce que fait la boucle while(...) à la ligne 5 (le programme boucle tant que PLOCK n'est pas passé à 1).

_pepe_

#4
May 19, 2017, 03:07 pm Last Edit: May 19, 2017, 03:38 pm by _pepe_
Le microcontrôleur de ta carte est (sauf erreur) un ATmega32U4. Son circuit PLL permet notamment de générer l'horloge de l'interface USB intégrée à partir d'une horloge de plus basse fréquence.

La datasheet du microcontrôleur donne le schéma suivant :



On y retrouve les bits de commande PINDIV et PLLE (écrits par le programme) et le bit d'état du verrouillage PLOCK (lu par le programme).

La partie à gauche du trait pointillé sert à sélectionner la source de l'horloge de référence. PINDIV permet de diviser la fréquence de cette horloge par 2 lorsqu'elle tourne à 16 MHz, afin d'obtenir les 8 MHz normalement attendus à l'entrée de la PLL. Les bits PDIV[3:0] du diviseur de la PLL permettent de multiplier cette fréquence pour obtenir une fréquence de 40, 48, 56, 72, 80, 88 ou 96 MHz en sortie de PLL (toutes les valeurs possibles de PDIV[3:0] ne sont pas autorisées), laquelle est ensuite divisée par 1 ou par 2 (en bas à droite) pour produire l'horloge USB à 48 MHz, et par 1, par 1,5 ou par 2 (en haut à droite) pour produire l'horloge du timer 4 à haute vitesse (64 MHz maxi sous 5V).

huasca

Merci pour ce rappel clair , c'est ce que j'avais déduis de ma lecture du datasheet et vous confirmez.
Vous trouverez la description de PLLCSR à la page 40.

J'arrive à "traduire" jusqu'à la ligne 5 , ensuite le while reste obscur , plus precisement :

1<<PLOCK

Si je me refere aux dictionnaires C++ nous avons affaire à un decalage de bit vers la gauche. Mais pour coller aux definitions il faudrait intervertir les operandes.
J'ai opté pour un pointeur mais il manque * sur &.

le commentaire de ligne precise // wait for PLOCK. Je peux deduire que la ligne 5 donne quelque chose comme:

TANT QUE LA CONDITION ( octet PLLCSR = 0001.0010 ET ( le bit PLOCK ( le bit0 ) poussé à 1 ) ) N'EST PAS VRAI

Mais c'est une traduction aleatoire , comment doit-on l'interpreter?

 
" La lumiere du soleil , quand il la deploie , depend de l'organe qui la voit "  W.BLAKE

kamill

Bonjour,

Je ne vois pas bien ce que tu n'arrives pas à comprendre.

_pepe_ t'a expliqué que la ligne 5 attend que le bit PLOCK soit à 1

1<<PLOCK avec PLOCK=0 ça donne 1. Donc on teste le bit 0 et on attend qu'il passe à 1.

huasca

D'avoir la tete dedans si longtemps , j'ai oublié d'etre plus precis ^^

Le fonctionnement du programme est compris , c'est uniquement cette utilisation de << qui m'echappe , je ne trouve pas de definition , ou plutot j'en trouve plusieurs !

- Soit " decalage de bit vers la gauche " qui s'applique à tout les bits d'un octet ( wikilivres )

- Soit un operateur d'insert ( microsoft )

Dans les deux cas rien ne me permet de traduire cette ligne correctement.

Je cherche à comprendre ce qui est ecrit pour pouvoir l'assimiler et le re-utiliser.

Pour etre encore plus precis :

Je connais son resultat mais comment traduire 1<<PLOCK ?







" La lumiere du soleil , quand il la deploie , depend de l'organe qui la voit "  W.BLAKE

kamill

#8
May 19, 2017, 05:28 pm Last Edit: May 19, 2017, 05:32 pm by kamill
C'est décalage à gauche de l'entier qui vaut 1 de PLOCK crans.
Sachant que PLOCK vaut 0, il n'y a pas de décalage.

Et c'est aussi l'opérateur d'insertion pour les flux. Sachant que en C++ tous les opérateurs peuvent être redéfinis dans la class sur laquelle ils s'appliquent.

_pepe_

#9
May 19, 2017, 06:04 pm Last Edit: May 19, 2017, 06:21 pm by _pepe_
L'utilisation du décalage du type ( 1<<numero_du_bit ) est assez courante sous GCC (la chaîne de compilation d'Arduino) pour désigner les bits d'un octet, car cette opération est facilement optimisée et le résultat considéré comme une constante.

Ainsi, quand on écrit :

Code: [Select]
while (!(PLLCSR & (1<<PLOCK)));

le programme généré teste directement le bit 0 du registre sans effectuer d'opération de décalage :

Code: [Select]
boucle:
  in   r0, 0x29   ; get PLLCSR register value
  sbrs r0, 0      ; skip next instruction if bit 0 is set --> suite
  rjmp boucle     ; jump to boucle
suite:
 ...

huasca

Ha ! c'est bien plus clair comme ça , merci Mr _pepe_ !

je ne comprenais pas pourquoi utiliser un decalage à gauche si un seul BIT est concerné ?

Hors pb de syntaxe evidement ,  (je ne sais pas encore ecrire en c++ ) je pensais plutot à :

while ( ( PLLCSR & ( PLOCK = FALSE ) ) ) pour tester le BIT

Mais en fait il s'agit de bloquer l'etat du BIT ?
" La lumiere du soleil , quand il la deploie , depend de l'organe qui la voit "  W.BLAKE

_pepe_

#11
May 19, 2017, 06:32 pm Last Edit: May 19, 2017, 06:56 pm by _pepe_
je ne comprenais pas pourquoi utiliser un decalage à gauche si un seul BIT est concerné ?
Le décalage permet de générer un octet de masque avec un seul bit à 1 à partir de la connaissance de la position de ce bit dans l'octet.

Par exemple (1<<PINDIV) vaut (1<<4) soit 00010000b en binaire. En définissant la valeur PINDIV égale à 4 dans l'environnement, on déclare de manière simple que PINDIV tel que défini par le constructeur est le bit 4 du registre. Cela évite de devoir déclarer les valeurs des masques correspondants, qui sont plus ennuyeux à calculer et plus difficiles à relire, et qui finalement ne servent souvent à rien (c.f. le code machine généré, qui ne réalise pas d'opération logique ET explicite comme spécifiée dans le code source).

On peut avec cette méthode générer un octet de masque avec plusieurs bits à 1 en énumérant la position de ces bits dans une suite de OU logiques.

Par exemple ( (1<<PINDIV) | (1<<PLLE) ) vaut ( (1<<4) | (1<<1) ) soit 00010010b en binaire.

Mais en fait il s'agit de bloquer l'etat du BIT ?
Non, ici il s'agit de lire le bit du registre pour savoir si le circuit de la PLL l'a passé à 1. Le programme doit rester bloqué au niveau du while(...) tant que ce bit est à 0, car cela signifie que la PLL n'est pas encore verrouillée.

(1<<PLOCK) vaut 00000001b
PLLCSR & (1<<PLOCK) vaut 00000001b (=vrai) si le bit PLOCK du registre PLLCSR est à 1, ou 00000000b (=faux) s'il est à 0
!(PLLCSR & (1<<PLOCK)) vaut faux si le bit PLOCK du registre PLLCSR est à 1, ou vrai s'il est à 0.
while (!(PLLCSR & (1<<PLOCK))) ; boucle sans rien faire (d'où le « ; ») tant que le bit PLOCK du registre PLLCSR est à 0.

huasca

D'accord , c'etait ma question sur la cinematique. Le BIT 0 ( PLOCK ) etant en lecture seule je me demandais ce qui determinait son etat.

J'ai confondu la validation de la fonction et l'etat de l'octet ( desolé ! )

Je cherche encore le chemin du BIT salvateur dans les datablocks des datasheets par pure curiosité.

Comme quoi le binaire et l'assembleur y a rien de mieux pour s'expliquer !

Je n'appréhendais pas le masque correctement , en m'en tenant aux def. trouvé sur le net.
L'application que vous expliquez n'est jamais apparue nulle part pendant mes recherches.

C'est maintenant extremement clair ! >>> Merci beaucoup ! <<<

à ce propos , si je veux une source absolue de connaissance C++ , quel ouvrage me conseillez-vous ?
( je ne crains pas le binaire ni l'ASM ( je suis elec à l'origine ) )



" La lumiere du soleil , quand il la deploie , depend de l'organe qui la voit "  W.BLAKE

J-M-L

#13
May 19, 2017, 07:27 pm Last Edit: May 19, 2017, 07:28 pm by J-M-L
En ligne je pense que ceci est une bonne référence

Quote
J'ai opté pour un pointeur mais il manque * sur &.
à lire ce que vous dites ci dessus on dirait que vous bloquiez sur le & qui est l'opérateur de bitmask ET LOGIQUE (AND) et non pas une histoire d'adresse ou de pointeur

Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

trimarco232

Bonjour,

pas évident en effet, on rencontre en 2 lignes :
héxadécimal  : 0x10
décimal, par défaut : le fameux 1
texte désignant le contenu d'un emplacement : PLLCSR
texte désignant une constante : PLOCK
instruction à effectuer par le mpu : |= et aussi : &
quant au non moins fameux << , qui ressemble à s'y méprendre à une instruction, est plutôt une directive destinée au préprocesseur (la preuve par l'assembleur)

Go Up