Regrouper plusieurs registres en un seul

Regrouper plusieurs registres en un seul - C - Programmation

Marsh Posté le 22-03-2010 à 13:28:34    

Bonjour,
 
Je programme actuellement un micro-contrôleur et je me suis posé la question suivante :
 
Actuellement j'ai une foule de variables "bit" différentes, pointant sur différents segments mémoire, ce qui dans certains cas me porte à effectuer une longue suite d'allocations genre :
 

Code :
  1. _RD1 = 1;
  2. _RE0 = 0;
  3. _RC4 = 1;
  4. ...


 
Là ou pour moi ça serait beaucoup plus simple de pouvoir faire  
 

Code :
  1. _registre = 5;


 
J'imagine qu'il existe un type de structure de donnée qui me permettrait directement de regrouper les différents "bit" concernés non?
Est-ce que vous pourriez me donner une piste s'il vous plait?
 
Merci d'avance


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 22-03-2010 à 13:28:34   

Reply

Marsh Posté le 22-03-2010 à 14:47:19    

tu sans doute stocker tes bits dans un int ou autre et ensuite affecter/lire à coup de masques.


---------------
What if I were smiling and running into your arms? Would you see then what I see now?  
Reply

Marsh Posté le 22-03-2010 à 14:52:13    

Salut,
 
Merci mais je fais ça comment ? Je fais comment pour définir une grandeur stockée sur une plage de mémoire non-contiguë?
Les variables en questions se trouvent dans des segments de mémoire définis par le micro-contrôleur, je peux pas décider où ils sont stockés.  
 
Je sais pas si je me suis bien expliqué :??:


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 22-03-2010 à 15:12:40    

Code :
  1. struct 4bit_int
  2. {
  3. unsigned int bit0 : 1;
  4. unsigned int bit1 : 1;
  5. unsigned int bit2 : 1;
  6. unsigned int bit3 : 1;
  7. };
  8. 4bit_int machin;
  9. machin.bit0 = true;
  10. machin.bit1 = 0;
 

tes 4 bits sont packés et tu peux y accéder facilement.

 

C'est pas trop ton problème ici, mais tu peux écrire ça par exemple :

 
Code :
  1. struct 9bit_int{
  2. unsigned int type:9;
  3. };
 

pour construire des entiers alignés sur 9 bits.


Message édité par snafu8 le 22-03-2010 à 15:14:06
Reply

Marsh Posté le 22-03-2010 à 15:20:01    

Salut,
 
Merci pour ta réponse.
Le truc qui me "dérange" c'est pas de pas pouvoir y accéder facilement, c'est que si j'ai 32 bits à placer, je dois taper 32 lignes.
 
C'est ça que j'aurais voulu éviter, et il me semble pas qu'avec ta méthode on y parvienne, non?
 
Merci


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 23-03-2010 à 10:40:42    

Tu dois forcément avoir moyen d'appeler le registre dans son intégralité sans avoir à définir le truc bit par bit. De la même façon que t'as _RA0, _RA1 et compagnie, tu devrais avoir un _RA tout court. Forcément.
C'est même pas un problème ce genre de truc quand on code sur un microcontrôleur, c'est une évidence d'avoir accès aux registres pleins.
 
Jette un coup d'oeil aux déclarations de ces accesseurs, tu devrais y trouver avec la déclaration des registres.
 
Sinon c'est quoi comme microcontrôleur ?

Reply

Marsh Posté le 23-03-2010 à 10:43:49    

Salut,

 

Le problème n'est pas là, j'ai accès à tout le registre. Le truc c'est que parfois je dois donner une valeur à plusieurs bits ne se trouvant pas dans le même registre (c'est pour cette raison que dans mon exemple j'ai parlé de _RD1 , _RE0 ,...

 

Edit: Il s'agit d'un PIC32 de chez Microchip


Message édité par esox_ch le 23-03-2010 à 10:44:03

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 23-03-2010 à 10:53:18    

Aaaaaaaaaaaaaah...
 
Ah bah là abandonne :D
Tu perdras plus de temps à mettre au point une solution qu'à les allouer un par un.
 
Parmi les trucs à faire, des fonctions qui contiennent plusieurs changements de registre, pour que t'aie juste à les appeler pour passer d'un mode défini à un autre. C'est à peu près tout.
 
Si c'est trop détaillé, ben t'as aucun moyen de gérer ce problème.

Reply

Marsh Posté le 23-03-2010 à 11:23:22    

D'accord ...
Je pensais qu'en C il y avait une façon de définir quels bits devaient être utilisés par une variable. Genre définir non seulement l'adresse d'un pointeur, mais où se situent tous les bits (pour qu'ils ne soient pas contiguë en mémoire)...
 
merci quand même


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 23-03-2010 à 12:36:09    

Ben oui tu peux toujours faire des registres hybrides qui contiennent des bits qui se situent à plusieurs endroits différents, mais bon, tu vas plus te faire chier qu'autre chose...

Reply

Marsh Posté le 23-03-2010 à 12:36:09   

Reply

Marsh Posté le 23-03-2010 à 13:34:21    

