Write default values to eeprom - gcc

This is my Setup:
Atmel studio 7.0
avr-gcc
ATmega644PA
I'm trying to write default values to the eeprom. I mean: in code, predefined values at a specific place in the eeprom.
I can use:
__attribute__((section(".eeprom")))
Which works to put the variables in the eeprom, but this links the variables automatic to a location.
I want to manually set the location where the variable is stored. How can I do this?
Thanks!
Ps: this needs to work for >300 variables

You can place all variables in one struct. The variables will be placed in EEPROM in the specified order.
struct {
uint8_t var1;
uint8_t var2;
uint16_t var3;
...
} eeprom_data __attribute__ ((section(".eeprom")));

you may encapsulate your need.
E.g. you may use this ASF API: http://asf.atmel.com/docs/3.22.0/xmegae/html/nvm_8h.html
Then write your default values into the EEPROM plus an identifier that your init routine has already set the default or not.
Pseudo-code:
if defaultWritten == true
myAppDataStruct = readFromEeprom()
else
initEeprom(yourDesiredAddress, myDefaultAppDataStruct)
You then use the myAppDataStruct as the representation of you EEPROM data.
Otherwise, you may use the approach of declaring the variables into the data section ".eeprom" but than the linker will align it for you.

The solution depends whether you want to intialise the EEPROM on programing time or at each startup of the device. I will describe the solution for programming time (It is what I understand from the question).
The __attribute__((section(".eeprom"))) will say to the linker : "put this variable in the .eep output file". The .eep file is a intel hex file format that will be flashed to EEPROM.
If you want to define specific location for your variable you could either generate and flash the .eep file manually or do a complete EEPROM map letting 0xFF for uninitialised values :
__attribute__((section(".eeprom"))) uint8_t eepContent[6] = {0,1,0xFF,3,4,5};
You could also manually define sections but this is only convenient if you want to use whole block of EEPROM memory not located at the beginning.

Related

Declaring a global variable in Linux Kernel and using it through out the device power on

