¿dónde se almacenan las variables constantes en el microcontrolador?

4

Según el diseño de memoria del programa C, las variables constantes se almacenan en Inicializado segmento de datos de la memoria RAM. Pero según algunos de los diseños de la memoria del microcontrolador, las variables const se almacenan en la memoria FLASH. También he visto que el tamaño del archivo BIN de mi código aumenta cuando cambio ¿Variables constantes a las definiciones de macros? Ayúdame a despejar esta ambigüedad. Utilicé Nuc2240 Cortex M0 .

    
pregunta Arun Joe

5 respuestas

5

Si estuviera escribiendo el ensamblador, usted decidiría qué ubicaciones se utilizan para contener qué constantes o variables, a través de directivas similares o similares.

Cuando estés escribiendo C, la cadena de herramientas C que estás utilizando almacenará el contenido donde se haya programado. Las variables obviamente tienden a ir en la RAM, las constantes pueden ir en la RAM o en Flash, el programa tiende a ir en Flash.

Todo depende de cómo se diseñó la herramienta para ese procesador objetivo en particular, de dónde obtiene sus instrucciones de dónde colocar las cosas. Es posible que todo esté incluido en el código, en cuyo caso no tiene nada que decir, va a donde los creadores de la cadena de herramientas eligieron enviarlo. Puede tomar directivas de algún lugar (código fuente, línea de comando, archivo de creación, variable de entorno) para que pueda volver a escribir.

Lea su documentación específica. No es física, todo depende del capricho del hombre.

    
respondido por el Neil_UK
4

La respuesta a su pregunta es específica de la arquitectura particular que está utilizando. Como ha mencionado ARM, le daré una respuesta basada en esto.

El ARM Cortex es un diseño basado en registros, por lo que básicamente cualquier operandos (constantes o no) deben, de alguna manera, abrirse camino en uno de los registros internos antes de que puedan ser utilizados por las instrucciones del programa. Esto es fundamental para responder a su pregunta, porque hay varias formas diferentes en que la arquitectura permite que esto se haga.

Para constantes pequeñas (normalmente menos de 8 o 10 bits), el valor se puede codificar directamente en ciertas instrucciones. Por ejemplo, hay una instrucción ADD #imm que agregará un valor de 12 bits codificado en la palabra de instrucción a un registro. Esto se puede utilizar para especificar directamente una constante en su programa. Si estuviera agregando la misma constante en varios lugares diferentes de su código, y el valor fuera de 12 bits o menos, entonces el compilador solo usaría una instrucción ADD #imm en todas partes donde se requería su constante. En otras palabras, la constante real se replicará en varias ubicaciones a lo largo del código almacenado en FLASH.

Si la constante es grande, entonces esto no funcionará, por lo que el valor deberá almacenarse en su propia ubicación de memoria FLASH dedicada. El chip tiene otra instrucción, llamada LDR, que utiliza para mover un valor desde una ubicación de memoria a los registros internos donde se puede usar. A esta instrucción no le importa si el valor se almacena físicamente en FLASH o RAM, simplemente extrae el valor de una dirección específica en la memoria y lo coloca en un registro. Tenga en cuenta que, en comparación con la situación con constantes pequeñas, esto requiere un ciclo de instrucción adicional, pero si la constante se usa repetidamente en un bloque de código, el compilador lo almacenará en caché colocándolo en un registro de reserva si hay uno disponible.

Sin embargo, ahora nos encontramos con un problema potencial. En la mayoría de los chips Cortex, la memoria FLASH se ejecuta a la misma velocidad o más lenta que el núcleo de la CPU. Si intentamos ejecutar una instrucción LDR desde una ubicación FLASH, esta operación de lectura de la memoria física debe competir con la lectura de la siguiente instrucción. Esto crea un cuello de botella, lo que hace que la CPU tenga que detenerse hasta que se hayan leído los datos. Peor aún, en muchas implementaciones, el FLASH se ejecuta muy lento y se utiliza un caché de canalización para enviar las instrucciones a la CPU más rápido. En estos dispositivos de lectura, digamos, una tabla de valores constantes puede exponer el cuello de botella fundamental del acceso FLASH que causa una pérdida severa de rendimiento.

