what happens if interrupt occurs while ISR running? - c++

I am programming arduino, I attached an interrupt on pin2 falling edge. While I am in the ISR and the ISR has not executed all the lines. Before finishing all the lines if falling edge comes again what happens? Does interrupt start from begining or ignor it. Here I am talking about only interrupt on pin2.

The Atmel processor disables interrupts when an interrupt is taken:
(Section 4.4: Bit 7 – I: Global Interrupt Enable)
The Global Interrupt Enable bit must be set for the interrupts to be
enabled. The individual interrupt enable control is then performed
in separate control registers. If the Global Interrupt Enable Register
is cleared, none of the interrupts are enabled independent of the
individual interrupt enable settings. The I-bit is cleared by hardware
after an interrupt has occurred, and is set by the RETI instruction to
enable subsequent interrupts. The I-bit can also be set and cleared by
the application with the SEI and CLI instructions, as described in the
instruction set reference.
Further:
External Interrupt Flag Register – EIFR
• Bits 7..0 – INTF6, INTF3 - INTF0: External Interrupt Flags 6, 3 - 0
When an edge or logic change on the INT[6;3:0] pin triggers an
interrupt request, INTF7:0 becomes set (one). If the I-bit in SREG and
the corresponding interrupt enable bit, INT[6;3:0] in EIMSK, are set
(one), the MCU will jump to the interrupt vector. The flag is cleared
when the interrupt routine is executed. Alternatively, the flag can be
cleared by writing a logical one to it. These flags are always cleared
when INT[6;3:0] are configured as level interrupt. Note that when
entering sleep mode with the INT3:0 interrupts disabled, the input
buffers on these pins will be disabled. This may cause a logic change
in internal signals which will set the INTF3:0 flags.
In other words, when another interrupt is detected, the flag register will have that bit set, and that interrupt taken when interrupts are enabled again (at return from interrupts if no separate action is taken).
http://www.atmel.com/Images/Atmel-7766-8-bit-AVR-ATmega16U4-32U4_%20Datasheet.pdf
If you want to, you could implement code that enables interrupt during that interrupt service routine, but you have to make sure that the code after such a point is fully re-entrant, and/or mask the current interrupt (some interrupt service routines are pretty darn hard to handle when you don't get another interrupt soon after, and it gets almost impossible if you get another one when you are currently in that handler). However, it is often the case for proper operating systems to enable all other interrupts - which means writing to the EIMSK register.
As a general rule, it's best to simply collect the necessary information in the interrupt handler, store it away in "safe" place (circular buffers are good for this), and signal that new data is available to a regular task in the system, and process the data there.
[Additionally, as far as I can tell, there is nothing stopping function calls inside an interrupt - as long as you understand what you are doing and there is no problems for example from calling the function from both the interrupt and the regular code at the same time]

Related

How to handle GPIO interrupt-like handling in Linux userspace

Not sure whether I should post this here or not but I gotta ask.
Context :
Linux on an embedded platform (CPU #~500MHz)
One team working on the single userspace software
One team working on Linux + driver + uboot etc.
The software has to handle GPIO, some are output (write when needed), some are input (read when needed for some, preferably interrupt-like for others).
The software is a multi-threaded app with ~10-15 threads in SCHED_FIFO scheduling policy.
Let's say I have a module called WGPIO which is a wrapper handling GPIO. (this is developed by the Linux team btw. WGPIO is still in user-space, but they could develop a driver if needed)
Here is some pseudo_code of what is designed as we speak.
gpio_state state = ON;
// IO_O is output. Set to ON, don't care if it's active_high or active_low btw
WGPIO_WriteOutput(IO_O,state);
// IO_I is input, read when needed
WGPIO_ReadInput(IO_I,&state);
// register callback when rising edge occurs on IO named IO_IT
WGPIO_SetCallback(IO_IT,EDGE_RISING,my_callback);
// Unmask to enable further IT-like processing
WGPIO_UnmaskIRQ(IO_IT);
I must be able to handle some of the GPIO changes in 5 to 10ms.
Is some userspace polling (WGPIO would have a SCHED_FIFO thread then) on multiple FDs enough to simulate an "interrupt-like" handling in my app ? This looks like the most simple idea.
If you need more details, feel free to ask.
Thanks in advance.
From kernel gpio/sysfs.txt:
"value" ... reads as either 0 (low) or 1 (high). If the GPIO
is configured as an output, this value may be written;
any nonzero value is treated as high.
If the pin can be configured as interrupt-generating interrupt
and if it has been configured to generate interrupts (see the
description of "edge"), you can poll(2) on that file and
poll(2) will return whenever the interrupt was triggered. If
you use poll(2), set the events POLLPRI and POLLERR. If you
use select(2), set the file descriptor in exceptfds. After
poll(2) returns, either lseek(2) to the beginning of the sysfs
file and read the new value or close the file and re-open it
to read the value.
"edge" ... reads as either "none", "rising", "falling", or
"both". Write these strings to select the signal edge(s)
that will make poll(2) on the "value" file return.
This file exists only if the pin can be configured as an
interrupt generating input pin.
The preferred way is usually to configure the interrupt with /sys/class/gpio/gpioN/edge and poll(2) for POLLPRI | POLLERR (important it's not POLLIN!) on /sys/class/gpio/gpioN/value. If your process is some "real-time" process that needs to handle the events in real time, consider decreasing it's niceness.
You can even find some example code on github that uses poll, ex. this repo.

Could ticker interrupts interfere with hardware interrupts?

Background
I was wondering if using ticker interrupts could interfere with hardware interrupts triggered by a button press.
Example
Imagine I would like to use these two types of interrupts:
a ticker timer to update a progress bar on a small display every n second
a hardware interrupt that starts/stops the process whose progress is displayed if the user presses a button
Important: Both interrupts set shared global volatile flags.
Main question
Would it be possible for the ticker interrupt to occur during a button induced interrupt and as a result for the program to end up in a state where the global flags are set contradictorily?
More specific questions
Does a hardware and a software interrupt have the same 'rank'?
If they occured at the same time, would the interrupt request occurring slightly later (but still overlapping with the first one) be ignored, or just put into a queue and execute straight after the first interrupt has finished? In this case, the flags would be set in an unexpected manner.
Can I disable one type of the interrupts inside the other type's ISR - i.e. ignore it?
I hope the problem statement is clear enough even without a code example.
I'mm assuming you are using an AVR.
When an interrupt fires, other interrupts are disabled while the interrupt routine is running. So any interrupts that occur in this time simply get flagged. When the interrupt routine returns, the global interrupt flag is re-enabled and any polled interrupts can then fire one at a time.
You can manually enable the global interrupts inside the routine for critical things that must run, but are disabled by default.
EDIT:
Is there a way to disable this flag setting? I don't want the ticker timer to perform an interrupt once the button has been pressed. This is why I asked about ranks and the ability to disable on type of interrupt, if there is such a thing
You can clear the pending interrupt, however you'll have to read the datasheet for your Arduino's AVR. You need to find the register for the external interrupt.
For example, on an atmega328p, external interrupt 0 can be cleared by setting its flag bit to 1:
EIFR |= (1 << INTF2);
EIFR = External Interrupt Flag Register
INTF2 = Bit 0 – INTF0: External Interrupt Flag 0
However, it may be far simpler to poll the button in your loop() function. Or at best, simply set a flag for you to act upon back in the loop() function. There you would be able to decide if you want to react or ignore to the interrupt
There is the issue of having your interrupts far too large. If you use timing, or require accuracy, this could be affected by a large amount over time. As the interrupt queue length is only 1 deep some interrupts could be lost. And the interrupt which powers millis() & micros() runs multiple times per millisecond, so a bulky interrupt could end up slowing down time.
Also do you have any debouncing code or hardware?
If not, the interrupt handling the button could be run multiple times on a single press.

How to know if system has just woken up from a mem sleep?

I have a Qt application that runs on Linux.
The user can switch the system to mem sleep using this application.
Switching to mem sleep is trivial, but catching the wake up event in user space isn't.
My current solution is to use a infinite loop to trap the mem sleep, so that when the system wakes up, my application always continues from a predictable point.
Here is my code:
void MainWindow::memSleep()
{
int fd;
fd = ::open("/sys/power/state", O_RDWR);// see update 1)
QTime start=QTime::currentTime();
write(fd,"mem",3); // command that triggers mem sleep
while(1){
usleep(5000); // delay 5ms
const QTime &end=QTime::currentTime();// check system clock
if(start.msecsTo(end)>5*2){// if time gap is more than 10ms
break; // it means this thread was frozen for more
} // than 5ms, indicating a wake up after a sleep
start=end;
}
:: close(fd); // the end of this function marks a wake up event
}
I described this method as a comment on this question, and it was pointed out that it's not a good solution, which I agree.
Question: Is there a C API that I can use to catch the wake up event?
Update:
1) what is mem sleep?
https://www.kernel.org/doc/Documentation/power/states.txt
The kernel supports up to four system sleep states generically, although three
of them depend on the platform support code to implement the low-level details
for each state.
The states are represented by strings that can be read or written to the
/sys/power/state file. Those strings may be "mem", "standby", "freeze" and
"disk", where the last one always represents hibernation (Suspend-To-Disk) and
the meaning of the remaining ones depends on the relative_sleep_states command
line argument.
2) why do I want to catch the wake up event?
Because some hardware need to be reset after a wake up. A hardware input device generates erroneous input events after system wakes up, so it has to be disabled before sleep(easy) and enable after wake up(this question).
This should/could be handled by the driver in the kernel, which I have access to, or fixed in hardware, which my team can do but does not have the time to do it.(why I, a app developer, need to fix it in user space)
3) constraints
This is embedded linux, kernel 2.6.37, arch:arm, march:omap2, distro:arago. It's not as convenient as PC distros to add packages, not does it have ACPI. And mem sleep support in kernel 2.6.37 isn't mature at all.
Linux device drivers for PCI devices can optionally handle suspend and resume which, presumably, the kernel calls, respectively, just before the system is suspended, and just after resuming from a suspend. The PCI entrypoints are in struct pci_driver.
You could write and install a trivial device driver which does nothing more than sense resume operations and provides an indication to any interested processes. The simplest might be to support a file read() which returns a single byte whenever a resume is sensed. The program only need open the device and leave a thread stuck reading a single character. Whenever the read succeeds, the system just resumed.
More to the point, if the devices your application is handling have device drivers, the drivers should be updated to react appropriately to a resume.
When the system wakes from sleep, it should generate an ACPI event, so acpid should let you detect and handle that: via an /etc/acpi/events script, by connecting to /var/run/acpid.socket, or by using acpi_listen. (acpi_listen should be an easy way to test if this will work.)
Check pm-utils which you can place a hook at /etc/pm/sleep.d
In the hook you can deliver signal to your application, e.g. by kill or any IPC.
You can also let pm-utils to do the computer suspend, which IMO is far more compatible with different configurations.
EDIT:
I'm not familiar with arago but pm-utils comes with arch and ubuntu.
Also note that, on newer system that uses systemd, pm-utils is obsoleted and you should instead put hooks on systemd.
REF: systemd power events

