Introduction to RTOS Part 9 - Hardware Interrupts | Digi-Key Electronics

Introduction to RTOS Part 9 - Hardware Interrupts | Digi-Key Electronics

¿Cómo integrar interrupciones de hardware con FreeRTOS?

Introducción a las interrupciones en sistemas embebidos

  • En episodios anteriores, se discutió el uso de ciertas llamadas a funciones de FreeRTOS dentro de rutinas de servicio de interrupción (ISR), destacando la importancia de las interrupciones en sistemas embebidos.
  • Muchos microcontroladores tienen periféricos integrados que generan interrupciones por hardware, como temporizadores o botones pulsados que cambian el voltaje en un pin.
  • Algunos microcontroladores cuentan con buses de comunicación que permiten enviar y recibir datos sin intervención del CPU, notificando al procesador sobre eventos asíncronos mediante señales eléctricas.

Prioridad y manejo de interrupciones

  • Las interrupciones por hardware tienen siempre una prioridad más alta que cualquier tarea en ejecución en FreeRTOS, independientemente de la prioridad asignada a esa tarea.
  • Algunos microcontroladores permiten solo una interrupción por hardware a la vez, mientras que otros permiten interrumpir otras interrupciones (interrupciones anidadas).
  • Al ocurrir una interrupción, se pausa la ejecución actual para ejecutar la ISR asociada; después se regresa a la tarea anterior o puede cambiarse a otra.

Creación y configuración de un temporizador por hardware

  • Se comenzará creando un simple temporizador por hardware en el ESP32, que tiene cuatro temporizadores con un prescaler de 16 bits y un contador de 64 bits.
  • El reloj base del temporizador es 80 MHz; al establecer un divisor adecuado, se puede hacer que el temporizador cuente a diferentes frecuencias. Por ejemplo, configurándolo para contar hasta un millón para obtener una frecuencia de 1 Hz.

Implementación del LED parpadeante

  • Se utilizará el LED integrado del ESP32 y se creará un manejador para este demo utilizando la biblioteca HAL del ESP32 incluida en Arduino.
  • La ISR simplemente alternará el estado del LED. Es importante asegurarse que esta ISR resida en RAM interna para acceso rápido.

Sincronización entre ISRs y tareas

  • En la configuración inicial, se define el pin del LED como salida y se inicia el temporizador con los parámetros especificados.
  • Se configura la ISR como función callback cuando el temporizador alcanza su valor máximo; además, se habilita para recargarse automáticamente tras cada activación.

Modificaciones para sincronización efectiva

  • Se implementa una limitación CPU única y se ajusta el divisor para alcanzar el conteo máximo más rápidamente (en 100 ms).
  • Se introduce una variable global contadora marcada como volatile para indicar al compilador que su valor puede cambiar fuera del contexto actual debido a su uso dentro de ISRs.

Uso seguro de mutexes y sección crítica

  • Para proteger las secciones críticas en FreeRTOS usando ESP-IDF, es necesario emplear "spin locks" que evitan que otras tareas accedan simultáneamente a recursos críticos.

¿Cómo manejar secciones críticas en FreeRTOS?

Secciones Críticas y Tareas

  • Las secciones críticas en ISR deben ser breves; la documentación de FreeRTOS advierte no llamar a otras funciones API dentro de estas secciones. Solo se incrementará una variable global antes de liberar el bloqueo y reactivar las interrupciones.
  • Se creará una tarea llamada "print values" que decrementará un contador global en un bucle, imprimiendo su valor cada vez. Es crucial proteger esta función como sección crítica para evitar problemas con interrupciones.
  • La versión estándar de FreeRTOS simplifica las secciones críticas al no incluir bloqueos por giro (spin locks). Si ocurre una interrupción durante la ejecución, esta no será descartada; el ISR se activará al salir de la sección crítica.
  • La tarea esperará dos segundos para permitir que el ISR incremente la variable global varias veces. En la configuración inicial, se inicia el terminal serial y la tarea correspondiente.
  • Al abrir el terminal serial, observamos que la variable global cuenta hacia abajo desde 19 cada dos segundos, mostrando repeticiones ocasionales debido a las interrupciones esperadas entre las impresiones seriales.

Sincronización entre Tareas e ISRs

  • Existen funciones adicionales en FreeRTOS para sincronizar variables y pasar datos entre ISRs y tareas. Es importante usar solo funciones que terminen con "from isr" cuando se llamen desde un ISR.
  • Se presentará cómo utilizar un semáforo binario dentro de un ISR. Dos tareas operan a diferentes prioridades: una tarea puede ser interrumpida por otra que espera un semáforo, lo cual provoca que el planificador ejecute la única tarea disponible.
  • Cuando el ISR termina su trabajo sobre recursos compartidos (como modificar una variable global), libera el semáforo, permitiendo que la tarea previamente bloqueada continúe su ejecución.
  • El procesamiento del dato debe diferirse a una tarea porque los ISRs deben ser cortos; esto permite que otras tareas tengan oportunidad de ejecutarse mientras los cálculos pesados son manejados posteriormente.
  • En este ejemplo práctico, ajustamos temporizadores para activar el ISR cada segundo y leemos valores del convertidor analógico-digital (ADC), almacenando resultados en una variable global.

