timer interrupt

Hello,

I am looking for information and example on programing a led that's is on / off every second, based on a 'timer' interrupt. So far I found very few information on timers.

By the way I am programing in C.

Reply to
zeneca
Loading thread data ...

An actual timer interrupt in Linux using C is not trivial. See for example "man timer_create".

You could simply make a never-ending loop (like Arduino) and sleep 1 second every loop. That means your program has just that one function, though. (Of course you could do other things instead of sleeping.)

If you want easy and reliable timer interrupts to do simple hardware things, use a microcontroller like the Pico, not a full Linux Raspberry Pi.

Reply to
A. Dumas

You could always use the poll() function, though the advisability of this depends on what else the program is doing apart from making an LED blink.

For instance, if poll() watches stdin and has a timeout value of 1 second, it would be trivial to use poll() to turn the LED on for a second, then off for a second until a key is hit, and then to write "Exiting NOW" to stdout and exit.

IME its useful to understand how to use poll(). This is because writing and debugging a program that uses it to handle input from several files is a lot simpler and less error-prone than using threads to do the same thing.

Reply to
Martin Gregorie

sleep()

e.g. #include<stdio.h>

main() { printf("Sleeping for 1 second.\n"); sleep(1); return 0; }

also see usleep() and nanosleep() despite being obsolete they may do what you want if available.

Reply to
nev young

Not strictly true. Windows has never supported nanosleep. On Posix, although deprecated, these days the OS actually translates it as

1000 * nanosleep (which is very much current).
Reply to
Folderol

Is interruptible and therefore may terminate early (same applies to poll and almost anything else you can use in C). If it doesn't terminate early it /will/ be late by whatever delay process switching and system load imposes.

There is no really correct way to do this because Linux is not a real time OS - but you can come close[1] on a reasonably quiet system by using nanosleep, checking the time when it returns and either acting or calculating the new interval until you should wake up.

[1] Almost certainly close enough for visual steadiness.
Reply to
Ahem A Rivet's Shot

Many thanks, but for the moment I m only testing /evaluating possibilities. I often use timer wile programing microcontrolers (Atmel) but here poll doesn't fit because the target is free running procces in backgound supposed to take some action every second?.

Reply to
zeneca

I originally wrote these for an Arduino but it works fine on any Linux computer. It is to be used in a processing loop (eg.. Arduino). It is written in C++ but easy enough to change them to C. The timer uses very little processor and unless you need microsecond accuracy it works fine.

/* * timer.h * * written by: knute johnson - 13 September 2021 * */

#undef FOR_ARDUINO // this code is not for arduino

#ifndef TIMER_H #define TIMER_H

#ifdef FOR_ARDUINO #include <Arduino.h>

#endif

class timer { private: // last time triggered unsigned long last_triggered; // period between triggers unsigned long period; // method to calculate time difference between two millis() readings unsigned long diff(unsigned long, unsigned long); #ifndef FOR_ARDUINO // a millis() function for non-Arduinos unsigned long millis(); #endif // flag is inverted during check() if period has been reached bool flag = false;

public: // create a new timer timer(unsigned long); // check to see if it is later than last trigger plus period bool check(); // reset the last trigger to now void reset(); // gets the status of the flag bool get_flag(); };

#endif /* timer.h */

-----------------------------------------------------------------------------------------------

/* * timer.cpp * * written by: Knute Johnson - 13 September 2021 * * This method is NOT thread safe, all calls to the constructor and the public * methods must be from the same thread. * */

#include "timer.h"

#ifndef FOR_ARDUINO #include <sys/time.h>

#include <cstddef>

#endif

// construct new timer // per - timer period in milliseconds timer::timer(unsigned long per) { period = per; last_triggered = millis(); }

#ifndef FOR_ARDUINO // a millis() function for non-arduino // returns - unsigned long of milliseconds since program started unsigned long timer::millis() { struct timeval tp;

gettimeofday(&tp,NULL); return tp.tv_sec * 1000 + tp.tv_usec / 1000; } #endif

// calculate elapsed time between two millis() readings // returns - unsigned long difference in milliseconds between two millis() // readings unsigned long timer::diff(unsigned long a, unsigned long b) { return a > b ? a - b : b - a; }

// check that the current time has surpassed the last trigger plus period // returns - true if it has been period milliseconds since timer was last // triggered bool timer::check() { unsigned long now = millis();

if (diff(now,last_triggered) >= period) { last_triggered = now; flag = !flag; return true; }

return false; }

// reset the last trigger to now void timer::reset() { last_triggered = millis(); }

// get the state of the flag bool timer::get_flag() { return flag; }

-------------------------------------------------------------------------------------------

Simple test program: #include <stdio.h>

#include <unistd.h>

#include "timer.h"

