Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

déclaration des registres en embarqué

6 réponses
Avatar
Stéphane Rey
Bonjour,

Dans un programme embarqué, j'ai déclaré les registres en tant que structure
puis, j'ai déclaré la structure. Cela prend visible de la mémoire RAM qui
est dans mon circuit très limitée.
Est-ce que dans ce cas là cela consomme effectivement un octet de mémoire ?
Devrais je préférer des déclaration avec des #define ?

Stéphane



Voici comment un registre est déclaré :

dans le fichier *.c
============
volatile CONFIG2STR _CONFIG2; /* Configuration Register 2 */

dans le fichier *.h
============
/*** CONFIG2 - Configuration Register 2 ***/
typedef union {
byte Byte;
struct {
byte RSTEN :1; /* RST Pin Function Selection */
byte IRQEN :1; /* IRQ Pin Function Selection Bit */
byte IRQPUD :1; /* IRQ Pin Pullup Control Bit */
byte OSCOPT0 :1; /* Selection Bits for Oscillator Option */
byte OSCOPT1 :1; /* Selection Bits for Oscillator Option */
byte :1;
byte :1;
byte :1;
} Bits;
struct {
byte RSTEN :1;
byte IRQEN :1;
byte IRQPUD :1;
byte OSCOPT :2;
byte :1;
byte :1;
byte :1;
} MergedBits;
} CONFIG2STR;
extern volatile CONFIG2STR _CONFIG2 @0x0000001E;
#define CONFIG2 _CONFIG2.Byte
#define CONFIG2_RSTEN _CONFIG2.Bits.RSTEN
#define CONFIG2_OSCOPT0 _CONFIG2.Bits.OSCOPT0
#define CONFIG2_OSCOPT1 _CONFIG2.Bits.OSCOPT1
#define CONFIG2_IRQEN _CONFIG2.Bits.IRQEN
#define CONFIG2_IRQPUD _CONFIG2.Bits.IRQPUD
#define CONFIG2_OSCOPT _CONFIG2.MergedBits.OSCOPT

dans le fichier *.c

volatile CONFIG2STR _CONFIG2; /* Configuration Register 2 */

6 réponses

Avatar
Emmanuel Delahaye
In 'fr.comp.lang.c', "Stéphane Rey" wrote:

Bonjour,

Dans un programme embarqué, j'ai déclaré les registres en tant que
structure puis, j'ai déclaré la structure. Cela prend visible de la


Mapper une structure sur du matériel est en général la dernière chose à faire
à moins qu'on cherche la non-portabilité à tout prix.... Je te conseille
plutôt ça

#ifndef H_ED_BITS_20030122152510
#define H_ED_BITS_20030122152510

