Toda la verdad sobre RTOS. Artículo # 16. Señales



Este artículo analizará las señales, que son los mecanismos más simples de interacción entre tareas en Nucleus SE. Proporcionan una forma económica de transferir mensajes simples entre tareas.


Artículos anteriores de la serie:
Artículo # 15. Particiones de memoria: servicios y estructuras de datos
Artículo # 14. Secciones de memoria: introducción y servicios básicos.
Artículo 13. Estructuras de datos de tareas y llamadas de API no compatibles
Artículo # 12. Servicios para trabajar con tareas.
Artículo # 11. Tareas: configuración e introducción a la API
Artículo # 10. Programador: funciones avanzadas y preservación del contexto
Artículo # 9. Programador: implementación
Artículo # 8. Nucleus SE: diseño interno y despliegue
Artículo # 7. Núcleo SE: Introducción
Artículo # 6. Otros servicios RTOS
Artículo # 5. Interacción de tareas y sincronización
Artículo # 4. Tareas, cambio de contexto e interrupciones
Artículo # 3. Tareas y planificación
Artículo # 2. RTOS: estructura y modo en tiempo real
Artículo # 1. RTOS: introducción.

Usando señales


Las señales difieren de todos los demás tipos de objetos del núcleo en que no son autónomas: las señales están asociadas con tareas y no pueden existir sin ellas. Si la aplicación está configurada para usar señales, cada tarea tiene un conjunto de ocho indicadores de señal.

Cualquier tarea puede establecer señales para otra tarea. Las señales solo pueden ser leídas por el propietario de la señal. Durante la lectura, las señales se reinician. Las tareas no pueden leer o restablecer señales de otras tareas.

Nucleus RTOS tiene una herramienta que permite a las tareas asignar funciones que se ejecutan cuando otra tarea establece uno o más indicadores de señal. Esto recuerda un poco a una rutina de procesamiento de interrupciones. Esta característica no es compatible con Nucleus SE; aquí, las tareas deben solicitar indicadores de señal explícitamente.

Configuración de señal


Como con la mayoría de los objetos Nucleus SE, la sintonización de señal está determinada por las directivas #define en nuse_config.h . El parámetro principal es NUSE_SIGNAL_SUPPORT , que activa el soporte de funcionalidad (para todas las tareas en la aplicación). La cuestión de indicar el número de señales no vale la pena: se asignan 8 banderas para cada tarea.

Establecer este parámetro de habilitación sirve como activador de señal principal. Esto proporciona una estructura de datos bien definida que tiene un tamaño apropiado. Además, esta opción activa la configuración de la API.

Activar llamadas API


Cada función API (llamada de utilidad) en Nucleus SE se activa mediante la directiva #define en nuse_config.h . Para señales, estas incluyen:

NUSE_SIGNALS_SEND NUSE_SIGNALS_RECEIVE 

Por defecto, están configurados en FALSO , deshabilitando así cada llamada de servicio y evitando que el código que los implementa se active. Para configurar las señales en la aplicación, debe seleccionar las llamadas API requeridas y establecer las directivas correspondientes en TRUE .

Lo siguiente es un extracto del archivo predeterminado nuse_config.h :

 #define NUSE_SIGNAL_SUPPORT FALSE /* Enables support for signals */ #define NUSE_SIGNALS_SEND FALSE /* Service call enabler */ #define NUSE_SIGNALS_RECEIVE FALSE /* Service call enabler */ 

Una función API activada con el soporte de señalización desactivado dará como resultado un error de compilación. Si su código usa una llamada API que no ha sido activada, se producirá un error de diseño porque el código de implementación no se incluyó en la aplicación. Por supuesto, la inclusión de dos funciones API es algo innecesaria, ya que no tiene sentido activar el soporte de señal en ausencia de estas API. Se han agregado activadores para compatibilidad con otras características de Nucleus SE.

Señales de llamada


Nucleus RTOS admite cuatro llamadas aéreas relacionadas con la señal que proporcionan la siguiente funcionalidad:

  • Enviar señales a una tarea determinada. Nucleus SE se implementa en la función NUSE_Signals_Send () .
  • Recepción de señales. Nucleus SE se implementa en la función NUSE_Signals_Receive () .
  • Registro de manejador de señal. No implementado en Nucleus SE.
  • Encienda / apague (control) las señales. No implementado en Nucleus SE.