Por esta razón, muchos compiladores buscarán copiar cualquier dato constante en ubicaciones de RAM de repuesto si es posible. Esto evitará estos problemas, y dado que la memoria RAM suele tener un acceso más rápido que FLASH, puede evitar muchos cuellos de botella en el rendimiento. Si de todos modos, si el programa no tiene memoria RAM no utilizada, virtualmente no es una sobrecarga para el compilador hacer esto.

Definitivamente, existe una lógica de cómo el compilador asigna datos constantes a la memoria física, pero afortunadamente en la mayoría de las situaciones, los diseñadores de chips y compiladores han hecho todo este trabajo por usted, y puede confiar en que está haciendo lo que sea. es mejor para su código particular y nivel de optimización.

    
respondido por el Jon
3

El enlace que proporcionó explica lo que sucede en las computadoras normales, que cargan todo (incluido el código) en la RAM, de todos modos (porque esto es lo único disponible, pero hay un montón de eso). No se aplica a la programación incrustada, donde también tiene disponible flash. Por lo tanto, si utiliza un script de vinculador adecuado para la programación incrustada (que debería ser la predeterminada para los IDE incrustados), los datos constantes terminan en flash, como debería ser.

Ahora, si usa definiciones de macro, es completamente diferente. Las macros se reemplazan dentro de el código fuente por el preprocesador, lo que significa que la constante se volverá a compilar de forma independiente cada vez que lo uses en tu código. Y, si lo usas varias veces, de hecho, el código será más grande. Esto, por supuesto, no debería ser el caso de constantes enteras simples. Para las constantes de cadena, los buenos compiladores intentarán fusionar varios valores idénticos para reducir este efecto y mantener el tamaño pequeño, pero esto no está garantizado, y puede depender de si las cadenas solo se usan dentro de la misma unidad de compilación (archivo de origen .c) o a través de Múltiples unidades de compilación. Para estructuras / objetos constantes, los compiladores generalmente no hacen mucha optimización.

Las respuestas serían más relevantes para su caso específico si proporcionó extractos de su código fuente e indica qué compilador / IDE está utilizando.

    
respondido por el dim
0

la respuesta depende de su definición de "variable constante" y del compilador utilizado.

si es una "variable constante", la mayoría de los compiladores la almacenarán como en flash.

si se declara a través de una macro, no puede ser una variable constante, es una constante. Por lo general, se almacena en flash y se copia en RAM.

    
respondido por el dannyf
0

Parece que estás confundiendo constantes con variables . Esto es especialmente importante si está utilizando C y no C ++.

En C, lo que se llama una variable constante (como const int ) se lanzará en la RAM. Así es como el compilador se enfrenta a la necesidad de hacer referencia a veces a la dirección de la variable (punteros).

Si esta es una variable global, el compilador colocará esto en la sección datos inicializados , lo que significa que los valores van a parpadear en la sección .etext y se copian en la sección .sdata ( parte de .data ) por el script de inicio . Si es una variable local, el código de inicio de la función lo hará como cualquier otra variable.

Sin embargo, si usa una macro, la "variable" no obtiene un espacio de direcciones. Eso significa que se carga como inmediato , ya sea por la misma instrucción que está usando (si el valor es lo suficientemente pequeño y la instrucción es inmediata) o se carga en un registro justo antes de la instrucción que usa la valor. Esto utilizará solo el espacio de memoria flash, suponiendo que esté ejecutando el código de memoria flash.

Por otro lado, si está utilizando C ++, el compilador realiza optimizaciones utilizando el valor directamente desde flash. Esto no se hace en C por diseño. Consulte esta respuesta para obtener más información.

    
respondido por el Ronan Paixão

Lea otras preguntas en las etiquetas