Ah bon? C'est compliqué à utiliser ou bien c'est chiant à définir ?
 
Merci :o


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 23-03-2010 à 14:00:43    

les deux. Je vois pas ce que tu essaye de faire/gagner

Reply

Marsh Posté le 23-03-2010 à 14:44:10    

Salut,
 
C'était juste que je me disais que s'il y avait plus simple/propre/rapide à faire que de créer une fonction qui fasse ça bit par bit, ça aurait été sympas.
Mais si c'est compliqué et qu'on y gagne rien, je vais rester comme ça.
 
Merci bien pour vos réponses :jap:
 
P.S: Juste par pure curiosité, le terme à chercher pour ces registres "hybrides" c'est quoi? J'ai regardé sous Hybric registers mais rien trouvé. Juste parce que ça m'a titillé :o


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 23-03-2010 à 14:59:00    

Ah bah tu fais une structure qui contient plein de pointeurs vers chaque bit et tu bidouille le bordel pour que ça marche.

Reply

Marsh Posté le 23-03-2010 à 16:06:07    

des pointeurs sur des bits c'ets juste pas possible hein [:pingouino]

Reply

Marsh Posté le 23-03-2010 à 16:48:39    

Mes souvenirs du C sont assez lointains, mais ce que tu veux faire, c'est pas possible avec une union ?
 
Quelque chose dans le genre :

Code :
  1. typedef union {
  2.    struct {
  3.       unsigned int bit0: 1;
  4.       unsigned int bit1: 1;
  5.       unsigned int bit2: 1;
  6.       unsigned int bit3: 1;
  7.       unsigned int bit4: 1;
  8.       unsigned int bit5: 1;
  9.       unsigned int bit6: 1;
  10.       unsigned int bit7: 1;
  11.    } bits;
  12.    unsigned char registre;
  13. } machin;


 
Ensuite, tu utilises machin.registre pour accéder au tout, ou machin.bits.bitX pour un bit en particulier.
 
Enfin, comme je l'ai dit, ça fait longtemps que je n'ai plus fait de C, je peux complètement me planter...

Reply

Marsh Posté le 23-03-2010 à 16:50:43    

Oui c'est sûr ça s'arrête à l'octet :)

 

D'où le "tu bidouilles le bordel" :D

 

Et non l'union ça marche pas, les bits sont pas contigus en mémoire.


Message édité par Kenelm le 23-03-2010 à 16:51:14
Reply

Marsh Posté le 23-03-2010 à 16:52:38    

Ah ouais, effectivement, j'avais raté le message disant que les bits n'étaient pas forcément contigus.

Reply

Marsh Posté le 23-03-2010 à 16:54:08    

wat :€ les bits si ils sont pas contigus en mémoire, je comrpends rien. L'unité atomique d'addressage etant l'OCTET ...

Reply

Marsh Posté le 23-03-2010 à 23:16:42    

Joel F a écrit :

wat :€ les bits si ils sont pas contigus en mémoire, je comrpends rien. L'unité atomique d'addressage etant l'OCTET ...

Non... ça dépend de l'architecture sur laquelle on travaille.. Sur certaines machines, on adresse des mots de 12, 14 bits... ça dépend.
 
Après ce que fait esox_ch en écrivant :

Code :
  1. _RD1 = 1;

est directement traduit en assembleur par une instruction qui met le bit 1 de rd à 1. ça évite de travailler sur le registre complet (qui lui en effet peut faire 8 bits ou une toute autre taille) avec des masques et on peut éventuellement gagner 1 ou 2 cycles machine.. Mais cette façon de faire est plus propre à l'assembleur qu'au C.
 
Sauf que pour répondre à sa question à mon avis c'est impossible d'accéder de façon concurrente à plusieurs zones mémoires.. En effet, on ne peut accéder qu'à un seul endroit à la fois. Et s'il doit travailler sur plusieurs bits épars, alors soit il revoit son code et cherche une meilleure solution, soit il continue de faire comme il fait maintenant. Car même si on imagine qu'il s'amuse à écrire une fonction qui récupère chaque bit de la valeur qu'il passe pour l'appliquer sur chaque bit souhaité chacun sur une adresse mémoire différente, toutes les affectations se feront les unes après les autres, et surtout ça va charger le code pour rien avec tout le mécanisme de décomposition...
 
Enfin, surtout ce que j'ai de la peine à comprendre est : quel sens est-ce que cela peut bien avoir de donner une valeur à des bits situés à différents endroits ?
 
En effet, quand on donne une valeur c'est justement pour travailler sur plusieurs bits, mais situés à une même adresse !
 
dire que RD(7 downto 0) = 42 c'est compréhensible et même plein de sens, en effet les 8 bits de RD se trouvent à la même adresse et sont donc liés. Mais dire que RD1, RA5, RB2, RC7, RA0, RE6, RD4 et RA3 forment un octet auquel on va donner des valeurs, là pour moi ça n'a strictement aucun sens. ça va rendre le code trop confus et complètement illisible.

Reply

Marsh Posté le 23-03-2010 à 23:28:27    

salut,

 

