Toda la verdad sobre RTOS de Colin Walls. Artículo # 4. Tareas, cambio de contexto e interrupciones

Identificadores de tareas


Debe poder identificar cada tarea en el sistema. Este requisito es importante para otros objetos del núcleo, pero hay algunos matices en las tareas que corresponden al tema de este artículo.



Los desarrolladores de RTOS utilizan diferentes enfoques para identificar tareas, pero se pueden distinguir cuatro estrategias generales:

  • La tarea se identifica utilizando un puntero a su "bloque de control". Los punteros son siempre únicos y también convenientes de usar, ya que se requiere acceso a la unidad de control para muchas llamadas API. Esto implica que todos los datos de la tarea se almacenan en la memoria de acceso aleatorio (RAM), lo que puede ser ineficiente. Un puntero normalmente ocupa unos 32 bits de memoria.
  • Se puede definir una tarea utilizando un "número de índice" arbitrario. Este valor puede ser útil cuando se otorga acceso a registros en ciertas tablas. Tal identificador puede ocupar ocho o menos bits de memoria, dependiendo de las limitaciones en el número de tareas que admite el RTOS.
  • Algunos RTOS permiten solo una tarea por nivel de prioridad y, por lo tanto, utilizan la prioridad para identificar de forma exclusiva una tarea. Esto significa que la prioridad de la tarea no se puede cambiar. Este enfoque es una variación del enfoque anterior.
  • Las tareas pueden tener nombres que son cadenas de caracteres. Esto puede ser útil para la depuración, pero es poco probable que sea un medio efectivo para identificar una tarea de manera única. Los RTOS que admiten la asignación de nombres de tareas generalmente tienen un identificador adicional (como un puntero) que usan las llamadas API, etc. un buen depurador le permite llamarlos localmente en el host.

Artículos anteriores de la serie:
Artículo # 3. Tareas y planificación
Artículo # 2. RTOS: estructura y modo en tiempo real
Artículo # 1. RTOS: introducción.

Cambio de contexto


El cambio de contexto es el proceso de transferir el control de una tarea a otra. Vale la pena explorar este tema más de cerca, ya que el funcionamiento del cambio de contexto es un principio fundamental del RTOS.

¿Qué es una tarea?


Sabemos que una tarea es un programa casi independiente que comparte el tiempo del procesador con otras tareas bajo el control de RTOS. Pero debes pensar en lo que realmente caracteriza la tarea.

Conjunto de registro


Una tarea es, en última instancia, un conjunto único de valores de registro del procesador. Se cargan en los registros del procesador (es decir, la tarea es actual) o se almacenan en algún lugar hasta el tiempo de ejecución programado. En un mundo ideal, un procesador central tendría varios conjuntos de registros, y cada uno podría asignarse a una tarea separada. Esto se ha implementado para ocasiones especiales. Hace muchos años, la serie TI 9900 de Texas Instruments tenía muchos conjuntos de registros para cada trabajo, pero se implementaron en la memoria principal, lo que limitó el rendimiento. La arquitectura SPARC (utilizada anteriormente en los sistemas de escritorio Unix) admite muchos conjuntos de registros en la "estructura de anillo", pero el número de conjuntos sigue siendo limitado.

Datos internos


La tarea probablemente tendrá su propia pila, cuyo tamaño se puede establecer por separado para cada tarea o puede ser un parámetro global para todas las tareas en el sistema. Esto, junto con los registros, proporciona almacenamiento de datos para tareas específicas. Puede haber otras áreas de memoria para almacenar datos para una tarea específica.

Recursos compartidos


Prácticamente cualquier recurso se puede compartir entre tareas. El código puede ser general: ciertas funciones o el código completo de la tarea. Es necesario asegurarse de que el código sea reentrante, en primer lugar, no se deben usar variables estáticas (especificadas como estáticas o simplemente fuera de la función). Tenga cuidado con los módulos de biblioteca estándar que no están destinados para uso incorporado; Por lo general, tienen muchas funciones poco confiables.

