¿Los microcontroladores admiten subprocesos?

4

Ha pasado un tiempo desde que tomé el curso "Sistemas embebidos" en el que estudiamos "Super-Loops", "RTOS", Semáforos, Multitarea (cooperativo vs premptive), lo siento mucho por esta pregunta.

Tenemos una aplicación donde tenemos una interfaz ADC para varias señales y donde enviamos SMS al mismo tiempo. Estamos utilizando super-loop. El problema es:

  

Cuando enviamos SMS, el resto de la aplicación tiene que esperar.

Mi pregunta es: los microcontroladores (PIC de 32 bits, ARM o basados en 8051, etc.) admiten subprocesos para que un subproceso pueda ocuparse de los SMS mientras leemos los ADC en un subproceso separado, o solo es cuestión de usar RTOS, que admite subprocesos múltiples vs super-loop que no?

    
pregunta engineer

2 respuestas

6

Mientras el microcontrolador admita interrupciones, tenga suficiente memoria y le dé un control total sobre el estado que asume la CPU (programa, registro, pila) cuando regrese de una interrupción, es posible realizar una multitarea preventiva completa. Esto se logra generalmente configurando un temporizador de hardware para generar una interrupción a intervalos regulares, y el cambio de contexto (también conocido como cambio de la tarea que se está ejecutando actualmente) en la rutina del servicio de interrupción (haciendo una copia de seguridad de los registros y la pila de la tarea actualmente en ejecución en la RAM restaurando el estado de copia de seguridad de otra tarea desde la RAM y regresando de la interrupción). La mayoría de los microcontroladores pueden hacer esto, aunque algunos microcontroladores de 8 bits no tienen RAM suficiente para guardar el estado de múltiples tareas pendientes (como algunas partes de ATtiny y PIC).

Si esto es o no práctico es una historia completamente diferente. Introduce mucha complejidad adicional, algo de sobrecarga, pero quizás lo más importante es la sincronización impredecible del firmware.

Creo que su problema se resuelve mejor con la multitarea cooperativa (super loop). Solo necesita refactorizar el código SMS en una forma de no bloqueo (piense en la variable de estado + declaración de cambio), para que la transmisión de un SMS no impida que la CPU ejecute su código ADC. Esencialmente, debe eliminar todo el código de bloqueo (retrasos, bucles de sondeo) tanto de su código ADC como de su código SMS.

Incluso más simple sería simplemente dar servicio al ADC en una interrupción de conversión completa. De esta manera, puede enviar el SMS con una implementación de controlador de bloqueo más simple (programada como una secuencia de pasos, ramas y retrasos en lugar de una máquina de estados explícita), mientras que el controlador de interrupciones aún maneja el ADC de forma transparente en el "primer plano".

    
respondido por el jms
0

Sí, la mayoría de los microcontroladores tienen suficiente soporte de hardware para que los hilos sean posibles. Si el mecanismo de llamada / retorno de hardware está basado en la pila, todo lo que realmente necesita es acceso arbitrario a la pila.

He realizado tareas múltiples muchas veces en varios PIC y dsPIC. Todo, desde el PIC 18 en adelante, soporta el enhebrado verdadero. Las partes centrales de 14 y 12 bits no le dan acceso completo a la pila de llamadas, por lo que no puede hacer subprocesos reales. He hecho lo que llamo pseudo-threading unas pocas veces. Aún puedes tener algo que en su mayoría se parece a un hilo independiente del software, aunque hay restricciones.

En general, es una abstracción de software útil para manejar cualquier entrada asíncrona con estado con una tarea separada. Hago esto rutinariamente, por ejemplo, para procesar la secuencia de comandos de UART desde el host.

No caiga en la arquitectura de "súper bucle", excepto para manejar una cantidad de eventos individuales. Entonces realmente se convierte en un bucle de eventos, por lo que es mejor llamarlo así. Por lo general, la tarea original ejecuta el bucle de eventos, después de inicializar el sistema e iniciar cualquier otra tarea que sea necesaria.

Tampoco cometa el error de suponer que la multitarea significa la prevención, o que requiere un RTOS. He realizado más de 100 proyectos de microcontroladores y he usado varias veces tareas múltiples. Hasta ahora no he encontrado un caso en el que la multitarea preventiva o un RTOS tuvieran sentido. Si te encuentras con esa estructura de software, es probable que no estés haciendo un microcontrol y estés más cerca de la informática general, incluso si está integrado.

Básicamente, use una tarea separada siempre que de otra manera quiera usar una máquina de estados llamada periódicamente desde un bucle de blooper. El código es mucho más limpio, más fácil de escribir y más fácil de mantener cuando la PC es la variable de estado. Solo asegúrate de llamar a TASK_YIELD en cualquier bucle donde esperes un evento.

Dado que el bucle de eventos principal es su propia tarea separada, también llama a TASK_YIELD periódicamente. Normalmente pongo la llamada a TASK_YIELD al inicio del bucle de eventos principal. Luego verifica cada evento en secuencia. Cuando encuentra un evento desencadenado, lo maneja y luego vuelve al inicio del bucle.

Mi código multitarea para PIC está disponible de forma gratuita en la versión de PIC Development Tools en enlace . Mire los archivos con "tarea" en su nombre en la FUENTE > Directorio PIC para las partes de 8 bits, y SOURCE > DSPIC para las partes de 16 bits. He usado estas instalaciones ampliamente, por lo que creo que son bastante sólidas.

En un PIC 18, la pila de llamadas está en la memoria dedicada. TASK_YIELD, por lo tanto, cambia la parte utilizada de la pila de llamadas a / desde un área de guardado para cada tarea. En los PIC de 16 bits, la pila es solo W15 apuntando a algún lugar en la memoria principal. Eso facilita el intercambio de tareas. Cada tarea obtiene un área de pila al frente. El intercambio de tareas es empujar los registros en la pila, apuntar W15 a la pila para la nueva tarea, y sacar los registros de la pila.

Recientemente medí el tiempo de bucle de la tarea en un proyecto dsPIC33EP actual. El procesador está funcionando a su velocidad máxima de 70 MHz en el reloj de instrucciones. En este caso, hubo 4 tareas. Éstos debían procesar el flujo UART desde otra micro, recepción de trama CAN de bajo nivel, procesamiento de trama CAN de nivel superior y el bucle de evento principal. Cuando no pasaba nada, el tiempo para un ciclo completo a través de todas las tareas era de 7 µs.

Añadido

Para abordar su ejemplo particular, las lecturas periódicas A / D deben tomarse en una rutina de interrupción. El proceso de SMS debe ser una tarea separada, tal vez dos. No estoy lo suficientemente familiarizado con los SMS para saber si la recepción es realmente asíncrona al envío.

Si es así, use una tarea para manejar lo que venga cada vez que la reciba, y otra tarea para enviar mensajes SMS, con lo que esté esperando en los eventos que puedan incluir. Cuando las tareas de envío de SMS esperan eventos, llama a TASK_YIELD en el bucle, lo que permite que todas las demás tareas continúen mientras esta tarea está bloqueada. Si está esperando las respuestas de SMS, haga que SMS reciba indicadores de conjunto de tareas cada vez que se reciban respuestas particulares. Las tareas de envío de SMS luego esperan en esas banderas, según corresponda.

Todo esto puede manejarse muy bien con tareas múltiples cooperativas. Un RTOS y todo el equipaje que viene con él se interpondría más de lo que ayudaría.

    
respondido por el Olin Lathrop

Lea otras preguntas en las etiquetas