5 years, 11 months ago.

Flash read/write with nucleo STM32L432, Bluepill or Blackpill

I need small logging functionality (about 4-8k) and do not like to use additional hardware (EEPROM or SDCard). I am aware of the limitted write count of flash, pls. do not discuss this point. I can't found any working sample for writing into flash. A simple function for writing/reading a byte,word or halfword is all I need. Any help? Thank's a lot

1 Answer

5 years, 11 months ago.

Hello Franz,

This page might help.

Hi Zoltan Thanks for your answer. I tried the solution on https://developer.mbed.org/users/olympux/code/eeprom_flash/. This solution seems to work with my board STM32F103. But here there is unresolved reference FLASH_PageErase(...) at line 25. Where is this funktion defined. I think I can't ignore PageErase. I also tried the Solution with the Stm Library. This library includes STM32F4xx.h. Here I don't know the corresponding & working h files for my boards (STM32L432 & STM32F103). The mbed standard lib do not include such basic flash functions ???

posted by Franz Ziegler 29 May 2018

It seems that MBED has changed since then. The FLASH_PageErase function is defined in the stm32f1xx_hal_flash_ex.c (resp. stm32l4xx_hal_flash_ex.c) file. To make the library compile add the following declaration to the EEPROM_Flash.h file:

void FLASH_PageErase(uint32_t PageAddress);
posted by Zoltan Hudak 30 May 2018

Hello Zoltan. Thanks for your answer. I inserted your proposed declaration into EEPROM_Flash.h. If I use Blue- or BlackPill boards as "F103RB" I get the following Error:

Error: Undefined symbol FLASH_PageErase(unsigned) (referred from /build/eeprom_flash/eeprom_flash.NUCLEO_F103RB.o).

If I use STM32L432 Board I get the following 2 errors: Error: Identifier "FLASH_TYPEPROGRAM_HALFWORD" is undefined in "eeprom_flash/eeprom_flash.cpp", Line: 41, Col: 33 Error: Identifier "FLASH_TYPEPROGRAM_WORD" is undefined in "eeprom_flash/eeprom_flash.cpp", Line: 50, Col: 33

I think I have no access to this object files from mbed online do I ? Did I reach my personal limit, or the limit of online mbed now ? What's the version number of online mbed. Does it correspond to the newest "mbed" libs? Is there a chance to use mbed with teensy 3.6 or can I use mbed for a STM32F405 (flight controller boards) in the future ? Actually I am testing chess programs and I am looking for smallest boards highest performance. Thanks a lot for any tips. Franz Ziegler

posted by Franz Ziegler 30 May 2018

So far I compiled offline. Sorry for that. Only the exported functions are availale when compiling online. That's why rather than using the FLASH_PageErase function we have to try the HAL_FLASHEx_Erase. That requires to define some additional variables. So we keep the eeprom_flash.h unchanged and rather modify the eeprom_flash.cpp as follows:

eeprom_flash.cpp

//...
FLASH_EraseInitTypeDef eraseInit = {
    FLASH_TYPEERASE_PAGES,  /*!< Pages erase only (Mass erase is disabled)*/
    0,                      /*!< Select banks to erase when Mass erase is enabled.*/
    EEPROM_START_ADDRESS,   /*!< Initial FLASH page address to erase when mass erase is disabled
                                 This parameter must be a number between Min_Data = 0x08000000 and Max_Data = FLASH_BANKx_END 
                                 (x = 1 or 2 depending on devices)*/
    1                       /*!< Number of pagess to be erased.
                                 This parameter must be a value between Min_Data = 1 and Max_Data = (max number of pages - value of initial page)*/
};

uint32_t pageError;
 
/*
 * Must call this first to enable writing
 */
void enableEEPROMWriting() {
    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
    //FLASH_PageErase(EEPROM_START_ADDRESS); // required to re-write
    //CLEAR_BIT(FLASH->CR, FLASH_CR_PER); // Bug fix: bit PER has been set in Flash_PageErase(), must clear it here
    HAL_FLASHEx_Erase(&eraseInit, &pageError);
}
//...
posted by Zoltan Hudak 31 May 2018

Hello Zoltan

Great ! It works on STM32F103C8T6. I'll test it later on STM32L432 also. My actual work: I am testing a chess program through different architectures and compilers starting from AVR ATTINY85 (8KB Flash) ATMEGA328 with gcc, STM32F103, STM32L432 on mbed, STM32F405 and Teensy 3.6 (180MHz) on arduino IDE or mbed (???).

