¿Qué sucede cuando los microcontroladores se quedan sin memoria RAM?

12

Puede ser solo una coincidencia, pero he notado que los microcontroladores que usé se reiniciaron cuando se quedaron sin RAM (Atmega 328 si es específico del hardware). ¿Es eso lo que hacen los microcontroladores cuando se quedan sin memoria? Si no, ¿qué pasa entonces?

¿Por qué / cómo? El puntero de pila ciertamente se incrementa ciegamente a un rango de memoria no asignado (o se desplaza), pero lo que sucede entonces: ¿existe algún tipo de protección que lo reinicie o sea (entre otros efectos) el resultado de la sobrescritura de datos críticos? ¿Datos (que asumo diferente del código que creo que se ejecuta directamente desde flash)?

No estoy seguro de que esto deba estar aquí o en el Desbordamiento de pila, hágame saber si debería ser movido, aunque estoy bastante seguro de que el hardware tiene un papel en eso.

Actualizar

Debo señalar que estoy particularmente interesado en el mecanismo real detrás de la corrupción de la memoria (¿es el resultado de la renovación del SP - > ¿eso depende de la asignación de memoria de la UC, etc.)?

    
pregunta Mister Mystère

4 respuestas

14

En general, la pila y el montón chocan entre sí. En ese punto, todo se vuelve desordenado.

Dependiendo de la MCU, una o varias cosas pueden suceder (o sucederán).

  1. Las variables se corrompen
  2. La pila se corrompe
  3. El programa se corrompe

Cuando sucede 1, empiezas a tener un comportamiento extraño: las cosas no hacen lo que deberían. Cuando pasan 2 se desata todo tipo de infierno. Si la dirección de retorno en la pila (si hay una) está dañada, entonces la respuesta de la llamada actual es algo que nadie sabe. En ese momento, básicamente, el MCU comenzará a hacer cosas al azar. Cuando vuelve a pasar 3, quién sabe qué pasaría. Esto solo sucede cuando estás ejecutando un código de RAM.

En general, cuando la pila se daña, todo termina. Justo lo que sucede depende de la MCU.

Puede ser que al intentar asignar la memoria, en primer lugar, falle para que no se produzcan daños. En este caso, la MCU podría generar una excepción. Si no hay un controlador de excepciones instalado, la mayoría de las veces la MCU solo se detendrá (un equivalente de while (1); . Si hay un controlador instalado, entonces podría reiniciarse limpiamente.

Si la asignación de memoria sigue adelante, o si lo intenta, falla y simplemente continúa sin memoria asignada, entonces estás en los reinos de "¿quién sabe?". La MCU podría terminar reiniciando a sí misma a través de la combinación correcta de eventos (las interrupciones causaron que se reiniciara el chip, etc.), pero no hay garantía de que eso suceda.

Lo que normalmente puede haber una alta probabilidad de que ocurra, sin embargo, si está habilitado, es el temporizador interno de vigilancia (si existe) que excede el tiempo de espera y reinicia el chip. Cuando el programa se completa completamente en este tipo de bloqueo, las instrucciones para restablecer el temporizador generalmente no se ejecutarán, por lo que se agotará y reiniciará.

    
respondido por el Majenko
12

Una vista alternativa: los microcontroladores no se quedan sin memoria.

Al menos, no cuando está programado correctamente. Programar un microcontrolador no es exactamente como la programación de propósito general, para hacerlo correctamente, debe tener en cuenta sus limitaciones y programar en consecuencia. Hay herramientas para ayudar a asegurar esto. Búsquelos y apréndalos, al menos cómo leer los scripts y advertencias del vinculador.

Sin embargo, como dicen Majenko y otros, un microcontrolador mal programado puede quedarse sin memoria, y luego hacer cualquier cosa, incluyendo un bucle infinito (que al menos le da al temporizador de vigilancia la posibilidad de reiniciarlo. Habilitaste el temporizador de vigilancia, no lo hiciste t usted?)

Las reglas de programación comunes para los microcontroladores evitan esto: por ejemplo, toda la memoria se asigna en la pila o se asigna de forma estática (global); "Nuevo" o "Malloc" están prohibidos. Lo mismo ocurre con la recursión, de modo que la profundidad máxima de anidamiento de subrutinas pueda analizarse y mostrar que se ajusta a la pila disponible.

Por lo tanto, el almacenamiento máximo requerido se puede calcular cuando el programa se compila o vincula, y se compara con el tamaño de la memoria (a menudo codificada en el script del vinculador) para el procesador específico al que se dirige.

Entonces es posible que el microcontrolador no se quede sin memoria, pero es posible que su programa. Y en ese caso, llegas a

  • reescribirlo, más pequeño, o
  • elija un procesador más grande (a menudo están disponibles con diferentes tamaños de memoria).

Un conjunto común de reglas para la programación de microcontroladores es MISRA-C , adoptado por la industria del motor.

En mi opinión, la mejor práctica es utilizar el subconjunto SPARK-2014 de Ada. Ada en realidad apunta a pequeños controladores como AVR, MSP430 y ARM Cortex razonablemente bien, y proporciona inherentemente un mejor modelo para la programación de microcontroladores que C. Pero SPARK agrega anotaciones al programa, en forma de comentarios, que describen lo que está haciendo el programa.

Ahora, las herramientas SPARK analizarán el programa, incluidas esas anotaciones, y demostrarán sus propiedades (o informarán de posibles errores). No tiene que perder tiempo o espacio de código para tratar con accesos de memoria erróneos o desbordamientos de enteros porque se ha comprobado que nunca ocurren.

Aunque SPARK tiene más trabajo por adelantado, la experiencia demuestra que puede llegar a un producto más rápido y más barato porque no pasa tiempo persiguiendo reinicios misteriosos y otros comportamientos extraños.

Una comparación de MISRA- C y SPARK

    
respondido por el Brian Drummond
6

Me gusta mucho la respuesta de Majenko y lo hice yo mismo. Pero quiero aclarar esto en un punto claro:

Cualquier cosa puede suceder cuando un microcontrolador se queda sin memoria.

Realmente no puedes confiar en nada cuando sucede. Cuando la máquina se queda sin memoria de pila, la pila probablemente se corrompe. Y como eso sucede, cualquier cosa puede pasar. Valores variables, derrames, registros temporales, todo se corrompe, interrumpiendo los flujos de programas. Si / then / elses puede evaluar incorrectamente. Las direcciones de retorno están distorsionadas, haciendo que el programa salte a direcciones aleatorias. Cualquier código que hayas escrito en el programa puede ejecutarse. (Considere el código como: "si [condición] entonces {fire_all_missiles ();}"). Además, una gran cantidad de instrucciones que no has escrito pueden ejecutarse cuando el núcleo salta a una ubicación de memoria no conectada. Todas las apuestas están desactivadas.

    
respondido por el PkP
1

AVR ha restablecido el vector en la dirección cero. Cuando sobrescribes la pila con basura aleatoria, eventualmente darás vueltas y sobrescribirás alguna dirección de retorno y señalará "a ninguna parte"; luego, cuando regrese de una subrutina a esa ubicación, la ejecución se realizará en bucle a la dirección 0 donde generalmente se encuentra un salto para restablecer el controlador.

    
respondido por el Ilia

Lea otras preguntas en las etiquetas