2011-12-15 13 views
5

Tengo una estructura de configuración que me gustaría guardar en el flash interno de la corteza M3 de ARM. Según las especificaciones, los datos guardados en el flash interno deben alinearse a 32 bits. Como tengo mucho booleano y caracteres en mi estructura, no quiero usar 32 bits para almacenar 8 bits ... Decidí empaquetar la estructura usando el preprocesador pragma __packed, luego cuando lo guardo como una estructura completa , Solo tengo que asegurarme de que el tamaño de la estructura sea divisible por 4 (4 bytes = 32 bits), lo hago añadiendo bytes de relleno si es necesario. Actualmente, durante el desarrollo modifico mucho la estructura, y para que esté alineada con los 32 bits, necesito cambiar los bytes de relleno todo el tiempo. En la actualidad, la estructura parezca SLIKE esteAlineación de la estructura C en la memoria FLASH interna

typedef __packed struct 
{ 
uint8_t status; 
uint16_t delay; 
uint32_t blabla; 
uint8_t foo[5]; 
uint8_t padding[...] // this has to be changed every time I alter the structure. 
} CONFIG; 

¿Hay una mejor manera de lograr lo que estoy haciendo? Soy bastante nuevo en la programación Embedded, y quiero asegurarme de no cometer errores.

Editar: Tenga en cuenta. Los datos se persistió en el extremo de la flash interna, por lo que omitiendo el relleno no va a funcionar ...

+1

Creo que su comprensión no es correcta. Es posible que las instrucciones en la memoria flash tengan que estar alineadas y eso estará garantizado por el compilador. Pero los datos almacenados en flash incluso desalineados pueden ser gestionados por núcleos m3 de la corteza del brazo. ¿Qué MCU de la empresa usas? –

Respuesta

4

Quizás esta es una idea:

typedef __packed struct { 
    uint8_t status; 
    uint16_t delay; 
    uint32_t blabla; 
    uint8_t foo[5]; 
} CONFIG; 

typedef __packed struct { 
    CONFIG cfg; 
    uint8_t padding[4 - (sizeof(CONFIG) % 4)] 
} CONFIGWRAPPER; 
+0

En realidad, cuando lo pienso. Si ya está alineado, agregamos 4 bytes para nada – stdcall

4

Solución 1: Se puede poner dentro de una unión que contiene su estructura y un conjunto de caracteres:

union 
{ 
    CONFIG config; 
    uint8_t total_size[32]; 
} my_union; 
+0

Eso es interesante, digamos que el tamaño de (CONFIG) es menor que el tamaño de total_size. y configuré la configuración en la unión. ¿Cuál será el tamaño de (mi_unión)? – stdcall

+0

Si 'CONFIG 'es más pequeño que' total_size' entonces 'sizeof (my_union)' tendrá el tamaño de 'total_size', concretamente 32. – Lindydancer

1

Solución 2: Se puede utilizar la función de IAR-específica #pragma location para colocar los datos de configuración en un lugar específico, como 32 a partir del final del flash. De esa manera usted no necesitaría para rellenar la estructura de cualquier manera:

/* Fictitious end of flash location. */ 
#pragma location=0x1234FFE0 
struct [... your struct goes here ...] 
3

En primer lugar, la alineación embalado es por lo general para evitar, si al final con datos no alineados a sus límites naturales, algunas CPUs se acaba de emitir una trampa cuando intenta acceder a ellos.

Primero, almacene los miembros en un orden para que el compilador no agregue vacíos para la alineación (o si lo hace, lo agrega al final). Si puede, haga que 1. el miembro tenga el requisito de alineación que desee, ya que eso obliga al compilador a al menos darle a la estructura mucha alineación.

Esto requiere algunos conocimientos sobre cómo los requisitos de alineación de su plataforma y compilador, p. Se puede olvidarse de la matriz de relleno, y cambiar

typedef struct 
{ 
uint8_t status; 
uint16_t delay; 
uint32_t blabla; 
uint8_t foo[5]; 
uint8_t padding[...]; 
} CONFIG; 

a

typedef struct 
{ 
uint32_t blabla; 
uint16_t delay; 
uint8_t status; 
uint8_t foo[5]; 
} CONFIG; 

Entonces decirle al compilador que esta estructura necesita 4 alineamiento de bytes (en este caso, es probable que ya lo hará como el primer miembro tiene 4 bytes o más requisito de alineación). p.ej. con gcc use attribute((__aligned__(4))

Luego escriba un pequeño programa de prueba que valide los requisitos de alineación que tiene (que es solo un pequeño programa que usa sizeof() y alignof() en su estructura), esto incluso le dirá si necesita agregar instrucciones para que la estructura esté alineada. Ejecute ese programa como parte de la compilación/empaque.

+0

Excelente respuesta y bien planteada. El programa de prueba de muestra es fundamental para su éxito o falla, NO PUEDE omitir este paso si desea hacer lo que está tratando de hacer con las estructuras en los dominios de compilación (considere que el hardware es un dominio de compilación). –

Cuestiones relacionadas