cancel
Showing results for 
Search instead for 
Did you mean: 

Storing variables to non-volatile flash on STM32L432KCU?

BNeub.1
Associate II

I have a routine that self-calibrates a system and returns two uint16_t values that I need to write into non-volatile memory and read at bootup.

The values will only be written once during production so write time isn't important. And it needs to be possible to overwrite (erase then write) them if hardware is swapped out.

I'm fairly beginner/intermediate on the software part but I understand I need to emulate some flash as EEPROM and erase full pages before writing again. I'm not entirely sure how to figure out what addresses are safe to use.

Could anyone point me to a tutorial or provide some example code? Currently using HAL libraries and generating the project from STM32CubeMX. I have not implemented any "middleware" yet which is mostly what I'm stuck at so any help finding the files and moving the correct ones into my correct project directories would be super helpful.

TIA

9 REPLIES 9

I wouldn't bother with EEPROM Emulation in this case.

Use the last page/sector in FLASH to store a structure, tell the linker/tools you have 2KB less available space.

HAL_FLASHEx_Erase() to erase

HAL_FLASH_Program() to program 64-bits at a time.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thank you!

Pardon the silly question but are there docs somewhere for those functions so I can see how to use them?

The STM32L4 reference manual shows this for main memory addresses:

0x0800 000 - 0x0800 07FF (2k) Page 0

...

0x0801 F800 - 0x0801 FFFF (2k) Page 127

So if I set it up for the linker/toolchain to use 254k, the last page (127) is free to manipulate?

berendi
Principal

HAL functions are barely documented. You either find an example that does more or less what you want or you are on your own.

The FLASH chapter in the reference manual explains the procedures to erase and write flash without HAL.

> So if I set it up for the linker/toolchain to use 254k, the last page (127) is free to manipulate?

Yes. There should be a line like this in the linker script

FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 256K

decrease LENGTH by 2 and the linker will keep its hands off the last page.

TDK
Guru

The best source for documentation of the HAL functions is in the source files themselves (IMO). I think they're decently documented. Some issues here and there. Opinions vary, as always.

                     ##### How to use this driver #####
  ==============================================================================
    [..]                             
      This driver provides functions and macros to configure and program the FLASH 
      memory of all STM32F4xx devices.
    
      (#) FLASH Memory IO Programming functions: 
           (++) Lock and Unlock the FLASH interface using HAL_FLASH_Unlock() and 
                HAL_FLASH_Lock() functions
           (++) Program functions: byte, half word, word and double word
           (++) There Two modes of programming :
            (+++) Polling mode using HAL_FLASH_Program() function
            (+++) Interrupt mode using HAL_FLASH_Program_IT() function
 
...
 
/**
  * @brief  Program byte, halfword, word or double word at a specified address
  * @param  TypeProgram  Indicate the way to program at a specified address.
  *                           This parameter can be a value of @ref FLASH_Type_Program
  * @param  Address  specifies the address to be programmed.
  * @param  Data specifies the data to be programmed
  * 
  * @retval HAL_StatusTypeDef HAL Status
  */
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
{
 
...

If you feel a post has answered your question, please click "Accept as Solution".

The API itself provides source, and usage info, this is in addition to an assortment of board/chip specific examples.

STM32Cube_FW_L4_V1.14.0\Projects\NUCLEO-L432KC\Examples\FLASH\FLASH_EraseProgram\Src\main.c

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thank you for the example as it demonstrates some serious issues in what they call documentation for HAL.

This is actually for the F4 series, and I do not think that it can program doublewords on stock ST boards as the description suggests. The voltage requirements are documented somewhere down in the middle of the file, where users of the public interface are not likely to look. So the user is never warned that programming dwords would fail, and there will be some nasty surprises e.g. when programming 32 bit words with Vdd just below 2.7V.

It works when it is called exactly the same way as in the example projects and running on a stock board. Good enough for a prototype, worse than nothing for real projects, because it supports false assumptions that can lead to expensive field repairs of bricked equipment.

TDK
Guru

> This is actually for the F4 series, and I do not think that it can program doublewords on stock ST boards as the description suggests.

I linked code for the F4 but the L4 is similar.

I'm not saying there are no issues with HAL. There are issues. Especially with the more complicated peripherals. But there is also a lot of misinformation spread around.

> there will be some nasty surprises e.g. when programming 32 bit words with Vdd just below 2.7V.

There may be surprises, but it says right in the function description what the valid voltage range is. Same for double word programs.

/**
  * @brief  Program word (32-bit) at a specified address.
  * @note   This function must be used when the device voltage range is from
  *         2.7V to 3.6V.
  *
  * @note   If an erase and a program operations are requested simultaneously,    
  *         the erase operation is performed before the program one.
  *  
  * @param  Address specifies the address to be programmed.
  * @param  Data specifies the data to be programmed.
  * @retval None
  */
static void FLASH_Program_Word(uint32_t Address, uint32_t Data)
{
  /* Check the parameters */
  assert_param(IS_FLASH_ADDRESS(Address));
  
  /* If the previous operation is completed, proceed to program the new data */
  CLEAR_BIT(FLASH->CR, FLASH_CR_PSIZE);
  FLASH->CR |= FLASH_PSIZE_WORD;
  FLASH->CR |= FLASH_CR_PG;
 
  *(__IO uint32_t*)Address = Data;
}

If you feel a post has answered your question, please click "Accept as Solution".

No. It is in the description of a static function, i.e. one that can not be called directly from the user program, so users of the actual public function that can be called are not likely to find it.

Thanks for this. I'm searching for the linker script but I'm not certain where to find it. I'm using IAR EWARM and everything just worked after install.

In stml432xx.h there are these lines:

/** @addtogroup Peripheral_memory_map
  * @{
  */
#define FLASH_BASE            (0x08000000UL) /*!< FLASH(up to 256 KB) base address */
#define FLASH_END             (0x0803FFFFUL) /*!< FLASH END address                */
#define FLASH_BANK1_END       (0x0803FFFFUL) /*!< FLASH END address of bank1       */
#define SRAM1_BASE            (0x20000000UL) /*!< SRAM1(up to 48 KB) base address  */
#define SRAM2_BASE            (0x10000000UL) /*!< SRAM2(16 KB) base address */
#define PERIPH_BASE           (0x40000000UL) /*!< Peripheral base address */
#define QSPI_BASE             (0x90000000UL) /*!< QUADSPI memories accessible over AHB base address */

Is modifying FLASH_END correct? I'm guessing no but I don't see that address anywhere else in the project files.