2012-08-02 16 views
6

En el Codevision compilador para Atmel procesadores, hay una posibilidad de especificar la dirección de almacenamiento de una variable global, por ejemploInicializando una variable y especificando la dirección de almacenamiento al mismo tiempo: ¿es posible?

int a @0x100; // will place the variable at the address 0x100 in RAM 

Por supuesto, como por C estándar, las variables pueden ser inicializadas a declaración

int a=42; 

Sin embargo, no encontré ninguna posibilidad de hacer ambas cosas. int a @0x100 = 42 o int a = 42 @0x100; no funcionan, causan errores de compilación.

Usted puede preguntar por qué es tan importante hacerlo, porque uno puede simplemente tener

int a @0x100; 

int main() 
{ 
    a = 42; 
    //... 
} 

Sin embargo, si tengo variables en el EEPROM, se tiene que inicializar ellos, porque esta es la única forma de generar automáticamente el archivo eeprom con los valores que contiene. No puedo asignar esos valores más adelante, porque en ese caso escribiría los valores en el eeprom en cada inicio del programa.

+0

Cuál particular, ¿Esta familia de procesadores Atmel ayuda a http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=102678? –

+0

ATmega, pero el manejo de eeprom es el mismo. El hilo solo describe con más detalle lo que escribí en mi último párrafo (si asigno un valor a una variable eeprom en la declaración 'eeprom int a = 42; 'significa que este valor se agregará al archivo eeprom generado que solo se escribirá una vez en el dispositivo. No se escribirá realmente en el eeprom cada vez que se inicie el programa, una muy buena característica). Si hubiera asignado el valor en un comando separado, se compilaría en una instrucción de escritura para el eeprom. Gracias por el enlace, intentaré preguntar si no obtengo nada útil aquí. – vsz

+0

Por favor, explíqueme lo que en realidad está tratando de hacer; parece que ha tomado un camino equivocado en busca de algo que se pueda hacer.Atmel no tiene nada que ver con nada de esto. ¿Desea controlar un valor que está en el espacio eeprom en una dirección específica? ¿Desea controlar un valor que está en un registro/memoria que no está en eeprom? si este último desea controlar la dirección para que su programa una vez iniciado pueda tener una variable que apunte a esa ubicación de registro/memoria (que no está en eeprom)? –

Respuesta

2

Sólo un vistazo a CodeVisionAVR ayuda,

"El siguiente procedimiento debe ser utilizado si una variable global, colocado en una dirección específica mediante el @ operator, debe ser inicializado durante la declaración:

/* the variable will be stored in EEPROM at address 0x10 */ 

eeprom int abc @0x10; 

/* and it will be initialized with the value 123 */ 

eeprom int abc=123; 
0

Puede utilizar puntero que apunta a una dirección absoluta:

volatile int *pa = (int *) 0x100; 

continuación, puede utilizar el operador de desreferencia * para acceder al valor en esa dirección, así:

int value = *pa; 

o

*pa = 0x10; 

Editar: No hay forma de declarar una variable para apuntar a un área específica y al mismo tiempo asignar un valor a esa área. No, a menos que el compilador tenga extensiones que lo permitan.

+0

Esta es solo otra forma de hacer 'int a @ 0x100;' (y es peligroso, porque el compilador podría asignar algo más a esa dirección). ¿Cómo inicializará el valor ** en ** esa dirección? Además, como se afirma en la pregunta, es más importante en el caso de las variables eeprom. – vsz

+1

@vsz Los compiladores para sistemas integrados son _muy_ estrictos cuando se trata de ubicaciones de memoria y memoria. Los sistemas integrados tienen áreas específicas para montón, pila y otros segmentos de datos. Solo si el sistema no está configurado correctamente, el compilador usará rangos de direcciones de memoria que no se supone que deba. –

+0

y 'int a @ 0x100;' no es compatible con ANSI C hasta donde yo sé. Por supuesto, los compiladores AVR (tanto codevision como AVR-GCC y posiblemente otros) tienen extensiones para este propósito. – vsz

2

Si bien no conozco ninguna forma de asignar directamente una variable EEPROM a una dirección específica e inicializarla, encontré este enlace muy útil: EEPROM data at fixed address.

