35 votos

¿Qué hace que el concepto de pila sea útil en la programación embebida?

A continuación se muestra una ilustración del concepto de pila:

Enter image description here

He leído muchas veces sobre el puntero de pila y cómo algunas variables se almacenan en SRAM en una pila.

Muchos tutoriales explican cómo funciona, pero no por qué existe este concepto.

Imagina que soy el programa y quiero guardar mi taza, mi reloj y mi sombrero en mi habitación. ¿Por qué voy a guardarlos uno encima del otro en lugar de ponerlos en lugares aleatorios de mi habitación?

El programa puede llegar a los datos siempre que tenga su dirección. Pero si el puntero de la pila pone x en la parte superior y. ¿Cómo va a llegar a y sin eliminar x entonces? Así que para mí una pila debe hacer las cosas (el acceso a los datos) aún más difícil.

¿Puede dar un ejemplo muy sencillo con registros o código ensamblador o código C para ilustrar el beneficio de este concepto de apilamiento, a saber, "Last in, first out" (LIFO)?

1voto

nness Puntos 175

La necesidad de una cola LIFO (también conocida como pila) aparece de forma natural en cuanto se introducen las llamadas a funciones.

Al llamar a una función, se sale temporalmente del contexto actual y se entra en el de la función. Y si hay una llamada a una función en esa función, también se sale temporalmente del contexto de la función y se entra en el de la función recién llamada.

La pila está ahí para permitirle saber "a dónde volver" al finalizar la función, a través de los niveles de anidamiento, y aquí es donde se requiere LIFO. Al mismo tiempo, los marcos de la pila permiten almacenar las variables locales a la función, y la pila es una forma conveniente y eficiente de almacenar variables automáticas.

1voto

dod_moshe Puntos 13

Creo que esto es el resultado de la evolución de dos factores:

  1. Simplicidad de hardware;
  2. Necesidad de disponer de medios abstractos para razonar sobre los programas.

En una simple aproximación, los procesadores pueden verse como máquinas que ejecutan microcódigos. De este modo, pueden describirse como:

  • Conjunto de registros, uno de los cuales sirve de puntero de instrucción;
  • Unidad aritmética lógica;
  • Bloque para leer datos y escribirlos en la memoria (tanto datos como instrucciones);
  • Bloque para decidir qué hacer con instrucciones específicas.

Esto es básicamente suficiente para ejecutar una lógica compleja arbitraria.

Uno puede dibujar un gráfico de ejecución, y ver que puede ser arbitrariamente complejo y hermoso en cierto sentido.

Ahora tenemos un ser humano que debe razonar sobre los programas. La representación gráfica del código, o incluso una lista de instrucciones de microcódigo, no es la forma más fácil de pensar en un programa.

Utilizamos análisis y síntesis para razonar sobre asuntos complejos, lo que significa que queremos dividir esta larga lista de microcódigos en sub-secciones que llamamos funciones.

Una vez hecho esto llegamos a un requisito de interfaz de una función que debe abordar:

  • cómo se pasan los parámetros;
  • cómo se devuelven los parámetros;
  • qué es el punto de entrada;
  • qué hacer cuando la función se completa.

De esta manera llegamos a la idea de buffer (marco) para almacenar los datos y el puntero de la instrucción para saltar en el completo.

Así, cuando se llama a una función, se establece un buffer, se salta a la función. Después de que se complete la ejecución se salta al siguiente destino.

Cuando se pasa del análisis a la síntesis se puede ver que el programa son funciones que llaman a otras funciones. Sus marcos forman estructuras llamadas pila.

Entonces, ¿por qué tenemos pila?

No por el hardware, sino por los humanos.

Los extraterrestres podrían escribir los programas de forma diferente.

1voto

Jeremy Ross Puntos 7484