I have multiple boards which were having different screen sizes(4",7",12" etc...). I need this info at multiple places in the Linux Kernel during boot time. We can know the device screen size by reading values on two input lines. I don't want to read every time these lines whenever I want to know the device screen size. I want to read these lines once at the beginning(maybe in the board file) and store it in a global variable. Check this global variable value where ever I need the screen size. Can anyone suggest where I can declare this global variable or any better way for this?
So you've given some thought to your problem and you think a "global" variable in the Linux kernel is the fastest/best solution. Where a "global" variable is a variable that one module defines and initializes and other modules can also read and modify it. You can do that by exporting the symbol with the EXPORT_SYMBOL macro.
As an example, look at this file on lines 54 and 55 the symbol drm_debug is declared as an unsigned int and exported for other driver modules to use. The other modules need to be informed about that symbol's existance before they can use it. In this case, that happens in this header file on line 781. So when another file or module wants to use that symbol, that source file includes the header, and then it just uses the variable as if it were declared in that file. If you don't want to create a header file for your "personal" global variables, you can just add that "extern" as a 1-liner to your global scope declarations for that source code file, and it will have the same effect.
In addition to exporting variables, you can also export functions in the same fashion. If you grep for "EXPORT_SYMBOL" in your kernel most of the hits are going to be functions. When you pass around a variable there is the chance that one module might change it at an inopportune moment when another module might be reading it causing undesired outcomes. I like to think of the function as a "read only" version of a variable, so only one module can change it, but everyone else can see it. Having one module being "responsible" for reading and interpreting the GPIO and then sharing that information with other modules to me seems to fit better with the exported function than with the exported variable.
Lastly, whenever you start sharing symbols in the kernel, you should give thought to the name of the global variable you choose. For example, don't take something that's already taken or likely to be taken.

Can register name be passed into assembly template in GCC inline assembly [duplicate]

I have recently started learning how to use the inline assembly in C Code and came across an interesting feature where you can specify registers for local variables (https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables).
The usage of this feature is as follows:
register int *foo asm ("r12");
Then I started to wonder whether it was possible to insert a char pointer such as
const char d[4] = "r12";
register int *foo asm (d);
but got the error: expected string literal before ā€˜dā€™ (as expected)
I can understand why this would be a bad practice, but is there any possible way to achieve a similar effect where I can use a char pointer to access the register? If not, is there any particular reason why this is not allowed besides the potential security issues?
Additionally, I read this StackOverflow question: String literals: pointer vs. char array
Thank you.
The syntax to initialize the variable would be register char *foo asm ("r12") = d; to point an asm-register variable at a string. You can't use a runtime-variable string as the register name; register choices have to get assembled into machine code at compile time.
If that's what you're trying to do, you're misunderstanding something fundamental about assembly language and/or how ahead-of-time compiled languages compile into machine code. GCC won't make self-modifying code (and even if it wanted to, doing that safely would require redoing register allocation done by the ahead-of-time optimizer), or code that re-JITs itself based on a string.
(The first time I looked at your question, I didn't understand what you were even trying to do, because I was only considering things that are possible. #FelixG's comment was the clue I needed to make sense of the question.)
(Also note that registers aren't indexable; even in asm you can't use a single instruction to read a register number selected by an integer in another register. You could branch on it, or store all the registers in memory and index that like variadic functions do for their incoming register args.)
And if you do want a compile-time constant string literal, just use it with the normal syntax. Use a CPP macro if you want the same string to initialize a char array.

__attribute__((io)), __attribute__((address)) in gcc for AVR don't seem to have any effect

I am trying to use variable attributes specifically provided by AVR flavor of gcc (https://gcc.gnu.org/onlinedocs/gcc/AVR-Variable-Attributes.html#AVR-Variable-Attributes).
The manual says that these special attributes should allow me to force the placement of a variable at the predetermined memory address. They even give an example:
volatile int porta __attribute__((address (0x600)));
But when I compile and debug this code example from the above mentioned document, the variable declared with such attribute is placed into a location in SRAM that compiler and linker determine, not at the address 0x600, as requested. Actually, if I remove the attribute entirely from the declaration, the end result does not change - the variable is placed at the same "whatever" address. Same thing happens when I use "io" and "io_low" attributes instead of "address".
I am using gcc toolchain packaged in the latest version Atmel Studio 7.0.19.31 targeted at 8-bit MCUs (ATMega64).
Hence the question: has anyone tried to use these special AVR-specific attributes with any success?
Important notes:
I am aware that in general to accomplish a placement of a variable at a fixed address in gcc you need to follow a two-step process (using section attribute and then modifying the linker script), but specificially for AVR it seems like these single-step attributes were provided, the question is how to make them work. A two-step process is not an option for me.
I am aware that in general one can always do this:
*(volatile int*)0x600 = your_data_here;
But this is not an option for me either, I need an actual variable declared (because I want to map it onto a bitwise structure to have access to individual bits without explicitly using the masks and logical operations.
So I am really looking for a way to make the provided attributes work, not for a workaround. What am I missing?
typedef struct {
uint8_t rx:4;
uint8_t tx:4;
} Pio_TXRXMUX_t;
#define Pio_TXRXMUX (*(volatile Pio_TXRXMUX_t *)(0x22)) //PORTA on ATMEGA1280

Print addresses of all local variables in C

I want to print the addresses of all the local and global variables which are being used in a function, at different points of execution of a program and store them in a file.
I am trying to use gdb for this same.
The "info local" command prints the values of all local variables. I need something to print the addresses in a similar way. Is there any built in command for it?
Edit 1
I am working on a gcc plugin which generates a points-to graph at compile time.
I want to verify if the graph generated is correct, i.e. if the pointers do actually point to the variables, which the plugin tells they should be pointing to.
We want to validate this points-to information on large programs with over thousands of lines of code. We will be validating this information using a program and not manually. There are several local and global variables in each function, therefore adding printf statements after every line of code is not possible.
There is no built-in command to do this. There is an open feature request in gdb bugzilla to have a way to show the meaning of all the known slots in the current stack frame, but nobody has ever implemented this.
This can be done with a bit of gdb scripting. The simplest way is to use Python to iterate over the Blocks of the selected Frame. Then in each such Block, you can iterate over all the variables, and invoke info addr on the variable.
Note that printing the address with print &var will not always work. A variable does not always have an address -- but, if the variable exists, it will have a location, which is what info addr will show.
One simple way these ideas can differ is if the compiler decides to put the variable into a register. There are more complicated cases as well, though, for example the compiler can put the variable into different spots at different points in the function; or can split a local struct into its constituent parts and move them around.
By default info addr tries to print something vaguely human-readable. You can also ask it to just dump the DWARF location expressions if you need that level of detail.
programmatically ( in C/C++ ) you use the & operator to get the address of a variable (assuming it's not a pointer):
int a; //variable declaration
print("%d", a); //print the value of the variable (as an integer)
print("0x%x", &a); //print the address of the variable (as hex)
The same goes for (gdb), just use &
plus the question has already been answered here (and not only)

memory mapped using linker

How can I force the linker to put some of my variables to specific place in memory. For example I want to allocate integer name in 0x8100000. If I didn't miss understand I can use:
int name __attribute__ ((section ("name_of_section")));
and then in linker scripts:
SECTIONS
{
...
. = 0x8100000;
.data : { name_of_section }
...
}
I want to use something similar for map a uC port.
But something doesn't match and I don't know where I made mistake. (I have never use linker script, so sorry if I wrote something very stupid).
Usually this is done without a linker script.
int volatile * const portA = 0x8100000; //portA is a constant pointer to a volatile int
...
*portA = 53; //write value 53 to output port
If you must use a linker script, it is going to be compiler and/or chip specific. Can you tell us what chip and toolchain you are using?
Thanks for all your advice! Now it's working.
.ld file:
SECTIONS
{
...
.data: {
...
}
...
var_name = 0x40010CA0;
}
.c file:
extern volatile int var_name;
After study docs which I linked above (Input Section Example), I tried also something like that:
.ld file:
.hrd_map 0x40010CA0 :
{
main.o(.b_section)
}
Where .b_section was a global variable with attribute:
int b __attribute__((section(".b_section")));
But it doesn't work, I got this kind of error: multiple definition of `main'.
I think that's because earlier in .ld file I have other asignment like: .data: {...} .bss .text.
Maybe someone know how to fix this, or how to get to some variables without using section attribute. I tried to look for symbols to variables in main.o file but I didn't see anything looking like symbol name for variable, except .b_section that I have created using section attribute and other (created by default? ) .data .bss .text etc.
#Dan You are right I am doing this for learning, and I agree with you. But on the other hand I think that this code will be quite portable beacuse every chip require .ld and Startup file and the definition of ports are also included in libraries.
I recommend NOT using the linker for access to hardware registers. Your code will be much easier to understand and maintain if you explicitly code the addresses. It is a good idea to gather all device-specific register information in an include file. For complex peripherals it is usually a good idea to typedef a structure for the register block associated with a peripheral, especially when the device supports several instances of a particular peripheral. Then use the technique from Luke's answer to get at the register or register block in your code. And the volatile keyword should always be used when accessing hardware registers.

Resources