Storing data on program memory

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello everyone,

I want to store program version (four bytes) in a static place inside program memory, i.e., in a specific absolute address.
I use "section" attribute to store this in a section at the program's end. However, the program's end isn't static at compile time (varies with program size).

I'm using AT90CAN128 mmcu.

Any ideas? Can I use interrupt vector space somehow?

Thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Look in the tutorials section for the tutorial on the PROGMEM attribute.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

PROGMEM is not static at "programming time". If I only declare a variable as PROGMEM, the final position of this data after compilation will depend of previous PROGMEM declarations. I need to store data in program memory AND in a specific absolute address, an address determined beforehand, not after compilation.
Thanks anyway.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

giusepe wrote:
Hello everyone,

I want to store program version (four bytes) in a static place inside program memory, i.e., in a specific absolute address.
I use "section" attribute to store this in a section at the program's end. However, the program's end isn't static at compile time (varies with program size).

There is a linker option that will put a section where you want it.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A search on "variable specific address" in the avr-gcc forum might give some.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
giusepe wrote:
Hello everyone,

I want to store program version (four bytes) in a static place inside program memory, i.e., in a specific absolute address.
I use "section" attribute to store this in a section at the program's end. However, the program's end isn't static at compile time (varies with program size).

There is a linker option that will put a section where you want it.

Yes, there is. However, the ".text" section, where all the program code is, starts at address 0, and cannot be moved to other position. So if I define a section, this should be after the program's end, and again, this is not a static position before compilation, because it depends on program's length.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Searching for "variable specific address" in avr-gcc forum:
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...

Searching for "data specific address FLASH":
https://www.avrfreaks.net/index.p...
https://www.avrfreaks.net/index.p...

Does any of those help?
Other search terms are thinkable that could yield more.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Put it at the very end. In the example below its at the end of flash, but I assume you will want it at the end of the application section instead (I would assume a bootloader in use, otherwise probably no point in making it an absolute address).

uint32_t pgm_version __attribute__((section(".version"))) = 0x12345678;
-Wl,-section-start=.version=0x1fffc 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using a external device (not a PC) who reads the version from program memory. The problem is that this device doesn't know the program length, so the version should be in a specific position to be found.
My program occupies ~32k, using bootloader will enlarge the program size up to ~64k, and I was looking for some alternative, because the update will be done via packets, and while more length has the sw, more messages and more time will need for update.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Read up on linker scripts. Create a section for this immovable data. Use a custom linker script to place it where you want it. Placing the section just before the beginning of the bootloader might be a good spot for it. That way it will be well out of the way of the program as it grows, and it will not interfere with the bootloader. Probably what you want to do is tweak the PROGMEM macros to reference this new section name.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

giusepe wrote:
skeeve wrote:
giusepe wrote:
Hello everyone,

I want to store program version (four bytes) in a static place inside program memory, i.e., in a specific absolute address.
I use "section" attribute to store this in a section at the program's end. However, the program's end isn't static at compile time (varies with program size).

There is a linker option that will put a section where you want it.

Yes, there is. However, the ".text" section, where all the program code is, starts at address 0, and cannot be moved to other position. So if I define a section, this should be after the program's end, and again, this is not a static position before compilation, because it depends on program's length.
What part of "where you want it" don't you understand?

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

skeeve wrote:
giusepe wrote:
skeeve wrote:
giusepe wrote:
Hello everyone,

I want to store program version (four bytes) in a static place inside program memory, i.e., in a specific absolute address.
I use "section" attribute to store this in a section at the program's end. However, the program's end isn't static at compile time (varies with program size).

There is a linker option that will put a section where you want it.

Yes, there is. However, the ".text" section, where all the program code is, starts at address 0, and cannot be moved to other position. So if I define a section, this should be after the program's end, and again, this is not a static position before compilation, because it depends on program's length.
What part of "where you want it" don't you understand?

