Flash y RAM: ejecución de código

Recientemente comencé a aprender ensamblador y llegué a saber acerca de las secuencias de comandos del enlazador y otros detalles de bajo nivel de la programación de hardware. También estoy aprendiendo arquitectura de computadoras y en algún momento llegué a temer que mi imagen del modelo de memoria podría haber sido incorrecta todo el tiempo.

Según lo que entiendo actualmente, todo el código y los datos residen en la memoria no volátil justo después de que 'quemamos' el binario en un procesador; la RAM, que es volátil, no contiene nada al reiniciar. Cuando el programa comienza a 'ejecutarse', lo hace desde la dirección 0x0000, que es casi siempre (AFAIK) la dirección más baja en Flash. Por lo tanto, las instrucciones se enganchan en el bus que conecta Flash al núcleo de la CPU y ahí es donde tiene lugar la ejecución real. Sin embargo, cuando hablamos de que la CPU recupera o almacena datos de la memoria, normalmente nos referimos a la RAM. Soy consciente de que también podemos leer/escribir datos de la memoria del programa (he visto que esto se hace en AVR) pero no es tan común? ¿Es porque la RAM es más rápida que la ROM que preferimos almacenar datos allí?

La respuesta aceptada a esta pregunta dice que la mayoría de las piezas de código se ejecutan fuera de la RAM.

¿Significa esto que el código de tiempo de ejecución de inicio (que a su vez se ejecuta desde Flash) tiene que copiar todos los códigos de operación del programa de Flash a la RAM y de alguna manera asigna las direcciones en Flash para que apunten a la RAM para que la CPU obtenga los códigos de operación desde allí? ¿Es similar al proceso en el que movemos las secciones .data de la ROM a la RAM al iniciar?

Puedo imaginar que esto sea más simple en las arquitecturas de von Neumann donde el programa y las memorias de datos comparten un bus, pero en las arquitecturas de Harvard, ¿no significaría esto que todo el código y los datos tienen que pasar primero por los registros de la CPU?

Como probablemente puedas adivinar, estoy un poco confundido por todo este asunto. Habiendo programado siempre a un nivel de abstracción más alto, me preocupan fácilmente esos detalles. Cualquier ayuda es apreciada.

En los microcontroladores simples, no es necesario copiar de la memoria del programa (a menudo flash hoy en día) a la RAM para poder ejecutarse.
Todo se debe a que una memoria RAM es más rápida que Flash, pero como pierde datos después de la pérdida de energía, surge la memoria no volátil Flash. Cuando está encendido, los datos se cargan desde Flash a la RAM y la CPU comienza a funcionar, todo eso se repite.

Respuestas (3)

Esto depende del dispositivo.

La memoria RAM se puede construir más rápido que Flash; esto comienza a ser importante en el rango de 100MHz.

Microcontroladores simples

Pequeños microcontroladores lentos se ejecutan directamente desde Flash. Estos sistemas suelen tener más Flash que SRAM también.

Sistemas de gama media

Una vez que su dispositivo se vuelve más rápido, la situación es un poco diferente. Los sistemas ARM de rango medio también pueden hacer eso, o pueden tener un cargador de arranque de ROM de máscara que hace algo más inteligente: tal vez descargar código desde USB o EEPROM externos a SRAM interna.

Grandes sistemas

Los sistemas más grandes y rápidos tendrán DRAM externa y Flash externa. Esto es típico de una arquitectura de teléfono móvil. En este punto, hay mucha RAM disponible y es más rápida que Flash, por lo que el gestor de arranque la copiará y ejecutará. Esto puede implicar pasarlo a través de los registros de la CPU o puede implicar una transferencia DMA si hay una unidad DMA disponible.

Las arquitecturas de Harvard suelen ser pequeñas, así que no se moleste con la fase de copia. He visto un ARM con "harvard híbrido", que es un espacio de direcciones único que contiene varias memorias pero dos unidades de recuperación diferentes. El código y los datos se pueden obtener en paralelo, siempre que no provengan de la misma memoria. Por lo tanto, puede obtener el código de Flash y los datos de SRAM, o el código de SRAM y los datos de DRAM, etc.

La memoria RAM suele ser más rápida que la memoria flash, pero en realidad no importa hasta que alcance velocidades de reloj superiores a 80-100 MHz, siempre que el tiempo de acceso a la memoria flash sea más rápido que el tiempo que se tarda en ejecutar una instrucción. no debería importar