También es posible compartir datos, pero es necesario un control de acceso cuidadoso. Idealmente, solo una tarea es el "propietario" de los datos en un momento dado.

Cómo mantener el contexto


Cuando se reprograma una tarea (es decir, deja de ser actual), su conjunto de registros debe guardarse en algún lugar. Hay al menos dos posibilidades:

  • Los registros se pueden almacenar en una tabla especial para tareas. Puede ser parte de un bloque de control de tareas (TCB). El tamaño es un valor predecible y constante (para una arquitectura de CPU específica).
  • Los registros se pueden insertar en la pila de tareas. Esto requiere la asignación de suficiente espacio de pila adicional y el almacenamiento del puntero (posiblemente en el TCB).

La elección del mecanismo depende de las características de un RTOS particular y del procesador de destino. Algunos dispositivos (generalmente de 32 bits) pueden acceder a la pila de manera eficiente; el resto (por ejemplo, 8 bits) puede ser más óptimo cuando se trabaja con tablas.

Creación dinámica de tareas


El aspecto principal de la arquitectura RTOS es que el RTOS es "estático" o "dinámico".

Cuando se utiliza un RTOS estático, todo se determina durante la compilación de la aplicación, en particular, el número de tareas en el sistema. Esta es una solución lógica para aplicaciones integradas, que generalmente tienen una funcionalidad limitada.

Dynamic RTOS lanza una tarea (que puede ser una tarea "principal" especializada), y también crea y elimina otras tareas según sea necesario. Esto permite que el sistema se adapte a los requisitos cambiantes y es un análogo más cercano del sistema de escritorio, que se comporta de esta manera. La vista estática / dinámica también se aplica a otros objetos del núcleo.

Requisito de creación dinámica de tareas


Esta característica está incluida en la mayoría de los RTOS comerciales. Sin embargo, solo una pequeña parte de las aplicaciones realmente necesita un modo dinámico de operación. Muy a menudo, el sistema se inicia, crea todas las tareas necesarias (y otros objetos) y luego nunca crea y destruye el código de la aplicación. La capacidad de crear tareas dinámicas se ha convertido en una formalidad. Un proveedor lo presentó, todos los demás hicieron lo mismo.

Cabe destacar que el estándar OSEK / VDX requiere una arquitectura estática, aunque esto puede aplicarse a aplicaciones bastante complejas. El resultado de estos requisitos es la incapacidad de implementar OSEK / VDX con un envoltorio, una capa intermedia sobre un RTOS regular (dinámico).

Errores de la creación dinámica de tareas


Hay varios problemas con el modo dinámico de operación que pueden ser problemáticos.

Primero, el sistema se vuelve más complejo, lo que significa que para las estructuras de datos que describen tareas (TCB), se necesita información adicional. Como regla general, se implementan en forma de listas bidireccionales, lo que genera costos asociados con la cantidad de memoria.
Todos los datos que describen la tarea deben almacenarse en la RAM. Esto es ineficiente, ya que la mayoría de ellos pueden ser simplemente elementos de datos persistentes copiados de la ROM. Además, en los procesadores de un nivel inferior (microcontroladores) puede que no obtenga RAM.

Probablemente lo más preocupante es la posibilidad de una escasez impredecible de recursos, que puede conducir a la incapacidad de crear nuevos objetos. Dado que la esencia de un sistema en tiempo real es su previsibilidad, esto es inaceptable. Por lo tanto, se debe tener cuidado al usar la creación de tareas dinámicas (y otros objetos).

Interrupciones


Es posible que se pueda implementar un sistema embebido en tiempo real sin el uso de interrupciones, pero esto no es típico.

Interrupciones y Kernel


Cuando se usa RTOS, un controlador de interrupciones (ISR) se hace lo más fácil posible para "robar" la cantidad mínima de tiempo de procesador de las tareas programadas. A menudo, un dispositivo puede ser simplemente reparado, y cualquier tarea requerida será puesta en cola para su procesamiento. Además, es difícil hablar en general sobre las interrupciones y su interacción con los núcleos, simplemente porque varían mucho. Por un lado, el desarrollador de RTOS puede garantizar que las interrupciones no se relacionen con el núcleo, y el programador tendrá que asegurarse de que el programador de tareas no esté sobrecargado, utilizando mucho tiempo de procesador en el ISR. Por otro lado, el RTOS puede controlar completamente todo el subsistema de interrupción. Ninguno de los enfoques descritos es correcto o incorrecto, simplemente son diferentes.

