Discussion:
Champs de bit et effets de bord
(trop ancien pour répondre)
Frédéric Praca
2015-07-26 11:41:37 UTC
Permalink
Bonjour à tous en ce dimanche pluvieux (au moins chez moi),
je suis confronté à un problème lié aux clauses de représentation et à
l'affectation d'une valeur dans une des composantes de l'enregistrement
concerné.
La définition de l'enregistrement est la suivante :
type Control_Register_1 is
record
Send_Break : Boolean;
Receiver_WakeUp : Boolean;
Receiver_Enable : Boolean;
Transmitter_Enable : Boolean;
IDLE_Interrupt_Enable : Boolean;
RXNE_Interrupt_Enable : Boolean;
Transmission_Complete_Interrupt : Boolean;
TXE_Interrupt_Enable : Boolean;
PE_Interrupt_Enable : Boolean;
Parity_Selection : Parity;
Parity_Control_Enable : Boolean;
WakeUp_Method : Wakeup_Methods;
Length : Word_Length;
USART_Enable : Boolean;
Oversampling_Mode : Oversampling_Modes;
end record with Size => 32;
for Control_Register_1 use
record
Send_Break at 0 range 0 .. 0;
Receiver_WakeUp at 0 range 1 .. 1;
Receiver_Enable at 0 range 2 .. 2;
Transmitter_Enable at 0 range 3 .. 3;
IDLE_Interrupt_Enable at 0 range 4 .. 4;
RXNE_Interrupt_Enable at 0 range 5 .. 5;
Transmission_Complete_Interrupt at 0 range 6 .. 6;
TXE_Interrupt_Enable at 0 range 7 .. 7;
PE_Interrupt_Enable at 0 range 8 .. 8;
Parity_Selection at 0 range 9 .. 9;
Parity_Control_Enable at 0 range 10 .. 10;
WakeUp_Method at 0 range 11 .. 11;
Length at 0 range 12 .. 12;
USART_Enable at 0 range 13 .. 13;
Oversampling_Mode at 0 range 15 .. 15;
end record;

Lorsque que j'essaye de mettre à True le champ Receiver_Enable qui se
trouve être le 3ème bit du premier octet, automagiquement, le 3ème bit du
second octet passe à True.
Le seul moyen d'obtenir les bonnes valeurs dans mon registre est de
passer par une initialisation complète du registre par aggrégat.

Qu'est-ce que je n'ai pas compris ou pas lu ?

Fred
Blady
2015-07-26 14:24:54 UTC
Permalink
Bonjour Frédéric,

t'est-il possible de pousser un bout de code compilable montrant le pb ?

