
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 datosArtí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.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_SENDNUSE_PIPE_RECEIVENUSE_PIPE_JAMNUSE_PIPE_RESETNUSE_PIPE_INFORMATIONNUSE_PIPE_COUNTPor 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 RTOSPrototipo 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 SEEsta 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 SELa 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 RTOSPrototipo 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 SEEsta 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 SELa 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 RTOSPrototipo 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 SEEsta 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 SEEl 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.