Search code examples
processoperating-systeminterruptavr-gcccontiki

How does Contiki OS process external interrupts?


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.


Solution

  • 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)
    

    http://en.wikipedia.org/wiki/Open collector