#ifdef __cplusplus
extern "C"
{
#endif

/* ---------------------------------------------------------------------
(c) ED 2002-2003
Project : CLIB
Function : Gestion des bits
Module : BITS
File : BITS.H
Created : 29-05-2002
Modified : 12-09-2003
--------------------------------------------------------------------- */

/* ---------------------------------------------------------------------
Log

0.0 29-05-2002 Creation
1.0 29-05-2002 Remplace BIT8() par BIT_8()
1.1 22-01-2003 Ajoute BIT_4()
1.2 11-02-2003 Ajoute BIT_2()
1.3 12-09-2003 Ajoute mVAL()

--------------------------------------------------------------------- */

/* constants =========================================================== */
#define BITS_VER "1.3"
#define BITS_ID "BITS (c) ED 2003"

/* Attention : not portable if ulong is > 32-bit */
#define BITS_NB_MAX 32

/* Attention, type 'ulong' */
#define BIT(bit) (1UL<<(bit))

#define bit31 BIT(31) /* 0x80000000UL */
#define bit30 BIT(30) /* 0x40000000UL */
#define bit29 BIT(29) /* 0x20000000UL */
#define bit28 BIT(28) /* 0x10000000UL */
#define bit27 BIT(27) /* 0x08000000UL */
#define bit26 BIT(26) /* 0x04000000UL */
#define bit25 BIT(25) /* 0x02000000UL */
#define bit24 BIT(24) /* 0x01000000UL */
#define bit23 BIT(23) /* 0x00800000UL */
#define bit22 BIT(22) /* 0x00400000UL */
#define bit21 BIT(21) /* 0x00200000UL */
#define bit20 BIT(20) /* 0x00100000UL */
#define bit19 BIT(19) /* 0x00080000UL */
#define bit18 BIT(18) /* 0x00040000UL */
#define bit17 BIT(17) /* 0x00020000UL */
#define bit16 BIT(16) /* 0x00010000UL */

#ifndef bit0
#define bit15 BIT(15) /* 0x00008000U */
#define bit14 BIT(14) /* 0x00004000 */
#define bit13 BIT(13) /* 0x00002000 */
#define bit12 BIT(12) /* 0x00001000 */
#define bit11 BIT(11) /* 0x00000800 */
#define bit10 BIT(10) /* 0x00000400 */
#define bit9 BIT(9 ) /* 0x00000200 */
#define bit8 BIT(8 ) /* 0x00000100 */
#define bit7 BIT(7 ) /* 0x00000080 */
#define bit6 BIT(6 ) /* 0x00000040 */
#define bit5 BIT(5 ) /* 0x00000020 */
#define bit4 BIT(4 ) /* 0x00000010 */
#define bit3 BIT(3 ) /* 0x00000008 */
#define bit2 BIT(2 ) /* 0x00000004 */
#define bit1 BIT(1 ) /* 0x00000002 */
#define bit0 BIT(0 ) /* 0x00000001 */
#endif

/* macros ============================================================== */

#define BITS_sid() (BITS_ID)
#define BITS_sver() ((char const *)BITS_VER)

#define BIT_2(a,b)
(((a)?bit1:0)
|((b)?bit0:0))

#define BIT_4(a,b,c,d)
(((a)?bit3:0)
|((b)?bit2:0)
|((c)?bit1:0)
|((d)?bit0:0))

#define BIT_8(a,b,c,d,e,f,g,h)
(((a)?bit7:0)
|((b)?bit6:0)
|((c)?bit5:0)
|((d)?bit4:0)
|((e)?bit3:0)
|((f)?bit2:0)
|((g)?bit1:0)
|((h)?bit0:0))

/* mask set/clear/toggle */
#define mSET(d_, m_) ((d_) |= (m_))
#define mCLR(d_, m_) ((d_) &= ~(m_))
#define mTGL(d_, m_) ((d_) ^= (m_))

/* binary mask update */
#define mUPDATE(sts, byte, bit)
(sts) ? mSET(byte, bit) : mCLR(byte, bit)

/* binary mask sts get */
#define mGET(d, m)
(!!((d) & (m)))

/* binary mask value get
d ::= data
w ::= width
l ::= LSB
*/
#define mVAL(d, w, l)
(((d) >> (l)) & (((w) == BITS_NB_MAX) ? -1 : (BIT (w) - 1)))

#ifdef __cplusplus
}
#endif

#endif /* H_ED_BITS_20030122152510 */
/* GUARD (c) ED 2000-2002 Dec 16 2002 Ver. 1.4 */

--
-ed- [remove YOURBRA before answering me]
The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html
C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp
FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/

Avatar
halfwolf
Salut,

"Stéphane Rey" wrote in message news:<4027aafa$...
extern volatile CONFIG2STR _CONFIG2 @0x0000001E;


Pas du C standard (@0x0000001E).

Dans un fichier qui m'a été fournit par NEC pour ma plateforme j'ai
par exemple :

struct bitf {
unsigned char bit00:1;
unsigned char bit01:1;
unsigned char bit02:1;
unsigned char bit03:1;
unsigned char bit04:1;
unsigned char bit05:1;
unsigned char bit06:1;
unsigned char bit07:1;
unsigned char bit08:1;
unsigned char bit09:1;
unsigned char bit10:1;
unsigned char bit11:1;
unsigned char bit12:1;
unsigned char bit13:1;
unsigned char bit14:1;
unsigned char bit15:1;
};

/* I/O register */
#define P0 *((volatile unsigned char *)0xfffff000)

/* I/O register bit */
#define _P00 ((volatile struct bitf *)0xfffff000)->bit00

Et là tu ne prends pas de place en mémoire.

J'aurais personnellement remplacé
#define _P00 ((volatile struct bitf *)0xfffff000)->bit00
par
#define _P00 ((volatile struct bitf *)&P0)->bit00
pour avoir unicité de l'adresse du registre.

Le conseil d'Emmanuel est de bon sens, mais AMHA on gagne en
lisibilité sur le code en mettant _P00 = 1 plutôt que mUPDATE(1, P0,
bit0) d'autant plus quand P00 est le nom utilisé dans la doc hardware
pour désigner le bit 0 du registre P0.