By the way, I tested mbed online compiler for it's interrupt performance: with STM32f103 (72MHz) I got a maximum of 36000 interrupts per second, with STM32L432 (80MHz, zero wait states) I got 60000 tick interrupts per second max. Comparison: ATTiny85 (20MHz) with assembly you get > 1 000 000. I'll do the same test for avr-gcc later.

Thank's a lot for your help !!!!!!!!!!!

posted by Franz Ziegler 31 May 2018

Hello Zoltan, I testet writing flash with Nucleo STM32L432 now. Can't I do it with the same procedures (The idee of HAL) ? I got the following two error messages:

Error: Identifier "FLASH_TYPEPROGRAM_HALFWORD" is undefined in "eeprom_flash.cpp", Line: 52, Col: 33 Error: Identifier "FLASH_TYPEPROGRAM_WORD" is undefined in "eeprom_flash.cpp", Line: 61, Col: 33

I could not find out where "FLASH_TYPEPROGRAM_....." is defined...

Thanks for any help Franz Ziegler

posted by Franz Ziegler 01 Jun 2018

Hello Fanz,

Sounds like a very interesting test. And it's quite shocking for me to learn that STM32 is not even close to an ATTiny in that regards!

After checking the stm32l4xx_hal_flash.c file it seems that STM32L4xx supports only FLASH_TYPEPROGRAM_DOUBLEWORD type for programming. So when compiling for the STM32L432 I would suggest to modify the library as follows:

eeprom_flash.h

//...
// Write functions
//HAL_StatusTypeDef writeEEPROMHalfWord(uint32_t address, uint16_t data);
//HAL_StatusTypeDef writeEEPROMWord(uint32_t address, uint32_t data);
HAL_StatusTypeDef writeEEPROMDoubleWord(uint32_t address, uint64_t data);
 //...

eeprom_flash.cpp

//...
/*
 * Writing functions
 * Must call enableEEPROMWriting() first
 */
//HAL_StatusTypeDef writeEEPROMHalfWord(uint32_t address, uint16_t data) {
//    HAL_StatusTypeDef status;
//    address = address + EEPROM_START_ADDRESS;
    
//    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, data);
    
//    return status;
//}
 
//HAL_StatusTypeDef writeEEPROMWord(uint32_t address, uint32_t data) {
//    HAL_StatusTypeDef status;
//    address = address + EEPROM_START_ADDRESS;
    
//    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
 
//    return status;
//}
 
HAL_StatusTypeDef writeEEPROMDoubleWord(uint32_t address, uint64_t data) {
    HAL_StatusTypeDef status;
    address = address + EEPROM_START_ADDRESS;
    
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
 
    return status;
}
//...

I'm not sure about the reading functions. So let's keep them unchanged and see how everything works.

posted by Zoltan Hudak 01 Jun 2018

Hello Zoltan Thank you for your help. I am approaching writing flash also on STM32L432 small step by small step.... Your last tip for writing flash on Nucleo STM32L432 seems to be a partial success only: Two problems:

A) First time touched flash (containing 0xffff....) can be written with your method "writeEEPROMDoubleWord". But any bit written to "0" can't be changed anymore. That means that the flash erase does not work correctly. I tried it with different EEPROM start addresses. May be something is wrong with the initialisation of the flash erase. I used the same method "enableEEPROMWriting()" as on STM32F103 boards with Parameters:

FLASH_EraseInitTypeDef eraseInit = { FLASH_TYPEERASE_PAGES, /*!< Pages erase only (Mass erase is disabled)*/ 0, /*!< Select banks to erase when Mass erase is enabled.*/ EEPROM_START_ADDRESS, /*!< Initial FLASH page address to erase when mass erase is disabled This parameter must be a number between Min_Data = 0x08000000 and Max_Data = FLASH_BANKx_END (x = 1 or 2 depending on devices)*/ 1 /*!< Number of pagess to be erased. This parameter must be a value between Min_Data = 1 and Max_Data = (max number of pages - value of initial page)*/ };

B) The first DoubeWord written to flash (after calling enableEEPROMWriting) always fails, leaving the bytes unchanged: 0xFFF.... I was using the correct flash address boundaries (multiples of 8, starting with 0).

Do we need another set of flash erase params or another flash erase method ?

Thank you for any help Franz

posted by Franz Ziegler 03 Jun 2018