La implementación de cada uno de estos desafíos se analiza en detalle a continuación.

Servicios de señalización y recepción.


Las operaciones fundamentales que se pueden realizar en un conjunto de señales de tareas son enviar datos (puede realizarse mediante cualquier tarea) y leer datos (por lo tanto, borrar los datos solo puede realizarlos la tarea del propietario). Nucleus RTOS y Nucleus SE proporcionan dos llamadas API básicas para estas operaciones, que se describirán a continuación.

Como las señales son bits, se visualizan mejor como números binarios. Dado que el estándar C históricamente no ha admitido la representación de constantes binarias (solo octales y hexadecimales), Nucleus SE tiene un útil archivo de encabezado nuse_binary.h , que contiene caracteres #definidos como b01010101 para todos los 256 valores de 8 bits. Lo siguiente es un extracto del archivo nuse_binary.h :

 #define b00000000 ((U8) 0x00) #define b00000001 ((U8) 0x01) #define b00000010 ((U8) 0x02) #define b00000011 ((U8) 0x03) #define b00000100 ((U8) 0x04) #define b00000101 ((U8) 0x05) 

Enviando señales


Cualquier tarea puede enviar señales a cualquier otra tarea en la aplicación. El envío de señales implica establecer uno o más indicadores de señal. Esta es una operación OR que no afecta a las marcas establecidas previamente.

Llamar para enviar señales a Nucleus RTOS
Prototipo de llamada de servicio:
ESTADO NU_Send_Signals (tarea NU_TASK *, señales NO FIRMADAS);

Parámetros:

tarea : puntero a la unidad de control de tareas a la que pertenecen los indicadores de señal establecidos;
señales : el valor de las banderas de señal establecidas.

Valor de retorno:

NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_TASK : puntero no válido a la tarea;

Llamar para enviar señales a Nucleus SE
Esta llamada a la API admite la funcionalidad principal de la API Nucleus RTOS.

Prototipo de llamada de servicio:

STATUS_NUSE_Signals_Send (tarea NUSE_TASK, señales U8);

Parámetros:

tarea : índice (ID) de la tarea a la que pertenecen los indicadores de señal establecidos;
señales : el valor de las banderas de señal establecidas.

Valor de retorno:

NUSE_SUCCESS : la llamada de servicio se completó con éxito;
NUSE_INVALID_TASK : índice de tarea no válido.

