Are these attributes incompatible? The address attribute seems to be ignored, emitting no warnings (-Wall).
(For reference, EEMEM is defined in eeprom.h as: #define EEMEM __attribute__((section(".eeprom"))).)
Using a declaration like:
uint8_t storedFlags EEMEM __attribute__((address (100)));
(and similarly for all the others) results in the variables being placed in whatever order the linker prefers, ignoring my attribute. Order of attributes doesn't make a difference.
I am aware of the preferred method (creating sections and passing their locations to the linker). I was just looking to shove them around for the moment, as I'm in active development and adding and removing allocations in EEPROM; I'd rather things not move around every other build so I don't have to reprogram EEPROM from default values every damn time. Worst of all, I'm sure I've done precisely this before, and had it work. Version differences? Coincidental assignments? (I have GCC 3.4 and 8.1, not sure what that project used; I'm using 8.1 for this one.)
The documentation for the address attribute states:
Variables with the address attribute are used to address memory-mapped peripherals that may lie outside the io address range.
Looking at the AVR memory space shows the I/O addresses fall under the SRAM data memory space.
This explains why your construct doesn't work as expected since EEMEM and the address attribute map to conflicting memory sections.
Edit: Testing with avr-gcc 3.6.2 suggest that the section attribute overrides the address attribute (without warning). Using eeprom_read_byte to read data from EEPROM, the following example gets correctly compiled by avr-gcc (correct because the address 0x0123 is passed to the eeprom_read_byte function):
#include <avr/eeprom.h>
uint8_t __attribute__((address (0x0123))) storedFlags;
int main(void){
if (eeprom_read_byte(&storedFlags) == 1){
return 1;
}
}
Edit2: tested on avr-gcc 11.1, also generates correct instructions.
Related
I'm using a library to register some structs at compile time. In this case it's registering a struct representing a JSON-RPC method that I'd like to expose. The library marks the structs with __attribute(section("xautodata_" "somename")) so that it'll be put in a separate section that can later be retrieved. The generated content will look like this:
static const autodata_json_command_ *__attribute__((__used__)) __attribute__((section("xautodata_" "json_command"))) autodata_json_command_151 = (&help_command);;
static const autodata_json_command_ *__attribute__((__used__)) __attribute__((section("xautodata_" "json_command"))) autodata_json_command_173 = (&stop_command);;
The code that later retrieves the commands will get a pointer to the section (and count the number of elements in that section) and iterate over it, like this:
size_t count;
struct json_command **commands = get_json_commands(&count);
for (size_t i=0; i<count; i++) {
// Access commands[i];
}
This works perfectly fine if we don't compile with -fsanitize=address, but it'll add padding when compiled with -fsanitize=address.
Without the address sanitizer commands are adjacent to each other, i.e., commands[0] and commands[1] are valid pointers to structs. With the sanitizer only every 8th command is a valid pointer (presumably due to padding).
Now for the real question: what's the cleanest way to fix this? Should I try to make the stepsize larger (in which case a preprocessor instruction is needed to distinguish the sanitizer use)? Or is there a way to disable this padding for things in the section?
GCC Asan deliberately avoids instrumenting variables in custom sections for the reasons you outlined (i.e. to preserve consecutiveness):
/* Don't protect if using user section, often vars placed
into user section from multiple TUs are then assumed
to be an array of such vars, putting padding in there
breaks this assumption. */
|| (DECL_SECTION_NAME (decl) != NULL
&& !symtab_node::get (decl)->implicit_section
&& !section_sanitized_p (DECL_SECTION_NAME (decl)))
(from gcc/asan.c). A special flag -fsanitize-sections=wildcard1,wildcard2,... can be used to force instrumentation in this case.
Clang Asan on the other hand ignores user section annotations (see AddressSanitizer.cpp).
I suggest to add a PR to Asan tracker to either make Clang behave like GCC or add a special flag to control instrumentation of user sections (in latter case we also need to update Asan Clang/GCC incompatibility wiki).
I recently ran into an embedded C program using the '#pragma align' directive:
/*
* Audio buffers
*/
#pragma align(4)
static uint32_t RxBuffer1[NUM_AUDIO_SAMPLES];
#pragma align(4)
static uint32_t RxBuffer2[NUM_AUDIO_SAMPLES];
#pragma align(4)
static uint32_t TxBuffer1[NUM_AUDIO_SAMPLES];
#pragma align(4)
static uint32_t TxBuffer2[NUM_AUDIO_SAMPLES];
Note that this code excerpt is for a DSP chip, thus it's not x86-64.
After doing some research, this appears to be a method for aligning variables in memory at a specified distance. For example, it would allow me to align three char vars at 1 byte intervals as opposed to placing them in the typical memory word width (e.g. 4 byte intervals). I understand that there are some penalties involved with storing variables at non-word intervals. This is due to the fact that memory is retrieved as words, thus it would be necessary to do shifting and masking if you were trying to just look at individual bytes.
However, I'm confused with how '#pragma align' is actually implemented. So my primary question: how does it work?
I'm hoping to get some comments regarding the following items:
- Is the '#pragma align' directive a common thing? Or is it dependent on the environment you're working in (i.e. does #pragma align exist for x86).
- Why is this a preprocessor directive? Why is the preprocessor responsible for this?
- What goes on behind the scenes when I later want to reference one of these oddly aligned variables? What does it reference to be able to know that 'variable x is byte 3 of memory word 0x1ABA9'.
Edit: I'm just now realizing that the #pragma directive is intended for machine specific compilers, thus the answer to my question may be heavily influenced by the environment I'm working in. To give you more information, I'm working with an Analog Devices Blackfin+ processor. A link to that chip is provided here.
Although it begins with #, #pragma is not a preprocessor directive, instead it is handled by the compiler.
Pragma directives are compiler-specific, so the specifics of how they work depend on the compiler.
It is not standard: C++11 uses the alignas specifier to achieve this. Older compilers have alternatives (such as MSVC _declspec(align(4))), and continue to support these for compatibility with existing source code.
That said, where supported #pragma align is reasonably similar between compilers, and works in exactly the way you describe, individually specifying the alignment of data types and members of structures. It certainly exists for all common x86 compilers.
As to how it is implemented, that is compiler specific. But in effect the compiler must tag the internal metadata for the type with its alignment requirement so that the correct machine code can be generated, and offsets to struct members calculated correctly, sizeof and pointer arithmetic works, and so forth. Each data type has a size and an alignment requirement anyway, and each member has an offset, so for a pragma to change them just involves changing what information the front-end sends to the back-end.
I often times write to memory mapped I/O pins like this
P3OUT |= BIT1;
I assumed that P3OUT was being replaced with something like this by my preprocessor:
*((unsigned short *) 0x0222u)
But I dug into an H file today and saw something along these lines:
volatile unsigned short P3OUT # 0x0222u;
There's some more expansion going on before that, but it is generally that. A symbol '#' is being used. Above that there are some #pragma's about using an extended set of the C language. I am assuming this is some sort of directive to the linker and effectively a symbol is being defined as being at that location in the memory map.
Was my assumption right for what happens most of the time on most compilers? Does it matter one way or the other? Where did that # notation come from, is it some sort of standard?
I am using IAR Embedded workbench.
This question is similar to this one: How to place a variable at a given absolute address in memory (with GCC).
It matches what I assumed my compiler was doing anyway.
Although an expression like (unsigned char *)0x1234 will, on many compilers, yield a pointer to hardware address 0x1234, nothing in the standard requires any particular relationship between an integer which is cast to a pointer and the resulting address. The only thing which the standard specifies is that if a particular integer type is at least as large as intptr_t, and casting a pointer to that particular type yields some value, then casting that particular value back to the original pointer type will yield a pointer equivalent to the original.
The IAR compiler offers a non-standard extension which allows the compiler to request that variables be placed at specified hard-coded addresses. This offers some advantages compared to using macros to create pointer expressions. For one thing, it ensures that such variables will be regarded syntactically as variables; while pointer-kludge expressions will generally be interpreted correctly when used in legitimate code, it's possible for illegitimate code which should fail with a compile-time error to compile but produce something other than the desired effect. Further, the IAR syntax defines symbols which are available to the linker and may thus be used within assembly-language modules. By contrast, a .H file which defines pointer-kludge macros will not be usable within an assembly-language module; any hardware which will be used in both C and assembly code will need to have its address specified in two separate places.
The short answer to the question in your title is "differently". What's worse is that compilers from different vendors for the same target processor will use different approaches. This one
volatile unsigned short P3OUT # 0x0222u;
Is a common way to place a variable at a fixed address. But you will also see it used to identify individual bits within a memory mapped location = especially for microcontrollers which have bit-wide instructions like the PIC families.
These are things that the C Standard does not address, and should IMHO, as small embedded microcontrollers will eventually end up being the main market for C (yes, I know the kernel is written in C, but a lot of user-space stuff is moving to C++).
I actually joined the C committee to try and drive for changes in this area, but my sponsorship went away and it's a very expensive hobby.
A similar area is declaring a function to be an ISR.
This document shows one of the approaches we considered
#define _FUID1(x) __attribute__((section("__FUID1.sec"),space(prog))) int _FUID1 = (x);
I am trying to make sense of the about the above define. the _FUID(x) macro. This relates to program memory and has the attribute of the section defining in the code section memory area?
what does the above trying to accomplish?
The macro isn't doing anything interesting or complicated at all; it just outputs a declaration for int _FUID1, with its parameter as an initializer, and with an attributes list ahead of it.
As for what the attributes list means, look at the documentation for variable attributes in GCC. section puts the variable in a named section, which allows the linker to relocate it to a special address or do some other interesting thing to it, and space isn't documented, but space(prog) sounds like a directive to put a value into the program address space instead of the data address space on a Harvard-architecture machine.
I think this is hardware specific (some Microchip unit), it places a value, for example:
__attribute__((section("__FUID1.sec"),space(prog))) int _FUID1 = (0xf1);
into unit id register 1 (__FUID1.sec), in the program flash to configure the hardware. See the pic documentation (for references to FUID) and MPLAB C30 manual (for description of memory spaces).
void __attribute__((__interrupt__, no_auto_psv)) _T1Interrupt(void) // 5 Hz
__attribute__ directive or macro is from GCC but __interrupt__ and no_auto_psv is not , it's specific to a hardware. So, how does GCC Compiler understand __interrupt__ and no_auoto_psv, I searched and didn't find any declaration in anywhere else.
So basically the _T1Interrupt function takes no argument and return nothing but has the above attribute?
In particular, these attributes are platform-specific extensions used in the Microchip XC16 compiler for 16-bit PIC24 and dsPICs.
Attributes are essentially extra information added to the parse tree of a compiler. They exist outside the C language semantics and are there to provide additional information that the compiler uses to act consistently with your expectations. In this case __interrupt__ tells it to treat the function as an ISR (with slightly different function prolog and epilog than a normal function: dsPIC ISRs use the RETFIE return instruction, vs. RETURN for normal functions), and no_auto_psv controls whether the compiler sets the PSVPAG register:
The use of the no_auto_psv attribute omits code that will re-initialize the PSVPAG value to the default for auto psv variables (const or those placed into space auto_psv). If your code does not modify the PSVPAG register either explicitly or using the compiler managed psv or prog qualifiers then the use of no_auto_psv is safe. Also, if your interrupt service routine (or functions called by your interrupt service routine) does not use any const or space auto_psv variables, then it is safe to use no_auto_psv.
(from http://www.microchip.com/forums/m394382.aspx)
The documentation for __attribute__() says:
GCC plugins may provide their own attributes.
So perhaps that's how it's being used in your situation.
What unwind said is true and the attritbutes are defined by the MPLAB extension for gcc. It's been a while since i've worked with microcontrollers so i can't provide more details on this front. However for your specific application (embedded c on pic micro-controller). The above is the proper way of declaring a function that is meant to implement an interrupt subroutine for timer 1. Interrupt subroutines rarely return anything, If you need to capture the value in the register i recommend you use the following structure as a global variable:
typedef struct T1OUT
{
int timer_register_value;
int flag;
} T1InteruptCapture;
The timer_register_value is the value you want out of your subroutine. While the flag value is memory lock that prevents the subroutine from over-writing your previous value. There are different ways of getting values out of your subroutine. I found this to be the easiest and the most time efficient. You can also look into implementing a mini-buffer. I recommend you avoid pointer with embedded C. I don't know if things have changed, in the last couple of years.
edit 1: MPLAB has some of the best documentation i've ever seen. I recommend you have a look at the one for your specific microcontroller. They provide sample code with great explanations.
edit 2: I not sure why you're using gcc. I would recommend you get the pic compiler from MPLAB. I believe it was called C30. and the associated .h file.