8

I was using a header file in my project that had the following define(s):

#ifdef __cplusplus
  extern "C" {
#endif 

#ifdef __cplusplus
  #define   __I     volatile             /*!< Defines 'read only' permissions*/
#else
  #define   __I     volatile const       /*!< Defines 'read only' permissions*/
#endif

The __I is used as follows in another header file:

    typedef struct {   
    // more members before         
      __I  uint32_t  CR;   /*!< GPIO Commit*/
    // more members after

    } GPIOA_Type;

#define GPIOF_BASE                      0x40025000UL
#define GPIOF                           ((GPIOA_Type *) GPIOF_BASE)

My question is why would the __I be made const in C but not in C++? You can still modify the value CR is pointing to since you have the address, but am just curios why the definition of __I is different.

For anybody interested what this is for or from, the __I defines are from IAR Embedded Workbench ARM for Cortex-M4 , and the struct is from Texas Instruments LM4F120H5QR CMSIS files.

SoftwareDev
  • 674
  • 1
  • 6
  • 14
  • 1
    In C++ `const` confers internal linkage. I don't know whether it does in C, but I suspect not. Anyway, note that `__I` is a name reserved to the implementation, and should not be used in user code. – Cheers and hth. - Alf Oct 19 '14 at 21:15
  • @Mat McNabb I meant that since I have the CR register exact address I can do the following #define GPIO_PORTF_CR_R (*((volatile unsigned long *)0x40025524)) , then do GPIO_PORTF_CR_R = xxxxx , and that changes the value of the register. – SoftwareDev Oct 19 '14 at 23:49
  • @SoftwareDev OK - the `volatile const CR` means you can't use `CR` to modify the register; of course it can be modified in other ways – M.M Oct 19 '14 at 23:53
  • @MattMcNabb Yeah that's what I thought you meant, just wanted to add that in for clarification for others. Thanks. – SoftwareDev Oct 19 '14 at 23:57

1 Answers1

8

In C++, const variables at file scope default to static linkage, which wouldn't be desired for memory-mapped GPIOs. The "right" fix for that is the extern keyword, but that can't be used here, since evidently __I needs to work with class members as well. So eliminating const makes the default linkage extern, as desired.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • If this is the reason, I'd also note that whoever wrote the original code probably should have "forked" `__I` to have a different version for member variables than for globals – M.M Oct 19 '14 at 21:15
  • @MattMcNabb: Hindsight is always 20-20. C++ support was probably added long after the macro was used in C code for both globals and members. – Ben Voigt Oct 19 '14 at 21:37
  • @BenVoigt Makes sense. So basically, the person who wrote this code said "there is not way to make CR read only in C++ even though that is what we want"? Although am leaning more towards the person who wrote the C code not reading the datasheet correctly because according it the CR register's value can be changed from the default, in fact if it can't be changed there is no way to enable a pull-up resistor in one of the switches in the development board am using. – SoftwareDev Oct 20 '14 at 00:08
  • @SoftwareDev: I didn't look at the particular register for the particular chip or even the LM4F family. But I guess these macros are used for all special function registers, not just GPIO CR? It might be a mistake that CR is marked input-only in the header, but surely there are quite a few registers which truly should be input-only. – Ben Voigt Oct 20 '14 at 00:36
  • @SoftwareDev: In fact, the header file might intentionally be more restrictive than the hardware. You only write `GPIOCR` if you are going to disable the programming function of programming pins... which is a one-way trip if you have a bug. – Ben Voigt Oct 20 '14 at 00:39