Cómo almacenar variables en la memoria FLASH

Estoy trabajando con una placa de evaluación STM32 de STMicro que incluye un procesador ARM Cortex-M4. Necesito una LUT para coseno y seno (variables de solo lectura). Necesito administrar mi memoria RAM, por lo tanto, quiero almacenar estos LUT en la memoria flash.

Primero: ¿es mejor crear un cálculo interpolado de coseno/seno o la lectura FLASH es lo suficientemente rápida?

En segundo lugar, cómo poner las variables en la memoria FLASH. ST proporciona algunos ejemplos, pero tal vez, para mi problema, solo necesito declarar las variables LUT como constantes estáticas y será como un código.

Respuestas (3)

La respuesta corta es declarar su variable con la constpalabra clave. Si su MCU realmente recuerda el valor de su constvariable (es decir, su cálculo de seno realmente funciona), tiene que almacenarse en la memoria flash, de lo contrario, se perdería en el primer reinicio después de la programación.

La respuesta larga tiene que ver con el script del enlazador. Estos scripts dependen de MCU y le dicen al enlazador dónde poner qué. Por lo general, este script lo proporciona el IDE, pero puede escribir el suyo propio. En mi configuración de STM32F4, mi secuencia de comandos del enlazador comienza con una declaración de este tipo:

MEMORY
{
    FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K
    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
    CCMRAM (xrw)    : ORIGIN = 0x10000000, LENGTH = 64K
    MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

Dice que el flash comienza en la dirección 0x08000000y la RAM en la dirección 0x20000000. Estas direcciones se pueden encontrar en la hoja de datos donde se describe el mapa de memoria. El resto del guión puede involucrarse, pero en algún momento estará presente algo similar a esto:

.text :
{
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
} >FLASH

Esto dice que todas las .textsecciones (así es como el compilador llama a la sección de código) y .rodatalas secciones (así es como el compilador llama a las constvariables) deben colocarse en la sección flash.

Como se sugirió anteriormente, el .maparchivo es la forma principal en que puede verificar qué coloca el enlazador y dónde. Le dices al enlazador que lo genere usando esta opción:

arm-eabi-gcc -Wl,-Map=my_program.map ...

Puede buscar su símbolo dentro de este archivo de mapa, ver en qué dirección se ha almacenado y compararlo con el mapa de memoria especificado en la hoja de datos de MCU.

No, no puede poner variables en la memoria de solo lectura. Sin embargo, puede poner constantes allí, que es todo lo que necesita, ya que está preguntando sobre una tabla de búsqueda de seno/coseno. Esos valores están fijados por matemáticas y no necesitan cambiar sobre la marcha.

Seguramente la documentación del lenguaje describe cómo forzar una matriz de constantes en la memoria del programa. Esto generalmente se hace con alguna palabra clave, o especificando atributos para una sección del enlazador, o posiblemente pasando información adicional al enlazador por separado.

En cuanto a cómo implementar una búsqueda de seno y coseno, consulte estas respuestas anteriores:

https://electronics.stackexchange.com/a/60819/4512
https://electronics.stackexchange.com/a/16516/4512

El uso de la palabra clave const con el lenguaje C parece colocar los datos en la memoria flash/de programa. ¿Cómo verificar, con el IDE (uso CooCox con el compilador ARM GNU gcc), si estas variables realmente están mapeadas en la memoria FLASH? gracias
@usuario: Probablemente, aunque en teoría eso solo le dice al compilador que no tiene la intención de modificar el valor. No hay forma de saberlo con certeza para ningún conjunto de herramientas de compilador/vinculador. Todavía necesita leer la documentación, que por supuesto debería hacerlo de todos modos. Tenga en cuenta que el OP nunca dijo qué idioma está usando.
@ user2412542 Puede agregar una opción al comando gcc y hacer que genere un archivo de mapa de memoria, o puede usar el comando objdump para ver dónde se colocarán varias cosas en la memoria.
En muchos compiladores, las variables con un constmodificador se asignarán en una sección de enlace separada de las que no lo tienen; normalmente habrá una opción para obligar a algunas secciones del enlazador a codificar espacio y, en muchos casos, las secciones que almacenan constvariables se colocarán allí automáticamente. Creo que los compiladores ARM suelen tener ese comportamiento predeterminado, por lo que una constdirectiva debería ser suficiente para lo que necesita.
Puede usar su memoria FLASH para almacenar variables. Sin embargo, no sale de la caja, hay algún código involucrado. Aquí hay un buen ejemplo, MCU diferente pero la misma familia Cortex. os.mbed.com/users/olympux/code/eeprom_flash

para tener datos puestos en flash declararlo como const

const unsigned int lut[]= { 0x1234, 0xab, 0xcd, 0xefa1123, 0x1122334, ...

Es posible que su secuencia de comandos de vinculación deba tener una entrada, depende del estilo y la antigüedad de su cadena de herramientas, podría ir en .text o .rodata u otro dependiendo nuevamente de su cadena de herramientas. y luego pondrías esa sección en flash.