Colas en FreeRTOS

2

Tengo múltiples tareas que todas escriben en una pantalla. Obviamente, sin controlar quién puede escribir en la pantalla cuando tenga problemas. Pensé que la forma más fácil de hacer esto era con hacer cola.

Tengo un QueueHandle global. En mi función int main(void) creo una cola de tamaño 10 (lo suficientemente grande para mis necesidades) con un tamaño de elemento igual a mi struct que contiene todos los datos.

struct screenData {
    uint8_t string;
    uint8_t line;
} data;

En las tareas que deben escribir en la pantalla que envían a la cola:

struct screenData * toSend;
data.string = "TEST";
data.line = 0;

toSend = &data;

xQueueSend ( xQueue, ( void * ) &toSend , xTicksToWait );

En la tarea que actualiza la pantalla, se lee de la cola y la coloca en la pantalla:

struct screenData * data;
xQueueReceive( xQueue, &( data ), xTicksToWait );

A continuación, accedo a los datos así: data->string; etc ...

Sin embargo, en la medida en que lo entiendo, esto pasa la dirección de la estructura. Lo que significa que si actualizo data , los datos almacenados en la estructura serán diferentes.

Lo que quiero hacer es tener una cola que pueda agregar a donde los datos enviados sean del tipo screenData , y leerá cada screenData entrante para poner un mensaje en la pantalla.

Esencialmente, ¿debería simplemente enviar la estructura completa a la cola? ¿En qué caso, es este el mejor uso de la cola? ¿O hay una mejor manera de almacenar datos en búfer?

Gracias

    

3 respuestas

6

Hay dos enfoques básicos que vienen a la mente.

1) Use una cola como se indica en el OP.

Según la documentación de la API de FreeRTOS para xQueueSend , todos los datos de su estructura screenData se copian en el en la cola (consulte la descripción del argumento pvItemToQueue : "Un puntero al elemento que se va a colocar en la cola. El tamaño de los elementos que contendrá la cola se definió cuando se creó la cola, por lo que esta cantidad de bytes se copiará de pvItemToQueue en el área de almacenamiento de la cola. "Esto significa que su suposición es incorrecta. Después de que la ejecución del código regresa de la llamada xQueueSend , puede modificar data sin temor a sobrescribir lo que se acaba de poner en cola .

2) Utilice un semáforo de exclusión mutua o mutex .

(lea más sobre la implementación de FreeRTOS Mutex en la documentación de la API de xSemaphoreCreateMutex ) para sincronizar el acceso a la pantalla entre diferentes tareas .

Los principales compromisos a considerar al elegir entre una cola o un mutex son los siguientes:

El uso de una cola almacenará en búfer los datos y no impedirá que se ejecuten tareas a menos que su cola se llene, pero requiere que asigne más memoria (10 * sizeof (screenData) en este caso).

El uso de un mutex no requiere la asignación de memoria, pero bloqueará la ejecución de tareas si más de una intenta acceder a la pantalla al mismo tiempo.

    
respondido por el semaj
4

Creo que su comprensión es incorrecta. El servicio FreeRTOS Queue hace una copia de los datos que envía. El tamaño de un elemento de cola se define cuando crea la cola. xQueueSend recibe un puntero al elemento pero hace una copia de ese elemento; no pone en cola el puntero. Entonces, si la tarea que llamó a xQueueSend modifica el elemento original posteriormente, esos cambios no se reflejarán en la copia que se colocó en la cola.

Aquí está la Descripción de la cola de FreeRTOS

Con respecto a sus preguntas: Sí, enviar una copia de los datos de pantalla parece razonable. Creo que su código de ejemplo es incorrecto. Si pretende colocar un elemento screenData en la cola y creó la cola con un tamaño de elemento igual a sizeof (screenData), debe pasar la dirección de data a xQueueSend. En otras palabras, no necesita toSend y debería llamar a xQueueSend de esta forma:

xQueueSend ( xQueue, ( void * ) &data , xTicksToWait );

Además, en la función que llama a xQueueReceive, debe declarar data como un tipo de datos de pantalla en lugar de un puntero a screenData. Luego, pase la dirección de los datos a xQueueReceive.

    
respondido por el kkrambo
0

en general, la mejor manera de manejar múltiples procesos escribiendo en la pantalla

es tener un proceso dedicado, que es el único que realmente escribe a sysout.

Todos los demás procesos utilizan un sistema de mensajería como 'msgsnd ()' para pasar

mensajes al único proceso que realmente se escribe en la pantalla.

El sistema operativo pone en cola los mensajes que se leerán mediante el proceso que se escribe en la pantalla.

Si esa cola se llena, el proceso de envío se bloqueará hasta que haya espacio en la cola.

esto normalmente resulta en que los procesos de usuario no necesitan mantener una cola de mensajes para la pantalla

    
respondido por el user3629249

Lea otras preguntas en las etiquetas