Cordialement, Pascal.
http://blady.pagesperso-orange.fr
Post by Frédéric Praca
Bonjour à tous en ce dimanche pluvieux (au moins chez moi),
je suis confronté à un problème lié aux clauses de représentation et à
l'affectation d'une valeur dans une des composantes de l'enregistrement
concerné.
type Control_Register_1 is
record
Send_Break : Boolean;
Receiver_WakeUp : Boolean;
Receiver_Enable : Boolean;
Transmitter_Enable : Boolean;
IDLE_Interrupt_Enable : Boolean;
RXNE_Interrupt_Enable : Boolean;
Transmission_Complete_Interrupt : Boolean;
TXE_Interrupt_Enable : Boolean;
PE_Interrupt_Enable : Boolean;
Parity_Selection : Parity;
Parity_Control_Enable : Boolean;
WakeUp_Method : Wakeup_Methods;
Length : Word_Length;
USART_Enable : Boolean;
Oversampling_Mode : Oversampling_Modes;
end record with Size => 32;
for Control_Register_1 use
record
Send_Break at 0 range 0 .. 0;
Receiver_WakeUp at 0 range 1 .. 1;
Receiver_Enable at 0 range 2 .. 2;
Transmitter_Enable at 0 range 3 .. 3;
IDLE_Interrupt_Enable at 0 range 4 .. 4;
RXNE_Interrupt_Enable at 0 range 5 .. 5;
Transmission_Complete_Interrupt at 0 range 6 .. 6;
TXE_Interrupt_Enable at 0 range 7 .. 7;
PE_Interrupt_Enable at 0 range 8 .. 8;
Parity_Selection at 0 range 9 .. 9;
Parity_Control_Enable at 0 range 10 .. 10;
WakeUp_Method at 0 range 11 .. 11;
Length at 0 range 12 .. 12;
USART_Enable at 0 range 13 .. 13;
Oversampling_Mode at 0 range 15 .. 15;
end record;
Lorsque que j'essaye de mettre à True le champ Receiver_Enable qui se
trouve être le 3ème bit du premier octet, automagiquement, le 3ème bit du
second octet passe à True.
Le seul moyen d'obtenir les bonnes valeurs dans mon registre est de
passer par une initialisation complète du registre par aggrégat.
Qu'est-ce que je n'ai pas compris ou pas lu ?
Fred
Frédéric Praca
2015-07-26 16:48:28 UTC
Permalink
Post by Blady
Bonjour Frédéric,
t'est-il possible de pousser un bout de code compilable montrant le pb ?
Cordialement, Pascal.
http://blady.pagesperso-orange.fr
Post by Frédéric Praca
Bonjour à tous en ce dimanche pluvieux (au moins chez moi),
je suis confronté à un problème lié aux clauses de représentation et à
l'affectation d'une valeur dans une des composantes de l'enregistrement
concerné.
type Control_Register_1 is
record
Send_Break : Boolean;
Receiver_WakeUp : Boolean;
Receiver_Enable : Boolean;
Boolean; RXNE_Interrupt_Enable : Boolean;
Transmission_Complete_Interrupt : Boolean;
Boolean;
Parity_Selection : Parity;
Parity_Control_Enable : Boolean;
WakeUp_Method : Wakeup_Methods;
Length : Word_Length;
USART_Enable : Boolean;
Oversampling_Mode : Oversampling_Modes;
end record with Size => 32;
for Control_Register_1 use
record
Send_Break at 0 range 0 .. 0;
Receiver_WakeUp at 0 range 1 .. 1; Receiver_Enable at 0 range
2 .. 2; Transmitter_Enable at 0 range 3 .. 3;
IDLE_Interrupt_Enable at 0 range 4 .. 4;
RXNE_Interrupt_Enable at 0 range 5 .. 5;
Transmission_Complete_Interrupt at 0 range 6 .. 6;
TXE_Interrupt_Enable at 0 range 7 .. 7; PE_Interrupt_Enable
at 0 range 8 .. 8; Parity_Selection at 0 range 9 .. 9;
Parity_Control_Enable at 0 range 10 .. 10; WakeUp_Method at 0
range 11 .. 11;
Length at 0 range 12 .. 12;
USART_Enable at 0 range 13 .. 13; Oversampling_Mode at 0
range 15 .. 15;
end record;
Lorsque que j'essaye de mettre à True le champ Receiver_Enable qui se
trouve être le 3ème bit du premier octet, automagiquement, le 3ème bit
du second octet passe à True.
Le seul moyen d'obtenir les bonnes valeurs dans mon registre est de
passer par une initialisation complète du registre par aggrégat.
Qu'est-ce que je n'ai pas compris ou pas lu ?
Fred
C'est facile, tout est là (https://github.com/FredPraca/ravenscar-sfp-
stm32f411-nucleo ) mais il faut disposer d'une carte STM32F411 Nucleo :)

Ceci dit, je crois voir trouvé la réponse dans le dernier post que
j'avais fait et auquel Jean-Pierre avait répondu.
Tout tournerait donc autour du chapitre C.6 de l'ARM et notamment de la
pragma Independant...

