Microchip XC8: ¿Cómo superponer variables específicas sin unión?

1

Tengo efectivamente tres conjuntos de variables para colocar en dos ubicaciones. Los juegos 1 y 2 nunca se usan juntos, por lo que pueden ocupar el mismo espacio. El set 3 debe ser único.

Sé que puedo usar una unión de estructuras para obtener lo que quiero, pero esa es una gran cantidad de datos para forzar en la misma área, y hace que los nombres sean innecesariamente complejos en mi opinión:

union
{
    struct
    {
        ...
    } set_1;
    struct
    {
        ...
    } set_2;
} shared_variables;

También puedo asignar una dirección específica a cada variable, pero eso no permite ninguna libertad para que el vinculador las optimice:

unsigned char foo_1 @ 0x1A0;
unsigned int  bar_1 @ 0x1A1;

unsigned long foo_2 @ 0x1A0;    //same address as foo_1

Puedo asignar un nombre de sección a cada variable y decirle al vinculador qué hacer con las secciones, pero todavía creo que es demasiado restrictivo:

unsigned char __section("set_1") foo_1;    //set_1 is 1 byte
unsigned int  __section("set_1") bar_1;    //set_1 is now 3 bytes

unsigned long __section("set_2") foo_2;    //set_2 is 4 bytes

//linker: -L-Ashared_class=<address_range> -L-Pset_1=shared_class -L-Pset_2=shared_class
//actually concatenates them somewhere in the specified range (total 7 bytes), not sure how to overlay them (total 4 bytes)

¿Hay alguna forma de decirlo? "No me importa si este conjunto de variables se superpone a ese conjunto de variables, pero este otro conjunto de variables debe ser único", y simplemente dejarlo así.

Editar en respuesta a los comentarios:

  • El conjunto 1 + el conjunto 2 + el conjunto 3 representan todas las variables que se utilizan en todo el proyecto.
  • El código que los usa está actualmente distribuido en 4 módulos de origen.
  • Como la mayoría, si no todos los chips en este rango de Microchip, la memoria está fragmentada en hardware en fragmentos de 80 bytes separados por registros de configuración de hardware. Hay otro modo de direccionamiento que requiere un puntero para acceder a todos los fragmentos como si fueran contiguos, pero que aplastarían el puntero registra un lote . (y parece que hay un error en el depurador que corrompe los datos que se usan de esa manera en ciertos casos; aunque la ejecución normal está bien)
pregunta AaronD

2 respuestas

1

Encuentro las uniones perfectamente bien para "compartir" variables. Permítanme expandir esto con el código:

typedef struct
{
  union
  {
     struct
     {
     } set_1;
     struct
     {
     } set_2;
  } set_union;
  struct
  {
  } set_3;
} data_set;

... Por supuesto, esto podría hacerse mucho más legible usando typedefs en set_1 y set_2 .

    
respondido por el Dzarda
1

Es sencillo resolver el problema "hace que los nombres sean innecesariamente complejos".

Ampliando tu ejemplo:

union
{
    struct
    {
        int fubar;
        ...
    } set_1;
    struct
    {
        int snafu;
        ...
    } set_2;
} shared_variables;

Una solución es usar algunas macros:

#define a (shared_variables.set_1)
#define b (shared_variables.set_2)

a.fubar = ...;

b.snafu += ...;

Parte de la ventaja de esta solución es que el código sigue siendo una C normal, y no depende de las características específicas del compilador.

Existe una pequeña posibilidad de que el compilador genere un mejor código cuando esté realizando todas las asignaciones de variables, en lugar de introducir parte de la información en el vinculador. Sin embargo, no sé lo suficiente sobre xc8 para decir que ese es el caso.

Editar:
Parece bien dirigir las variables a segmentos específicos. Eso solo afectará a los dos conjuntos que son mutuamente excluyentes, y no a todas las variables.

El manual de usuario del compilador xc8 también describe otro mecanismo para colocar objetos en "5.14.4.8 LA DIRECTIVA #PRAGMA PSECT ", que puede ser preferible, AFAICT un solo #pragma colocaría todas las variables subsiguientes.

Esto parece mucho más simple, y menos propenso a errores que __section("...") en cada variable, en comparación con un solo #pragma frente a cada lista de variables.

Hay una advertencia específica sobre el #pragma , que probablemente no se aplica a las variables mutuamente excluyentes:

  

Este pragma no debe usarse para ninguno de los aspectos de datos (datos o   idata) que contienen variables inicializadas.

Sin embargo, usaría una unión + dos estructuras a menos que haya más restricciones.

Edit2:
Cuando la asignación de memoria es muy ajustada, y es esencial para empaquetar variables en segmentos de tamaño fijo, podría escribir un programa para generar el código C de la declaración. Usaría un lenguaje con buen procesamiento de texto para hacerlo más fácil.

    
respondido por el gbulmer

Lea otras preguntas en las etiquetas