La construcción física de la memoria RAM nos permite construir dispositivos muy rápidos; mucho más rápido que flash. En este punto, tiene sentido copiar bloques de código en la RAM antes de la ejecución. Esto también brinda beneficios adicionales para el desarrollador, como la posibilidad de modificar el código en tiempo de ejecución.

en las arquitecturas de von Neumann donde el programa y las memorias de datos comparten un bus, pero en las arquitecturas de Harvard, ¿no significaría esto que todo el código y los datos tienen que pasar primero por los registros de la CPU?

No necesariamente. Aquí es donde entra en juego el direccionamiento virtual . En lugar de que el código del programa se refiera a las direcciones RAM de hardware sin procesar, en realidad hace referencia a un espacio de direcciones virtuales. Los bloques de espacio de direcciones virtuales se asignan a dispositivos de memoria física, que pueden ser RAM, ROM, flash o incluso búferes de dispositivos.

Por ejemplo, cuando hace referencia a la dirección 0x000f0004 en un micro, es posible que esté leyendo la dirección 0x0004 de la memoria flash. La dirección virtual es 0x000f0004, pero la dirección física es solo 0x0004: todo el espacio de direcciones 0x000fxxxx se asigna a un dispositivo de memoria física de 4 KB. Este es solo un ejemplo, por supuesto, y el método de administrar y organizar el espacio de direcciones virtuales difiere enormemente entre las arquitecturas.

Como tal, cuando dice que "el programa comienza a ejecutarse [...] desde la dirección 0x0000, que es casi siempre la dirección más baja en flash", no se garantiza que sea correcto. De hecho, muchos microcontroladores comienzan en 0x1000.

Habría dicho que la distinción se vuelve relevante alrededor de 20-40MHz, no 100Mhz, ya que la mayoría de los dispositivos flash que he visto comienzan a requerir un estado de espera en ese punto. En muchos casos, el código flash incluirá un circuito para que cada recuperación tome múltiples palabras de instrucción, de modo que para muchos tipos de código, la "penalización" por ejecutar desde flash será solo del 5 al 10%, pero para algunos otros tipos de código (por ejemplo, con una gran cantidad de saltos) la penalización puede ser mucho más severa.
Eso no es direccionamiento virtual, es E/S mapeada en memoria (la región de memoria se asigna a E/S usando un periférico, el nombre en muchas MCU es "Controlador de memoria estática"). Por supuesto, la E/S llega a otra memoria, por lo que a veces no pensamos en ella como E/S. Pero definitivamente no es un mapeo de memoria virtual.

Lo que dices no es del todo cierto o falso. Hay diferentes escenarios para esto.

Eso depende de si está programando en el hardware sin procesar o en el hardware instalado con el sistema operativo.

Su sistema operativo que se ejecuta en la computadora de uso general obtiene el código del HDD y lo almacena en la RAM para un acceso más rápido. Si su procesador intenta buscar directamente desde el HDD de forma continua, las operaciones serían mucho más lentas debido a la falta de coincidencia de velocidad entre dos. Entonces, su RAM entra en juego donde se almacena parte de su código repetitivo para un acceso más rápido. Y eso también está disponible en la memoria caché del procesador para hacerlo aún más rápido.

Ahora, cuando está trabajando en un microcontrolador, depende totalmente de usted dónde ubica sus datos en el chip. Si los datos son estáticos, es posible que desee ubicarlos en la memoria de código, lo que ahorrará RAM, que es comparativamente mucho más pequeña que la memoria de código. En el lenguaje C, cuando inicializa el tipo de datos usando static o en algún compilador, los datos del prefijo const se almacenarán en la memoria del código o se almacenarán en la RAM. Y en el ensamblaje, usa directamente DB (Definir byte en el caso de Basic 8051) para inicializar los datos en la ubicación particular. Ahora, incluso en algunos controladores como PIC ARM, puede escribir ROM en el tiempo de ejecución, pero la obtención de datos llevará mucho tiempo.

Además, hay hardware de cargador de arranque en controladores sofisticados y de nivel medio que les dice a los controladores o al procesador desde dónde ejecutar el código de inicio o es el código de inicio que en realidad está segmentado en la memoria. Por lo tanto, hay muchas posibilidades debido al avance. , Preferiría decir un avance híbrido en la industria que mezcla todo el concepto de RAM ROM y memorias convencionales. Así que básicamente tu confusión es válida.