Timer interrupt on Raspberry Pi under Linux

Gordon Williams picture Gordon Williams · Sep 23, 2015 · Viewed 12.1k times · Source

Is it possible to set a hardware timer peripheral up on the Raspberry Pi and get an interrupt at a certain time (while running under Linux)? Is there a library/example?

I know you can get an irq when a pin changes via wiringPi (when running with admin privileges), so if there's a free timer peripheral it seems possible.

this post on the Pi forums implies that there is a free STC register, and this one gives some info but is tagged 'BareMetal', which I assume means Linux isn't involved?

Background: I know this is not what Linux is good at at all, however I'm interested in adding a hardware timer capability to the Espruino JS interpreter. It's originally meant for microcontrollers and contains some code that expects to be run via a timer IRQ (eg. for software PWM, timed pulses, and other bits and bobs) - that part of it would be effectively useless if running in a thread.

Answer

JSU picture JSU · Dec 15, 2016

If I've understood your question you can access the timer indirectly via alarm() and signal().

Here is a very simple Hello World program for the Raspberry Pi, using wiringPi, that toggles pin 40 and pin 38. Pin 40 is toggled in the main loop and pin 38 from the alarm interrupt signal.

Compile with: gcc -Wall -o helloworld helloworld.c -lwiringPi

Control+c to quit.

I hope this helps,

JSU

helloworld.c

#include <wiringPi.h>
#include <stdlib.h>

#include <signal.h>
#include <unistd.h>

void alarmWakeup(int sig_num);


int main(int argc, char *argv[])
{
    unsigned int j;

    wiringPiSetupPhys();//use the physical pin numbers on the P1 connector


    pinMode(40, OUTPUT);
    pinMode(38, OUTPUT);

    signal(SIGALRM, alarmWakeup);   
    ualarm(5000, 5000);


    while(1)
    {
        digitalWrite(40, HIGH); //pin 40 high
        for(j=0; j<1000000; j++);//do something
        digitalWrite(40, LOW);  //pin 40 low
        for(j=0; j<1000000; j++);//do something
    }

    return 0;

}//int main(int argc, char *argv[])


void alarmWakeup(int sig_num)
{
    unsigned int i;

    if(sig_num == SIGALRM)
    {
        digitalWrite(38, HIGH); //pin 38 high
        for(i=0; i<65535; i++); //do something
        digitalWrite(38, LOW);  //pin 38 low
    }

}