Implementación de señalización en Nucleus SE
A continuación se muestra el código completo para la función NUSE_Signals_Send ():

 STATUS NUSE_Signals_Send(NUSE_TASK task, U8 signals) { #if NUSE_API_PARAMETER_CHECKING if (task >= NUSE_TASK_NUMBER) { return NUSE_INVALID_TASK; } #endif NUSE_CS_Enter(); NUSE_Task_Signal_Flags[task] |= signals; NUSE_CS_Exit(); return NUSE_SUCCESS; } 

El código es muy simple. Después de cualquier verificación de los parámetros, los valores de la señal pasan a través de la operación OR en los indicadores de señal de la tarea especificada. Las tareas de bloqueo no afectan las señales.

Recepción de señales


Una tarea solo puede leer su propio conjunto de indicadores de señal. Durante la lectura, los valores del indicador se restablecen.

Llamada para recibir señales en Nucleus RTOS
Prototipo de llamada de servicio:
NO FIRMADO NU_Receive_Signals (VOID);

Parámetros: ninguno.

Valor de retorno:
Valores de bandera de señal.

Llamar para recibir señales en Nucleus SE
Esta llamada a la API admite la funcionalidad principal de la API Nucleus RTOS.

Prototipo de llamada de servicio:
U8 NUSE_Signals_Receive (nulo);

Parámetros: ninguno.

Valor de retorno:
Valores de bandera de señal.

Implementación de la recepción de señal de Nucleus SE
El siguiente es el código completo para la función NUSE_Signals_Receive () :

 U8 NUSE_Signals_Receive(void) { U8 signals; NUSE_CS_Enter(); Signals = NUSE_Task_Signal_Flags[NUSE_Task_Active]; NUSE_Task_Signal_Flags[NUSE_Task_Active] = 0; NUSE_CS_Exit(); return signals; } 

El código es muy simple. Se copia el valor de las banderas, se restablece el valor inicial y la función API devuelve la copia. Las tareas de bloqueo no afectan las señales.

Estructuras de datos


Como las señales no son objetos independientes, el uso de la memoria depende de las tareas a las que pertenecen. A continuación hay información para una comprensión completa. Las señales usan una estructura de datos (en RAM), que, como otros objetos de Nucleus SE, es una tabla cuyas dimensiones corresponden al número de tareas en la aplicación. Esta estructura de datos solo se usa si el soporte de señal está habilitado.

Recomiendo encarecidamente que el código de la aplicación no acceda a esta estructura de datos directamente, sino que use las funciones API disponibles. Esto evita la incompatibilidad con futuras versiones de Nucleus SE, efectos secundarios no deseados, y también simplifica la transferencia de la aplicación a Nucleus RTOS. La estructura de datos se discute en detalle a continuación para simplificar la comprensión de la llamada de servicio y los principios de depuración.

La estructura de los datos colocados en la RAM.


Estructura de datos:
NUSE_Task_Signal_Flags [] : una matriz de tipo U8 con una entrada para cada tarea configurada, los indicadores de señal se almacenan en esta matriz.

Esta estructura de datos se inicializa a ceros mediante la función NUSE_Init_Task () al cargar Nucleus SE.

Estructura de datos colocados en ROM


Las señales carecen de estructuras de datos en ROM.

Cantidades de memoria para almacenar datos de señal


Al igual que con todos los objetos centrales de Nucleus SE, la cantidad de memoria requerida para las señales es predecible.

La cantidad de datos en la ROM para todas las señales en la aplicación es 0.

La cantidad de memoria para almacenar datos en RAM (en bytes) para todas las señales en la aplicación es igual al número de tareas configuradas ( NUSE_TASK_NUMBER ). Pero, de hecho, estos datos pertenecen a las tareas y se describen en el artículo anterior sobre las tareas.

Llamadas API no realizadas


No se implementan dos llamadas de señalización API Nucleus RTOS en Nucleus SE:

Registro de controlador de señal


Esta llamada API configura el procedimiento de procesamiento de señal (función) para la tarea actual. Nucleus SE no necesita esto porque los manejadores de señal no son compatibles.

Prototipo de llamada de servicio:
ESTADO NU_Register_Signal_Handler (VOID (* signal_handler) (UNSIGNED));

Parámetros:
signal_handler : una función que se debe invocar al recibir señales

Valor de retorno:
NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_POINTER : puntero nulo al controlador de señal ( NULL )

Control (activación / desactivación) de señales


Este servicio activa y / o desactiva señales para la tarea actual. Para cada tarea, hay 32 señales disponibles. Cada señal está representada por un bit en signal_enable_mask . Agregar un bit a signal_enable_mask habilita la señal correspondiente, y eliminar un bit la deshabilita.

Prototipo de llamada de servicio:
UNSIGNED NU_Control_Signals (UNSIGNED enable_signal_mask);

Parámetros:
enable_signal_mask : patrón de bits que representa las señales correctas.

Valor de retorno:
Máscara para activar / desactivar la señal anterior.

Nucleus RTOS Compatible


Al desarrollar Nucleus SE, mi objetivo era mantener el nivel de código compatible con Nucleus RTOS. Las señales no son una excepción y, desde el punto de vista del desarrollador, se implementan de la misma manera que en Nucleus RTOS. Hay algunas incompatibilidades que considero válidas, dado que el código final es mucho más fácil de entender y puede usar la memoria de manera más eficiente. De lo contrario, las llamadas a la API Nucleus RTOS se pueden transferir casi directamente a las llamadas de Nucleus SE.

Manejadores de señal


En Nucleus SE, los manejadores de señales no se implementan para simplificar la estructura general.

Disponibilidad de señal y cantidad


En Nucleus RTOS, las tareas pueden tener 32 señales de señal. En Nucleus SE, decidí reducir su número a ocho, ya que esto será suficiente para aplicaciones más simples y ahorrará recursos de RAM. Si es necesario, las señales se pueden desactivar por completo.

Llamadas API no realizadas


Nucleus RTOS admite cuatro llamadas de servicio de señalización. De estos, dos no se implementaron en Nucleus SE. Su descripción se puede encontrar arriba en la sección "Llamadas API no realizadas".

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 , correo electrónico: colin_walls@mentor.com.

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


All Articles