2010-11-20 3 views
0

Tout d'abord, désolé pour le titre, il était difficile de trouver une description. J'essaye de créer une structure qui accédera à un périphérique qui a peu de registres internes contrôlés par 3 lignes d'adresse. J'ai donc la définition de la structure suivante:En C, un pointeur vers une structure qui a besoin d'accéder à une liste de pointeurs d'octets

typedef struct { 
    union { 
    unsigned char *reg0aPtr; 
    unsigned char *reg0bPtr; 
    } RegsAddrOffset0; 

    union { 
    unsigned char *reg1aPtr; 
    unsigned char *reg1bPtr; 
    } RegsAddrOffset1; 

    ... 

    union { 
    unsigned char *reg7aPtr; 
    unsigned char *reg7bPtr; 
    } RegsAddrOffset7; 
} DeviceRegMap; 

Ensuite, si je déclare une variable comme si

DeviceRegMap *uartRegMap = (DeviceRegMap *)(0xD0000000); 

Maintenant, si je tente de d'utiliser la variable uartRegMap pour accéder à la mémoire mappée registres Je pensais que je verrait que * (uartRegMap-> RegsAddrOffset0.reg0aPtr) lirait les données de l'adresse 0xD0000000, ce qui est fait. Si j'utilise * (uartRegMap-> RegsAddrOffset1.reg1bPtr), je pensais que j'accéderais à 0xD0000001, mais il accède en fait à l'adresse 0xD0000004. Comme le processeur est en 32 bits, l'alignement naturel est de 4 octets. Je pense que la taille d'un pointeur est un entier qui dans ce cas est de 32 bits, c'est la raison pour laquelle j'accède sur des plages d'adresses de 4 octets (par exemple, 0xD0000000, 0xD0000004, 0xD0000008, etc.).

Si je déclarais une instance du type de données DeviceRegMap j'attendre l'initialisation suivante:

DeviceRegMap uartRegMap = { 
    (unsigned char *)0xD0000000, 
    (unsigned char *)0xD0000001, 
    ... 
    (unsigned char *)0xD0000007, 
}; 

Alors si je voulais accéder à l'adresse 0xD0000007 puis j'utiliser * (uartRegMap.RegsAddrOffset7.reg7bPtr)

La question est pourquoi le pointeur vers le type de données DeviceRegMap accède-t-il à la mémoire sur les alignements 4 octets (par exemple, 0xD0000000, 0xD0000004, etc.) au lieu des alignements d'octets (par exemple, 0xD0000000, 0xD0000001, etc). En ce qui concerne l'ensemble d'outils, j'utilise le compilateur de diabète de Wind River. Merci.

Mark

EDIT: D'après le commentaire de abelenky

+2

Quelle est votre question? "Je veux juste m'assurer de comprendre ce qui se passe." Ce n'est pas une question. – abelenky

+0

Pourquoi utilisez-vous une «union» de deux éléments du même type? –

+0

Juste pour ajouter un aperçu supplémentaire de ce qui se passe. Le code a été développé par un autre ingénieur dont j'ai hérité pour un pilote de périphérique UART. L'UART possède environ 21 registres différents qui sont accessibles via trois lignes d'adresses mappées en mémoire. Comme les gens l'ont souligné, les syndicats ne sont vraiment pas nécessaires, mais ils ajoutent de la clarté à la lecture du code. Par exemple, à un décalage de 0x00, il y a les registres de maintien TX et RX avec quelques autres registres. Donc le code utilise -> RHR ou -> THR qui aide à la lisibilité. – lordhog

Répondre

1

Si vous souhaitez accéder aux parties d'un registre de mémoire mappée taille octets, procédez comme suit:

struct DeviceRegMap { 
    volatile unsigned char byte0; 
    volatile unsigned char byte1; 
    volatile unsigned char byte2; 
    volatile unsigned char byte3; 
}; 

static struct DeviceRegMap *device = (struct DeviceRegMap *)(0xD0000000); 

maintenant device->byte0 points 0xD0000000 et device->byte3 des points à 0xD00000003. Est-ce que c'est ce que tu veux?

+0

Roland, je pense que cela devrait fonctionner.Je vais devoir attendre de travailler pour tester le matériel. Merci – lordhog

0

La plupart des compilateurs ont un moyen d'indiquer qu'une structure doit être bien empaquetée, sans rembourrage à des fins d'alignement.

Je ne suis pas familier avec votre compilateur, mais parcourir la documentation pour quelque chose comme

#pragma pack 

avant la définition de votre structure.

+0

Oui, j'ai déjà essayé celui-là. – lordhog

Questions connexes