Laboratorio 13: Aplicaciones multitarea bajo un kernel de planificación no expropiativo Programación de sistemas y dispositivos José Manuel Mendías Cuadros Dpto. Arquitectura de Computadores y Automática Universidad Complutense de Madrid J.M. Mendías 2016 Crear una aplicación multitarea bajo un kernel de planificación no expropiativo de tareas multiestado. laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II o El punto de partida es una aplicación funcional que consta de 6 tareas: PSyD 2 • Las tareas serán funcionalmente las mismas que en el Lab 12, todas son periódicas (alguna con periodicidad variable) • Existirá una hebra en foreground (RTI por temporizador) encargada de pasar a preparadas aquellas taras cuyo periodo de ejecución haya vencido. • Las tareas preparadas se ejecutarán secuencialmente por orden de prioridad por una única hebra en background. o Adicionalmente, existirá una hebra adicional: una RTI por pulsación de pulsador • Cada vez detecte una pulsación de cualquier pulsador, activará un flag para que la hebra en foreground envíe por la UART0 un mensaje. o La UART0 no es necesario protegerla ya que solo es usado por la hebra en background. o Las tareas que producen/consumen scancodes utilizarán una variable global compartida que no es necesaria proteger, al no existir expropiación. o Al igual que en Lab 12, esta aplicación se ampliará con 2 tareas adicionales funcionalmente equivalentes a las allí realizadas. J.M. Mendías 2016 declaraciones ... laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II #define MAX_TASKS #define TICKS_PER_SEC PSyD 3 (10) (100) typedef struct { void (* pfunction) (uint32 *, uint32 *); uint32 state; uint32 period; uint32 ticks; boolean ready; } task_t; Las tareas serán multiestado uint32 create_task( void (*pfunction)(uint32 *, uint32 *), uint32 state, uint32 period ); void delete_task( uint32 i ); void scheduler_init( void ); void scheduler( void ) __attribute__ ((interrupt ("IRQ"))); void dispacher( void ); J.M. Mendías 2016 laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II PSyD 4 declaraciones #define INIT #define RUN (0) (1) #define #define #define #define (1) (2) (3) (4) WAIT_KEYDOWN SCAN WAIT_KEYUP END_SCAN Declara los estados en que pueden estar las tareas uint8 scancode; boolean flagTask5 = FALSE; boolean flagTask6 = FALSE; volatile boolean pb_pressed = FALSE; Declara los recursos de sincronización entre tareas void Task1( uint32 *state, uint32 *period ); void Task2( uint32 *state, uint32 *period ); ... void Task6( uint32 *state, uint32 *period ); Declara tareas void isr_pb( void ) __attribute__ ((interrupt ("IRQ"))); RTI por presión de pulsador laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II J.M. Mendías 2016 programa principal PSyD 5 void main( void ) { sys_init(); timers_init(); ... keypad_init(); Inicializa dispositivos uart0_puts("\n\n Ejecutando kernel de planificación no expropiativo\n"); uart0_puts("----------------------------------\n\n"); scheduler_init(); Inicializa el Kernel Crea tareas create_task( Task1, INIT, 50 ); create_task( Task2, INIT, 10 ); ... create_task( Task6, INIT, 10 ); timer0_open_tick( scheduler, TICKS_PER_SEC ); pbs_open( isr_pb ); ... Instala planificador Instala RTI J.M. Mendías 2016 programa principal / RTI laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II ... PSyD 6 while( 1 ) { Entra en estado IDLE, sale por interrupción sleep(); if( pb_pressed ) { uart0_puts( " (INT) Se ha pulsado algún pushbutton...\n" ); pb_pressed = FALSE; } Todas las tareas preparadas se ejecutan por orden de prioridad dispacher(); } } void isr_pb( void ) { pb_pressed = TRUE; EXTINTPND = BIT_RIGHTPB; EXTINTPND = BIT_LEFTPB; I_ISPC = BIT_PB; } Activa flag J.M. Mendías 2016 laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II PSyD 7 tareas (i) void Task1( uint32 *state, uint32 *period { switch( *state ) { case INIT: Muestra un mensaje de presentación uart0_puts( " Task 1: iniciada.\n" ); por la UART0 led_on( LEFT_LED ); led_off( RIGHT_LED ); *state = RUN; break; default: led_toggle( LEFT_LED ); Conmuta el estado de los leds led_toggle( RIGHT_LED ); break; }; } J.M. Mendías 2016 laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II PSyD 8 tareas (ii) void Task2( uint32 *state, uint32 *period ) { switch( *state ) { case INIT: uart0_puts( " Task 2: iniciada.\n" ); *state = WAIT_KEYDOWN; break; case WAIT_KEYDOWN: if( !(PDATG & 0x2) ) { *state = SCAN; *period = 3; } break; case SCAN: scancode = keypad_scan(); flagTask5 = flagTask6 = TRUE; *state = WAIT_KEYUP; *period = 10; break; case WAIT_KEYUP: if( PDATG & 0x2 ) { *state = END_SCAN; *period = 10; } break; case END_SCAN: *state = WAIT_KEYDOWN; *period = 10; break; }; } Muestra un mensaje de presentación por la UART0 Muestrea el teclado esperando presión cada 0,1 segundos (10 ticks) Espera rebote de presión Lee el scancode Activa flags Muestrea el teclado esperando presión cada 0,1 segundos (10 ticks) Espera rebote de depresión J.M. Mendías 2016 tareas (iii) void Task3( uint32 *state, uint32 *period { rtc_time_t rtc_time; laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II switch( *state ) { case INIT: Muestra un mensaje de presentación uart0_puts( " Task 3: iniciada.\n" ); por la UART0 *state = RUN; break; default: Lee la hora del RTC rtc_gettime( &rtc_time ); uart0_puts( " (Task 3) Hora: " ); uart0_putint( rtc_time.hour ); uart0_putchar( ':' ); uart0_putint( rtc_time.min ); Muestra la hora del RTC por la UART0 uart0_putchar( ':' ); uart0_putint( rtc_time.sec ); uart0_puts( "\n" ); break; }; PSyD 9 ) } J.M. Mendías 2016 tareas (iv) laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II void Task4( uint32 *state, uint32 *period ) { static uint32 ticks; PSyD 10 switch( *state ) { case INIT: Muestra un mensaje de presentación uart0_puts( " Task 4: iniciada.\n" ); por la UART0 ticks = 0; *state = RUN; break; default: ticks += TICKS_PER_SEC * 10; Actualiza el numero de ticks trancurridos uart0_puts( " (Task 4) Ticks: " ); uart0_putint( ticks ); Muestra los ticks transcurridos por la UART0 uart0_puts( "\n" ); break; }; } J.M. Mendías 2016 laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II PSyD 11 tareas (v) void Task5( uint32 *state, uint32 *period ) { switch( *state ) { case INIT: Muestra un mensaje de presentación uart0_puts( " Task 5: iniciada.\n" ); por la UART0 *state = RUN; break; default: Chequea si hay nuevo scancode if( flagTask5 == TRUE ) { uart0_puts( " (Task 5) Tecla pulsada: " ); Muestra el scancode por la UART0 uart0_puthex( scancode ); uart0_puts( "\n" ); flagTask5 = FALSE; } break; }; } J.M. Mendías 2016 laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II PSyD 12 tareas (vi) void Task6( uint32 *state, uint32 *period ) { switch( *state ) { case INIT: Muestra un mensaje de presentación uart0_puts( " Task 6: iniciada.\n" ); por la UART0 *state = RUN; break; default: Chequea si hay nuevo scancode if( flagTask6 == TRUE ) { Muestra el scancode por el display 7‐segmentos segs_putchar( scancode ); flagTask6 = FALSE; } break; }; } J.M. Mendías 2016 Licencia CC (Creative Commons) laboratorio 12: Aplicaciones multihebra bajo el RTOS uC/OS‐II o Ofrece algunos derechos a terceras personas bajo ciertas condiciones. Este documento tiene establecidas las siguientes: PSyD 13 Reconocimiento (Attribution): En cualquier explotación de la obra autorizada por la licencia hará falta reconocer la autoría. No comercial (Non commercial): La explotación de la obra queda limitada a usos no comerciales. Compartir igual (Share alike): La explotación autorizada incluye la creación de obras derivadas siempre que mantengan la misma licencia al ser divulgadas. Más información: https://creativecommons.org/licenses/by‐nc‐sa/4.0/