2

I've been using the LPC8xx range of Cortex-M0+ MCUs quite successfully. One difficiency: these don't have inbuilt EEPROM (to preserve settings across power cycles etc). However there is a work-around: using the in-application flash programmer, a page (64 bytes) of flash memory can be erased and rewritten.

I used this example: http://www.lpcware.com/content/forum/eeprom-emulation which works.

My question: this example hard-codes the address of flash to which it will to write to. This seems very dangerous to me. Is there a way to allocate a 64byte aligned block of 64bytes in the flash memory space so that I can be sure it's safe to write to?

(I'm using LPCXpresso / GCC)

jdesbonnet
  • 393
  • 1
  • 3
  • 12
  • Thanks for your help with this. I've written a demo for the LPC812 (which should work with all LPC8xx devices) and a blog post based on what I learned here: http://jdesbonnet.blogspot.ie/2015/02/nxp-lpc8xx-eeprom-emulation.html – jdesbonnet Feb 18 '15 at 16:25

2 Answers2

1

Just exclude the top page of flash from the available program memory in your linker map, and building should fail with an error at the link stage if program code overflows into it. You can if you want create a data section in the reserved page and use a pragma to put a data structure there, if you want to hard code the address only in the linker map and nowhere else.

Of course if you contemplate upgrading or downgrading to a part with a different flash size you will have to move it.

Another possibility could be to use the 2nd lowest flash page - you probably need the lowest for an entry point (and possibly the vector table, if that is inflexible?) But that could be one linker section, then a gap for a data page, and then another linker section for ordinary program code extending to the limit of what the current chip has.

Beware default uploads may wipe out your storage by starting with a full-flash erase.

Chris Stratton
  • 33,282
  • 3
  • 43
  • 89
1

You could declare a const array, that the compiler should allocate to Flash, and use compiler constraints to force it to a 64-byte boundary. In GCC, this would be:

const char flashpage[64] __attribute__ ((aligned (64)));

Note that the syntax may vary by compiler.

The compiler will then recognise that symbol anywhere else that it normally would, and you can use flashpage as a pointer to the location (because of course flashpage is just a const char *).

Note that one thing that this doesn't do is guarantee that the object will be at the same location across multiple builds. That probably doesn't matter, because the entire Flash is usually erased each time you reprogram the MCU, but depending on the specifics of your implementation it might.

markt
  • 4,936
  • 2
  • 15
  • 13
  • I just did a quick test and found (using an STM32F4 Disco, Coocox, GCC) that if I don't set an initial value for the array then it assigns it to RAM, but if I do set an initial value then it assigns it to Flash. – markt Feb 10 '15 at 03:51
  • In practice, this won't work - they need an entire erase-unit-page if they want to be able to rewrite it at runtime without taking extroardinary measures to preserve surrounding program code. – Chris Stratton Feb 10 '15 at 04:53
  • @ChrisStratton That's hair-splitting. Just allocate a larger space. – markt Feb 10 '15 at 07:48
  • Thanks, I implemented this and it seems to be working nicely. As markt pointed out I found I needed to assign a constant to it in order to have it allocated in flash space (else it went into RAM). Also re @ChrisStratton observation: one of the LPC8xx features is to be able to read/write 64 byte chunks of flash – jdesbonnet Feb 10 '15 at 13:21
  • @markt thanks for that tip. I have follow on question in relation to that suggestion. The memory layout of this space will be defined by a struct. I would like to initialize with default values. I could manually serialize the default values struct into bytes and use `= {123,23,433....};` but I'd prefer to somehow use the struct to make the code more readable and maintainable. I can't find any way of doing this. Seems arrays can be initialized only by a string literal or sequence of number literals in curly brackets. Any suggestions? – jdesbonnet Feb 10 '15 at 17:57
  • I came up with a solution: use the struct instead of byte array to allocate space in flash. However that will require careful crafting of the stuct to be 64 bytes long. I found away around that: not to use the struct directly but wrap it in a union with a 64 byte array to ensure that 64 bytes are allocated. I think this should be fine as long as my struct does not exceed 64 bytes. – jdesbonnet Feb 10 '15 at 18:47
  • @jdesbonnet Using a struct inside a union is what I would have done as well. Depending on the contents of the struct, you may also need to use the __attribute__((packed)) qualifier. – markt Feb 10 '15 at 21:54