Uso Eficiente de Semáforos

  • Utilizamos un semáforo binario para notificar a nuestra tarea lectora cuando es momento de leer desde la variable global. Esto requiere usar funciones especiales "from isr".
  • Estas funciones nunca bloquearán ya que los ISRs no pueden esperar; si intentas tomar un mutex o semáforo sin disponibilidad, deberás manejarlo de manera diferente.
  • Muchas funciones "from isr" tienen parámetros especiales para determinar si desbloquearon alguna nueva tarea debido a acciones previas como liberar un mutex o semáforo.
  • Dentro de nuestra tarea principal, esperamos indefinidamente hasta que esté disponible el semáforo binario liberado por el ISR. Una vez disponible, imprimimos los valores del ADC obtenidos anteriormente.

Ejecución Final y Desafíos

  • Al cargar este código en nuestro ESP32, deberíamos ver valores del ADC impresos en terminal cada segundo. Este método es efectivo para hacer esperar a una tarea hasta recibir datos disponibles desde un ISR.

Sincronización de Tareas e Interrupciones en RTOS

Diseño de un Sistema con Buffer Doble

  • Se recomienda utilizar un buffer doble o circular para manejar la recolección de datos, permitiendo que una parte sea leída mientras la otra se llena. Esto es crucial para el cálculo del promedio de 10 muestras.
  • La tarea B debe gestionar el terminal serial, haciendo eco de cualquier carácter recibido y mostrando el valor del promedio cuando se ingresa el comando "avg".
  • Es importante considerar cómo manejar los desbordamientos del buffer, donde la interrupción intenta escribir en un elemento que aún no ha sido leído por la tarea A.

Aplicaciones Prácticas y Ejemplos

  • Este diseño es común en sistemas operativos en tiempo real (RTOS), donde una tarea realiza cálculos complejos sobre datos entrantes mientras otra maneja la entrada/salida del usuario.
  • Idealmente, se podría usar un controlador de acceso a memoria directa (DMA) para ayudar con la muestreo de datos, aunque la sincronización entre tareas e interrupciones seguiría siendo similar.

Desafíos y Consideraciones Futuras

  • Al ingresar "avg", se muestra el promedio más reciente calculado. Este ejercicio integra muchos conceptos previos aprendidos.
Video description

Hardware interrupts are important in many embedded systems. They allow us to respond to external events (such as a button being pressed) or internal events (such as a timer expiring) in an asynchronous manner, which means that the processor can stop whatever it was doing to run an interrupt service routine (ISR). The solution to the challenge in the video can be found here: https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-9-hardware-interrupts/3ae7a68462584e1eb408e1638002e9ed Code for this video series (including demonstrations, challenges, and solutions) can be found here: https://github.com/ShawnHymel/introduction-to-rtos In most RTOSes, such as FreeRTOS, hardware interrupts occur at a higher priority than all other tasks. This means, unless specifically disabled, hardware interrupts will halt the execution of any currently running task. The CPU will be forced to handle the interrupt before returning to the task. A few tips when working with interrupts: ISRs should never block, which means you should only use FreeRTOS kernel function calls that end in “FromISR” You should keep ISRs as short as possible to avoid delaying tasks longer than necessary Any global variables that get updated in an ISR should be declared with the “volatile” qualifier Rather than perform processing inside an ISR, you can “defer processing” by collecting data into a buffer and letting a task do the processinging. In the video, we look at how to accomplish deferred processing using semaphores (note that you can also use queues and task notifications). When an ISR is done, it can set a lock (e.g. “give” a semaphore), which will unblock a task. This task can then use any data collected by the ISR (e.g. a new ADC value, a buffer filled with data from the serial port, etc.). With this method, you can keep ISRs short while relying on a task to perform any necessary processing. Product Links: https://www.digikey.com/en/products/d...​ Related Videos: Introduction to RTOS Part 1 - What is a Real-Time Operating System (RTOS)? - https://youtu.be/F321087yYy4​ Introduction to RTOS Part 2 - Getting Started with FreeRTOS - https://youtu.be/JIr7Xm_riRs​ Introduction to RTOS Part 3 - Task Scheduling - https://youtu.be/95yUbClyf3E​ Introduction to RTOS Part 4 - Memory Management - https://youtu.be/Qske3yZRW5I​ Introduction to RTOS Part 5 - Queue - https://youtu.be/pHJ3lxOoWeI​ Introduction to RTOS Part 6 - Mutex - https://youtu.be/I55auRpbiTs​ Introduction to RTOS Part 7 - https://youtu.be/5JcMtbA9QEE​ Introduction to RTOS Part 8 - https://youtu.be/b1f1Iex0Tso Introduction to RTOS Part 9 - https://youtu.be/qsflCf6ahXU Introduction to RTOS Part 10 - https://youtu.be/hRsWi4HIENc Introduction to RTOS Part 11 - https://youtu.be/C2xKhxROmhA Introduction to RTOS Part 12 - https://youtu.be/LPSHUcH5aQc Related Project Links: https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-9-hardware-interrupts/3ae7a68462584e1eb408e1638002e9ed Related Articles: https://www.digikey.com/en/maker/videos/shawn-hymel/getting-started-with-stm32-and-nucleo-part-3-how-to-run-multiple-threads-with-cmsis-rtos-interface Learn more: Maker.io - https://www.digikey.com/en/maker Digi-Key’s Blog – TheCircuit https://www.digikey.com/en/blog Connect with Digi-Key on Facebook https://www.facebook.com/digikey.electronics/ And follow us on Twitter https://twitter.com/digikey