1

I am using MPLABX IDE MCC generated code. At some point inside UART driver, there is the following code for UART state.

typedef union {
    struct {
      unsigned perr : 1;
      unsigned ferr : 1;
      unsigned oerr : 1;
      unsigned reserved : 5;
    };
    uint8_t status;
}uart1_status_t;

As far as I can understand there are 2 types inside the union, 1 struct and 1 8-bit unsigned variable. I have 2 questions:

  1. what is actually ...perr : 1; What is done here? type is not indicated only unsigned is written and what is ":1"? It is not a value given to perr? As I tried this out on a C compiler, I saw these are actually bits of the status variable. perr and ferr are 0th and 1st bits but oerr is 4th? Why?
  2. The struct does not have an 'instance', so how can I access it? I am confused of this section. Since it is a union, these bits and status variable are stored at the same memory location, hence whenever I try to access status it also means accessing these perr, ferr, oerr values? Is it right?
Arda30
  • 107
  • 5
  • *"perr and ferr are 0th and 1st bits but oerr is 4th?"* Unless MPLABX is doing something unusual, that result seems incorrect. Please double check that is what you are really seeing. – user694733 Mar 25 '19 at 10:27

2 Answers2

3
  1. This is a common (bad) way of declaring hardware registers. The struct is a bit-field and the individual members refers to bits in the 8 bit register. The syntax allows you to access either individual bits or the whole register.

    In this case the struct is anonymous so if you have uart1_status_t u1; you can access bits as u1.perr rather than u1.somename.perr. Anonymous structs is a C11 feature though in this case it is probably some non-standard extension they've used pre-C11.

    They use unsigned meaning unsigned int, since that's the default type to use for bit-fields. But note that this code is completely non-portable and relies on a certain compiler implementation of bit-fields.

  2. Elsewhere you'll have something like volatile uart1_status_t* UART1_STATUS = ... pointing at an absolute address. (Likely too with some non-standard syntax like @.) Since these are memory-mapped hardware registers, they are already in place in the MCU and you don't allocate space for them.

Lundin
  • 195,001
  • 40
  • 254
  • 396
1
  1. This question is a duplicate, the answer is "they are bit fields, the numbers after the colons specify the width of the field in bits". Here is an earlier question with a good answer.
  2. There probably is a macro somewhere that provides the address of the register cast to the proper type, and given the name from the processor docs.
unwind
  • 391,730
  • 64
  • 469
  • 606