Guardar contexto


Los ISR siempre necesitan mantener un "contexto" para que el código interrumpible no se vea afectado por los cálculos de ISR. En un sistema implementado sin un RTOS, es simplemente una cuestión de guardar los registros utilizados por el ISR (generalmente en la pila) y restaurarlos antes de regresar. Algunos procesadores tienen una pila ISR dedicada, mientras que otros simplemente usan la misma pila que el código de la aplicación.

Cuando se usa RTOS, el enfoque puede ser exactamente el mismo. Del mismo modo, la pila utilizada por el ISR puede ser "prestada" de la tarea actual, o puede ser otra pila asignada para interrupciones. Algunos núcleos implementan esta característica, incluso si el procesador en sí no admite la pila de interrupciones. La situación se complica si el ISR realiza una llamada a la API que afecta al programador de tareas. Esto puede hacer que la interrupción regrese a otra tarea desde la que se inició cuando ocurrió la interrupción.

Interrupciones y Programador


Hay varias circunstancias en las que el código de ejecución ISR puede volver a otra tarea:

  • ISR puede asignar una prioridad más alta a una tarea ya completada, en lugar de la actual, si se utiliza el programador de tareas prioritarias.
  • ISR puede pausar la tarea actual.
  • Usando el Programador de intervalos de tiempo (TS), el controlador de interrupción del temporizador del sistema controlará los intervalos de tiempo y puede llamar al programador si es necesario.

Temporizador de reloj (Tick Clock)


En los sistemas embebidos, a menudo se encuentra el uso de un "temporizador de reloj" periódico (intervalo de tiempo). En algunos RTOS, es un componente requerido. Por lo general, la presencia de un temporizador de reloj es opcional, y su ausencia simplemente impide la disponibilidad de ciertos servicios. El controlador de interrupción del temporizador generalmente proporciona cuatro funciones:

  • Si se utiliza un programador de intervalos de tiempo, el controlador de interrupción del temporizador controlará el contador de tiempo y programará una nueva tarea cada vez que se agote el tiempo.
  • Proporciona soporte de tiempo del sistema. Esta es principalmente una variable de 32 bits que se incrementa con un temporizador y puede ser predefinida o solicitada por tareas.
  • Si el RTOS proporciona aplicaciones con temporizadores, entonces será compatible con un controlador de interrupción de temporizador que será responsable de la caducidad y la reprogramación.
  • Si el RTOS admite tiempos de espera en el bloqueo de llamadas a la API o las tareas pueden estar en estado de suspensión, el controlador de interrupción del temporizador admitirá estos intervalos de tiempo.

Cuando trabajamos en nuestro propio sistema operativo OSRV MAX en tiempo real (artículos publicados anteriormente sobre él), nuestro equipo "encontró" el blog de Colin Walls, un experto en microelectrónica y firmware en Mentor Graphics. Los artículos parecían interesantes, los tradujeron por sí mismos, pero para no "escribir en la mesa" decidieron publicar. Espero que también te sean útiles. Si es así, entonces planeamos publicar todos los artículos traducidos en la serie.

Sobre el autor: Colin Walls ha trabajado en la industria electrónica durante más de treinta años, dedicando la mayor parte de su tiempo al firmware. Ahora es ingeniero de firmware en Mentor Embedded (una división de Mentor Graphics). Colin Walls a menudo habla en conferencias y seminarios, autor de numerosos artículos técnicos y dos libros sobre firmware. Vive en el Reino Unido. Blog profesional de Colin: blogs.mentor.com/colinwalls, correo electrónico: colin_walls@mentor.com

Lea los artículos primero, segundo y tercero de la serie publicada anteriormente.

Source: https://habr.com/ru/post/es415427/


All Articles