
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 datosArtículo # 14. Secciones de memoria: introducción y servicios básicos.Artículo 13. Estructuras de datos de tareas y llamadas de API no compatiblesArtículo # 12. Servicios para trabajar con tareas.Artículo # 11. Tareas: configuración e introducción a la APIArtículo # 10. Programador: funciones avanzadas y preservación del contextoArtículo # 9. Programador: implementaciónArtículo # 8. Nucleus SE: diseño interno y despliegueArtículo # 7. Núcleo SE: IntroducciónArtículo # 6. Otros servicios RTOSArtículo # 5. Interacción de tareas y sincronizaciónArtículo # 4. Tareas, cambio de contexto e interrupcionesArtículo # 3. Tareas y planificaciónArtí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 #define NUSE_SIGNALS_SEND FALSE #define NUSE_SIGNALS_RECEIVE FALSE
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 RTOSPrototipo 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 SEEsta 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 SEA 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 RTOSPrototipo 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 SEEsta 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 SEEl 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.