It is possible to wake sensor nodes on external interrupts that are generated by peripheral sensors. The following explains how Contiki OS handles external interrupts. In case of the ATmega128RFA1
the external interrupts INT0
to INT4
are able to wake the MCU even from deep sleep.
an overview over processes and interupts in contiki is here:
https://github.com/contiki-os/contiki/wiki/Processes
http://de.slideshare.net/DingxinXu/contiki-introduction-iifrom-what-to-how
http://senstools.gforge.inria.fr/doku.php?id=os:contiki
contiki utilizes the ISR vectors of the MCU
this example is for ATmega128RFA1. the external interrupt is INT0 on PD0 (pin 25)
in the ISR the only action is to poll an associated contiki process. Internally this sends a poll request to the process. The process catches the poll request and then executes the calculations associated with the external interrupt. This proceeding prevents long lasting calculations in the ISR.
ISR :
ISR(INT0_vect)
{
process_poll(&extern_interupt_process);
PRINTF("interrupt was triggered on INT0... \n");
}
to enable the external interupts on INT0:
EIMSK = 0xb00000000; //disable interrupts before changing EICRA
EICRA |= 0xb00000011; //EICRA 0000|0011 rising edge triggers interrupt int0
EIMSK |= 0xb00000001; // enable INT0
(datasheet p. 219 ff)
process :
PROCESS(extern_interupt_process, "external_interrupt_process");
PROCESS_THREAD(extern_interupt_process, ev, data)
{
PROCESS_BEGIN();
while(1) {
PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
// process data here
}
PROCESS_END();
}
use autostart_process() to start the extern_interrupt_process or start it manually in contiki-main.c
if the sensor has an open collector output activate the internal pull-up resistor and set the interrupt control register to trigger an interrupt on low-level (see this: wiring a sensor with open collector output)
DDRD &= 0xb00000000; // PD0 as input
PORTD |= 0xb00000001; // enable internal pull-up on PD0
EIMSK &= 0xb00000000; //disable interrupts before changing EICRA
EICRA &= 0xb00000000; //EICRA 0000|0000 low-level triggers interrupt on int0
EIMSK |= 0xb00000001; // enable INT0` (datasheet p. 219 ff)