• AVR Freaks

AnsweredHot!Place constant at specific location in flash

Author
Vincent44
Starting Member
  • Total Posts : 47
  • Reward points : 0
  • Joined: 2014/09/19 03:41:47
  • Location: France
  • Status: offline
2020/07/07 00:38:01 (permalink)
0

Place constant at specific location in flash

Hi,
 
I need to store a constant value at a specific location in flash.
The idea is that the bootloader can read this location, to know what is the current firmware version.
Ideally, I also need to be able to read this value directly from the .hex file. Therefore, I don't want the APP to write it in flash at runtime.

I started with the following declaration:
static const uint16_t TEST_VERSION __attribute__ ((space(prog),address(0x9D016000))) = 36 ;

 
To read the value, I simply go with :
uint16_t tmpUint16;
uint16_t * ptr ;
ptr = (void *) 0x9D016000 ;
tmpUint16 = (uint16_t) *ptr ;


As seen from several posts in the forum, I tried with/without const, static, volatile.
Also tried some other attributes, but it made no difference
- used: seem to only be made for functions, not for variables/constants
- optimize(-O0) : ignored by compiler
- Tried several flash address, in case there was some specific restrictions for some addresses
 

Keeping the default settings of my project, this does not work : I the value is always read as 0xFF.
Reading the flash and checking at 0x9D016000, confirms this.
The compiler seem to automatically remove this constant from the program, as it is not used. Setting code optimisation to 0 does not help.

With optimization 1 and unchecking the "remove unused section" parameter in xc32-ld, I am able to read my constant.
However, this will significantly change the program size, from 70kB to 80kO ... which is quite a lot to just add a 16 bit variable !
Attachments are not available: Download requirements not met
Is there a simple way to achieve my goal ?
 
Thanks.
post edited by Vincent44 - 2020/07/07 00:40:37

Attachment(s)

Attachments are not available: Download requirements not met
#1
andersm
Super Member
  • Total Posts : 2839
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: Place constant at specific location in flash 2020/07/07 05:00:34 (permalink)
0
To read the value, even simpler go with :
uint16_t tmpUint16 = TEST_VERSION;

Now the linker knows the constant is used, and won't remove it. If you insist on pointer tricks, add the "used" attribute to the definition.
#2
aschen0866
Super Member
  • Total Posts : 4587
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: Place constant at specific location in flash 2020/07/07 07:38:04 (permalink)
0
You can also try removing the static storage specifier. I'll add the volatile qualifier to be on the safe side.

const volatile uint16_t TEST_VERSION __attribute__ ((space(prog),address(0x9D016000))) = 36;

and the .map says:

_089006605f04873a
0x9d016000 0x2
_089006605f04873a
0x9d016000 0x2 build/default/production/main.o
0x9d016000 TEST_VERSION

#3
Vincent44
Starting Member
  • Total Posts : 47
  • Reward points : 0
  • Joined: 2014/09/19 03:41:47
  • Location: France
  • Status: offline
Re: Place constant at specific location in flash 2020/07/08 00:14:54 (permalink)
0
Thanks for the replies.
 
andersm, I need to read from my bootloader, that's why I need to use a pointer to the specific flash address.
aschen0886, as much as possible, I tried to not modify the linker, as it's not something I am verify confident.
 
After a lot of tests, I manage to acheive my goal, using all the following attributes :
 
static const uint8_t FIRMWARE_VERSION [2] __attribute__ ((keep, used, space(prog),address(0x9D016000))) = {1, 0} ; // v1.0

Note that I changed my variable type from uint16 to uint8[2], to better match my project.
#4
rjc101
Super Member
  • Total Posts : 133
  • Reward points : 0
  • Joined: 2016/07/08 14:56:34
  • Location: 0
  • Status: offline
Re: Place constant at specific location in flash 2020/07/08 02:48:17 (permalink) ☼ Best Answerby Vincent44 2020/07/20 00:05:24
0
I use this to read the bootloader firmware version, so just swap the elements around between the two.  Naturally you'll need to pick an address within the confines your app.
In the main app
 
#define BOOTLOAD_VERSION_ADDRESS 0x9D1FFFF8
const uint32_t *aBLVersion = (uint32_t *) BOOTLOAD_VERSION_ADDRESS;

 
Then in the bootloader
#define BOOTLOAD_VERSION_ADDRESS 0x9D1FFFF8
const volatile uint32_t __attribute__( (space( prog ), keep, address( BOOTLOAD_VERSION_ADDRESS )) ) afwVersion = FW_VERSION;

I guess you would just do this the other way around.
 
I use a single uint32_t and split it up for major, minor, and patch - just seemed easier to me that way.
#define FW_MAJOR_VERSION 1
#define FW_MINOR_VERSION 0
#define FW_PATCH_VERSION 1
#define FW_VERSION_STR "1.0.1"
#define FW_VERSION ((FW_MAJOR_VERSION << 16) + (FW_MINOR_VERSION << 8) + FW_PATCH_VERSION)

#5
Jump to:
© 2020 APG vNext Commercial Version 4.5