Description of __attribute__ compilation attribute in embedded C

Perseverance, gold and stone can be carved

Article directory

  • foreword
  • Parameter introduction
    • 1. aligned
    • 2. packed
    • 3. at
    • 4. section
  • Summarize

Foreword

__attribute__ is a major feature mechanism of the GNU C extension, which is used to set function attributes (Function Attribute), variable attributes (Variable Attribute) and type attributes (Type Attribute).
__attribute__ is identified by two _ before and after, and the backend is followed by () to indicate that the parameter attribute follows. The syntax format is:

_ attribute _ (( ATTRIBUTE ))

Among them, ATTRIBUTE is the description of the attribute, and multiple descriptions are separated by commas. GCC currently supports several attributes. The following describes common attribute settings.

Parameter introduction

1, aligned

aligned is used for variables, structures or unions, and sets an alignment format of a specified size, in bytes (valid parameter value is a power of 2), for example:

struct _array_
{<!-- -->
    char flag;
    int state;
    int length;
}__attribute__((aligned(8)));

struct _array_ array_zero;
int main(void)
{<!-- -->
    printf("This struct size is %d\r\\
",sizeof(array_zero));
}

output result

This struct size is 16

It should be noted that the aligned attribute makes the compiler do its best to ensure that when allocating variable space, it sets an 8-byte alignment size. If the attribute is not followed by a specified number, the compiler will use the largest and most beneficial alignment for your target machine.

struct _array_
{<!-- -->
    char array;
    int flag;
}__attribute__((aligned(2)));

struct _array_ array_zero;
int main(void)
{<!-- -->
    printf("This struct size is %d\r\\
",sizeof(array_zero));
}

As in the above code, specify the 2-byte alignment for its method. The structure alignment is 4-byte alignment, and the actual alignment is 4-byte alignment. The compiled output is as follows:

This struct size is 8

It should be noted that the effectiveness of the attribute attribute is also related to your linker. If your linker only supports a maximum of 16-byte alignment, then it is useless for you to define 32-byte alignment at this time.

2, packed

The attribute packed is used for variables and types. When it is used for variables or structure members, it means to use the smallest possible alignment. When it is used for enumeration, structure or union types, it means that the type uses the smallest memory. Just the opposite when the attribute aligned refers to byte alignment. Referring to the aligned code test, write the following test code

struct _array_
{<!-- -->
    char array;
    int false;
}__attribute__((packed));

struct _array_ array_zero;
int main(void)
{<!-- -->
    printf("This struct size is %d\r\\
",sizeof(array_zero));
}

The structure type array is modified by the packed attribute to cancel the byte alignment, and the member variables are aligned by 1 byte. The compiled output is as follows:

This struct size is 5

The effects of its properties are similar to #pragma pack(1). It should be noted that packed only works on modified objects, not on embedded structures. As follows:

struct S{<!-- -->
    char eox;
    int length;
};

struct_array_
{<!-- -->
    char array;
    int false;
    struct S _S_;
}__attribute__((packed));

struct _array_ array_zero;
int main(void)
{<!-- -->
    printf("This struct size is %d\r\\
",sizeof(array_zero));
}

The structure type array in the code is modified by the packed attribute, and member variables are aligned by 1 byte. However, the structure S is not modified and is still aligned by 4 bytes. The compiled output is as follows:

This struct size is 13

3, at

It is used to set the absolute address of the variable, specifying that a variable is in a given address in RAM or FLASH, the syntax is __attribute__((at(addr))).
1) Locate in the flash, which is generally used for curing information, such as factory-set parameters, parameters configured by the host computer, ID number of the ID card, flash marks, etc.
2) Locate in RAM, generally used for cache with relatively large amount of data, such as serial port receiving cache, and then a specific variable at a certain location

const uint8_t array[] __attribute__((at(0x08002800)))={<!-- -->0xA5,0x5A};//locate to flash, the address is 0X08002800
uint8_t RecvBuffer[MAX_RECV_LEN] __attribute__ ((at(0x00025000))); //Receive buffer, maximum MAX_RECV_LEN bytes, starting address is 0x00025000

Take positioning to flash as an example, add definition code to the project. Compile and view the map file, under the Global Symbols category, find the array definition address information

array 0x08002800 Data 2 main.o(.ARM.__AT_0x08002800)

Or use J-FLASH to open the compiled binary file, locate it at address 0X8002800, and the parameter value has been written.

To locate in flash, you need to add const keyword modification. In addition, regarding the use of definitions, the following two points need to be noted

1. Absolute positioning cannot be defined in the function. Local variables are defined in the stack area. The stack area is automatically allocated and released by MDK. It cannot be defined as an absolute address and can only be defined outside the function.
2. The defined length cannot exceed the size of the stack or Flash, otherwise, the stack and Flash will overflow.

4, section

This attribute is used to modify functions or variables, and compile the modified variables or functions into specific segments during compilation. The syntax uses __attribute__((section(“xxx”)))

uint8_t ret attribute((section(“.test.”))) = 0;

This paragraph of statement means to define uint8_t type variable, its initial value is 0, compile and put it into the input section of “.test.”. Add code to the project, open the map file, and find the corresponding information.

ret 0x200000d0 Data 1 main.o(.test.)

Or the modifier function, which is also the scene where this attribute is used the most. It is generally used in combination with other attributes and used in the Initcall mechanism. like:

void func_attribute(void) __attribute__ ((section(".fun.")));

void func_attribute(void)
{<!-- -->
    DEBUG_log("This is test\r\\
");
}

Compile and open the map file, and find the corresponding attribute table as follows:

func_attribute 0x08000161 Thumb Code 10 main.o(.fun.)

Summary

__attribute__ supports joint use of multiple attributes, separated by (, ) in brackets. Generally common in the operating system, most of the first contact with this extended attribute is based on the Initcall mechanism under Linux, or the automatic initialization mechanism (Initcall) in RTT. I have time to write an article about the introduction of the Initcall mechanism, which is used as a record.
The code words are not easy, please correct me if there are any mistakes or omissions. One-click three times even better! (^_^)!