6 votos

RTOS: ¿Por qué necesitamos versiones especiales para los ISR?

En algunos kernels de RT, si se quiere enviar a un semáforo o bandera desde un ISR, se necesita llamar a una versión especial del método, en lugar de la normal llamada desde una tarea normal. Ejemplos:

Sin embargo, hay otros núcleos en los que esto no es necesario. Por ejemplo:

  • OSSemPost() en uC/OS pueden ser llamados tanto desde tareas como desde ISRs.
  • release() en mbed-rtos, puede ser llamado desde Threads e ISRs.
  • semGive() en VxWorks parece que se puede llamar desde un ISR según los documentos, y a primera vista no existe ningún método especial para los ISR.

¿Por qué hay que crear versiones especiales? Entiendo que la publicación de un semáforo o bandera puede hacer que se despierte una tarea bloqueada de mayor prioridad. Y es por eso que el planificador es más probable que se ejecute cuando se llama a la llamada de retorno de salida de la ISR (me refiero a esas funciones necesarias para ser llamadas cuando se quiere usar código del kernel dentro de la ISR, como portEXIT_SWITCHING_ISR() en FreeRTOS, o OSIntExit en uC/OS). Entonces, ¿por qué el método especial post además de la llamada ISRexit?

7voto

alex Puntos 3964

He estado leyendo el código fuente tanto de FreeRTOS como de CoOS.

En FreeRTOS (el puerto que encontré primero en Google), el xSemaphoreGiveFromISR() llamadas a la función xQueueGenericSendFromISR() y esta función tenía este comentario:

/* Similar to xQueueGenericSend, except we don't block if there is no room
    in the queue.  Also we don't directly wake a task that was blocked on a
    queue read, instead we return a flag to say whether a context switch is
    required or not (i.e. has a task with a higher priority than us been woken
    by this post). */

En cuanto a CoOS, la función isr_PostSem llamado desde un ISR sólo pone en cola una solicitud en la llamada "cola de solicitudes de servicio", utilizando la función InsertInSRQ . No tengo ni idea de lo que es esta cola, probablemente es alguna tarea del sistema para descargar el trabajo de los ISRs y así dejar que las interrupciones se completen rápidamente.

En cuanto a mbed, que sólo tiene 1 versión del método, está basado en CMSIS RTOS, y hay una llamada a la función osSemaphoreRelease() . Hay un comentario sobre esta y otras funciones similares:

The following CMSIS-RTOS functions can be called from threads and interrupt
service routines (ISR):
  - osSignalSet
  - osSemaphoreRelease
  - osPoolAlloc, osPoolCAlloc, osPoolFree
  - osMessagePut, osMessageGet
  - osMailAlloc, osMailCAlloc, osMailGet, osMailPut, osMailFree

Functions that cannot be called from an ISR are verifying the interrupt
status and return in case that they are called from an ISR context the status
code osErrorISR. In some implementations this condition might be caught using
the HARD FAULT vector.

Así que parece ser sólo el diseño del kernel, algunos diseñadores optaron por tener funciones separadas y dejar que el programador hiciera la distinción, y otros prefirieron tener sólo un método y comprobar internamente si la llamada se hizo desde un ISR.

0 votos

¡+1 por encontrar realmente la fuente y los comentarios que explican cuál es la diferencia y por qué!

5voto

GSerg Puntos 33571

En muchas arquitecturas de microcontroladores pequeños, no existe una verdadera pila de datos para las variables automáticas. En su lugar, dichas variables se asignan estáticamente, utilizando una función de análisis que tiene en cuenta todo el "árbol" de llamadas a funciones para asegurarse de que se conserva (la mayor parte) de la funcionalidad de una pila.

Una implicación de esto es que las funciones individuales no pueden ser reentrantes, al menos, no sin una gran sobrecarga. Si intentas llamar a una función desde un ISR, podrías estar interrumpiendo la misma función que ha sido llamada desde el código principal. Esencialmente, cada ISR tiene su propio "árbol" de llamadas a funciones (normalmente un árbol muy pequeño), y todos esos árboles tienen que ser físicamente distintos en términos de la RAM de datos que utilizan.

Por lo tanto, cada función debe ser asignada a un árbol u otro, y se necesitan copias separadas de las funciones que pueden ser llamadas desde varios árboles.

Creo que encontrarás que las implementaciones de RTOS que tienen funciones separadas están dirigidas a esas arquitecturas de procesadores más pequeños, mientras que las que no las tienen están dirigidas completamente a arquitecturas que tienen verdaderas pilas de datos.

0 votos

Buen punto, pero no creo que este sea el problema, ya que la mayoría de los RTOS están dirigidos a microcontroladores de 32 bits. No puedo decir acerca de algunos puertos FreeRTOS, pero estoy seguro de que he llamado funciones recursivas en CoOS (hasta que me quedé sin pila lol).

0 votos

"La mayoría" no es "todos". Sé que algunos de esos RTOS tienen puertos para PICs de 8 bits y 8051s, que son dos ejemplos de arquitecturas que no tienen verdaderas pilas de datos. Es posible que hayas estado usando CoOS en una arquitectura (y compilador) que no tenía esta restricción.

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