Hoy en día, a menudo pensamos en cómo la pila de un hilo le ayuda a tener la propiedad de los datos en lugar de compartirlos con otros hilos, pero en el mundo embebido sin sistema operativo, donde la arquitectura del software es un súper bucle, una pila puede parecer o incluso ser una complicación innecesaria, pero la mayoría de las veces ayuda más de lo que perjudica.

El superbucle de los programas embebidos suele consistir en una serie de llamadas a funciones dentro de un bucle "forever". Puede haber algún tipo de evento que cada función llegue a ver en cada llamada, el bucle entero puede bloquearse esperando un evento, o varias otras variaciones, pero siguen un patrón. (En arduino el súper bucle llama a la función del bucle una vez por ciclo a través del bucle real) Un súper bucle puede llamar a múltiples funciones (que representan diferentes módulos, como una interfaz de comunicación, la monitorización de la fuente de energía, la medición de algún sistema, el almacenamiento de datos en un almacenamiento no volátil, decirle a una mano robótica que frene su movimiento de agarre porque sus dedos se están acercando a la superficie que está agarrando, ). Cada una de estas funciones puede tener algún estado persistente que podría residir en la memoria global / ser declarado como variables globales (o podría hacerse de una manera más referenciada a objetos), pero es muy probable que al menos a veces una función del módulo necesite algunos datos temporales que sólo necesitan ser utilizados durante la duración de una sola llamada a esa función. Podrías declarar esos datos como globales y decirle a todos los demás que no los usen, pero si el espacio de la RAM es escaso, entonces podría no haber suficiente espacio para ello. Podrías usar la asignación de heap y liberarla cuando hayas terminado, pero eso introduce complicaciones (olvidarse de liberar en todas las rutas de código, doble liberación, fragmentación de heap, manejo de fallos de asignación de memoria, ).

Utilizando una pila cada módulo consigue reutilizar el mismo espacio de memoria. Es una superposición dinámica que funciona automáticamente para los casos en que la memoria sólo se necesita durante la duración de una sola llamada. Esto también hace que los casos que necesitan más memoria persistente sean más obvios, y puedes dedicar más esfuerzo a diseñar y planificar para ellos.

En una cpu con caché de datos también te beneficias de que la memoria de la pila esté casi siempre en la caché porque se accede a ella muy a menudo.

He programado varios sistemas en ensamblador, y uno de ellos no tenía pila de hardware. Tiene 16 registros, lo que normalmente era suficiente, pero también era muy común necesitar almacenar 1 palabra más por un momento y tener que gastar enormes cantidades de esfuerzo buscando un registro que estuviera libre (para esa parte del código) y luego probar que de hecho estaba libre. Hubiera sido mucho más fácil y seguro poder simplemente pulsar, hacer mis cosas, y salir.

Las pilas son tan útiles que al menos algunos 8051 tienen un espacio de memoria separado que es sólo la memoria de la pila. Algunos compiladores introducen una segunda pila de datos cuando compilan para AVR. Y Atmel (ahora parte de Microchip) hizo que los registros de algunos de sus microcontroladores estuvieran mapeados en la memoria, por lo que en algunos de sus sistemas más pequeños los registros podían usarse como pila.

El dolor de hacer los offsets de los punteros de la pila se ve muy aliviado por los compiladores del lenguaje y los depuradores conscientes del lenguaje. Es muy molesto cuando no se tiene acceso a ellos, pero incluso entonces prefiero tener una pila que no tenerla.

Recientemente estuve diseñando un sencillo programa embebido de bajo nivel que dormía el 99,9999% del tiempo y respondía a los eventos en las interrupciones, y para ello consideré ir (casi) sin pilas. Los ISRs no podían ser interrumpidos por sí mismos, cada uno de los módulos podía poseer algunos registros y RAM, y nadie, aparte del código de inicialización, necesitaba más que unos pocos bytes de datos.

-2voto

Rishi Puntos 29

Se utiliza una pila porque es más rápido implementarla en el hardware que llevar la cuenta de las variables en el software

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X