La solución que utilicé fue la de declarar una estructura en EEPROM y tener todas las variables EEPROM en su programa ser miembro de esa estructura. El orden en que define los miembros de la estructura será el orden en que el vinculador los coloque en el espacio de direcciones EEPROM. Dado que la estructura será la única declaración EEPROM global, es seguro decir que se dirigirá a la dirección 0x0000. Por lo tanto, sabrá la dirección de cada variable EEPROM.

Ejemplo:

typedef eeprom struct EEvars 
{ 
    eeprom char foo1; // will be located at EEPROM address 0x0000 
    eeprom char foo2; // will be located at EEPROM address 0x0001 
    eeprom short foo3; // will be located at EEPROM address 0x0002 
    eeprom long foo4; // will be located at EEPROM address 0x0004 
    eeprom char[3] fooArr; // fooArr[0] @ 0x0008; fooArr[1] @ 0x0009; 
          // fooArr[2] @ 0x000A 
} EEVARS; 

A continuación, puede inicializar las variables en la declaración de la estructura. Cuando compile, esto creará el archivo .eep con los valores inicializados en las direcciones EEPROM conocidas.

eeprom EEVARS eepromInit = {0xAA, 0xBB, 0xCCDD, 0xEEEEFFFF, {0xF0, 0xF1, 0xF2}}; 

Esto funciona especialmente bien en escenarios en los que se utiliza la sección de cargador de arranque del AVR para actualizar el flash y el nuevo programa necesita acceder a las variables almacenadas EEPROM.Incluso le permite agregar variables EEPROM a través de actualizaciones de software, siempre y cuando las agregue al final de la estructura para no alterar las direcciones de las variables ya establecidas.

2

Sé de lo que estás hablando y he tenido el mismo problema yo mismo. El problema es que usar el símbolo @ con una dirección en línea con la variable en sí es una adición de perno a la mayoría de las cadenas de herramientas. Si bien es compatible con una gran cantidad de cadenas de herramientas incrustadas para que pueda indicar explícitamente dónde se encuentran los SFR u otros registros, no es un comportamiento normal para el estándar C.

Si bien no estoy familiarizado con el compilador particular que está utilizando , Sé que la mayoría de los compiladores proporcionan una forma más compleja de especificar el mapa de memoria. La serie ATmega de Atmel, por ejemplo, proporciona la capacidad de especificar una sección de memoria personalizada en la configuración del proyecto. En una cadena de herramientas GNU, por ejemplo, estas secciones se utilizan como parte de las declaraciones de variables mediante el atributo sección con la variable:

__attribute__((__section__("<section_name>"))) 

Para la serie ATmega a localizar cualquier memoria EEPROM mediante la inclusión en la misma línea que su declaración de variables (ya sea antes o después, siempre y cuando se trata antes de que el '=' en una misión) el texto:

__attribute__((__section__(".eeprom"))) 

Si desea garantizar que la dirección de memoria específica en la EEPROM se establece en un valor como parte de su imagen binaria, por lo que solo se programa una vez cuando la imagen se escribe por primera vez, puede declarar una sección de memoria personalizada en usted r configuración del proyecto (está en la "Configuración de memoria" de la configuración "Toolchain" si está desarrollando en Atmel Studio).

Por ejemplo, he hecho exactamente lo que describes con un bloque de datos declarando la sección ".tune_data" en la parte EEPROM de la configuración de memoria (siguiendo la documentación provista para direccionar desplazamientos, etc.) luego declarando una variable como la siguiente:

const __attribute__((__section__(".tune_data))) Tune_Data_s as_tune_data = { <all_my_data> }; 

está claro que va a ser un poco diferente, ya que no está utilizando un compilador de GNU y no pueden estar utilizando Atmel Studio. Sin embargo, si lo analizas, casi todas las herramientas para la programación integrada proporcionan una forma de declarar una sección de memoria personalizada que luego se puede adjuntar a una variable en el código a través de un pragma (o atributo para cadenas de herramientas GNU). La especificación debería estar disponible a través de un argumento de línea de comandos y/o modificación de un linkerscript estándar con opciones de línea de comandos para especificar un linkerscript no predeterminado. Sé que el segundo método es la única forma de hacerlo en una cadena de herramientas proporcionada por IAR.

Cuestiones relacionadas