Multiple triggers on a single interruption on Arduino

I am working on Arduinos and I would like to use interrupts to use a rotary encoder. But I would like to reduce the interrupt code to the minimum.
Can I use multiple triggers on a single interrupt?
I would like to replcace my actual code :
attachInterrupt(0, ChangeA, CHANGE);
To something like
attachInterrupt(0, FailingA, FAILING);
attachInterrupt(0, RisingA, RISING);
Is it possible?
No, not exactly possible. The external interrupt is configured to react only to one of the possibilities internally.
One thing you can do is to use a CHANGE interrupt service routine and test the value of the pin at the beginning of the ISR to do FallingA() or RisingA().
There is a potential problem here. The pin may have changed again before you test it, so the interrupt that triggered the interrupt could have been falling, say, and your test determines that it was rising. One way to guard against two quick interrupts is to check if the flag is still set. It should have been cleared if at the start of the interrupt, and if it is set then a change happened again. There is no practical way to guard against three quick changes.
If you really want to use two separate ISRs, do you have an extra pin available? If so, you could just wire the pins together and run a FALLING ISR on one and a RISING ISR on the other.

How to test Interrupt Latency?

Windows Embedded Compact 7.
Is there a way to test interrupt latency time from user space?
Are there any tools provided as part of platform builder?
I also saw a program called Intrtime.exe - but no examples on how to use it.
How does one test the interrupt latency time?
Reference for Intrtime.exe but how do I implement it?
http://www.ece.ufrgs.br/~cpereira/temporeal_pos/www/WindowsCE2RT.htm
EDIT
Also found:
ILTiming.exe Real-Time Measurement Tool (Compact 2013)
http://msdn.microsoft.com/en-us/library/ee483144.aspx
This really is a test that requires hardware, and there are a couple "latencies" you might measure. Once is the time from the interrupt signal to when the driver ISR reacts and the second is from when the interrupt occurs to when an IST reacts.
I did this back in the CE 3.0/CE 4.0 days by attaching a signal generator to an interruptable input an then having an ISR pulse a second input and an IST pulse a third input when they received the interrupt. I hooked a scope up to the input and outputs and used it to measure time between the input signal and output signals to get not just latency, but also jitter. You could easily add a 4th line for CE 7 so you could check an IST in user space and an IST in kernel space. I'd definitely be interested to see the results.
I don't think you can effectively measure this with software running on the platform, as you get into the problem of the code trying to do the measurement affecting the results. You're also talking time way, way below the system tick resolution so the scheduler is going to be problematic as well. CeLog might be able to get you an idea on these times, but getting it set up and running is probably more work than just hooking up a scope.
What is usually meant by interrupt latency is the time between an interrupt source asserting the interrupt line and a thread (sometimes in user-space) being scheduled and then executing as a result.
Unless your CPU has some accurate way of time-stamping interrupt events as they arrive at the CPU (rather than when an ISR runs), the only truly accurate measurement is one done externally - by measuring the time between a the interrupt line being asserted and some observable signal that the thread responding to the interrupt can control. A DSO or logic analyser is usually used for this purpose.
Software techniques usually rely on storing an accurate time-stamp at the earliest opportunity in an ISR. If you're certain the time between interrupt line becoming asserted and the ISR running is negligible, this might be valid. If, on the other hand, disabling of interrupts is being used to control concurrency, or interrupts are nested, you probably want to be measuring this as well.