Sistemas Empotrados de Tiempo Real Máster en Ingeniería Electrónica Práctica de laboratorio: uCOS-II Nombre Curso académico 2011/12 DNI (1) Preparación (10 min.) - Descomprime el archivo SETR_UCOS2.zip. Dentro del directorio LAB, haz doble click sobre el archivo LAB.SLN para abrir la “solución” en Visual Studio. Deberías ver la siguiente pantalla: - Este fichero contiene los proyectos LAB y UCOS_II. UCOS_II, a partir de los correspondientes archivos fuente, genera la librería UCOS_II.LIB. Esta librería, una vez generada, es enlazada con la aplicación al compilar el proyecto LAB. o Para compilar uC/OS-II, sitúa el cursor del ratón sobre el icono del proyecto UCOS_II, despliega el menú asociado al botón derecho del ratón y selecciona ‘Build’ o ‘Rebuild’. o Para compilar la aplicación-ejemplo, sitúa el cursor del ratón sobre el icono del proyecto LAB, despliega el menú asociado al botón derecho del ratón y selecciona ‘Build’ o ‘Rebuild’. o Para ejecutar la aplicación-ejemplo, despliega el menú ‘Debug’ de la parte superior de la ventana y selecciona ‘Start without debugging’. - El archivo que contiene el código fuente correspondiente a la aplicación-ejemplo es TEST.C. Este archivo es el que tienes que modificar en las secciones siguientes. (2) Análisis de la aplicación y su código fuente (20 min.) - Ejecuta la aplicación tal y como se ha descrito anteriormente. - Observa los siguientes aspectos de la ejecución de esta aplicación: ejecución concurrente de las tareas, utilización de la CPU, variabilidad de uso de la pila para las diferentes tareas, variabilidad de los tiempos de ejecución, etc. - Detén el programa cuando quieras pulsando ESC - Localiza la función main. Observa cómo se declara la tarea TaskStart: puntero a la función, paso del puntero correspondiente a la pila de la tarea (localiza la declaración de la pila en el programa). Observa que cuando se ejecuta OSStart() el planificador toma el control y comienzan a ejecutarse las tareas en base a su prioridad y la llegada de eventos. P - ¿Cómo se llama el array que se utiliza como pila de la tarea TaskStart? - Localiza la tarea TaskStart. Observa que esta tarea tiene una parte importante de inicialización antes de entrar en el bucle infinito típico de las tareas de uC/OS-II. Observa cómo se declaran las tareas de la aplicación así como los mailbox. P - ¿Cómo se llaman los mailbox que se declaran? - Localiza las tareas Task1, Task2, Task3, Task4, Task5 y TaskClk. P - ¿Qué tareas son periódicas y cuáles no? ¿Hay alguna que tenga varios puntos de suspensión? ¿Qué prioridades tienen? ¿Por qué evento esperan? Periódicas (Tarea/Prio/Periodo): Aperiódicas (Tarea/Prio/Evento): Varios puntos de suspensión (Tarea/Prio): (3) Modificación 1 (20 min.) - Modifica las dos tareas que visualizan las barras giratorias, de forma que sus códigos fuente sólo tengan un punto de suspensión dentro del bucle infinito (una única invocación de OSTimeDly). Código fuente de la tarea que gira la barra en sentido horario: - Modifica los tiempos de suspensión de las tareas que visualizan la barra giratoria. Consigue que la tarea que dibuja la barra giratoria en el sentido de las agujas del reloj tenga un periodo de 0.5 segundos y la que lo hace en el sentido contrario tenga un periodo de 0.25 segundos. Utiliza para ello la constante del sistema OS_TICKS_PER_SEC, cuyo valor es el número de ticks por segundo con el que está configurado el temporizador del sistema. Invocaciones a OSTimeDly para ambas tareas: SENTIDO HORARIO: SENTIDO ANTI-HORARIO: (4) Modificación 2 (20 min.) - Modifica la tarea que envía un mensaje a través de un mailbox para que visualice el mensaje antes de enviarlo. - Convierte la tarea emisora en tarea receptora del mensaje y viceversa. En vez de transmitir las letras de la A a la Z, haz que la transmisión sea un número aleatorio generado por la tarea transmisora. Para ello, utiliza la función de librería rand() (acuérdate de incluir la cabecera: #include <stdlib.h>), la cual genera un número aleatorio entre 0 y RAND_MAX (= 32767). También necesitarás invocar la función sprintf para convertir un entero en cadena (así: sprintf(str,”%d”,n), donde ‘str’ es una cadena de tamaño suficiente, char str[10], y ‘n’ es el entero a convertir) y la función de librería de uCOS-II PC_DispStr(x, y, string, color). Código final de la tarea transmisora: (5) Modificación 3 (50 min.) - Crea dos tareas Task6 y Task7, de forma que Task6 actúe como productora de un buffer LIFO (last in first out) y Task7 sea la consumidora, protegiendo adecuadamente las regiones críticas correspondientes. Por un lado, el buffer LIFO viene dado por: #define N 20 int buffer[N]; int nitems = -1; // indica la última posición ocupada Por otro lado, las operaciones producir y consumir se definen de la siguiente forma: PRODUCIR: CONSUMIR: if (nitems < (N-1)) { if (nitems >= 0) { item = rand(); item = buffer[nitem]; sprintf(str,”%d”,item); nitems--; PC_DispStr(70,19,str,<color>); sprintf(str,”%d”,item); nitems++; PC_DispStr(70,20,str,<color>); buffer[nitem] = item; } } OS_TimeDlyHMSM(0,0,rand()%6,0); OS_TimeDlyHMSM(0,0,rand()%6,0); Modifica el fichero OS_CFG.H, habilitando la generación de código para las funciones de semáforos (#define OS_SEM_EN 1). Código final de las tareas: