1
\$\begingroup\$

I am trying to follow the best practices in register mapping. I have a MAX30001 analog front end for ECG applications (Datasheet) and in page 38, there is a table that contains user command and register map: 32 words, each with 24 bits of information. Should I use structures or macros ?

Using structures with bit fields:

typedef struct {
 volatile uint8_t Bit0 : 1;
 volatile uint8_t Bit1 : 1;
 volatile uint8_t Bit2 : 1;
 volatile uint8_t Bit3 : 1;
 // ... 
 // and so on
 // ... 
 volatile uint8_t Bit23 : 1;
} foo;

Using macros:

#define STATUS (*(volatile uint32_t*)0x01))
Nick Alexeev
38.9k17 gold badges104 silver badges249 bronze badges
asked Nov 26, 2017 at 20:26
\$\endgroup\$
3
  • \$\begingroup\$ Could you explain how would you use structures or macros? For each, add an example (and external references, if any), perhaps. I probably understand what you mean [I think]. But it would be better if you explain yourself. \$\endgroup\$ Commented Nov 26, 2017 at 20:55
  • \$\begingroup\$ let's say you want to set BINT (statusReg:bit3) ... how would the code look for each of the mapping methods? ... which would be easier to read? \$\endgroup\$ Commented Nov 26, 2017 at 21:42
  • \$\begingroup\$ Alright. post edited. \$\endgroup\$ Commented Nov 26, 2017 at 22:35

2 Answers 2

2
\$\begingroup\$

In the general case, where you have memory mapped registers, you should always avoid bitfield structs. This is because those are very poorly specified by the C standard. Fundamental things that you may assume are specified, are not. This includes bit order, byte order, padding & alignment.

In addition, uint8_t among other types, is not even an allowed type in bitfields! You can only use int types, though if int counts as signed or unsigned is not specified either...

To sum it up, bitfields are horribly unreliable and you are left at the mercy of the compiler implementation (if any) when you use them.

What you should do instead, is to always use address and bit mask macros, together with the bit-wise operators. Those are 100% well-defined and portable.

answered Nov 27, 2017 at 7:30
\$\endgroup\$
1
\$\begingroup\$

The MAX30001 uses an SPI interface. It's not a memory-mapped device, so neither structures nor macros are usable here.

About all you can usefully do is define a bunch of macros to represent the register numbers and individual bits within them, e.g:

#define MAX30001_NO_OP 0x00
#define MAX30001_STATUS 0x01
#define MAX30001_STATUS_EINT 0x800000
#define MAX30001_STATUS_EOVF 0x400000
#define MAX30001_STATUS_FSTINT 0x200000
// etc

Even for memory-mapped devices, it's generally best to avoid bitfields (like Bit0:1). C compilers often handle them poorly, and make few guarantees about how bitfields will be packed into a structure. Use macros to represent individual bits within a single register.

answered Nov 26, 2017 at 22:48
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.