C12 - Interrupts
Interrupt Concepts
Definición
- Es cuando se suspende temporalmente la ejecución del programa para ejecutar una subrutina
- Cuando acaba la interrupción se vuelve a reanudar la ejecución donde se habia quedado
- La interrupción se "dispara" (trigger) a través de una acción del hardware
Interrupt Setup ritual
- Arm/Disarm
- Arm - Permite al hardware hacer trigger a la interrupción
- Disarm - Deshabilita la función de trigger
- Cada interrupción tiene un bit de arm/disarm
- Enable NVIC (Nested Vectored Interrupt Controller)
- Es un módulo que controla todas las interrupciones. Se activa el NVIC específico para el device que usaremos
- Para deshabilitar hacemos un set al bit PRIMASK
- En C hay las funciones EnableInterrupts() y Disable Interrupts() para activar/desactivar las interrupciones
- Global enable bit I
- Este bit se activa haciendo un clear. Este bit activa y desactiva todas las interrupciones
- Si el bit es 1 muchas de las interrupciones no están permitidas, estan disable
- Priority
- No se si se refiere a la prioridad del device al thread principal o a que puede haber varias devices por interrupción y cada una tiene una prioridad
- El registro BASEPRI controla la prioridad de las interrupciones
- Trigger - Es un evento asincrono. Es el encargado de activar el device que activa la interrupción. En el registro RIS hay un bit que nos indica que ha habido un trigger.
5 condiciones que han de ser true para que una interrupción sea generada
- Device arm
- NVIC enable
- Global enable
- Prioridad de la itnerrupción actual ha de ser superior al nivel actual
- Hardware event trigger
Context Switch
- Es el proceso de cambiar del main program a la rutina de la interrupción
- Que pasa cuando ocurre una interrupción?
- 1.- Acaba la instrucción que está procesando
- 2.- Se suspende la ejecución del programa main
- Guarda en la posición en en la que se ha quedado
- Se guarda R0, R1, R2, R3, R12, R14 (LR), R25 (PC) y PSR y se hace un push a la pila
- 3.- Se pone un "special code" en el LR (Link Register) LR = 0xFFFFFFF9 Este patrón indica que estamos ejecutando una ISR
- 4.- En el registro IPSR se guarda el número de la interrupción
- 5.- En PC se carga la dirección de la ISR. La dirección de la ISR se llama vector
Volver del ISR al main thread
- Al final del Interrupt Service Routine hay la instrucción BXLR
- Ésta hace un pop de la pila (donde había guardado el estado de ejecución del main thread)
Good Practices
- Acknowledge - Acordarse de siempre hacer un clear del trigger flag
- Hacer que la interrupción sea lo más corta posible para asegurarnos que se pueda dar servicio a todas las interrupciones
- No deben haber delay loops
- Hay que tener en cuenta cada cuanto se ejecuta una interrupción y el tiempo que le lleva. Si el tiempo que le lleva es tiempo cada cuanto se ejecuta es un problema
Las interrupciones son mas apropiadas que otros sistemas de sincronización
- Cuando el tiempo en que ocurre el evento es variable y la estructura I/O es compleja
- Cuando los diferentes devices tienen diferentes velocidades de sincronización
- Cuando es necesario desarrollar un sistema de real-time
- Cuando tiene que ver con eventos importantes del sistema
Aspectos esenciales que debe tener el µC para usar interrupciones
- La interrupción debe tener una conexión separada al procesador para cada device
- El µC debe poder determinar de que device vino la interrupción
- El µC tiene que poder hacer acknowledge (poder hacer clear al flag de trigger)
- Cuando se diseña una interrupción es importante saber que device activó el flag de trigger y hacer clear de ese flag
Inter-thread Communication and Synchronization
Multi-threading
- Un main program y multiples ISRs
- Sincronizar varios threads es crítico y tiene que ser eficiente
- Hay 3 métodos para sincronizar los threads (pasar info del main thread al background thread) - Se utilizan variables globales porque son accesibles por los dos threads
- Binary semaphore (flag)
- Mailbox
- Fifo buffer
Binary semaphore (flag)
- El flag se usa para indicar un cambio de estado en el device
- Es una variable global
- El main quiere saber si ha ocurrido un evento para ello comprueba el flag El flag lo activa el ISR cuando ocurre el evento
- Tiene dos componentes: el flag y el data
- El flag tiene la misma función que con Binary semaphore
- En el data se pasa cualquier valor entre el ISR y el main program (ej. los datos del registro UART_DR_R)
Fifo Buffer
- Ponemos el data que recoge la ISR en el fifo buffer - Hacemos un PUT
- Desde el main recogemos los datos del fifo buffer con un GET
Explicar a parte de que el método mailbox y fifo son unos paradigmas llamados producer consumer.
Producer se refiere al thread que "produce" el dato y Consumer se refiere al thread que utiliza ese dato.
COMPLETAR