Je comprend tout à fait ta remarque.
La raison est simple : Sur mon micro, t'as des modules hardware spécialisés (SPI, interruptions externes,USB,...) qui se trouvent aussi sur les même registres.
Je me trouve donc parfois à avoir un port "RD" de 16 bits, dont 13-14 sont occupés par ces fonctions hardware, et d'avoir absolument besoin des 2-3 qui restent comme bits numériques à usage général. Dans mon cas actuel, je dois utiliser ces bits pour communiquer des données en parallèle avec un FPGA. ça serait sans aucun doutes plus simple (et propre) si je pouvais décider que tout le port D (par exemple) servirait à charger les données sur l'FPGA, mais pas de bol c'est pas possible à cause de ces modules spécialisés. Donc je me trouve à devoir recycler des bits à droite et à gauche pour arriver aux 2x16 bits que j'ai besoin de passer à mon FPGA, et je me les trouve bien éparpillés sur tous les registres. Donc justement afin d'éviter les codes à rallonge et confus (comme tu le dis si bien), j'essayais de les regrouper dans une seule et même entité "virtuelle".

 

Donc voilà le pourquoi du comment :bounce:

Message cité 1 fois
Message édité par esox_ch le 23-03-2010 à 23:28:59

---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 24-03-2010 à 07:05:28    

abaddon2002 a écrit :

Non... ça dépend de l'architecture sur laquelle on travaille.. Sur certaines machines, on adresse des mots de 12, 14 bits... ça dépend.


 
On s'en fout de la taille, tes 12 ou 14 bits non necessairement contigus ...

Reply

Marsh Posté le 24-03-2010 à 10:44:58    

esox_ch a écrit :

La raison est simple : Sur mon micro, t'as des modules hardware spécialisés (SPI, interruptions externes,USB,...) qui se trouvent aussi sur les même registres.
Je me trouve donc parfois à avoir un port "RD" de 16 bits, dont 13-14 sont occupés par ces fonctions hardware, et d'avoir absolument besoin des 2-3 qui restent comme bits numériques à usage général. Dans mon cas actuel, je dois utiliser ces bits pour communiquer des données en parallèle avec un FPGA. ça serait sans aucun doutes plus simple (et propre) si je pouvais décider que tout le port D (par exemple) servirait à charger les données sur l'FPGA, mais pas de bol c'est pas possible à cause de ces modules spécialisés. Donc je me trouve à devoir recycler des bits à droite et à gauche pour arriver aux 2x16 bits que j'ai besoin de passer à mon FPGA, et je me les trouve bien éparpillés sur tous les registres. Donc justement afin d'éviter les codes à rallonge et confus (comme tu le dis si bien), j'essayais de les regrouper dans une seule et même entité "virtuelle".

La solution la plus simple, à mon avis, consiste à faire un codeur. Une fonction pour la lecture, une autre pour l'écriture. La lecture c'est la même chose mais dans l'autre sens. Exemple :

Code :
  1. void writeToFPGA(int16_t word1, int16_t word2) {
  2.    /* mot 1 */
  3.    _RA5 = (word1 & 0x01) >> 0x00;
  4.    _RB4 = (word1 & 0x02) >> 0x01;
  5.    _RD0 = (word1 & 0x04) >> 0x02;
  6.    _RC1 = (word1 & 0x08) >> 0x03;
  7.    _RA7 = (word1 & 0x10) >> 0x04;
  8.    /* etc jusqu'au bit 15 */
  9.    /* mot 2 */
  10.   /* même traitement que pour le mot 1 */
  11. }


 

Joel F a écrit :

On s'en fout de la taille, tes 12 ou 14 bits non necessairement contigus ...

Toutes les mémoires n'alignent pas nécessairement les bits sur des puissance de 2. Particulièrement chez microchip.


Message édité par abaddon2002 le 24-03-2010 à 10:47:34
Reply

Marsh Posté le 24-03-2010 à 10:56:24    

je repee je parle de CONTIGUITE. Le bit (le BIT pas le BYTE) n est contigu aux bits n+1 et n-1. Alignement ou pas : E

Reply

Marsh Posté le 24-03-2010 à 13:41:05    

Merci à vous pour vos réponses fort instructives!
Je vais faire comme ça!


---------------
Si la vérité est découverte par quelqu'un d'autre,elle perd toujours un peu d'attrait
Reply

Marsh Posté le 24-03-2010 à 21:25:31    

Joel F a écrit :

je repee je parle de CONTIGUITE. Le bit (le BIT pas le BYTE) n est contigu aux bits n+1 et n-1. Alignement ou pas : E


Ce n'était pas ce dont tu parlais en #19.

Reply

Marsh Posté le 25-03-2010 à 08:51:40    

ou ça ?

Reply

Marsh Posté le 25-03-2010 à 13:06:03    

Lors de ton intervention : "wat :€ les bits si ils sont pas contigus en mémoire, je comrpends rien. L'unité atomique d'addressage etant l'OCTET ..."
 
Mais c'est pas grave, j'ai compris ce que tu as dit après coup (et non pas j'ai compris après coup ce que tu as dit).

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed