6 years, 3 months ago.

How best to work with flash memory on stm32f767zi?

Have a good day! I have something problem with flash_api.h file. In my project i want to write calibration values to memory. I opened repasitory on github and find flash_api. But erase,programn and read function doesn't work. May be you can answer, why this functions doesn't work. A fragment of the header file and the test code is presented below.

Thanks :3

include the mbed library with this snippet

int32_t flash_init(flash_t *obj);

/** Uninitialize the flash peripheral and the flash_t object
 *
 * @param obj The flash object
 * @return 0 for success, -1 for error
 */
int32_t flash_free(flash_t *obj);

/** Erase one sector starting at defined address
 *
 * The address should be at sector boundary. This function does not do any check for address alignments
 * @param obj The flash object
 * @param address The sector starting address
 * @return 0 for success, -1 for error
 */
int32_t flash_erase_sector(flash_t *obj, uint32_t address);

/** Read data starting at defined address
 *
 * This function has a WEAK implementation using memcpy for backwards compatibility.
 * @param obj The flash object
 * @param address Address to begin reading from
 * @param data The buffer to read data into
 * @param size The number of bytes to read
 * @return 0 for success, -1 for error
 */
int32_t flash_read(flash_t *obj, uint32_t address, uint8_t *data, uint32_t size);

/** Program pages starting at defined address
 *
 * The pages should not cross multiple sectors.
 * This function does not do any check for address alignments or if size is aligned to a page size.
 * @param obj The flash object
 * @param address The sector starting address
 * @param data The data buffer to be programmed
 * @param size The number of bytes to program
 * @return 0 for success, -1 for error
 */
int32_t flash_program_page(flash_t *obj, uint32_t address, const uint8_t *data, uint32_t size);

include the mbed library with this snippet

#include "mbed.h"
DigitalOut myled(LED1);
Serial pc(SERIAL_TX, SERIAL_RX);
flash_t a;
int main() {
    //++
    if (!flash_init(&a)){
        pc.printf("Flash is available\r");
    } else {
        pc.printf("ERROR\r");
    }
    //++
    uint32_t st_adrr = flash_get_sector_size(&a,0x60000000);
    pc.printf("The start address for the flash region: %d\r",st_adrr);
    if (!flash_erase_sector(&a,0x60000000)){
        pc.printf("Erase done!\r");
    } else {
        pc.printf("Erase fail!\r");
    }
    //++can write info to flash!
    uint8_t data = 240;
    if (!flash_program_page(&a,0x60000000,&data,1)){
        pc.printf("Programm success\r");
    } else {
        pc.printf("Programm falue\r");
    }
    //Check read from flash!
    int ret = flash_read(&a,0x60000000,&data,1);
    if (!ret){
        pc.printf("Value: %d\r",data);
    } else {
        pc.printf("ERROR for read\r");
    }
    while(1) {
        myled = 1; // LED is ON
        wait(0.2); // 200 ms
        myled = 0; // LED is OFF
        wait(1.0); // 1 sec
    }
}

1 Answer

6 years, 3 months ago.

Hello Alex,

  • Rather than calling the flash_get_sector_size try to call the flash_get_start_address function to get the start address of the NUCLEO-F767ZI's flash memory (returns 0x08000000).
  • Get the flash size with the get_flash_size function (returns 0x00200000).
  • Calculate the last address in flash memory as flash_start+flash_size-1 (=0x081FFFFF).
  • As you can see the address 0x60000000 (used in your program) is well beyond the last flash memory location .

For example:

#include "mbed.h"

FlashIAP flash;

int main()
{
    flash.init();

    const uint32_t  flash_start = flash.get_flash_start();
    const uint32_t  flash_size = flash.get_flash_size();
    const uint32_t  flash_end = flash_start + flash_size - 1;
    const uint32_t  page_size = flash.get_page_size();
    uint32_t        sector_size = flash.get_sector_size(flash_end);
    uint8_t*        page_buffer = new uint8_t[page_size];
    uint32_t        addr = flash_end - sector_size + 1;
    uint8_t         data_write = 55;
    uint8_t         data_read = 0;

    printf("flash_start = 0x%.8x\r\n", flash_start);
    printf("flash_size = 0x%.8x\r\n", flash_size);
    printf("flash_end = 0x%.8x\r\n", flash_end);
    printf("page_size = 0x%.8x\r\n", page_size);
    printf("sector_size = 0x%.8x\r\n", sector_size);
    printf("addr = 0x%.8x\r\n", addr);
    printf("data_write = %d\r\n", data_write);
    printf("data_read before writing to flash = %d\r\n", data_read);
    page_buffer[0] = data_write;
    flash.erase(addr, sector_size);
    flash.program(page_buffer, addr, page_size);
    page_buffer[0] = 0;
    flash.read(page_buffer, addr, page_size);
    data_read = page_buffer[0];
    delete[] page_buffer;
    flash.deinit();
    printf("data_read after writing to flash = %d\r\n", data_read);
}

But why to bother with Flash IAP when MBED devised also a better API. The NVStore API stores data by keys in the internal flash and keeps chip's wear out (due to repeated erase and write to the same memory location) as low as possible.

Accepted Answer

Thanks for your advice!!!

posted by Alex Rahov 31 May 2019