Unidad Didáctica 3: Arquitectura de los C Interrupciones

Anuncio
Sistemas Operativos de
Tiempo Real
Sistemas embebidos para tiempo real
Índice
•
•
•
•
Introducción
Tareas y el planificador (scheduler)
Tareas y datos
Semáforos y datos compartidos
Introduccion a los RTOS
Sistemas embebidos de tiempo real
2
Introducción
• RTOS es muy diferente a un OS convencional
– La aplicación y el RTOS se enlazan juntos.
– Los RTOS más básicos no se protegen.
– Se pueden eliminar servicios no usados para
ahorrar memoria.
• Existe una amplia oferta
– FreeRTOS, µC/OS, eCos, QNX, Nucleus,
VxWorks, LynxOS, etc.
– WSN/IoT: TinyOS, ContikiOS
– Algunos conformes al estándar POSIX (IEEE 1003.4)
Introduccion a los RTOS
Sistemas embebidos de tiempo real
3
RTOS vs. Kernel (RTK)
• Para algunos:
– RTOS = kernel = real-time kernel (RTK)
• Para otros:
– RTOS > kernel
– kernel: incluye sólo los servicios más básicos
– RTOS: incluye soporte de red, herramientas
de depurado, gestión de memoria, etc.
• Para el texto y para nosotros:
– RTOS y Kernel son sinónimos
Introduccion a los RTOS
Sistemas embebidos de tiempo real
4
Tareas
• Tarea:
– bloque básico de un sist. basado en un RTOS
– una función (o varias) en C, no retorna nunca
(bucle infinito).
– número de tareas acotado sólo por memoria.
• Inicialización:
– cada tarea se inicializa (mediante una llamada
a una función del RTOS) especificando:
• su punto de entrada (función), su prioridad, la
memoria que necesita, etc.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
5
Ejemplo: Uso de un RTOS
void main(void)
{
/* Initialize (but don’t start) the RTOS */
InitRTOS();
/* Tell the RTOS about our tasks */
StartTask(RespondToButton, HIGH_PRIORITY);
StartTask(CalculateTankLevels, LOW_PRIORITY);
/* Actually start the RTOS.(This function never returns.) */
StartRTOS();
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
6
Tareas: estados
• Running
tarea de mayor
prioridad lista
Running
– se está ejecutando
– una sola tarea en este estado
Ready
• Blocked
– nada que hacer, esperando
algún evento externo
es la tarea de
mayor prioridad
• Ready
– trabajo que hacer y esperando
necesita
evento externo
Blocked
Introduccion a los RTOS
ocurre el
evento
externo
Nota: Otros estados:
suspended, pended waiting,
dormant.
Sistemas embebidos de tiempo real
7
Planificador (scheduler)
• Planificador:
– es la función del kernel que decide que se ejecutará
• Cada tarea tiene:
– prioridad definida y estado (running, ready, blocked)
• Planificador selecciona
– tarea con la mayor prioridad que está lista para ejecutar.
• Transiciones:
– tarea se bloquea sola cuando no tiene que hacer
– tarea bloqueada pasa a lista, si otra la despierta
– conmutación entre Ready y Running: planificador
Introduccion a los RTOS
Sistemas embebidos de tiempo real
8
Planificador: implementación
• Schedulers en RTOS
– sencillos
– no trata de ser “justo”, a diferencia de
Windows/Linux/Unix,
– tareas de baja prioridad pueden “morirse
de hambre”
– responsabilidad del diseñador (no del
RTOS!) asegurarse que todas las tareas
cumplen con sus requerimientos
Introduccion a los RTOS
Sistemas embebidos de tiempo real
9
Planificador: FAQ
• ¿Cómo sabe el planificador que una tarea se ha
bloqueado o desbloqueado?
• ¿Qué pasa si todas las tareas están
bloqueadas?
• ¿Qué pasa si dos tareas con la misma prioridad
están ready?
• Si mientras una tarea está ejecutándose, otra
de mayor prioridad se desbloquea, ¿qué pasa?
Introduccion a los RTOS
Sistemas embebidos de tiempo real
10
Expropiación (Preemption)
• RTOS expropiativo (preemptive RTOS)
– detendrá la ejecución de una tarea tan pronto como
una tarea de mayor prioridad pasa a ready.
– Ejemplo: una tarea se desbloquea cuando una ISR
le envía un mensaje o libera un semáforo.
• RTOS no-expropiativo (non-preemptive RTOS)
– detendrá la ejecución de una tarea de baja prioridad
solamente si esa tarea se bloquea (e.g., después de
un pend or delay) o cede el control (yield)
Introduccion a los RTOS
Sistemas embebidos de tiempo real
11
Ejemplo de aplicación
struct {
}
/* “Levels Task” */
long lTankLevel;
void vCalculateTankLevels(void)
long lTimeUpdated;
{
tankdata[MAX_TANKS];
/* low priority task */
int i = 0;
while (TRUE) {
/* “Button Task” */
!! read float levels in task i
void vRespondToButton(void)
!! do bunches of calculations
{
tankdata[i].lTimeUpdated =
/* high priority task */
!! current time
int i;
tankdata[i].lTankLevel =
while (TRUE) {
!! result of long calculation
!! Block until button pressed
!! pick next tank to handle, etc.
i = !! ID of button pressed
i = !! next tank
!! output ITankLevel
}
!! output ITimeUpdated
}
}
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
12
Ejemplo
Running
Presionan un botón: RTOS le pasa el procesador a
vButtonTask en cuanto vLevelTask queda ready.
Prioridad creciente
vLevelTask ocupada haciendo
calculos mientras vButtonTask
espera presionen un botón
Ready
Blocked
vButtonTask termina y se
bloquea de nuevo
RTOS le devuelve el procesador
a vLevelTask
vButtonTask
vLevelTask
tiempo
Introduccion a los RTOS
Sistemas embebidos de tiempo real
13
Tareas y datos
• Cada tarea tiene su contexto (privado)
– Registros
– Contador de programa (PC)
– Pila (Stack): variables locales
• Conservación del contexto
– una tarea no sabe cuando dejara y volverá a
ejecutarse
– el contexto debe guardarse y restaurarse
• El resto de los datos -variables globales, estáticaspueden ser compartidos entre tareas, entonces...
Introduccion a los RTOS
Sistemas embebidos de tiempo real
14
Tareas y datos: datos compartidos
• Si varias tareas comparten datos, hay
que tomar las mismas precauciones que
cuando comparten datos rutinas de
primer y segundo plano:
– Deshabilitar las interrupciones
– Impedir la conmutación de tareas.
• Hay que ser cuidadoso, pues a veces los
datos compartidos no están a la vista...
Introduccion a los RTOS
Sistemas embebidos de tiempo real
15
static int cErrors;
void Task1(void){
...
vCountErrors (1);
...
}
void Task2(void) {
...
vCountErrors (2);
...
}
LDI R16, 0x01
RCALL vCountErrors
...
void vCountErrors(int cNewErrors){
cErrors += cNewErrors;
}
Introduccion a los RTOS
vCountErrors:
LDI R30,(cErrors)
LDI R31,((cErrors+1)
LD
R17, Z
ADD R16, R17
ST
Z, R17
RET
Sistemas embebidos de tiempo real
16
Task1: Runing
void Task1(void)
...
vCountErrors
...
}
void Task2(void)
...
vCountErrors
...
}
LDI R16, 0x01
RCALL vCountErrors
{
(1);
Conmuta Task1 a Task2
{
ST
RET
(2);
LDI R16, 0x02
RCALL vCountErrors
void vCountErrors(int cNewErrors)
{
cErrors += cNewErrors;
}
Conmuta Task2 a Task1
(restaura contexto: R17)
• Resultado final
Z, R17
no se guarda
cErrors = 1
R17 = 1
vCountErrors:
LDI R30,(cErrors)
LDI R31,((cErrors+1)
LD
R17, Z
ADD R16, R17
ST
Z, R17
RET
ST Z, R17
RET
– Debería ser:
cErrors
– Sin embargo da: cErrors
Introduccion a los RTOS
vCountErrors:
LDI R30,(cErrors)
LDI R31,((cErrors+1)
LD
R17, Z
ADD R16, R17
cErrors = 0
cErrors = 0
R17 = 2
cErrors = 2
R17 = 1
cErrors = 1
= 3
= 1
Sistemas embebidos de tiempo real
17
Funciones reentrantes
•
Pueden ser llamadas por más de una tarea y
siempre funcionarán correctamente
–
•
aunque ocurra: conmutación de tareas o
interrupciones
Una función es reentrante si:
1) Usa variables globales -compartidas- atómicam
(variables automáticas OK)
2) Llama solamente a funciones reentrantes.
3) Usa el hardware de forma atómica.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
18
Funciones reentrantes
int public_int;
int initialized = 4;
char *string = “Where does this string go?”;
void *vPointer;
void function (int parm, int *parm_ptr)
{
static int static_local;
int local;
...
}
Suponer que desde ésta
función se acceden a todas
las variables listadas:
¿Es la función reentrante?
• Recordar: donde son almacenadas las variables
Introduccion a los RTOS
Sistemas embebidos de tiempo real
19
Funciones reentrantes
static int static_int;
int public_int;
int initialized = 4;
char *string = “Where does this string go?”;
void *vPointer;
Problema:
variables globales
void function (int parm, int *parm_ptr)
{
static int static_local;
int local;
...
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
20
Funciones reentrantes
static int static_int;
int public_int;
int initialized = 4;
char *string = “Where does this string go?”;
void *vPointer;
void function (int parm, int *parm_ptr)
{
static int static_local;
int local;
...
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
Problema:
variables globales
Sin Problema:
variables locales
21
Funciones reentrantes
static int static_int;
int public_int;
int initialized = 4;
char *string = “Where does this string go?”;
void *vPointer;
void function (int parm, int *parm_ptr)
{
static int static_local;
int local;
...
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
Problema:
variables globales
Posible Problema:
copia local puntero
Sin Problema:
variables locales
22
Funciones reentrantes
static int num_errores = 0;
¿Es ésta función reentrante?
void ImprimeErrores() {
if(num_errores > 10){
num_errores -= 10;
printf("Se han producido otros 10 errores más\n");
}
}
• Motivos...
Introduccion a los RTOS
Sistemas embebidos de tiempo real
23
Hardware compartido
• Problemas por código no entrante:
– Impresión mezclada entre tareas... (Impresora)
– Salida enmarañada en pantalla... (Monitor)
– Paquetes mezclados en un enlace inalámbrico.
• Requerimiento para código reentrante:
– Una vez que una tarea comienza una
“transacción” de hardware debe completarla
antes de liberar el hardware.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
24
Datos compartidos
• Entonces, ¿no se pueden compartir datos?
– No. Si se puede si se acceden de forma atómica.
• Atomicidad no ocurre “sola”
– En algún microcontrolador tal vez...
• Lenguaje C:
• MSP430:
• ATmega:
cErrors++;
inc b, &cErrors
LDI ...
(múltiples instrucciones)
– Primero identificar secciones críticas y luego...
– Hacerla atómica deshabilitando/habilitando
interrupciones (u otros métodos)....
Introduccion a los RTOS
Sistemas embebidos de tiempo real
25
Bibliografía
• “An Embedded Software Primer”, David E. Simon
– Chapter 6: Introduction to Real-Time Operating
Systems
Introduccion a los RTOS
Sistemas embebidos de tiempo real
26
Sistemas Operativos de
Tiempo Real (2)
Sistemas embebidos para tiempo real
Índice
• Introducción
• Tareas y el planificador (scheduler)
• Tareas y datos
 Semáforos y datos compartidos
Introduccion a los RTOS
Sistemas embebidos de tiempo real
28
Datos compartidos
• Comunicación entre tareas:
– enfoque más sencillo: estructura/variable compartida
• Exclusión mutua
– asegurar acceso exclusivo para evitar datos corruptos
• Métodos:
– Deshabilitar interrupciones
– Operación Test&Set atómica (eg. 68000)
– Deshabilitar scheduling
– Semáforos...
Introduccion a los RTOS
Sistemas embebidos de tiempo real
29
Semáforos y recursos compartidos
Recurso: tramo de vía
Introduccion a los RTOS
Sistemas embebidos de tiempo real
30
Semáforos en RTOS
• Nomenclatura:
–
–
–
–
Take–Release
Raise–Lower
Wait–Signal
Pend–Post
(posta, llave)
(semáforo ferroviario)
(esperar-avisar)
• Semáforos para exclusión mutua (MutEx)
– proteger recursos compartidos: datos
compartidos
• Semáforos para comunicación entre tareas.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
32
Semáforos: protección de datos
/* “Levels Task” */
struct {
void vCalculateTankLevels(void)
long lTankLevel;
{
long lTimeUpdated;
/* low priority task */
int i = 0;
}
tankdata[MAX_TANKS];
while (TRUE) {
!! read float levels in task i
/* “Button Task” */
!! do bunches of calculations
void vRespondToButton(void)
TakeSemaphore( );
{
/* high priority task */
int i;
tankdata[i].lTimeUpdated =
while (TRUE) {
!! current time
!! Block until button pressed
tankdata[i].lTankLevel =
!! result of long calculation
ReleaseSemaphore( );
i = !! ID of button pressed
!! pick next tank to handle, etc.
!! output ITankLevel
TakeSemaphore( );
!! output ITimeUpdated
ReleaseSemaphore( );
i = !! next tank
}
}
}
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
33
Flujo de ejecución con semáforos
vCalculateTankLevel
vRespondToButton
TakeSemaphore( );
tankdata[i].lTimeUpdated
usuario presiona un botón
se desbloquea tarea botón
!! Block until button pressed
i = !! ID of button pressed
tankdata[i].lTankLevel
ReleaseSemaphore( );
semáforo no disponible
se bloquea tarea botón
liberando el semáforo
se desbloquea la tarea botón
tarea botón se bloquea
continua con tarea niveles
Introduccion a los RTOS
Sistemas embebidos de tiempo real
TakeSemaphore( );
!! output tank level,
timestamp
ReleaseSemaphore( );
34
Ejemplo de semáforos: µC/OS
• Notación
– el prefijo OS indica funciones del kernel
– Creación/inicialización: OSSemCreate()
– Tomar y liberar un semáforo: OSSemPend(),OSSemPost()
– Estructura OS_EVENT representa el semáforo
• Parámetros:
– OS_EVENT *p_semTemp;
– p_semTemp = OSSemCreate(1);
– OSSemPend(p_semTemp,WAIT_FOREVER);
• Otro servicio del RTOS
– Retardo: OSTimeDly()
Introduccion a los RTOS
Sistemas embebidos de tiempo real
35
#define PRIORITY_READ 11
#define PRIORITY_CONTROL 12
#define STK_SIZE 1024
static unsigned ReadStk[STK_SIZE];
static unsigned CtrlStk[STK_SIZE];
static int iTemperatures[2];
OS_EVENT *p_semTemp;
void main (void) {
OSInit( );
OSTaskCreate (vReadTmpTsk, NULLP, (void *) &ReadStk[STK_SIZE], PRIORITY_READ);
OSTaskCreate (vCtrlTask,
NULLP, (void *) &CtrlStk[STK_SIZE], PRIORITY_CONTROL);
p_semTemp = OSSemCreate(1);
OSStart ( );
}
void vRdTmpTsk (void) {
while (TRUE) {
OSTimeDly(5);
OSSemPend(p_semTemp,WAIT_FOREVER);
!! read in iTemperatures[0];
!! read in iTemperatures[1];
OSSemPost (p_semTemp);
}
}
void vCtrlTsk(void) {
while (TRUE) {
OSSemPend (p_semTemp, WAIT_FOREVER);
if(iTemperatures[0] != iTemperatures[1])
!! set off howling alarm;
OSSemPost (p_semTemp);
!! do other useful work
}
}
Semáforos y funciones reentrantes
void Task1(void)
{
vCountErrors (1);
}
void Task2(void)
{
vCountErrors (2);
}
Introduccion a los RTOS
static int cErrors;
void vCountErrors(int cNewErrors)
{
cErrors += cNewErrors;
}
Sistemas embebidos de tiempo real
37
Semáforos y funciones reentrantes
void Task1(void)
{
vCountErrors (1);
}
void Task2(void)
{
vCountErrors (2);
}
static int cErrors;
static NU_SEMAPHORE semErrors;
void vCountErrors(int cNewErrors)
{
NU_Obtain_Semaphore(&semError,NU_SUSPEND);
cErrors += cNewErrors;
NU_Release_Semaphore(&semError);
}
• Terminología:
– Se ha "protegido” cErrors con semáforos
• Notación:
– En este caso RTOS: Nucleus (prefijo NU)
Introduccion a los RTOS
Sistemas embebidos de tiempo real
38
Múltiples semáforos
• En un sistema pueden coexistir varios
semáforos:
– Cada semáforo protege un sólo recurso compartido.
– Cada tarea sólo tiene que esperar si el recurso que
tiene que utilizar está bloqueado.
– El RTOS no sabe qué recursos están protegidos por
qué semáforos. Eso es tarea del programador.
• Counting semaforos
– Control sobre un conjunto de N recursos.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
39
Semáforos para señalización
• Semáforo como método de comunic. entre
tareas.
• Ejemplo impresión de reportes:
– Datos:
• Buffer de donde se arma el reporte, números líneas totales
e impresas.
– Tareas:
• PrinterTask: espera por el reporte y luego envía línea a
línea desde el buffer a la impresora.
– ISR:
• La impresora interrumpe al final de cada línea y carga la
siguiente línea a imprimir.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
40
Semáforos para señalización
static
static
static
static
char a_chPrint[10][21]; /*outp buf */
int iLinesTotal;
int iLinesPrinted;
OS_EVENT *semPrinter;
void vPrinterTask(void) {
BYTE byError;
int wMsg;
while (TRUE) {
/* wait for a job to print */
wMsg = (int) OSQPend (QPrinterTask,
WAIT_FOREVER, &byError);
!! Format the report into a_chPrint
iLinesTotal = !! count of lines in reprt
/* print first line of report */
iLinesPrinted = 0;
vHardwarePrinterOutputLine(
a_chPrint[iLinesPrinted++]);
OSSemPend(semPrinter, WAIT_FOREVER,
&byError);
}
void vPrinterInterrupt (void) {
if (iLinesPrinted == iLinesTotal)
/* report done: release semaphore */
OSSemPost(semPrinter);
else
/* report not done: print next line */
vHardwarePrinterOutputLine(
a_chPrint[iLinesPrinted++]);
}
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
41
Discusión
• Semáforo usado como señal:
– Tarea que envía: hace un post.
– Tarea que recibe: hace un pend.
– Comparación con exclusión mutua:
• la misma tarea llama a pend, y luego post.
• Especial cuidado con:
– Valor inicial del semáforo: debe ser elegido bien.
• En el ejemplo el semáforo fue inicializado como no disponible.
• Depende de la aplicación.
– Orden cuando existen múltiples pends.
• En el ejemplo, la tarea espera por una cola y el semáforo
Introduccion a los RTOS
Sistemas embebidos de tiempo real
42
Problemas
• Baśicos
– Olvidar de tomar (pend) el semáforo.
– Olvidar de liberar (post) el semáforo.
– Tomar o liberar el semáforo equivocado.
– Ocupar el semáforo por demasiado tiempo.
• Inversión de prioridad
• Deadlock, o abrazo mortal
Introduccion a los RTOS
Sistemas embebidos de tiempo real
43
Inversión de prioridad
• Ejemplo:
Prioridad creciente
– Tareas C, B y A de prioridad creciente
– Tareas C y A comparten un recurso
Tarea A
Tarea B
Tarea C
Introduccion a los RTOS
Sistemas embebidos de tiempo real
44
Inversión de prioridad
Tarea A se desbloquea.
RTOS conmuta a A.
Tarea A trata de tomar
Tarea B se desbloquea.
el semaforo que tiene C
RTOS conmuta a B.
y se bloquea.
Prioridad creciente
Tarea C toma el
semaforo que
comparte con A
Tarea A
Tarea B se ejecuta por mucho tiempo
Tarea C no puede ejecutar para liberar
el semaforo.
Task A se pierde un deadline.
Tarea B
Tarea C
tiempo
Introduccion a los RTOS
Sistemas embebidos de tiempo real
45
Abrazo mortal (bloqueo mutuo)
OS_EVENT *p_sem_A, *p_sem_B;
int a, b; /* Variables compartidas */
void Tarea1(void)
{
OSSemPend(p_sem_A, WAIT_FOREVER);
OSSemPend(p_sem_B, WAIT_FOREVER);
a = b;
OSSemPost(p_sem_B);
OSSemPost(p_sem_A);
}
void Tarea2(void)
{
OSSemPend(p_sem_B, WAIT_FOREVER);
OSSemPend(p_sem_A, WAIT_FOREVER);
b = a;
OSSemPost(p_sem_A);
OSSemPost(p_sem_B);
}
Introduccion a los RTOS
Sistemas embebidos de tiempo real
46
Opciones para datos compartidos
• Deshabilitar interrupciones
– manera más drástica
– afecta tiempo de respuestas de todas las tareas y ISR
– único método para compartir datos con ISR
• Semáforos
– afecta aquellas que esperan el mismo semáforo, sin impacto en ISR
– aumenta probabilidad de errores de programación
• Deshabilitar conmutación de tareas (deshab. planificador)
–
–
–
–
planificador (scheduler) no conmuta tareas
funcionalidad presente en algunos RTOS
Overhead para habilitar y deshabilitar es pequeño.
Tiempo de respuesta: afecta todas las tareas pero no ISR
Introduccion a los RTOS
Sistemas embebidos de tiempo real
47
Resumen
• RTOS
– Características, diferencias con OS convencional
• Tareas
– Bloque fundamental, estados, contexto, scheduler...
• Funciones reeentrantes
• Recursos compartidos:
– Datos, hardware.
• Semáforos
– Mutex o comunicación entre tareas, problemas
• Opciones para resolver bug de datos compartidos.
Introduccion a los RTOS
Sistemas embebidos de tiempo real
48
Bibliografía
• “An Embedded Software Primer”, David E. Simon
– Chapter 6: Introduction to Real-Time Operating
Systems
• “MicroC OS II: The Real Time Kernel”
Introduccion a los RTOS
Sistemas embebidos de tiempo real
49
Descargar