De plus, la portabilité du code sur une autre plateforme alors qu'on
tape directement dans des registres spécifiques, ça me paraît
discutable. On peut tout au plus parler de portabilité sur un autre
compilateur.

Je préfère aussi avoir le code suivant :

# define LED_ON 1
# define LED_OFF 0
# define LED_RUN _P00
avec lors de l'utilisation
LED_RUN = LED_ON;

et si la led change de port (car nouveau hardware) il suffit juste de
changer le define de LED_RUN, plutôt que :

# define LED_ON 1
# define LED_OFF 0
# define LED_RUN_REGISTER P0
# define LED_RUN_BIT 0
# define UPDATE_LED_RUN(val_)
mUPDATE(val_, LED_RUN_REGISTER, BIT(LED_RUN_BIT))

et d'être obligé de changer LED_RUN_REGISTER et LED_RUN_BIT.

Enfin, la méthode d'Emmanuel est meilleure lorsqu'on veut indiquer à
une fonction de modifier ce bit car le pointeur sur bit n'existe pas :
on ne peut donc pas avoir une fonction SetLed générique utilisée de la
façon suivante :
SetLed(&_P00);
on est obligée d'avoir
SetLed(&P0, 0);

En espérant avoir aidé,

HalfWolf

Avatar
Stéphane Rey
merci pour ces suggestions.
Il semble que la définition faite par motorola ne prennent finalement pas
d'octets en RAM.

Son avantage est de pouvoir grouper des vits au sein d'un même champs et
d'adresser ce champs.

Si par exemple dans un registre 8 bits, il y a trois bits au milieu qui
correspondent à une info, il est aisé avec cette méthode d'accéder à ces
trois bits sous forme d'un champ unique.
Excellent pour la lisibilité. Par contre, je ne suis pas sûr que cela se
porte bien. J'essairais sur un autre micro Philips


Stéphane

"Stéphane Rey" wrote in message
news:4027aafa$
Bonjour,

Dans un programme embarqué, j'ai déclaré les registres en tant que
structure

puis, j'ai déclaré la structure. Cela prend visible de la mémoire RAM qui
est dans mon circuit très limitée.
Est-ce que dans ce cas là cela consomme effectivement un octet de mémoire
?

Devrais je préférer des déclaration avec des #define ?

Stéphane



Voici comment un registre est déclaré :

dans le fichier *.c
=========== > volatile CONFIG2STR _CONFIG2; /* Configuration Register 2 */

dans le fichier *.h
=========== > /*** CONFIG2 - Configuration Register 2 ***/
typedef union {
byte Byte;
struct {
byte RSTEN :1; /* RST Pin Function Selection */
byte IRQEN :1; /* IRQ Pin Function Selection Bit */
byte IRQPUD :1; /* IRQ Pin Pullup Control Bit */
byte OSCOPT0 :1; /* Selection Bits for Oscillator Option */
byte OSCOPT1 :1; /* Selection Bits for Oscillator Option */
byte :1;
byte :1;
byte :1;
} Bits;
struct {
byte RSTEN :1;
byte IRQEN :1;
byte IRQPUD :1;
byte OSCOPT :2;
byte :1;
byte :1;
byte :1;
} MergedBits;
} CONFIG2STR;
extern volatile CONFIG2STR _CONFIG2 @0x0000001E;
#define CONFIG2 _CONFIG2.Byte
#define CONFIG2_RSTEN _CONFIG2.Bits.RSTEN
#define CONFIG2_OSCOPT0 _CONFIG2.Bits.OSCOPT0
#define CONFIG2_OSCOPT1 _CONFIG2.Bits.OSCOPT1
#define CONFIG2_IRQEN _CONFIG2.Bits.IRQEN
#define CONFIG2_IRQPUD _CONFIG2.Bits.IRQPUD
#define CONFIG2_OSCOPT _CONFIG2.MergedBits.OSCOPT

dans le fichier *.c

volatile CONFIG2STR _CONFIG2; /* Configuration Register 2 */




Avatar
halfwolf
"Stéphane Rey" wrote in message news:<4028e3b3$...
merci pour ces suggestions.
Il semble que la définition faite par motorola ne prennent finalement pas
d'octets en RAM.

Son avantage est de pouvoir grouper des vits au sein d'un même champs et
d'adresser ce champs.

