
Este artículo continúa la revisión de los buzones que comenzó en el artículo anterior de la serie "La verdad sobre RTOS".
Artículos anteriores de la serie:
Artículo # 21. Buzones: Introducción y servicios básicosArtículo # 20. Semáforos: servicios auxiliares y estructuras de datosArtículo # 19. Semáforos: introducción y servicios básicos.Artículo # 18. Grupos de banderas de eventos: servicios auxiliares y estructuras de datosArtículo # 17. Grupos de banderas de eventos: Introducción y servicios básicosArtículo # 16. SeñalesArtí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.
Servicios de buzones auxiliares
Nucleus RTOS tiene cuatro llamadas API que proporcionan funciones auxiliares relacionadas con los buzones: descartar un buzón, recuperar información sobre un buzón, recuperar el número de buzones en una aplicación y recuperar punteros a todos los buzones de una aplicación. Las primeras tres de estas características se implementan en Nucleus SE.
Restablecer buzón
Esta llamada de servicio API restablece el buzón a su estado inicial, no utilizado. El mensaje almacenado en el buzón se perderá. Cualquier tarea suspendida en el buzón se reanudará con el código de retorno
NUSE_MAILBOX_WAS_RESET .
Llame para restablecer un buzón en Nucleus RTOSPrototipo de llamada de servicio:
ESTADO NU_Reset_Mailbox (buzón NU_MAILBOX *);Parámetros:
buzón : un puntero a la unidad de control del buzón.
Valor de retorno:
NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_MAILBOX : puntero de buzón no válido.
Llame para restablecer un buzón en Nucleus SEEsta llamada de servicio API admite la funcionalidad principal de la API Nucleus RTOS.
Prototipo de llamada de servicio:
ESTADO NUSE_Mailbox_Reset (buzón NUSE_MAILBOX);Parámetros:
buzón - índice (ID) del buzón volcado.
Valor de retorno:NUSE_SUCCESS : la llamada se completó correctamente;
NUSE_INVALID_MAILBOX : índice de buzón no válido.
Implementar restablecimiento de buzón en Nucleus SEEl código de opción para la función
NUSE_Mailbox_Reset (después de verificar los parámetros) se selecciona mediante compilación condicional, dependiendo de si el soporte para tareas de bloqueo (pausa) está activado o no. Consideraremos ambas opciones.
Si el bloqueo no está activado, el código para esta función API es bastante simple. El buzón se marca como no utilizado estableciendo el parámetro
NUSE_Mailbox_Status [] en
FALSE .
Si el bloqueo está activado, el código se vuelve más complejo:
while (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; /* check whether any tasks are blocked */ /* on this mailbox */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { NUSE_Task_Blocking_Return[index] = NUSE_MAILBOX_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Mailbox_Blocking_Count[mailbox]--; } #if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK); #endif
El buzón se restablece al estado "Vacío".
A cada tarea suspendida en el buzón se le asigna el estado "Listo" con el código de retorno
NUSE_MAILBOX_WAS_RESET . Una vez completado este proceso, si se utiliza el planificador prioritario, se realiza la llamada de servicio
NUSE_Reschedule () , ya que una o más tareas con una prioridad más alta podrían estar listas y esperar el permiso para ejecutarse.
Recuperando información del buzón
Esta llamada de servicio proporciona un conjunto de información del buzón. La implementación de esta llamada en Nucleus SE difiere de Nucleus RTOS en que devuelve menos información, ya que los nombres de objetos y el orden de la pausa no son compatibles, y la pausa de la tarea puede desactivarse.
Llame para obtener información del buzón Nucleus RTOSEsta llamada a la API admite la funcionalidad principal de la API Nucleus RTOS.
Prototipo de llamada de servicio:
ESTADO NU_Mailbox_Information (NU_MAILBOX * buzón, CHAR * nombre, OPTION * suspend_type, DATA_ELEMENT * message_present, UNSIGNED * tareas_waiting, NU_TASK ** first_task);Parámetros:
buzón - puntero a la unidad de control del buzón;
nombre : un puntero de 8 caracteres al nombre del buzón. El byte nulo de terminación también se incluye en esta área;
suspend_type : puntero a la variable en la que se almacena el tipo de suspensión de la tarea. Puede tomar los valores
NU_FIFO y
NU_PRIORITY ;
message_present : un puntero a una variable que tomará el valor
NU_TRUE o
NU_FALSE , dependiendo de si el buzón está lleno o no;
task_waiting : un puntero a una variable que tomará la cantidad de tareas suspendidas en este buzón;
first_task : un puntero a un puntero de tarea que llevará un puntero a la primera tarea en pausa.
Valor de retorno:
NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_MAILBOX : puntero de buzón no válido.
Llame para obtener información sobre el buzón de correo de Nucleus SEEsta llamada de servicio API admite la funcionalidad principal de la API Nucleus RTOS.
Prototipo de llamada de servicio:
ESTADO NUSE_Mailbox_Information (buzón NUSE_MAILBOX, U8 * mensaje_presentante, U8 * tareas_en espera, NUSE_TASK * primera_tarea);Parámetros:
buzón - índice del buzón sobre el que se solicita información;
message_present : un puntero a una variable que toma el valor
VERDADERO o
FALSO , dependiendo de si el buzón está lleno o no;
task_waiting : un puntero a una variable que tomará la cantidad de tareas suspendidas en este buzón (no se devuelve nada si la suspensión de tareas está desactivada);
first_task : un puntero a una variable del tipo
NUSE_TASK , que tomará el índice de la primera tarea suspendida (no se devuelve nada si la suspensión de la tarea está desactivada).
Valor de retorno:
NUSE_SUCCESS : la llamada se completó correctamente;
NUSE_INVALID_MAILBOX : índice de buzón no válido;
NUSE_INVALID_POINTER : uno o más parámetros de puntero son incorrectos.
Implementación de información de buzón en Nucleus SELa implementación de esta llamada API es bastante simple:
*message_present = NUSE_Mailbox_Status[mailbox]; #if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Mailbox_Blocking_Count[mailbox]; if (NUSE_Mailbox_Blocking_Count[mailbox] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_MAILBOX_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == mailbox)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif return NUSE_SUCCESS;
La función devuelve el estado del buzón. Luego, si se activan las llamadas de servicio para bloquear tareas, se devuelve el número de tareas suspendidas y el índice de la primera (de lo contrario, estos parámetros se establecen en 0).
Obtener el número de buzones
Esta llamada de utilidad devuelve el número de buzones en la aplicación. Mientras que en Nucleus RTOS su número puede cambiar con el tiempo, y el valor de retorno mostrará el número actual de buzones, en Nucleus SE el número de buzones se establece en la etapa de compilación y no se puede cambiar.
Llamar a un contador de buzón en Nucleus RTOSEsta llamada a la API admite la funcionalidad principal de la API Nucleus RTOS.
Prototipo de llamada de servicio:
NU_SIGNED NU_Established_Mailboxes (VOID);Parámetros:
Están ausentes
Valor de retorno:
El número de buzones creados en la aplicación.
Llamar a un contador de buzón en Nucleus SEEsta llamada a la API admite la funcionalidad principal de la API Nucleus RTOS.
Prototipo de llamada de servicio:
U8 NUSE_Mailbox_Count (nulo);Parámetros:
Están ausentes
Valor de retorno:
El número de buzones configurados en la aplicación.
Implementación de un contador de buzones en Nucleus SELa implementación de esta llamada API es extremadamente simple: se
devuelve el valor de la directiva
#define NUSE_MAILBOX_NUMBER .
Estructuras de datos
Los buzones utilizan dos o tres matrices de estructuras de datos (todas las cuales se encuentran en la RAM), que, como otros objetos de Nucleus SE, son un conjunto de tablas cuyo tamaño depende del número de buzones configurados y sus parámetros.
Recomiendo encarecidamente que el código de la aplicación no utilice el acceso directo a estas estructuras de datos, sino que se refiera a ellas a través de las funciones API proporcionadas. Esto evita la incompatibilidad con futuras versiones de Nucleus SE y los efectos secundarios no deseados, y también simplifica la transferencia de la aplicación a Nucleus RTOS. La siguiente es una descripción detallada de las estructuras de datos para una mejor comprensión de cómo funciona el código de llamada de servicio y para la depuración.
Datos de RAM
Estos datos tienen la siguiente estructura:
NUSE_Mailbox_Data [] : una matriz de tipo
ADDR que tiene una entrada para cada buzón configurado, almacena los datos del buzón.
NUSE_Mailbox_Status [] es una matriz
U8 que tiene una entrada para cada buzón configurado, supervisa el uso de los buzones. Un valor distinto de cero (
VERDADERO ) indica que el buzón está lleno.
NUSE_Mailbox_Blocking_Count [] : una matriz de tipo
U8 , contiene un contador de tareas bloqueadas para cada buzón. Esta matriz solo se crea si la funcionalidad de bloqueo de llamadas API está activada.
Estas estructuras de datos se inicializan con ceros en la función
NUSE_Init_Mailbox () cuando se inicia Nucleus SE. Esto es lógico, ya que cada buzón se crea vacío (sin usar).
Las siguientes son las definiciones de estas estructuras de datos del archivo
nuse_init.c .
RAM ADDR NUSE_Mailbox_Data[NUSE_MAILBOX_NUMBER]; RAM U8 NUSE_Mailbox_Status[NUSE_MAILBOX_NUMBER]; #if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Mailbox_Blocking_Count[NUSE_MAILBOX_NUMBER]; #endif
Datos ROM
Para la implementación de buzones, no se utilizan datos en ROM.
La cantidad de memoria para buzones
Al igual que con todos los objetos del núcleo de Nucleus SE, la cantidad de memoria requerida para los buzones se conoce de antemano.
La cantidad de memoria para datos en ROM para todos los buzones de la aplicación es 0.
La cantidad de datos en RAM para todos los buzones de la aplicación (en bytes) con llamadas API activadas para bloquear tareas se puede calcular de la siguiente manera:
NUSE_MAILBOX_NUMBER * (sizeof (ADDR) +2)De lo contrario:
NUSE_MAILBOX_NUMBER * (sizeof (ADDR) +1)Llamadas API no realizadas
Las cuatro llamadas de utilidad que se pueden encontrar en Nucleus RTOS no se implementan en Nucleus SE.
Crear buzón
Esta llamada de servicio API crea un buzón. Nucleus SE no lo necesita, ya que los buzones se crean de forma estática.
Prototipo de llamada de servicio:
ESTADO NU_Create_Mailbox (buzón NU_MAILBOX *, CHAR * nombre, OPCIÓN NO FIRMADA suspend_type);Parámetros:
buzón : un puntero a la unidad de control del buzón proporcionado por el usuario; Se usa para administrar buzones en otras llamadas API
nombre : puntero al nombre de 7 caracteres del buzón con cero bytes de terminación;
suspend_type : indica el principio de suspender una tarea en un buzón. Puede tomar los valores
NU_FIFO y
NU_PRIORITY , que significan el principio FIFO (Primero en
entrar , primero en salir) o el principio de prioridad de suspensión de tareas, respectivamente.
Valor de retorno:
NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_MAILBOX : puntero nulo a la unidad de control del buzón (
NULL ), o el puntero ya está en uso;
NU_INVALID_SUSPEND : parámetro inválido
suspend_type .
Eliminar un buzón
Esta llamada al servicio API elimina un buzón creado previamente. Nucleus SE no necesita esto, porque los buzones se crean de forma estática y no se pueden eliminar.
Prototipo de llamada de servicio:
ESTADO NU_Delete_Mailbox (buzón NU_MAILBOX *);Parámetros:
buzón : un puntero a la unidad de control del buzón.
Valor de retorno:
NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_MAILBOX : puntero de buzón no válido.
Punteros de buzón
Esta llamada a la API forma una lista secuencial de punteros a todos los buzones del sistema. Nucleus SE no lo necesita, ya que los buzones se identifican mediante un índice simple, no un puntero.
Prototipo de llamada de servicio:
UNSIGNED NU_Mailbox_Pointers (NU_MAILBOX ** pointer_list, UNSIGNED maximum_pointers);Parámetros:
pointer_list : puntero a una matriz de punteros
NU_MAILBOX ; esta matriz se llenará con punteros a los buzones creados en el sistema;
maximum_pointers : el número máximo de punteros en la matriz.
Valor de retorno:
El número de punteros
NU_MAILBOX en la matriz.
Grabe un mensaje en el buzón para entregarlo a todos los destinatarios
Esta llamada de servicio envía un mensaje a todas las tareas que están esperando mensajes de un buzón específico. En Nucleus SE, esta llamada de utilidad no se implementa, ya que agregaría una complejidad innecesaria.
Prototipo de llamada de servicio:
ESTADO NU_Broadcast_To_Mailbox (buzón NU_MAILBOX *, mensaje VOID *, suspensión NO FIRMADA);Parámetros:
buzón - puntero a la unidad de control del buzón;
mensaje : puntero al mensaje transmitido;
suspender : indica si se suspende la tarea de llamada si el buzón ya contiene un mensaje; puede ser
NU_NO_SUSPEND ,
NU_SUSPEND o un valor de tiempo de espera.
Valor de retorno:
NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_MAILBOX : puntero de buzón no válido;
NU_INVALID_POINTER : puntero nulo a un mensaje (
NULL );
NU_INVALID_SUSPEND : intento de suspender un hilo no relacionado con la tarea;
NU_MAILBOX_FULL : el buzón ya contiene un mensaje;
NU_TIMEOUT : una vez que caduca el tiempo de espera, el buzón sigue lleno;
NU_MAILBOX_DELETED : el buzón se eliminó mientras se suspendió la tarea.
NU_MAILBOX_RESET : el buzón se restableció mientras se suspendió la tarea.
Nucleus RTOS Compatible
Como con todos los demás objetos de Nucleus SE, mi objetivo era maximizar la compatibilidad del código de la aplicación con Nucleus RTOS. Los buzones no son una excepción y, desde el punto de vista del usuario, se implementan de la misma manera que en Nucleus RTOS. También hay una cierta incompatibilidad, que consideré aceptable dado el hecho de que, como resultado, el código será más comprensible y más eficiente en términos de la cantidad de memoria requerida. De lo contrario, las llamadas a la API de Nucleus RTOS se pueden transferir directamente a Nucleus SE.
Identificadores de objetos
En Nucleus RTOS, todos los objetos se describen mediante estructuras de datos (unidades de control) de un tipo específico. Un puntero a esta unidad de control sirve como identificador para el buzón. Decidí que en Nucleus SE, se necesita un enfoque diferente para el uso eficiente de la memoria: todos los objetos del núcleo se describen mediante un conjunto de tablas en RAM y / o ROM. El tamaño de estas tablas está determinado por el número de objetos configurados de cada tipo. El identificador de un objeto particular es el índice en esta tabla. Así que
definí NUSE_MAILBOX como el equivalente de
U8 , una variable (no un puntero) de este tipo sirve como el identificador del buzón. Esta ligera incompatibilidad es fácil de manejar si el código se transfiere de Nucleus SE a Nucleus RTOS y viceversa. Por lo general, no se realizan operaciones en identificadores de objetos que no sean mover y almacenar.
Nucleus RTOS también admite nombres de buzones. Estos nombres se usan solo para la depuración. Los excluí de Nucleus SE para ahorrar memoria.
Tamaño y tipo de mensaje
En Nucleus RTOS, un mensaje de buzón consta de cuatro palabras de 32 bits. En Nucleus SE, decidí reducir este valor a una variable de tipo
ADDR . Este cambio resulta en ahorros significativos de memoria y tiempo de ejecución de tareas reducido. También sugiere que el uso habitual de un buzón es reenviar información de una tarea a otra. Esta incompatibilidad no causará grandes problemas al portar aplicaciones a Nucleus RTOS. Nucleus SE puede modificarse si se necesita un formato de mensaje diferente.
Llamadas API no realizadas
Nucleus RTOS admite nueve llamadas de oficina de buzón. De estos, cuatro no están implementados en Nucleus SE. Los detalles de estos desafíos, así como las razones por las que fueron excluidos de Nucleus SE, se describen anteriormente.
El siguiente artículo analizará las colas.
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.