embedded - son - ¿Las interrupciones interrumpen otras interrupciones en Arduino?
programacion de interrupciones en arduino (3)
Tengo un Arduino Uno (dispositivo pequeño impresionante!). Tiene dos interrupciones; llamémoslos 0 y 1 . Adjunto un manejador para interrumpir 0 y otro diferente para interrumpir 1, usando attachInterrupt()
: http://www.arduino.cc/en/Reference/AttachInterrupt .
La Interrupción 0 se activa y llama a su manejador, que realiza algunos cálculos de números. Si el controlador de la interrupción 0 todavía se está ejecutando cuando se activa la interrupción 1 , ¿qué sucederá?
¿Interrumpirá 1 interrupción interrumpirá 0 , o interrumpirá 1 espera hasta que se termine de ejecutar el controlador de la interrupción 0 ?
Tenga en cuenta que esta pregunta se relaciona específicamente con Arduino.
¿Interrumpirá 1 interrupción interrumpirá 0 o interrumpirá 1 espera hasta que se termine de ejecutar el controlador de la interrupción 0?
A menos que vuelva a habilitar específicamente las interrupciones dentro de una ISR (Rutina de servicio de interrupción), se completa cualquier interrupción que se esté ejecutando actualmente, más una instrucción de código de máquina más , antes de que se realice el servicio de la siguiente interrupción.
La mayoría de las interrupciones establecen un indicador dentro del procesador, que se verifica entre las instrucciones, para ver si se debe reparar la interrupción. Las banderas se comprueban en orden de prioridad. En el Uno que es:
1 Reset
2 External Interrupt Request 0 (pin D2) (INT0_vect)
3 External Interrupt Request 1 (pin D3) (INT1_vect)
4 Pin Change Interrupt Request 0 (pins D8 to D13) (PCINT0_vect)
5 Pin Change Interrupt Request 1 (pins A0 to A5) (PCINT1_vect)
6 Pin Change Interrupt Request 2 (pins D0 to D7) (PCINT2_vect)
7 Watchdog Time-out Interrupt (WDT_vect)
8 Timer/Counter2 Compare Match A (TIMER2_COMPA_vect)
9 Timer/Counter2 Compare Match B (TIMER2_COMPB_vect)
10 Timer/Counter2 Overflow (TIMER2_OVF_vect)
11 Timer/Counter1 Capture Event (TIMER1_CAPT_vect)
12 Timer/Counter1 Compare Match A (TIMER1_COMPA_vect)
13 Timer/Counter1 Compare Match B (TIMER1_COMPB_vect)
14 Timer/Counter1 Overflow (TIMER1_OVF_vect)
15 Timer/Counter0 Compare Match A (TIMER0_COMPA_vect)
16 Timer/Counter0 Compare Match B (TIMER0_COMPB_vect)
17 Timer/Counter0 Overflow (TIMER0_OVF_vect)
18 SPI Serial Transfer Complete (SPI_STC_vect)
19 USART Rx Complete (USART_RX_vect)
20 USART, Data Register Empty (USART_UDRE_vect)
21 USART, Tx Complete (USART_TX_vect)
22 ADC Conversion Complete (ADC_vect)
23 EEPROM Ready (EE_READY_vect)
24 Analog Comparator (ANALOG_COMP_vect)
25 2-wire Serial Interface (I2C) (TWI_vect)
26 Store Program Memory Ready (SPM_READY_vect)
(Tenga en cuenta que el reinicio no puede ser enmascarado).
Posiblemente, una interrupción de bajo nivel podría estar en curso (por ejemplo, TIMER0_OVF_vect). Mientras está ocupado haciendo sus cosas, pueden ocurrir otros eventos de interrupción (y establecer los bits correspondientes en la CPU). Serán atendidos en el orden anterior, no en el orden en que realmente ocurren a tiempo.
Hay registros de hardware en los que se puede escribir para cancelar una interrupción pendiente, es decir, para borrar el indicador.
La razón para mencionar "una instrucción de código de máquina más" es que el procesador está diseñado para garantizar que cuando las transiciones de interrupciones no estén habilitadas, a interrupciones habilitadas, siempre se ejecute una instrucción más.
Esto te permite escribir código como este:
interrupts (); // guarantees next instruction executed
sleep_cpu (); // sleep now
Sin eso, podría producirse una interrupción antes de irse a dormir. Lo que significa que nunca te despiertas, porque confiabas en la interrupción que se produce durante el sueño, no antes.
Qué maravillosamente tonto de Freescale y Atmel para usar los mismos nombres de instrucciones, pero con significados invertidos.
Es por eso que prefiero los mnemónicos de interrupts
y no noInterrupts
porque la intención es muy clara. Estos son implementados por define en el núcleo incluye archivos.
Dejaré mi respuesta para esta vieja pregunta, porque la respuesta aprobada está desactualizada.
Docs mencionan que las interrupciones del arduino tienen prioridad:
Si su croquis usa múltiples ISR, solo se puede ejecutar uno a la vez, otras interrupciones se ejecutarán después de que el actual finalice en un orden que depende de la prioridad que tengan.
También proporciona un enlace para información adicional:
Para obtener más información sobre las interrupciones, consulte las notas de Nick Gammon .
Según las secciones ¿Qué es la prioridad de interrupción? y ¿Pueden ocurrir interrupciones mientras que las interrupciones están deshabilitadas? podemos concluir que:
- Las interrupciones se basan en la lista de banderas. Cuando ocurre un evento se establece la bandera correspondiente.
- Si el IRS no puede activarse en este momento, puede llamarse en cualquier momento más tarde porque la bandera está guardada.
- Hay una lista de todas las interrupciones disponibles que generalmente depende del chip. Cuanto más arriba en la lista, mayor es la prioridad .
Por lo tanto, las diferentes interrupciones no se interrumpirán entre sí, se ejecutarán de acuerdo con su prioridad.
En el hardware Arduino (también conocido como AVR), las interrupciones anidadas no se producen a menos que intencionalmente se creen las condiciones para que esto ocurra.
Desde avr-lib:
El hardware AVR borra el indicador de interrupción global en SREG antes de ingresar un vector de interrupción. Por lo tanto, las interrupciones normalmente permanecerán inhabilitadas dentro del manejador hasta que el manejador salga, donde la instrucción RETI (que es emitida por el compilador como parte del epílogo de la función normal para un manejador de interrupciones) eventualmente volverá a habilitar más interrupciones. Por esa razón, los manejadores de interrupciones normalmente no se anidan. Para la mayoría de los manejadores de interrupciones, este es el comportamiento deseado, para algunos incluso es necesario para evitar interrupciones infinitamente recursivas (como las interrupciones UART o interrupciones externas activadas por nivel). En raras ocasiones, aunque podría desearse volver a habilitar el indicador de interrupción global tan pronto como sea posible en el controlador de interrupciones, para no diferir ninguna otra interrupción más de lo absolutamente necesario. Esto podría hacerse usando una instrucción sei () justo al comienzo del controlador de interrupciones, pero esto deja algunas instrucciones dentro del prólogo de la función generada por el compilador para ejecutarse con interrupciones globales deshabilitadas.
(fuente: http://linux.die.net/man/3/avr_interrupts )