Si par exemple dans un registre 8 bits, il y a trois bits au milieu qui
correspondent à une info, il est aisé avec cette méthode d'accéder à ces
trois bits sous forme d'un champ unique.
Excellent pour la lisibilité. Par contre, je ne suis pas sûr que cela se
porte bien. J'essairais sur un autre micro Philips


Je ne vois vraiment pas l'intérêt qu'apporte l'utilisation de

extern volatile CONFIG2STR _CONFIG2 @0x0000001E;

qui n'est valide que sur ton compilateur par rapport à

# define _CONFIG2 *((volatile CONFIG2STR*)0x0000001E)

qui est standard et donc valide sur tout compilateur.
A moins que quelque chose m'échappe...

HalfWolf

Avatar
halfwolf
Je voulais dire

# define _CONFIG2 (*((volatile CONFIG2STR*)0x0000001E))

au lieu de

# define _CONFIG2 *((volatile CONFIG2STR*)0x0000001E)

car sinon il y a un problème de priorité des opérateurs (. plus prioritaire que *).

Pour résumer :

dans le fichier *.h
=========== /*** CONFIG2 - Configuration Register 2 ***/
typedef union {
byte Byte;
struct {
byte RSTEN :1; /* RST Pin Function Selection */
byte IRQEN :1; /* IRQ Pin Function Selection Bit */
byte IRQPUD :1; /* IRQ Pin Pullup Control Bit */
byte OSCOPT0 :1; /* Selection Bits for Oscillator Option */
byte OSCOPT1 :1; /* Selection Bits for Oscillator Option */
byte :1;
byte :1;
byte :1;
} Bits;
struct {
byte RSTEN :1;
byte IRQEN :1;
byte IRQPUD :1;
byte OSCOPT :2;
byte :1;
byte :1;
byte :1;
} MergedBits;
} CONFIG2STR;
#define _CONFIG2 (*((volatile CONFIG2STR*)0x0000001E))
#define CONFIG2 _CONFIG2.Byte
#define CONFIG2_RSTEN _CONFIG2.Bits.RSTEN
#define CONFIG2_OSCOPT0 _CONFIG2.Bits.OSCOPT0
#define CONFIG2_OSCOPT1 _CONFIG2.Bits.OSCOPT1
#define CONFIG2_IRQEN _CONFIG2.Bits.IRQEN
#define CONFIG2_IRQPUD _CONFIG2.Bits.IRQPUD
#define CONFIG2_OSCOPT _CONFIG2.MergedBits.OSCOPT

HalfWolf
Avatar
Stéphane Rey
J'ignorais que cette syntaxse était propre à mon compilateur....
J'ai essayé avec les #define et cela fonctionne bien.

Je vais corriger le header file fournit par Motorola...
Merci
Stéphane



"HalfWolf" wrote in message
news:
Je voulais dire

# define _CONFIG2 (*((volatile CONFIG2STR*)0x0000001E))

au lieu de

# define _CONFIG2 *((volatile CONFIG2STR*)0x0000001E)

car sinon il y a un problème de priorité des opérateurs (. plus
prioritaire que *).


Pour résumer :

dans le fichier *.h
=========== > /*** CONFIG2 - Configuration Register 2 ***/
typedef union {
byte Byte;
struct {
byte RSTEN :1; /* RST Pin Function Selection */
byte IRQEN :1; /* IRQ Pin Function Selection Bit */
byte IRQPUD :1; /* IRQ Pin Pullup Control Bit */
byte OSCOPT0 :1; /* Selection Bits for Oscillator Option */
byte OSCOPT1 :1; /* Selection Bits for Oscillator Option */
byte :1;
byte :1;
byte :1;
} Bits;
struct {
byte RSTEN :1;
byte IRQEN :1;
byte IRQPUD :1;
byte OSCOPT :2;
byte :1;
byte :1;
byte :1;
} MergedBits;
} CONFIG2STR;
#define _CONFIG2 (*((volatile CONFIG2STR*)0x0000001E))
#define CONFIG2 _CONFIG2.Byte
#define CONFIG2_RSTEN _CONFIG2.Bits.RSTEN
#define CONFIG2_OSCOPT0 _CONFIG2.Bits.OSCOPT0
#define CONFIG2_OSCOPT1 _CONFIG2.Bits.OSCOPT1
#define CONFIG2_IRQEN _CONFIG2.Bits.IRQEN
#define CONFIG2_IRQPUD _CONFIG2.Bits.IRQPUD
#define CONFIG2_OSCOPT _CONFIG2.MergedBits.OSCOPT

HalfWolf