Fred
J-P. Rosen
2015-07-27 06:09:57 UTC
Permalink
Post by Frédéric Praca
Post by Blady
Bonjour Frédéric,
t'est-il possible de pousser un bout de code compilable montrant le pb ?
Cordialement, Pascal.
http://blady.pagesperso-orange.fr
Post by Frédéric Praca
Bonjour à tous en ce dimanche pluvieux (au moins chez moi),
je suis confronté à un problème lié aux clauses de représentation et à
l'affectation d'une valeur dans une des composantes de l'enregistrement
concerné.
[...]
Post by Frédéric Praca
Post by Blady
Post by Frédéric Praca
Lorsque que j'essaye de mettre à True le champ Receiver_Enable qui se
trouve être le 3ème bit du premier octet, automagiquement, le 3ème bit
du second octet passe à True.
Le seul moyen d'obtenir les bonnes valeurs dans mon registre est de
passer par une initialisation complète du registre par aggrégat.
Qu'est-ce que je n'ai pas compris ou pas lu ?
Fred
C'est facile, tout est là (https://github.com/FredPraca/ravenscar-sfp-
stm32f411-nucleo ) mais il faut disposer d'une carte STM32F411 Nucleo :)
Ceci dit, je crois voir trouvé la réponse dans le dernier post que
j'avais fait et auquel Jean-Pierre avait répondu.
Tout tournerait donc autour du chapitre C.6 de l'ARM et notamment de la
pragma Independant...
Ptet ben quoui, Ptet ben qunon...

Normalement, modifier un bit ne doit pas modifier les autres. Ceci dit,
si les composants ne sont pas indépendants, et que la /lecture/ d'un bit
le remet à True (autrement dit, il est volatile), alors on peut observer
ce phénomène.
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
Frédéric Praca
2015-07-27 13:25:01 UTC
Permalink
Post by J-P. Rosen
Post by Frédéric Praca
Post by Blady
Bonjour Frédéric,
t'est-il possible de pousser un bout de code compilable montrant le pb ?
Cordialement, Pascal.
http://blady.pagesperso-orange.fr
Post by Frédéric Praca
Bonjour à tous en ce dimanche pluvieux (au moins chez moi),
je suis confronté à un problème lié aux clauses de représentation et
à l'affectation d'une valeur dans une des composantes de
l'enregistrement concerné.
[...]
Post by Frédéric Praca
Post by Blady
Post by Frédéric Praca
Lorsque que j'essaye de mettre à True le champ Receiver_Enable qui se
trouve être le 3ème bit du premier octet, automagiquement, le 3ème
bit du second octet passe à True.
Le seul moyen d'obtenir les bonnes valeurs dans mon registre est de
passer par une initialisation complète du registre par aggrégat.
Qu'est-ce que je n'ai pas compris ou pas lu ?
Fred
C'est facile, tout est là (https://github.com/FredPraca/ravenscar-sfp-
stm32f411-nucleo ) mais il faut disposer d'une carte STM32F411 Nucleo :)
Ceci dit, je crois voir trouvé la réponse dans le dernier post que
j'avais fait et auquel Jean-Pierre avait répondu.
Tout tournerait donc autour du chapitre C.6 de l'ARM et notamment de la
pragma Independant...
Ptet ben quoui, Ptet ben qunon...
Normalement, modifier un bit ne doit pas modifier les autres. Ceci dit,
si les composants ne sont pas indépendants, et que la /lecture/ d'un bit
le remet à True (autrement dit, il est volatile), alors on peut observer
ce phénomène.
Alors effectivement, l'enregistrement contenant l'ensemble des registres
est bien déclaré "volatile". De plus, dans la documentation du STM32F411,
il est bien précisé que l'écriture de ces registres doit se faire par 16
ou 32 bits.
Toutefois, ce qui m'étonne c'est que le champ Receiver_Enable en question
n'est que placé par logiciel et pas par le matériel et qu'encore plus
fort, l'écriture semble se faire en miroir !
Du coup, j'en arrive à me demander s'il n'y aurait pas une option de
compilation, un aspect ou une pragma à rajouter.

Fred
J-P. Rosen
2015-07-27 20:35:21 UTC
Permalink
Post by Frédéric Praca
Alors effectivement, l'enregistrement contenant l'ensemble des registres
est bien déclaré "volatile". De plus, dans la documentation du STM32F411,
il est bien précisé que l'écriture de ces registres doit se faire par 16
ou 32 bits.
Toutefois, ce qui m'étonne c'est que le champ Receiver_Enable en question
n'est que placé par logiciel et pas par le matériel et qu'encore plus
fort, l'écriture semble se faire en miroir !
Du coup, j'en arrive à me demander s'il n'y aurait pas une option de
compilation, un aspect ou une pragma à rajouter.
Si ton besoin est vraiment d'écrire 16bits à une adresse précise d'un
périphérique, alors il est beaucoup plus simple de faire une routine en
assembleur (une instruction) que de se torturer l'esprit pour faire
générer au compilateur l'instruction que l'on veut...