Mmmm... maybe there is something that I can't understand. The ".text" section start at address 0, right? Then, I cannot declare a section between address 0 and the program' end, isn't it? At least, the linker throws an error. Also, the ".text" section cannot be moved, because this section includes the interrupt vector. As I understand, the section must be after the ".text" section, not where I want. What do you propose?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The ".text" section start at address 0, right? Then, I cannot declare a section between address 0 and the program' end, isn't it?
Is it possible to shorten the .text section maybe? And then place your fixed section at the end of FLASH (or at the end of the non-bootloader FLASH if youre using a bootloader)?

Quote:

not where I want

As I understood it your requirement was for a fixed place, in general. Do you have exact demands on the specific address of this fixed section?

Quote:

the linker throws an error

I confess up-front that I have not dibbled with these things myself, but I have read thee earlier threads on this subject. As I understand it it is not enough just to introduce a new section in the code and as an option on the compile/link command line. You also have to fiddle with the "linker script". Did you read the threads I linked to above? IIRC at least one of them delves into the linker script fiddling.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, I read them, thanks Johan. The main problem is that I need to know where in the program space is the version of the software and, if the software changes, the version must stay at the same position, because an external device reads the sw version from at90. The ".text" section cannot be moved, it contains the interrupt vector. A new section must begin after the ".text" section. If the next software version grows n bytes, ".text" will grow and my section will be displaced n bytes in program space. The version won't be at the same place that was before when the external device attempt to read it.
The use of bootloader is a possible solution. However, by the way that the at90 sw update will be done, this scheme delays the update time too much, and I was looking for some alterative. For example, store the version in an unused interrupt jump.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

The version won't be at the same place that was before when the external device attempt to read it.

But, but, but...? As I read some of those posts you can place a section at an absolute address, regardless of where .text ends (as long as they don't overlap of-course).

Eg, clawson wrote

Quote:
simply put the data into a named section and use --section-start to the linker to position it at the very top of code flash

And in the last thread I linked to Galiya does something similar (he has problems accessing the data from his AVR code, but as I read it that is because he does not use LPM instructions, or in C xxx_P access functions).

What did you read out of those threads?

(I'm participating in this thread for two or three reasons: i) Its fun and interesting, ii) I might learn something, and iii) I like the dynamics of these discussions. I have never used the technique myself, and nor am I likely to ever need it. I might try it out just for fun another time...)

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

giusepe,

I don't get it - in what way is Curt's post not EXACTLY what you are looking for here?

You use attribute to place a variable in a named section and then the --section-start option in your LDFLAGS to position it to an absolute address (last few bytes of flash space, well away from the rest of the program, being the obvious position)

BTW how can an external device read this positioned test anyway? Are you suggesting it's going to read it using ISP or JTAG or something?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

giusepe wrote:
skeeve wrote:
...What part of "where you want it" don't you understand?

Mmmm... maybe there is something that I can't understand. The ".text" section start at address 0, right? Then, I cannot declare a section between address 0 and the program' end, isn't it? At least, the linker throws an error. Also, the ".text" section cannot be moved, because this section includes the interrupt vector. As I understand, the section must be after the ".text" section, not where I want. What do you propose?
Unless you want your data in the middle of the .text section,
I don't see the problem.
Putting it at the end of flash should do the trick
until you fill the flash with code.
If you only use 90% of your flash,
you will have more options.
You don't need to edit the linker script.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

until you fill the flash with code

And when that happends, there is no room for the version information anywhere anyhow so then the discussion becomes theoretically academic.

Quote:
I don't get it - in what way is Curt's post not EXACTLY what you are looking for here?

Just in case anyone finds my latest posts confusing: I actually missed Curts post when re-browsing the thread.. So a reference to earlier threads on the subject was an overkill...

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

*sigh*

I should probably put this into a sub-tutorial someplace.

I'm placing the length of my code at the location immediately after the interrupt vectors. It is trivial to change this to placing the program version there. The following has been hacked from my current setup, but should work.

This procedure will entail two things: defining a new memory section, and hacking the linker script so that your section is placed where you want.

We're going to call the new section "progver". In your main code file, place the following:

const uint32_t ProgramVersion __attribute__ ((section (".progver"))) = 0xAA55;

Where 0xAA55 is your code version.

Next, find the architecture type for your processor. I was using an ATmega2560, which is architecture avr6. Let's assume you're doing the same thing. Go to \avr\lib\ldscripts and find your script (in my case, avr6.x). Copy this file to your project directory and rename it linker_script.x

Edit the script and place the definition for the .progver section after the .vectors section:

. . .
  /* Internal text space or external memory.  */
  .text :
  {
    *(.vectors)
    KEEP(*(.vectors))
    *(.progver)
    KEEP(*(.progver))
    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    *(.progmem*)
    . = ALIGN(2);
. . .

Notice that the placement of .progver will cause the section to be placed after the interrupt vectors but before the PROGMEM constants.

WARNING! If your section is not a multiple of 2 bytes long, be sure to put another ". = ALIGN(2);" line after your "KEEP(*(.progver))" line!!

Change your makefile to had the linker point at the modified linker script instead of the generic one. The following makefile was generated from the WinAVR Mfile template, a highly recommmended practice:

#---------------- Linker Options ----------------
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to  map file
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
. . .
LDFLAGS += -T linker_script.x

Now compile your code. Check your map file - your new section should be immediately after the interrupt vectors. In my case, that section is called ".length" and is located at location 0xE4:

.text           0x00000000    0x2254a
 *(.vectors)
 .vectors       0x00000000       0xe4 c:/winavr/.../avr6/crtm2560.o
                0x00000000                __vectors
                0x00000000                __vector_default
 *(.vectors)
 *(.length)
 .length        0x000000e4        0x4 obj/MPB.o
                0x000000e4                ProgramLength
 *(.progmem.gcc*)
 .progmem.gcc_sw_table
                0x000000e8       0x68 obj/CmdTrack.o

Hope this helps!

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes! That will work, thank you all.

About the problem of setting the version after ".text":
Sorry for my explanations, I have problems with English.
- I have a sw installed on at90
- I need to know his version
- The sw occupies 32k. Suppose that I put the version at 64k, and leave enough space for enlarge program.
- The sw update is done with CAN bus messages, containing binary data.
- When I send the binay for update, I must send messages for 64k, instead of 32k (real program size), to save the version at the position 64k. This slow down the update process too much for my system. That's why I don't want to save the version so far in program space, to avoid send unnecesary messages.
I know that several solutions can be implemented to avoid send 64k, however, these solutions were error prone, and the system must be very robust.

Again, thanks for your help and patience.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stu_san wrote:
Edit the script and place the definition for the .progver section after the .vectors section:
. . .
  /* Internal text space or external memory.  */
  .text :
  {
    *(.vectors)
    KEEP(*(.vectors))
    *(.progver)
    KEEP(*(.progver))
    /* For data that needs to reside in the lower 64k of progmem.  */
    *(.progmem.gcc*)
    *(.progmem*)
    . = ALIGN(2);
. . .

Notice that the placement of .progver will cause the section to be placed after the interrupt vectors but before the PROGMEM constants.

WARNING! If your section is not a multiple of 2 bytes long, be sure to put another ". = ALIGN(2);" line after your "KEEP(*(.progver))" line!!

Are the *(.progmem.gcc*) sections normally empty?
Could a section named "$.progmem.gcc.progver"
be used without changing the linker script?

Also, given a 32K program, a section at 33K should
give one enough slack without too much inefficiency.

BTW where do .hash, .dynsym, etc. at the beginning of SECTIONS end up?
As I might have already proved,
my knowledge of linker scripts is a bit sporadic.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles