7 votos

Crear tabla de búsqueda programable en STM32

Estoy tratando de definir una tabla de consulta que no es una constante en un STM32F103. Básicamente quiero tener una página de flash que actúa como una constante de la tabla de búsqueda en el funcionamiento normal, pero de vez en cuando (creo que días de diferencia) yo quiero ser capaz de borrar la tabla y escribir uno nuevo a la página de flash. Creo que entiendo cómo utilizar el HAL de funciones para hacer lo que tengo en mi programa, pero me parece que se tendría que declarar este bloque de memoria en el conector del archivo y estoy teniendo un montón de problemas para encontrar un ejemplo que cubre. El valor predeterminado mem.ld de CubeMX se parece a esto:

MEMORY
{
  FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 128K
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
}

Me parece que se necesita una salida de secciones de bloque después de que donde yo cometer una palabra clave a >FLASH, pero no sé qué palabras clave que sería o cómo iba a declarar la tabla en el código para darle la dirección correcta.

He visto el emulado de la EEPROM de la nota de aplicación, pero parece como un montón de sobrecarga adicional para la memoria que no va a ver bastante de borrado/escritura de ciclos para estar preocupados acerca de la memoria de la vida. Ayuda!

7voto

Matheor Puntos 31

Nota: el enlace no es una parte del lenguaje C, de normas, de modo que cada compilador implementa enlazador de archivos de forma diferente. Usted parece estar usando GCC, así que voy a compartir algo de código que trabaja con él.

enlazador.ld:

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 8K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 31K
/*(1)*/ FIXED_DATA(rw)  : ORIGIN = 0x8007C00, LENGTH = 1K /* your LUT here*/
}
............
.FIXED_DATA (NOLOAD):/*(2)*/
  {
    *(STATIC_DATA);/*(3)*/
  } >FIXED_DATA /*(4)*/

En C:

__attribute__((section("STATIC_DATA"))) 
             const static volatile statistic_static_data_t staticData;

Lo que esto hace:

(1) crear un área denominada FIXED_DATA de la ubicación y el tamaño. Tenga en cuenta que mi código es desde un dispositivo diferente. Revise su hoja de datos hacen ver que lo que el tamaño de los bloques son (pueden incluso no ser de igual tamaño en el interior de un dispositivo!). Asegúrese de reducir el tamaño de la memoria FLASH en consecuencia, de lo contrario aparecerá un mensaje de error acerca de ellos que no encajen en la memoria.

(2) crear una sección denominada FIXED_DATA. No tiene que ser llamado FIXED_DATA realidad, sino que también ayuda a guardar la pista. Atributo NOLOAD dice que el vinculador no llenar el área de (ver más abajo).

(3) poner todas las variables marcadas DATOS ESTÁTICOS en esta sección de memoria

(4) poner todo en la presente sección en el área denominada FIXED_DATA que hemos creado anteriormente

En el archivo C, sólo tienes que etiquetar las variables que desea poner en la zona. Recomiendo llamar a ellos const porque generalmente no quieren escribir en flash directamente. Volátiles ayuda con las optimizaciones del compilador que asumir const datos nunca cambia.

¿Por qué ir a través de todo este problema, en lugar de utilizar el sencillo soluciones en otras respuestas? Porque es actualizable. Si, en el futuro, desea realizar una actualización de FW, es posible que desee mantener los datos almacenados en la memoria. El NOLOAD instrucción en el vinculador archivo no sólo eso: el vinculador no llenar los datos con 0, como se haría normalmente si usted tiene una variable global que viven allí.

Usted puede encontrar más información sobre el arcano formas del enlazador si la búsqueda para "ld sintaxis"

4voto

Stefan Arentz Puntos 151

Esto no es complicado de hacer.

Básicamente lo que necesitas es una constante variable global que se coloca en flash y definir la ubicación mediante un pragma.

En C++ la cabecera podría ser algo como esto:

class FlashLookUpTable
{
    public:
    struct LookUpTable_t
    {
        uint32_t table[100];
    };

    public:
    static LookUpTable_t const * GetLookUpTablePointer();

    private:
    static const uint32_t FLASH_PAGE_SIZE = 1024U; // or whatever the flash smallest deletable size is
    // This variable contains the number of bytes needed to store the structure in complete flash pages
    static const uint32_t ARRAY_SIZE = (sizeof(LookUpTable_t)/FLASH_PAGE_SIZE) + FLASH_PAGE_SIZE;

    union FlashPageSizedStructure
    {
        LookUpTable_t t;
        uint8_t flashpage[ARRAY_SIZE];
    }

    static const FlashPageSizedStructure tableInFlash;

};

Y esto es cómo la aplicación se ve:

// the exact pragma depends on the compiler used, this one works for IAR
// the location should be at the start of a page boundary, especially when using this union approach
#pragma location=0x800FC00U
const FlashLookUpTable::FlashPageSizedStructure FlashLookUpTable::tableInFlash = 
{
    // initialize values here
}

FlashLookUpTable::LookUpTable_t const * FlashLookUpTable::GetLookUpTablePointer(void) const 
{
    return &tableInFlash.t;
}

Para escribir esa página en flash, usted necesita un buffer (ya sea en la RAM o en flash) con el mismo tamaño de una página flash, porque tienes que borrar la página antes de escribir de nuevo, por lo que un cambio de lugar de un único valor no es posible.

Dependiendo de exactamente cómo usted lo usa, usted puede ser que necesite para declarar la estructura como volatile. Esto sucede especialmente si usted tiene acceso a la tabla directamente (no con un puntero, como en este caso).

Algunos compiladores optimizar el código de tal manera, de que se tome la constante fuera de la tabla directamente en el código. El resultado es, que si cambia el valor en la tabla, el valor no es tomado en cuenta en el código.

El compilador IAR tenía algunos problemas (se fija en la versión actual) el manejo de un static volatile const así que me cambié a la utilización de un puntero.


Si desea cambiar los valores, necesitamos algún tipo de flash algoritmo.

La escritura de flash siempre se compone de:

  1. Copia de seguridad del contenido de la página
  2. Actualización de copia de seguridad con los valores cambiados
  3. Borrar página
  4. Escribir la página
  5. por seguridad: comparar página escrita con copia de seguridad

Nota para el avanzado: En algunos casos puede explotar que puede escribe ceros en las posiciones donde estaba, por lo que podría cambiar un 0x7F a 0x3F, pero no al revés. En el caso de que usted no necesita hacer una página de borrado. Algunos controladores pueden no ser compatibles con esta.

4voto

user46195 Puntos 31

Sí, sería más limpio declarar una sección para su mesa.

Pero la forma más fácil es simplemente reducir la sección FLASH por el tamaño de la página y luego:

 int *table = (int *) (0x0800000 +0x20000 - PAGE_SIZE)
 

1voto

GetFree Puntos 495

Si tiene flash de sobra, puede declarar una variable const global del doble del tamaño de una página flash, y redondear su dirección de inicio hasta un múltiplo del tamaño de la página flash. Un poco derrochador, pero no hay necesidad de hacer magia linkerscript.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X