Si Ada autorise l'insertion de code machine, c'est vraiment pour des cas
comme ça. A ce niveau, ça ressort du principe "on dit ce qu'on fait, et
on fait ce qu'on dit"
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
Frédéric Praca
2015-07-27 21:23:32 UTC
Permalink
Post by J-P. Rosen
Post by Frédéric Praca
Alors effectivement, l'enregistrement contenant l'ensemble des
registres est bien déclaré "volatile". De plus, dans la documentation
du STM32F411,
il est bien précisé que l'écriture de ces registres doit se faire par
16 ou 32 bits.
Toutefois, ce qui m'étonne c'est que le champ Receiver_Enable en
question n'est que placé par logiciel et pas par le matériel et
qu'encore plus fort, l'écriture semble se faire en miroir !
Du coup, j'en arrive à me demander s'il n'y aurait pas une option de
compilation, un aspect ou une pragma à rajouter.
Si ton besoin est vraiment d'écrire 16bits à une adresse précise d'un
périphérique, alors il est beaucoup plus simple de faire une routine en
assembleur (une instruction) que de se torturer l'esprit pour faire
générer au compilateur l'instruction que l'on veut...
Si Ada autorise l'insertion de code machine, c'est vraiment pour des cas
comme ça. A ce niveau, ça ressort du principe "on dit ce qu'on fait, et
on fait ce qu'on dit"
Justement, non, je ne voulais pas écrire 16 bits mais un seul sur 16 et
j'ai eu un effet de bord.
Ceci dit, ce n'est pas si grave, il faut juste savoir qu'il faut écrire
la totalité du record.

D'ailleurs, j'ai un autre exemple :
type Mantissa is range 0 .. 2**12 - 1 with Size => 12;
type Fraction is range 0 .. 2**4 - 1 with Size => 4;

type Baud_Rate_Register is
record
DIV_Fraction : Fraction;
DIV_Mantissa : Mantissa;
end record with Size => 32;
for Baud_Rate_Register use
record
DIV_Fraction at 0 range 0 .. 3;
DIV_Mantissa at 0 range 4 .. 15;
end record;

Ici, si j'écris
USART2.BRR.DIV_Mantissa := 16#445#;
USART2.BRR.DIV_Fraction := 16#c#;
Un dump mémoire montre un contenu final à 0x00005c5c alors que
l'intermédiaire était bien 0x00004450.
Par contre, si je fais
USART2.BRR := Baud_Rate_Register'(DIV_Mantissa => 16#445#,
DIV_Fraction => 16#c#);

Pas de problème, le contenu final vaut bien 0x0000445c.

Au final, je n'ai pas besoin de faire un coup d'assembleur pour pallier
au problème et je préfère autant ne pas avoir à en faire vu que c'est
déjà pour éviter les déclarations toutes en Word avec des constantes à la
C que j'ai tout passé en clauses de représentation.
Je me posais simplement la question du pourquoi cela fonctionnait comme
ça.

Fred
Stephane Riviere
2015-07-31 14:52:00 UTC
Permalink
Post by J-P. Rosen
Normalement, modifier un bit ne doit pas modifier les autres. Ceci dit,
Aucune idée sur ce composant précis, mais il existe des
micro-contrôleurs imposant une séquence précise de lecture écriture pour
la modification d'un bit, afin de garantir la non altération des autres
bits du registres.

La réponse se trouve dans le datasheet de ce composant, précisément dans
la partie "programming", puis classiquement "reading and writing
registers". Regarder aussi du coté des notes d'application, on y
apprends pas mal de choses et de non-dits...
--
Stéphane Rivière
Continuer la lecture sur narkive:
Loading...