µPOSIX: Una biblioteca POSIX para microcontroladores

Anuncio
μPOSIX: Una biblioteca POSIX
para microcontroladores
Pablo Ridolfi, Leandro Kollenberger
Laboratorio de Procesamiento Digital - Departamento de Ingeniería Electrónica
Universidad Tecnológica Nacional - Facultad Regional Buenos Aires
Buenos Aires, Argentina
{pridolfi, lkollenberger}@frba.utn.edu.ar
1. Introducción
Actualmente el mercado de microcontroladores ofrece una
gran variedad de arquitecturas con configuraciones de
periféricos y memoria muy diferentes entre sí, ya sea que se
trabaje con un mismo o diferentes fabricantes de circuitos
integrados. Esta variabilidad de hardware resulta en una
escasa capacidad de portabilidad del firmware o software
embebido que el desarrollador debe enfrentar (Fig. 1),
muchas veces diseñando su propia Capa de Abstracción de
Hardware (HAL, por sus siglas en inglés), y por lo tanto
desperdiciando tiempo que podría dedicarse a la implementación de su aplicación. En este trabajo se propone la
utilización del estándar POSIX para la implementación de
una HAL orientada a su uso en microcontroladores, que
provea una interfaz estándar y unificada para el manejo de
periféricos y dispositivos, así como el desarrollo de
aplicaciones multihilo de tiempo real a partir del uso de las
funciones Pthread (POSIX Threads) (Fig. 2).
Figura 1. Modelo actual de API para microcontroladores
Figura 2. Modelo de API propuesto por μPOSIX
2. Implementación de POSIX Threads (Fig. 3)
Figura 3. Posibles estados de un Thread de μPOSIX
Al llamarse a pthread_create(), se piden recursos de memoria al sistema para
el almacenamiento del estado de ejecución del nuevo thread. Acto seguido se
setea en estado READY: el hilo está en la cola de ejecución esperando acceder
a recursos de CPU. Desde ese momento, el scheduler selecciona la próxima
tarea a ser ejecutada cambiando su estado a RUNNING y le cede el uso del
CPU. El scheduler podrá pausar esta tarea para resumirla más tarde según
sea necesario y según lo dicte su política de scheduling. Esta tarea podrá
pasar al estado BLOCKED si en algún momento requiere el acceso a algún
recurso bloqueante. En este caso el scheduler le asignará el CPU a otra tarea
que esté en la cola de tareas en estado READY, buscando a partir de las de
prioridad más alta, hasta que la tarea anterior en estado BLOCKED consiga el
acceso a su recurso pedido, caso en el que volverá a estado READY y a la cola
de espera antes de pasar a ejecución. El thread seguirá un ciclo de ejecución
hasta que finalice o sea cancelado externamente por otro thread. Si el thread
finaliza, llamará internamente a la función pthread_exit(), quien se ocupará
de marcarlo como ZOMBIE, y esperar un pthread_join() de otro thread para
pasarle su valor de retorno, y finalmente pasar a estado DETACHED. Si se
requiere, se puede llamar a la función pthread_detach(), que pasará a la tarea
a este último estado sin la necesidad de devolver un parámetro. Por último,
el scheduler se encargará de liberar los recursos de los threads en estado
DETACHED en su próximo barrido de la lista de tareas.
3. Ejemplos de uso
/* Uso de GPIO */
int fd_gpio = open("/dev/gpio", 0);
/* Set SysTick user IRQ Handler */
int fd_systick = open("/dev/systick", 0);
/* GPIO0 Off */
devGPIO_pin_t led = devGPIO_pins[0];
led.value = 0;
ioctl(fd_gpio, devGPIO_REQ_WRITE_BIT, &led);
ioctl(fd_systick, devSysTick_REQ_SET_CALLBACK,
(void *)mySysTickCallback);
/* GPIO0 Toggle */
ioctl(fd_gpio, devGPIO_REQ_TOGGLE_BIT, &led);
/* Crear Thread */
pthread_t id;
pthread_create(&id, 0, thread_entry, (void*)argumento);
Más información en github.com/pridolfi/uposix
Descargar