0

I have the following problem: I'm trying to define some basic struct, that helps me map a part of the controller memory to use it in more efficient way. Let me present you an example:

typedef struct
{
    ICR1_t      ICR1_dByte;    /* 0x46 - 0x47  */
    OCR1B_t     OCR1B_dByte;   /* 0x4A - 0x4B  */
    OCR1A_t     OCR1A_dByte;   /* 0x48 - 0x49  */
    TCNT1_t     TCNT1_dByte;   /* 0x4C - 0x4D  */
    TCCR1B_t    TCCR1B_Byte;   /* 0x4E */
    TCCR1A_t    TCCR1A_Byte;   /* 0x4F */
    uint8_t     Filler[8];     /* 0x50-0x57 */
    TIFR1_t     TIFR1_Byte;    /* 0x58 */
    TIMSK1_t    TIMSK1_Byte;   /* 0x59 */
}Timer1_str;

Usage define:

#define TIMER1str (*(volatile Timer1_str *)(TIMER1_START_ADDRESS))

Where the TIMER1_START_ADDRESS is defined as

(uint8_t *)&ICR1

(ICR1 is a part of basic definitions, some address, that's never mind)

So, my particular question is how to fill the gap in memory, located under 0x50-0x57 address? In current solution, the variable "Filler" is visible under all auto complement tools, so it is possible to invoke field:

TIMER1str.Filler[0] = 0xAA;

I wish to hide implementation of that filler. My first thought was to implement this filler as anonymous union, like this:

...
    TCCR1A_t    TCCR1A_Byte;   /* 0x4F */
    union { Filler[8]; };      /* 0x50-0x57 as anonymous */
    TIFR1_t     TIFR1_Byte;    /* 0x58 */
....

But this solution is not working...

How to hide structure a member? It should set the memory but should not be accessible.

timrau
  • 22,578
  • 4
  • 51
  • 64
Tomas
  • 3,269
  • 3
  • 29
  • 48

2 Answers2

2

It looks like you're coding for an AVR.

Don't do this. Use the definitions of these registers provided by your compiler.

As written, your code specifies that the Timer1_str structure will exist at some location in system memory to be determined by the linker. Without any additional support, this code will not work, because this structure will be mapped to SRAM, causing writes to it to have no special effects. Even if you use the linker to map this structure to the appropriate addresses (which may or may not be possible), the code generated by the compiler to work with it will be suboptimal, because it will be unable to use the IN and OUT instructions to manipulate these registers. (To generate these instructions, the address being written to must be known at compile time.) Additionally, the compiler may generate code which does not access these registers appropriately - for instance, here it may generate writes to TCNT in the wrong order.

  • +1...for example AVR libc has [](http://www.nongnu.org/avr-libc/user-manual/group__avr__io.html) – Clifford Mar 03 '14 at 22:56
  • Hello, In fact You are right that this is mentioned to be for an AVR, however it was rather an wrapper to solution that AVR developers itroduce to us. In fact the question was much more focused on practical approach of defining anonymous unions/arrays inside of other structures to be able to "skip" some addresses. – Tomas May 10 '15 at 11:05
0

C does not support this. Anonymous nested structures and unions do not hide the member, they merely allow you to access the member as if they were members of the containing class.

One possibility is to use C++ compilation if that is supported by your compiler:

struct Timer1_str
{
    public :
        ICR1_t      ICR1_dByte;    /* 0x46 - 0x47  */
        OCR1B_t     OCR1B_dByte;   /* 0x4A - 0x4B  */
        OCR1A_t     OCR1A_dByte;   /* 0x48 - 0x49  */
        TCNT1_t     TCNT1_dByte;   /* 0x4C - 0x4D  */
        TCCR1B_t    TCCR1B_Byte;   /* 0x4E */
        TCCR1A_t    TCCR1A_Byte;   /* 0x4F */
    private :
        uint8_t     Filler[8];     /* 0x50-0x57 */
    public :
        TIFR1_t     TIFR1_Byte;    /* 0x58 */
        TIMSK1_t    TIMSK1_Byte;   /* 0x59 */
} ;
Clifford
  • 88,407
  • 13
  • 85
  • 165
  • And does all Cpp compilers guarantee, that data in structure will be located directly in order of typing them? – Tomas Mar 03 '14 at 22:14
  • @user2759473: Good question. Yes I believe so, but packing and alignment may vary. Using your compiler's packing directives may be advisable. In the end your chip or compiler vendor will almost certainly have provided a header defining peripheral registers access, and as duskwulf has pointed out, that is probably a better solution. – Clifford Mar 03 '14 at 22:49