Cómo escribir/leer en FLASH en STM32F4, Cortex M4

5 minutos de lectura

avatar de usuario
alex m

Quiero escribir una variable, por ejemplo, un número entero con el número 5 en el FLASH y luego, después de que se apague y el dispositivo se encienda nuevamente, léalo.

Ya sé que para escribir algo primero necesito borrar la página y luego escribir.

En el manual dice:

  1. Escriba OPTKEY1 = 0x0819 2A3B en el registro de clave de opción Flash (FLASH_OPTKEYR)
  2. Escriba OPTKEY2 = 0x4C5D 6E7F en el registro de clave de opción Flash (FLASH_OPTKEYR)

¿Cómo realizo estas tareas?

El sector 0 tiene una dirección de bloque de 0x0800 0000 a 0x0800 3FFF, aquí es donde quiero escribir.

Aquí el enlace al manual, página 71: Manual STM32

  • Depende mucho del hardware. Algunos tipos de memoria flash no permiten operaciones sin bloques en absoluto.

    – 0andriy

    08/06/2017 a las 20:10

  • @ 4386427 Eso es incorrecto. OPTKEY1 y OPTKEY2 son valores, no direcciones. Agregarlos a la dirección de FLASH_OPTKEYR provocará un bloqueo o un comportamiento inesperado.

    usuario149341

    30 de junio de 2017 a las 23:18

  • @duskwuff – Ya veo. Lo leí como si OPTKEY1 y OPTKEY2 fueran dos registros dentro de un grupo de registros llamado FLASH_OPTKEYR. Comentario borrado. Gracias.

    – Apoya a Ucrania

    1 de julio de 2017 a las 6:07

  • Por supuesto, leer el manual en profundidad es una opción, pero generalmente también hay una nota de la aplicación sobre cómo se hace esto. Verifique las notas de la aplicación “emulación de eeprom” o “cargador de arranque”.

    – Lundin

    5 de septiembre de 2017 a las 9:57


  • Me gustaría señalar que la memoria flash solo tiene un número limitado de ciclos de escritura y borrado antes de degradarse. Recomiendo enfáticamente usar NVRAM respaldada por batería o alguna memoria no volátil externa de alta resistencia, por ejemplo, MRAM, para almacenar datos no volátiles que cambian con frecuencia. Personalmente, siempre voy con MRAM para esas cosas.

    – datenwolf

    30 de julio de 2020 a las 10:08

Puede usar el siguiente código para escribir datos en flash con la biblioteca HAL.

void Write_Flash(uint8_t data)
{
     HAL_FLASH_Unlock();
     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );
     FLASH_Erase_Sector(FLASH_SECTOR_6, VOLTAGE_RANGE_3);
     HAL_FLASH_Program(TYPEPROGRAM_WORD, FlashAddress, data);
     HAL_FLASH_Lock();
}

Debe actualizar el script del enlazador de la siguiente manera. Agregar DATA en MEMORY y añadir .user_data en SECTIONS.

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 320K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 2048K
DATA (rwx)      : ORIGIN = 0x08040000, LENGTH = 128k
}

/* Define output sections */
SECTIONS
{
 .user_data :
  {
    . = ALIGN(4);
     KEEP(*(.user_data))
    . = ALIGN(4);
  } > DATA

Debe agregar el siguiente atributo en el código principal para leer datos después de encender

__attribute__((__section__(".user_data"))) const char userConfig[64];

Después de todo esto, puede leer sus datos flash llamando userConfig[0].

  • gracias, y como leería los valores en la flash? Porque primero necesito leerlos, borrar el flash y por ultimo escribir los viejos mas los nuevos. ¿Derecha?

    – Álex m.

    5 ago. 2017 a las 16:00


  • puedes leer la primera variable de 8 bits con llamadas userConfig[0] y siguiendo 8 bits en userConfig[1].

    – Gurtaç Kadem

    8 de agosto de 2017 a las 6:22

  • Aquí hay otro ejemplo. Creo que es un UCM diferente pero de la misma familia Cortex. Aunque estoy bastante seguro de que debería funcionar. os.mbed.com/users/olympux/code/eeprom_flash

    – Barmaley

    16/04/2018 a las 19:33

  • Me he dado cuenta de que, aunque la lectura desde la memoria flash integrada es extremadamente rápida, la escritura en ella (incluso después de haber borrado el sector) es muy lenta. ¿Es este el comportamiento esperado (es decir, es una limitación de hardware)? Estoy midiendo velocidades de escritura alrededor de 7 veces más lentas que escribir en un dispositivo flash (una tarjeta micro SD) sobre SPI a 1MHz.

    – karl71

    5 de abril de 2019 a las 15:43

  • @ karl71 Las tarjetas SD pueden tener clasificaciones de velocidad muy diferentes a las de la memoria flash MCU en chip, ya que la primera suele ser crítica para la velocidad (esto se debe en gran parte a las optimizaciones del proceso, la temporización de la unidad de ejecución frente a las características de temporización de la memoria flash). Por ejemplo, en la hoja de datos del STM32L412xx (sección 6.3.10) verá una tabla de tiempo para “Características de la memoria flash”. El tiempo de programación 64b es de 90 ms y el tiempo de 32 dword es de ~2-3 ms. Pero si observa el SanDisk MD8832 ultrarrápido utilizado en tarjetas SD (hoja de datos Tabla 11, sección 10.3.2), la escritura de una página es de 30 ns. Eso es 100-1000 veces más rápido.

    – Pedro T

    21 de marzo de 2020 a las 17:40


avatar de usuario
Esteban

Estoy usando STM32F407 y Atollic TrueSTUDIO® para STM32 versión 9.3.0.

Al usar el código sugerido anteriormente

atributo((sección(“.user_data”))) const char userConfig[64];

mi compilador asumió userConfig ser cero constante. Tuve que quitar el const de la declaración para que funcione.

Mi solución completa consta de dos partes (como ya se dijo anteriormente, pero con algunas modificaciones adicionales):

Paso 1 edite el archivo del enlazador:

En memoria’

FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 896K /* origin size was 1024k, subtracted size of DATA */
DATA (rx)       : ORIGIN = 0x080E0000, LENGTH = 128K

En ‘SECCIONES’

/* User data section at the end of the flash to store calibration data etc. */
.user_data (NOLOAD):
{
  . = ALIGN(4);
  _user_data_start = .; /* create a global symbol at user_data start */
   KEEP(*(.user_data))
  . = ALIGN(4);
  _user_data_end = .;  /* create a global symbol at user_data end */
} >DATA

Paso 2 escribir código:

uint8_t userConfig[64] __attribute__ ((section(".user_data")));
extern uint32_t _user_data_start;
extern uint32_t _user_data_end;
uint8_t ConfArray[16];
uint32_t TestArray[2];

// Copy a part from the userConfig to variable in RAM
for (i = 0; i < 16; i++)
{
    ConfArray[i] = userConfig[i];
}

// get the address of start and end of user_data in flash
// the & is importand, else you would get the value at the address _user_data_start and _user_data_end points to
TestArray[0] = (uint32_t)&_user_data_start;
TestArray[1] = (uint32_t)&_user_data_end;

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad