Este documento describe el uso de semáforos y mutex en FreeRTOS para sincronizar tareas y proteger el acceso a recursos compartidos. Los semáforos y mutex permiten que las tareas se bloqueen hasta que ocurra un evento o hasta que se libere el recurso protegido. Las colas FIFO también se utilizan para permitir que las tareas se comuniquen y compartan datos de manera ordenada y sincronizada.
0 calificaciones0% encontró este documento útil (0 votos)
132 vistas33 páginas
Este documento describe el uso de semáforos y mutex en FreeRTOS para sincronizar tareas y proteger el acceso a recursos compartidos. Los semáforos y mutex permiten que las tareas se bloqueen hasta que ocurra un evento o hasta que se libere el recurso protegido. Las colas FIFO también se utilizan para permitir que las tareas se comuniquen y compartan datos de manera ordenada y sincronizada.
Este documento describe el uso de semáforos y mutex en FreeRTOS para sincronizar tareas y proteger el acceso a recursos compartidos. Los semáforos y mutex permiten que las tareas se bloqueen hasta que ocurra un evento o hasta que se libere el recurso protegido. Las colas FIFO también se utilizan para permitir que las tareas se comuniquen y compartan datos de manera ordenada y sincronizada.
Este documento describe el uso de semáforos y mutex en FreeRTOS para sincronizar tareas y proteger el acceso a recursos compartidos. Los semáforos y mutex permiten que las tareas se bloqueen hasta que ocurra un evento o hasta que se libere el recurso protegido. Las colas FIFO también se utilizan para permitir que las tareas se comuniquen y compartan datos de manera ordenada y sincronizada.
Descargue como PDF, TXT o lea en línea desde Scribd
Descargar como pdf o txt
Está en la página 1de 33
Sincronización entre Tareas
• Al usar un RTOS, se recomienda que las tareas se
comuniquen entre si con llamadas al sistema del RTOS.
• En el caso de que una tarea esté esperando por ejemplo que
se presione una tecla, la tarea puede quedar bloqueada hasta que se produzca el evento (el evento es en este caso será la acción de presionar la tecla).
• Para ello existe el concepto de “Semáforo”.
Que es un semáforo? • Un semáforo restringe el acceso a una sección particular del programa (de la misma forma que un semáforo vial no permite el cruzar la calle si están pasando autos).
• En caso que restrinja el acceso a un determinado recurso, el
uso del semáforo será una convención a la que se deben adherir tolas las tareas que requieran acceso a ese recurso.
• La creación de un semáforo consume memoria del sistema.
Además cuando se produce un cambio en el semáforo, el scheduler verifica si es necesario realizar una cambio de contexto, lo cual implica un uso de la CPU. Semáforos en RTOS • Los semáforos tienen dos operaciones asociadas:
o Tomar el semáforo: es equivalente a que el semáforo
pase al color rojo.
o Liberar el semáforo: es equivalente a que pase a verde.
• En el caso de que el semáforo se puede tomar o liberar una vez,
se llama “semáforo binario”. • Nunca tomar un semáforo en una interrupción. Semáforos en FreeRTOS • Para crear un semáforo con el CMSIS-RTOS de CubeMX se usa: osSemaphoreDef(BinarySem01); BinarySem01Handle = osSemaphoreCreate( osSemaphore ( BinarySem01 ), 1 );
• Donde el valor numérico 1 en osSemaphoreCreate, indica que
es un semáforo binario. Semáforos en FreeRTOS • Se pueden crear desde la interface gráfica de CubeMX Semáforos en FreeRTOS • Al presionar “Add” se abre otra ventana Semáforos en FreeRTOS • Para tomar un semáforo con el CMSIS-RTOS de CubeMX se usa: int32_t osSemaphoreWait (osSemaphoreId semaphore_id, uint32_t millisec);
• Se debe especificar la identificación del semáforo (por ej.:
BinarySem01) y luego el tiempo máximo de bloqueo en milisegundos. • Si se realizó la operación con éxito, devuelve “osOK”. Si expiró el tiempo máximo de bloqueo devuelve “osErrorOS”. Si el id del semáforo es incorrecto devuelve “osErrorParameter”. Semáforos en FreeRTOS • Para liberar un semáforo con el CMSIS-RTOS de CubeMX se usa: osStatus osSemaphoreRelease (osSemaphoreId semaphore_id)
• Se debe especificar la identificación del semáforo.
• Si se realizó la operación con éxito, devuelve “osOK”. En otro caso devuelve “osErrorOS”.
• La función tiene en cuenta si se libera el semáforo desde una
interrupción. Semáforos en FreeRTOS • Si el semáforo se usará para proteger el acceso a un recurso (sección crítica), se lo debe tomar con tiempo de retorno máximo finito. Ej.: if (osSemaphoreWait(BinarySem01, 10000) ==osOK){ ---//acceso al recurso osSemaphoreRelease(BinarySem01); //Liberar semáforo }
• Todas las funciones de FreeRTOS que bloquean a la tarea que la
llaman tienen un tiempo de bloqueo máximo. Se debe verificar que se realizo el acceso al semáforo o sino si expiro el tiempo. Semáforos en FreeRTOS • Si el semáforo se usará esperar una evento, se lo puede esperar en forma indefinida. Ej.: if (osSemaphoreWait(BinarySem01, osWaitForever) ==osOK){ ---//acción que espera que se produzca el evento. }
void Interrup_ISR(void){//rutina de interrupción
osSemaphoreRelease(BinarySem01); } • El valor de osWaitForever es el máximo que permite el RTOS. Implementación de Semáforos • Los semáforos son objetos del kernel, se deben usar con racionalidad, ocupan memoria y tiempo de CPU.
• El scheduler debe verificar si se realiza una cambio de contexto cada
vez que se opera sobre un semáforo. Si el manejo del evento es inmediato o diferido dependerá de las prioridades de las tareas.
• Deben ser vistos por todo el sistema, se crean en forma global.
• Los semáforos son útiles si hay dependencias entre tareas y eventos
o entre tareas solamente. Ejemplo: diagrama de ejecución Exclusión entre Tareas • Cuando varias tareas que se ejecutan en forma concurrente quieren acceder al mismo recurso, entrarán en conflicto. Pero no se accederá en forma simultánea, sino que habrá en cambio de contexto entre que se empieza y termina de modificar el recurso.
• El problema se evita turnando el acceso al recurso. Esto se
llama exclusión mutua y se tienen varias estrategias: Exclusión: Alternativa 1 • Se deshabilitan las interrupciones, no puede ocurrir ningún cambio de contexto. • Se debe tener en cuenta que el sistema se vuelve cooperativo y no se atiende ningún evento. • FreeRTOS provee las macros taskENTER_CRITICAL() y taskEXIT_CRITICAL(). Su uso debe ser apareado (un enter es seguido de un exit). Exclusión: Alternativa 2 • Suspender el scheduler: se usa la función osThreadSuspendAll(); la cual suspende a todas la tareas restantes, pero mantiene las interrupciones activas. • Se eliminan los cambios de contexto durante el acceso al recurso. Luego se reanuda el scheduler con osThreadResumeAll();. • Se debe tener cuidado de que todos los eventos pendientes, serán atendidos inmediatamente después de la reactivación (semáforos, etc.). Exclusión: Alternativa 3 • Subir la prioridad de la tarea: FreeRTOS permite modificar la prioridad de las tareas. • Al aumentar la prioridad de la tarea que accede al recurso, no se realizará el cambio de contexto. • De esta forma se pueden tener interrupciones habilitadas y atención de los eventos y al mismo tiempo definir un umbral de tareas que no competirán con la tarea crítica. Exclusión: Alternativa 4 • Usar un mutex del sistema: FreeRTOS provee un elemento que es similar a un semáforo, pero con soporte para exclusión mutua. • Es una diferencia conceptual. Cuando varias tareas quieren usar un recurso, se resguarda al mismo con un mutex. Se puede interpretar como una llave de acceso al recurso. • La única tarea que puede accederlo es la que tiene tomado el mutex. • Es imprescindible que al terminar de usar el recurso, se libere el mutex. Mutex en FreeRTOS • Posee las mismas funciones que el semáforo:
• Para crear un mutex con el CMSIS-RTOS de CubeMX se usa:
osStatus osMutexRelease (osMutexId mutex_id) Mutex en FreeRTOS • Se puede crear un mutex desde la interface gráfica de CubeMX Mutex en FreeRTOS • Al presionar “Add” se abre otra ventana Implementación de Mutex • Cuando se usan mutex en FreeRTOS se realiza un manejo distinto al semáforo, para considerar el caso de “inversión de prioridades”. • Ejemplo: Una tarea de alta prioridad está bloqueada. Mientras, una tarea de menor prioridad que la anterior toma un mutex para acceder a un recurso. Luego la tarea de mayor prioridad pasa al estado Ready e intenta acceder al recurso. • En este caso, la tarea de alta prioridad debe esperar a que se libere el mutex. Implementación de Mutex Ahora una tarea de prioridad intermedia, pasa al estado Running durante un tiempo. • Como resultado la tarea de prioridad alta esta esperando a la tarea de prioridad menor (por eso es inversión de prioridad), pero esta última no liberará el mutex porque no recibe tiempo de ejecución.
Para evitar esto, el mutex en FreeRTOS incorpora un método
llamado “priority inheritance”. • Cuando ocurre una inversión de prioridades, el scheduler eleva la prioridad de la tarea que tiene el mutex al nivel de la tarea que tiene mayor prioridad. • Esto es una excepción al mecanismo “Fixed priority preemptive scheduling”. Intercambio de datos entre Tareas (Queue) • Las tareas son funciones en C, que cuando dejan de ser ejecutadas, las referencias a su pila dejan de ser válidas.
• Queda como alternativa usar variables globales para
intercambiar datos. Pero se tiene el problema: • Cuidar el acceso al recurso. • Las tareas que se ejecutan aperiódicamente esperan una lectura/escritura de un dato para procesar.
• Se necesita un sistema de comunicación de datos
sincronizado. Intercambio de datos entre Tareas • Para modularizar la implementación del sistema, se suele separar las tareas en dos grupos: • Una tarea produce datos. • Otra los consume (si no tiene datos para consumir se bloquea).
• Si se producen mas datos de los que se consumen se
necesita un buffer o un almacenamiento temporal de los mismos. Si el buffer se llena, la tarea productora se bloquea. • La forma mas simple de solucionarlo es usando pilas tipo FIFO o “Queue”. Intercambio de datos entre Tareas • El OS provee las funciones para operar sobre las Queue. Permite crearla, introducir datos o sacar datos. • Las Queue se crean en el “Heap” del sistema. Ocupan recursos. • Permite trabajar con cualquier tipo de datos, no solo los con que se creo. • Se crean antes de iniciar el scheduler. • Es importante estimar la cantidad de elementos máximos en la Queue, luego no se puede modificar este parámetro. Queue FIFO en FreeRTOS • Para crear una Queue con el CMSIS-RTOS de CubeMX se usa: Queue01Handle = osMessageCreate(osMessageQ(Queue01));
• Para leer un dato de la Queue se usa:
osEvent osMessageGet (osMessageQId queue_id, uint32_t millisec) • Tiene un tiempo máximo de espera por el dato en milisegundos. En caso de que la lectura se realice con éxito osEvent.status será osEventMessage y el dato estará en osEvent.value . En caso de time-out osEvent.status será osEventTimeout. Queue FIFO en FreeRTOS • Para escribir un dato en la Queue se usa:
milisegundos. En caso de que la operación se realice con éxito osStatus será osOK. En otro caso osStatus será osErrorOS. Queue FIFO en FreeRTOS • Para saber cuantos datos hay en la Queue se usa:
uint32_t osMessageWaiting(osMessageQId queue_id)
• Retorna la cantidad de elementos en la Queue.
• Es importante que antes de leer un dato de la Queue se verifique que tenga datos. En caso contrario la lectura será bloqueante. • Los semáforos y mutex se implementan con Queue de un único elemento. Queue en FreeRTOS • Se puede crear una Queue desde la interface gráfica de CubeMX Queue en FreeRTOS • Al presionar “Add” se abre otra ventana ¿Por qué usar un RTOS? • Para cumplir con compromisos temporales estrictos. • El RTOS ofrece funcionalidad para asegurar que una vez ocurrido un evento, la respuesta ocurra dentro de un tiempo acotado. Es importante aclarar que esto no lo hace por sí solo sino que brinda al programador herramientas para hacerlo de manera más sencilla que si no hubiera un RTOS (esto implica que una aplicación mal diseñada puede fallar en la atención de eventos aún cuando se use un RTOS). • Para no tener que manejar el tiempo “a mano” • El RTOS absorbe el manejo de temporizadores y esperas, de modo que hace más facil al programador el manejo del tiempo. ¿Por qué usar un RTOS? • Multitarea. • Simplifica sobremanera la programación de sistemas con varias tareas. • Escalabalidad • Al tener ejecución concurrente de tareas se pueden agregar las que haga falta, teniendo el único cuidado de insertarlas correctamente en el esquema de ejecución del sistema. • Mayor reutilizabilidad del código • Si las tareas se diseñan bien (con pocas o ninguna dependencia) es más fácil incorporarlas a otras aplicaciones. Contras de un RTOS • Se gasta tiempo del CPU en determinar en todo momento qué tarea debe estar corriendo. Si el sistema debe manejar eventos que ocurren demasiado rápido tal vez no haya tiempo para esto. • Se gasta tiempo del CPU cada vez que debe cambiarse la tarea en ejecución. • Se gasta memoria de código para implementar la funcionalidad del RTOS. • Se gasta memoria de datos en mantener una pila y un TCB (bloque de control de tarea) por cada tarea.