Toda la verdad sobre RTOS. Artículo # 25. Canales de datos: introducción y servicios básicos



Después de un breve descanso, continuamos publicando traducciones de The Whole Truth About RTOS por Colin Walls. Esta vez hablaremos sobre los canales de datos (en adelante denominados canales), que ya se mencionaron en uno de los artículos anteriores, es decir, en el n . ° 5 . Los canales, en comparación con los buzones ( # 21 y # 22 ) o las colas ( # 23 y # 24 ), proporcionan una forma más flexible de transferir mensajes simples entre tareas.

Artículos anteriores de la serie:

Artículo # 24. Colas: servicios auxiliares y estructuras de datos.
Artículo 23. Colas: introducción y servicios básicos.
Artículo # 22. Buzones: servicios auxiliares y estructuras de datos
Artículo # 21. Buzones: Introducción y servicios básicos
Artículo # 20. Semáforos: servicios auxiliares y estructuras de datos
Artículo # 19. Semáforos: introducción y servicios básicos.
Artículo # 18. Grupos de banderas de eventos: servicios auxiliares y estructuras de datos
Artículo # 17. Grupos de banderas de eventos: Introducción y servicios básicos
Artículo # 16. Señales
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 canales


En Nucleus SE, los canales se identifican durante la fase de ensamblaje. Cada aplicación puede tener hasta 16 canales. Si no hay canales configurados en la aplicación, ni las estructuras de datos ni los códigos de llamadas de servicio relacionados con los canales se incluirán en la aplicación.

Canal de transmisión de datos: un conjunto de almacenamientos, el tamaño de cada uno de los cuales le permite colocar un elemento de datos de una longitud especificada por el usuario en bytes. El acceso a los datos se controla de tal manera que varias tareas pueden usarlos de manera segura. Las tareas pueden escribir datos en el canal hasta que todas las áreas estén llenas. Las tareas pueden leer datos del canal y los datos se reciben de acuerdo con el principio FIFO. Intentar escribir en un canal lleno o leer desde un canal vacío puede provocar un error o una suspensión de la tarea, dependiendo de la configuración de llamada API seleccionada y la configuración de Nucleus SE.

Canales y colas


Nucleus SE también admite colas que se han discutido en detalle en artículos anteriores (# 23 y # 24). La principal diferencia entre canales y colas es el tamaño del mensaje. Las colas contienen mensajes que consisten en una sola variable de tipo ADDR, generalmente punteros. El canal contiene mensajes de tamaño arbitrario, individuales para cada canal en la aplicación y asignados durante la configuración de parámetros.

Configuración del canal


Numero de canales


Como con la mayoría de los objetos de Nucleus SE, la personalización del canal está controlada por las directivas #define en nuse_config.h . El parámetro principal es NUSE_PIPE_NUMBER , que determina el número de canales configurados en la aplicación. De forma predeterminada, este valor es cero (es decir, no hay canales en la aplicación) y puede tomar valores hasta 16. Un valor incorrecto generará un error de compilación, que se generará al registrar el archivo nuse_config_check.h (este archivo se incluye en nuse_config.c y compila junto con él), que activará la directiva #error .

Seleccionar un valor distinto de cero sirve como activador principal de los canales. Este parámetro se usa para determinar las estructuras de datos y su tamaño depende de su valor (más sobre esto en el próximo artículo). Además, un valor distinto de cero activa la configuración de la API.

Activar llamadas API


Cada función API (llamada de utilidad) en Nucleus SE tiene la directiva de habilitación #define en nuse_config.h . Para los canales, estos símbolos son:

NUSE_PIPE_SEND
NUSE_PIPE_RECEIVE
NUSE_PIPE_JAM
NUSE_PIPE_RESET
NUSE_PIPE_INFORMATION
NUSE_PIPE_COUNT

Por defecto, están configurados en FALSO , por lo que todas las llamadas de servicio están deshabilitadas, lo que bloquea la inclusión de código que las implementa. Para configurar canales en la aplicación, debe seleccionar las llamadas de servicio API necesarias y establecerlas en VERDADERO .

El siguiente es un fragmento de código del archivo predeterminado nuse_config.h .

#define NUSE_PIPE_NUMBER 0 /* Number of pipes in the system - 0-16 */ /* Service call enablers */ #define NUSE_PIPE_SEND FALSE #define NUSE_PIPE_RECEIVE FALSE #define NUSE_PIPE_JAM FALSE #define NUSE_PIPE_RESET FALSE #define NUSE_PIPE_INFORMATION FALSE #define NUSE_PIPE_COUNT FALSE 

Si las funciones de API están activadas, pero no hay canales en la aplicación (excepto NUSE_Pipe_Count () , que siempre está habilitado), se producirá 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.

Llamadas de canal de arriba


Nucleus RTOS admite diez canales generales que proporcionan la siguiente funcionalidad:

  • Enviando un mensaje al canal. Nucleus SE se implementa en la función NUSE_Pipe_Send () .
  • Recibe mensajes del canal. Nucleus SE se implementa en la función NUSE_Pipe_Receive () .
  • Envía un mensaje a la parte superior del canal. Nucleus SE se implementa en NUSE_Pipe_Jam () .
  • Restaurar el canal a un estado no utilizado con la liberación de todas las tareas suspendidas (restablecer). En Nucleus SE, implementado en NUSE_Pipe_Reset () .
  • Obteniendo información sobre un canal específico. Nucleus SE se implementa utilizando NUSE_Pipe_Information () .
  • Devuelve el contador de canales configurados actualmente en la aplicación. Nucleus SE se implementa usando NUSE_Pipe_Count () .
  • Agregar un nuevo canal a la aplicación (creación). No implementado en Nucleus SE.
  • Eliminar un canal de una aplicación. No implementado en Nucleus SE.
  • Devuelve punteros a todos los canales de la aplicación. No implementado en Nucleus SE.
  • Enviar un mensaje a todas las tareas suspendidas en el canal (difusión). No implementado en Nucleus SE.

Considere la implementación de cada una de estas llamadas de servicio con más detalle.

Llamadas de servicio para escribir y leer desde canales


Las operaciones básicas que se realizan en los canales son la grabación (también llamada envío) y la lectura (también conocida como recepción de mensajes). Además, es posible grabar datos al comienzo del canal (interferencia). Nucleus RTOS y Nucleus SE proporcionan tres llamadas API principales para estas operaciones, que se analizarán a continuación.

Grabación de canales


La llamada de la utilidad Nucleus RTOS API para escribir en el canal es muy flexible, lo que le permite suspender tareas implícitamente o con un tiempo de espera si la operación no puede completarse de inmediato (por ejemplo, cuando intenta escribir en un canal lleno). Nucleus SE tiene un desafío similar, pero la pausa de tareas es opcional y no se implementa un tiempo de espera.

Nucleus RTOS también proporciona un servicio de transmisión de canales, pero no es compatible con Nucleus SE. Se describirá en la sección Llamadas de API no realizadas del siguiente artículo.

Llamar para enviar mensajes a un canal en Nucleus RTOS

Prototipo de llamada de servicio:

ESTADO NU_Send_To_Pipe (NU_PIPE * pipe, VOID * message, UNSIGNED size, UNSIGNED suspend));

Parámetros:

pipe : un puntero al bloque de control de canal proporcionado por el usuario;
mensaje - puntero al mensaje a enviar;
tamaño : el número de bytes en el mensaje. Si el canal admite mensajes de longitud variable, este parámetro debe ser igual o menor que la longitud del mensaje admitida por el canal. Si el canal admite mensajes de una longitud fija, este parámetro debe ser igual al tamaño del mensaje admitido por el canal;
suspender : la especificación de la suspensión de la tarea puede tomar los valores NU_NO_SUSPEND , NU_SUSPEND o el valor de tiempo de espera.

Valor de retorno:

NUSE_SUCCESS : la llamada se completó correctamente;
NU_INVALID_PIPE : puntero no válido al canal;
NU_INVALID_POINTER : puntero nulo a un mensaje ( NULL );
NU_INVALID_SIZE : el tamaño del mensaje no es compatible con el tamaño del mensaje admitido por el canal;
NU_INVALID_SUSPEND : intento de suspender un hilo no relacionado con la tarea;
NU_PIPE_FULL : el canal está lleno y no se especificó el tipo de suspensión de la tarea;
NU_TIMEOUT : el canal está lleno incluso después de que la tarea se suspende por un período de tiempo específico;
NU_PIPE_DELETED : el canal se eliminó mientras se suspendió la tarea;
NU_PIPE_RESET : el canal se restableció mientras se suspendía la tarea.

Llamar para enviar mensajes a un canal en Nucleus SE

Esta llamada de servicio API admite la funcionalidad principal de la API Nucleus RTOS.

Prototipo de llamada de servicio:

ESTADO NUSE_Pipe_Send (canalización NUSE_PIPE, mensaje U8 *, suspensión U8);

Parámetros:

tubería - índice (ID) del canal utilizado;
mensaje - un puntero al mensaje a enviar (una secuencia de bytes de longitud permitida para un canal dado);
suspender : especificación de suspensión de tareas, puede tomar los valores NUSE_NO_SUSPEND y NUSE_SUSPEND .

Valor de retorno:

NUSE_SUCCESS : la llamada se completó correctamente;
NUSE_INVALID_PIPE : índice de canal no válido;
NUSE_INVALID_POINTER : puntero nulo a un mensaje ( NULL );
NUSE_INVALID_SUSPEND : intenta suspenderlo de un hilo no relacionado con la tarea o cuando el bloqueo de la tarea está desactivado;
NUSE_PIPE_FULL : el canal está lleno y no se especificó el tipo de suspensión de la tarea;
NUSE_PIPE_WAS_RESET : el canal se restableció mientras se suspendió la tarea.

Implementación de la publicación de canales en Nucleus SE

La versión del código de función API NUSE_Pipe_Send () (después de verificar los parámetros) se selecciona mediante compilación condicional dependiendo de si el soporte para llamadas API está activado para bloquear (pausar) tareas o no. A continuación consideramos ambas opciones.

Si el bloqueo está desactivado, el código para esta llamada a la API es bastante simple:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

La función verifica si hay espacio libre en el canal y usa el índice NUSE_Pipe_Head [] para colocar el mensaje en el área de datos del canal.

Si se activa el bloqueo de tareas, el código se vuelve más complejo:

 do { if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_FULL; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else /* pipe element available */ { data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Head[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Head[pipe] += msgsize; if (NUSE_Pipe_Head[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Head[pipe] = 0; } NUSE_Pipe_Items[pipe]++; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Algunas aclaraciones pueden ser útiles.

El código está encerrado en un bucle do ... while , que se ejecuta mientras el parámetro de pausa de la tarea es NUSE_SUSPEND .

Si el canal está lleno y el parámetro de suspensión es NUSE_NO_SUSPEND , la llamada a la API finaliza con el valor NUSE_PIPE_FULL . Si el parámetro de suspensión es NUSE_SUSPEND , la tarea se detiene. Al finalizar (es decir, cuando se reanuda la tarea), si el valor de retorno es NUSE_SUCCESS , es decir, la tarea se reanudó porque se leyó el mensaje (y no porque se reinició el canal), el código vuelve al comienzo del bucle.

Si el canal no está lleno, el mensaje proporcionado se guarda utilizando el índice NUSE_Pipe_Head [] en el área de datos del canal. Comprueba si el canal ha pausado tareas (mensajes pendientes). Si hay tales tareas, se reanuda la primera de ellas. La variable de suspensión se establece en NUSE_NO_SUSPEND , y la llamada a la API se completa con el valor NUSE_SUCCESS .

Leyendo desde el canal


La llamada a la utilidad Nucleus RTOS API para leer desde el canal es muy flexible, lo que le permite pausar tareas implícitamente o con un tiempo de espera si la operación no se puede completar de inmediato (por ejemplo, cuando intenta leer un canal vacío). Nucleus SE tiene una llamada de utilidad similar, pero la pausa de tareas es opcional y no se implementa un tiempo de espera.

Desafío de lectura de canales en Nucleus RTOS

Prototipo de llamada de servicio:

ESTADO NU_Receive_From_Pipe (NU_PIPE * pipe, VOID * message, UNSIGNED size, UNSIGNED * actual_size, UNSIGNED suspend);

Parámetros:

pipe : un puntero al bloque de control de canal proporcionado por el usuario;
mensaje : un puntero al almacenamiento del mensaje recibido;
tamaño : el número de bytes en el mensaje. Debe coincidir con el tamaño del mensaje especificado al crear el canal;
suspender : especificación de suspensión de tareas, puede tomar NU_NO_SUSPEND , NU_SUSPEND o valores de tiempo de espera.

Valor de retorno:

NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_PIPE : puntero no válido al canal;
NU_INVALID_POINTER : puntero nulo a un mensaje ( NULL );
NU_INVALID_SUSPEND : intenta pausar una tarea desde un hilo no asociado con la tarea;
NU_PIPE_EMPTY : el canal está vacío y no se especificó el tipo de suspensión de la tarea;
NU_TIMEOUT : el canal está vacío incluso después de suspender la tarea por el valor de tiempo de espera especificado;
NU_PIPE_DELETED : el canal se eliminó mientras se suspendió la tarea;
NU_PIPE_RESET : el canal se eliminó mientras se suspendió la tarea.

Desafío de lectura de canal en Nucleus SE

Esta llamada de servicio API admite la funcionalidad principal de la API Nucleus RTOS.

Prototipo de llamada de servicio:

ESTADO NUSE_Pipe_Receive (canalización NUSE_PIPE, mensaje U8 *, suspensión U8);

Parámetros:

tubería - índice (ID) del canal utilizado;
mensaje : puntero al almacenamiento del mensaje recibido (una secuencia de bytes, cuya longitud coincide con el tamaño del mensaje del canal);
suspender : especificación de suspensión de tareas, puede tomar los valores NUSE_NO_SUSPEND y NU_SUSPEND .

Valor de retorno:

NUSE_SUCCESS : la llamada se completó correctamente;
NUSE_INVALID_PIPE : índice de canal no válido;
NUSE_INVALID_POINTER : puntero nulo a un mensaje ( NULL );
NUSE_INVALID_SUSPEND : un intento de suspender una tarea de un hilo no asociado con la tarea o con el soporte para la suspensión de tareas deshabilitado;
NUSE_PIPE_EMPTY : el canal está vacío y no se especificó el tipo de suspensión de la tarea;
NUSE_PIPE_WAS_RESET : el canal se restableció mientras se suspendió la tarea.

Implementación de lector de feeds en Nucleus SE

La versión del código de función API NUSE_Pipe_Receive () (después de verificar los parámetros) se selecciona mediante compilación condicional, dependiendo de si el soporte API para llamadas de bloqueo (suspensión de tareas) está activado o no. Consideraremos ambas opciones a continuación.

Si el bloqueo está desactivado, el código para esta llamada a la API es bastante simple:

 if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { return_value = NUSE_PIPE_EMPTY; } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; *actual_size = msgsize; return_value = NUSE_SUCCESS; } 

La función verifica la presencia de un mensaje en el canal y utiliza el índice NUSE_Pipe_Tail [] para obtener el mensaje del área de datos del canal, y devuelve datos a través del puntero del mensaje.

Si se activa el bloqueo de tareas, el código se vuelve más complejo:

 do { if (NUSE_Pipe_Items[pipe] == 0) /* pipe empty */ { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_PIPE_EMPTY; } else { /* block task */ NUSE_Pipe_Blocking_Count[pipe]++; NUSE_Suspend_Task(NUSE_Task_Active, (pipe << 4) | NUSE_PIPE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) { suspend = NUSE_NO_SUSPEND; } } } else { /* message available */ data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *message++ = *data++; } NUSE_Pipe_Tail[pipe] += msgsize; if (NUSE_Pipe_Tail[pipe] == (NUSE_Pipe_Size[pipe] * msgsize)) { NUSE_Pipe_Tail[pipe] = 0; } NUSE_Pipe_Items[pipe]--; if (NUSE_Pipe_Blocking_Count[pipe] != 0) { U8 index; /* check whether a task is blocked */ /* on this pipe */ NUSE_Pipe_Blocking_Count[pipe]--; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_PIPE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == pipe)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } *actual_size = msgsize; return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND); 

Algunas aclaraciones pueden ser útiles.

El código está encerrado en un bucle do ... while , que se ejecuta mientras el parámetro de pausa de la tarea es NUSE_SUSPEND .

Si el canal está vacío y el parámetro de suspensión es NUSE_NO_SUSPEND , la llamada a la API finaliza con el valor NUSE_PIPE_EMPTY . Si el parámetro de suspensión es NUSE_SUSPEND , la tarea se detiene. Al finalizar (es decir, cuando se reanuda la tarea), si el valor de retorno es NUSE_SUCCESS , es decir, la tarea se reanudó porque se envió el mensaje (y no porque se restableció el canal), el código vuelve al comienzo del bucle.

Si el canal contiene mensajes, el mensaje almacenado se devuelve utilizando el índice NUSE_Pipe_Tail [] . Comprueba si hay tareas pausadas (en espera de ser enviadas) en este canal. Si hay tales tareas, se reanuda la primera de ellas. La variable de suspensión se establece en NUSE_NO_SUSPEND , y la llamada a la API termina con el código NUSE_SUCCESS .

Grabar al inicio del canal


La llamada a la utilidad de la API Nucleus RTOS para escribir al comienzo del canal es muy flexible, lo que le permite pausar tareas implícitamente o con un tiempo de espera si la operación no se puede completar de inmediato (por ejemplo, al intentar escribir en un canal completo). Nucleus SE tiene una llamada de utilidad similar, pero la pausa de tareas es opcional y no se implementa un tiempo de espera.

Llamada para escribir al comienzo del canal en Nucleus RTOS

Prototipo de llamada de servicio:

ESTADO NU_Send_To_Front_Of_Pipe (tubería NU_PIPE *, mensaje VOID *, tamaño SIN FIRMAR, suspensión SIN FIRMAR);

Parámetros:

pipe : un puntero al bloque de control de canal proporcionado por el usuario;
mensaje - puntero al mensaje a enviar;
tamaño : el número de bytes en el mensaje. Si el canal admite mensajes de longitud variable, este parámetro debe ser igual o menor que el tamaño del mensaje admitido por el canal. Si el canal admite mensajes de longitud fija, este parámetro debe coincidir con el tamaño de mensaje admitido por el canal;
suspender : especificación de suspensión de tareas, puede tomar NU_NO_SUSPEND , NU_SUSPEND o valores de tiempo de espera.

Valor de retorno:

NU_SUCCESS : la llamada se completó correctamente;
NU_INVALID_PIPE : puntero no válido al canal;
NU_INVALID_POINTER : puntero nulo a un mensaje ( NULL );
NU_INVALID_SIZE : el tamaño del mensaje es incompatible con el tamaño del mensaje admitido por el canal;
NU_INVALID_SUSPEND : intento de suspender un hilo no relacionado con la tarea;
NU_PIPE_FULL : el canal está lleno y no se especificó el tipo de suspensión de la tarea;
NU_TIMEOUT : el canal está lleno incluso después de que la tarea se suspende por un período de tiempo específico;
NU_PIPE_DELETED : el canal se eliminó mientras se suspendió la tarea;
NU_PIPE_RESET : el canal se restableció mientras se suspendía la tarea.

Llame para escribir al comienzo del canal en Nucleus SE

Esta llamada de utilidad admite la funcionalidad principal de la API Nucleus RTOS.

Prototipo de llamada de servicio:

ESTADO NUSE_Pipe_Jam (canalización NUSE_PIPE, mensaje ADDR *, suspensión U8);

Parámetros:

tubería - índice (ID) del canal utilizado;
mensaje : un puntero al mensaje a enviar, que es una secuencia de bytes igual al tamaño del mensaje configurado en el canal;
suspender: especificación de suspensión de tareas, puede ser NUSE_NO_SUSPEND o NUSE_SUSPEND .

Valor de retorno:

NUSE_SUCCESS : la llamada se completó correctamente;
NUSE_INVALID_PIPE : índice de canal no válido;
NUSE_INVALID_POINTER : puntero nulo a un mensaje ( NULL );
NUSE_INVALID_SUSPEND : un intento de suspender una tarea de un hilo no asociado con la tarea o cuando el bloqueo de la tarea está desactivado;
NUSE_PIPE_FULL : el canal está lleno y no se especificó el tipo de suspensión de la tarea;
NUSE_PIPE_WAS_RESET : el canal se restableció mientras se suspendió la tarea.

Implementación de grabación de entrada de canal en Nucleus SE

El código de variante de la función NUSE_Pipe_Jam () es muy similar a NUSE_Pipe_Send () , excepto que el índice NUSE_Pipe_Tail [] se usa para almacenar datos en él, por lo tanto:

 if (NUSE_Pipe_Items[pipe] == NUSE_Pipe_Size[pipe]) /* pipe full */ { return_value = NUSE_PIPE_FULL; } else /* pipe element available */ { if (NUSE_Pipe_Tail[pipe] == 0) { NUSE_Pipe_Tail[pipe] = (NUSE_Pipe_Size[pipe] - 1) * msgsize; } else { NUSE_Pipe_Tail[pipe] -= msgsize; } data = &NUSE_Pipe_Data[pipe][NUSE_Pipe_Tail[pipe]]; for (i=0; i<msgsize; i++) { *data++ = *message++; } NUSE_Pipe_Items[pipe]++; return_value = NUSE_SUCCESS; } 

En el próximo artículo, consideraremos llamadas de servicio adicionales relacionadas con los canales, así como las estructuras de datos correspondientes.

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/es433046/


All Articles