int main() { timer test(1000); // create a new timer with 1 second timeout int n = 0;

while (1) { if (test.check()) printf("%d:%s\n",n++,test.get_flag() ? "true" : "false"); usleep(100); // sleep for 100us } }

Reply to
Knute Johnson

That would be sleep(), then, or possibly usleep() if you want to keep exact clock time by reducing the wait time my the number of microseconds the code in your loop takes to execute. However, don't forget that Linux is NOT a real-time OS and so your program may get suspended or slowed down while a system process executes.

The poll() and the earlier select() library functions are designed to support asynchronous i/o - the function typically watches several channels, which may be character oriented or buffered files. If the timeout is unset, poll() waits until data is received on one of the channels its watching, when it executes code associated with the channel that received the data before going back to waiting for a input on one of the channels. It uses no cpu time while waiting for a event.

If a timeout value is set, if nothing happens until timeout expiry, when poll() exits. When that happens you'd normally normally do any required housekeeping and then call poll() again or, if a 'stop' command is received on stdin, the program might release any resources it holds and exit.

As others have said, if all you want is to stop execution for a fixed amount of time, there are other library functions such as sleep() to do that. sleep() delays by whole seconds but there are other functions that are finer grained down to intervals measured in microseconds and nanoseconds.

If you haven't found them yet, you really need to get to know the 'apropos' and 'man' commands, which are used to search for and display manual pages for everything in Linux from commands to library functions.

If you're new to Linux, you may also want to find a copy of "UNIX Systems Programming" by David Curry - it covers all aspects of writing C programs to run under any of the *nix operating systems. There's a lot in it, but its well organised, well written and contains excellent example code.

-- Martin | martin at Gregorie | gregorie dot org

Reply to
Martin Gregorie

Just make sure you check that whatever sleep function you are using in whatever language, is doing what you expect for sub-second values, by timing how long it takes do to a few thousand calls.

For example sleeps of down to 1ms may sleep for the expected time, but under that it may either return straight away causing the loop to run too fast, or always sleep for a minimum of 1ms, causing the loop to be too slow.

I've seen this change from platform to platform, and language to language, including on Windows differences between Python 2 (<1ms returned immediately) and Python 3 (minimum sleep of 1ms).

---druck

Reply to
druck

IIUIC you can set up a timer alarm to send a signal to process after a predetermined time.

Interrupts are kernel space, not user space, so cannot be utilised directly.

>
Reply to
The Natural Philosopher

Why? Linux can do multithreading.

Reply to
Brian Gregory

I wouldn't know what windows does. I'm a unix (now linux) user since the 1980s. And AFAIK Pi's don't run windows.

Reply to
nev young

formatting link

I don't think Microsoft support the Pi, but people seem to find ways

formatting link
Reply to
Andy Burns

zeneca,

A word of warning :

Most of the people here have adviced to use sleep(). There is something you should be aware of when you chose to use that method :

The distance between two code executions seperated by sleep()s is whatever time you set sleep() to *plus* the time your code takes to do its thing (and before you ask : trying to recalculate the sleep time each step to account for the code-execution delay comes with its own problems).

Opposed to that an event from a system timer will /allways/ be the set time apart [1], regardless of how much time the fired-up code takes.

[1] even though the to-be-fired-up code may be delayed due to another processes timeslice still running.

Ofcourse, this is also a timers drawback : if the fired-up code takes more than the set time the next iteration of the fired-up code will start to run when the last one has not yet finished. And that can give .... interresting results. :-)

Bottom line: Using Sleep()s in a loop works good enough when the timing isn't all that important.

Regards, Rudy Wieser

Reply to
R.Wieser

Unless the process gets a signal and doesn't ignore it, in which case the sleep returns as soon as the signal handler is done. Sleep can return early or late, it will never return on time.

Reply to
Ahem A Rivet's Shot

Sure. I guess that is why they asked about timer interrupts. But can you give an example of how to use timer interrupts (hardware or otherwise) using C on Raspberry Pi OS? Easy enough on a microcontroller, but ...

Reply to
A. Dumas

As I said already, you need to set a signal and let the kernel return a signal to your process after a timeout. You cannot access interrupts directly from user space in Linux...

Reply to
The Natural Philosopher

Yes, but I wanted to hear Rudy say that. Also, it's still not trivial, is it? It has been too long since I did it, or tried it.

Reply to
A. Dumas

Well handling a timer interrupt in a multitasking environment ain't trivial either.

In essence I think - and I haven't time to try it - its a matter of:

- setting a timer to return a signal after a certain time. (Not sure the exact syntax)

- suspending the thread to wait for the signal. ( use pause() or sigwait() )

In essence signals are the asynchronous message from kernel to user space I guess. Not hardware interrupts!

formatting link
seems to be a good starting point

Reply to
The Natural Philosopher

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.