As mentioned in STM32L152R reference manual, before entering the STOP mode, all EXTI, peripherals and RTC interrupt pending bits should be reset, otherwise the stop mode entrance is ignored. Is there any way to perform this at once?
Related
Summary:
An ISR necessarily causes its own trigger pin to toggle randomly multiple times. These toggles (during the ISR) should be ignored, but aren't, and result in another interrupt to be set as pending and get executed afterwards.
I have a serial bit-bang device that I read via an interrupt. Device has a data pin and a "clock" pin. Data pin is HIGH by default. When the device is ready to be read, it pulls this data pin LOW. After this falling edge, each pulse on the "clock" pin shifts one bit out to the data pin.
An interrupt triggers on the falling edge of the data pin, and ISR bangs 24 bits of data out of the same data pin. Therefore, additional random falling edges on the data pin causes another interrupt to be set as pending. Which triggers immediately after the actual ISR has returned, resulting two consecutive interrupts being run per one "real" interrupt.
I have tried multiple ways to disable interrupts and/or clear pending interrupts, none of which seem to have any effect whatsoever. I suspect that this is because manipulating interrupt related registers is not allowed/or ignored in an ISR.
The device is Atmel ATSAMD21. (ARM Cortex M0+). Code is built under Atmel Studio with optimisation level -Og.I am okay with using ASF and/or SAM libraries/definitions, ARM CMSIS or baremetal register manipulation. Whichever happens to work.
Here is what I tried so far:
void interrupt_cb ( void )
{
// Trying to disable interrupts
// Executed at the beginning of the ISR
NVIC_DisableIRQ(EIC_IRQn);
ext_irq_disable( <pin> );
__disable_irq();
// body
// < code that results in same pin >
// < that the interrupt is triggered >
// < to be toggled randomly. >
// Trying to clear pending interrupts
// Executed just before the ISR returns.
NVIC_ClearPendingIRQ( EIC_IRQn );
NVIC->ICPR[0] |= 4; //probably same as the above
EIC->INTENCLR.bit.EXTINT2 = 1;
}
Or a combination of these commands.
so i'm using an STM32F4 based bare bone board (Black Pill) to run a program for my project
i m using the STM32CubeIDE for code generating
Current Overtime cases explanatory
the figure you just saw, is a graph i made simply on paint to explain the post
my project revolve around inductance load protection against short circuits, (doesn't matter but just clarification)
i m using interrupts, where the first interrupt triggers once the current reaches a reference 1 value
second interrupt triggers once the if reaches Value Reference 1
since current noises can't be filtered in my case, I have to avoid the triggering of instruction of int 2
there for I put a delay that is a bit bigger then the noise period (about 100ns)
if delay ended and int trigger is still on (high) , shut down the system (change the output)
if delay ended and int trigger is off (low), keep the system running (keep initial output)
this is the code i came up with so far
enter code here
I believe what you're looking for is a "Timer" and some interrupt handling magic. I will expand a little.
If your interrupt is OFF (in NVIC only, the rest is configured), but an interrupt triggering event occurred, the interrupt will NOT fire (obviously). But if you enable the interrupt in NVIC after that, it will fire immediately.
Example:
You set up a GPIO as input, you setup EXTI (external interrupt) and SYSCFG (binding port to EXTI), basically, you make a rising edge interrupt
In NVIC the corresponding interrupt is OFF
Rising edge happens on GPIO, immediately goes back down to LOW
You enable an interrupt in NVIC
Interrupt fires (even if the input never had a rising edge after NVIC interrupt was turned on)
My idea is the following.
In the interrupt 1 handler, you do 2 things.
Disable interrupt 2 in NVIC
Launch a delay via Timer with interrupt.
When interrupt 1 fires, it immediately disables interrupt 2 and enables timer. The timer eventually fires its own interrupt, where it enables interrupt 2 in NVIC. If interrupt 2 event happened, the interrupt 2 handler will be called immediately. If not, interrupt 2 will not fire.
During all this waiting your MCU is free to do whatever it wants, full interrupt implementation.
Let say an interrupt (interrupt 1) happens while I am in an ISR for another interrupt (interrupt 2) with the same or higher priority. Then before exiting the current ISR, I clear the interrupt flag of interrupt 1. Will the interrupt handler of interrupt 1 still be executed or interrupt 1 will be ignored?
For context, I am using STM32 microcontroller.
Thank you
AFAIK from the past experience of other CPUs, you loose the interrupt.
In such a case before clearing the interrupt 1 flag:
simply read the interrupt 1 flag bit and store it temporarily
clear the interrupt flag (in some CPUs reading it, clears it automatically)
at the end of the interrupt 2 check the stored bit
if it is not set, just leave interrupt 2 routine
if it is set and both interrupts have same priority (or it does not matter!):
just jump/call the other interrupt 1 routine ("stay" in interrupt 2 routine execution)
if it is set and interrupt 1 has not the same priority and you really have to assign it the proper one:
then it gets difficult, here some options:
once I forced the cpu to trigger an other unused interrupt 3 of the same priority like interrupt 1, so using interrupt 3 to execute "interrupt 1" routine
build the interrupt priority handling in code as far as you need it and can, using above trick and more...
PS: This should be described in the manual of the processor, whether clearing the interrupt bit will loose its execution - mostly yes, the interrupt bit is simply a "interrupt pending" bit. It's sometimes not easy to find the description, but daily business.
I am working with a very custom and not public Secure IC which has ARM Cortex M3 core.
In case of hw security violation, this IC triggers an NMI interrupt so it is fine, I am doing whatever I need for violation.
But It always enters into NMI Handler again and again when a violation is occurred.
We probably need to clear interrupt pending flag not sure but it should be cleaned directly.
Because SCB->ICSR bit31 says that "entering the handler clears this bit to 0".
I also tried to clear pending flag using NVIC_ClearPendingIRQ() but it does not accept negative IRQ values while NMI is -14.
I tried to set manually NVIC->ICPR[0] = (1 << 2); like as manufacturer examples (but manufacturer example resets device in NMI handler which is different case) but it does not work.
It is custom IC and custom external event which triggers generic Cortex M NMI interrupt and can be a specific case to IC but is there any limitation for NMI like "you can not clear NMI pending flag and you have to reset it bla bla"?
Thank you
The NMI is acting just like any other interrupt here.
From the Cortex-M Generic Device User Guide:
For a level-sensitive interrupt, when the processor returns from the ISR, the NVIC samples the interrupt signal. If the signal is
asserted, the state of the interrupt changes to pending, which might
cause the processor to immediately re-enter the ISR. Otherwise, the
state of the interrupt changes to inactive.
For a pulse interrupt, the NVIC continues to monitor the interrupt signal, and if this is pulsed the state of the interrupt changes to
pending and active. In this case, when the processor returns from the
ISR the state of the interrupt changes to pending, which might cause
the processor to immediately re-enter the ISR.
What this is saying is that unless you clear the hardware state which is generating the interrupt request, the interrupt will pend again.
Clearing the interrupt pending state only allows you to disable an IRQ if the request has already been cleared.
For details on how your secure device operates, you need to speak to your vendor. They may be unhappy about you discussing their product here...
I have read the ARM document about Cortex-M3 (or M0) and it say it can be used as level sensetive or pulse (edge) interrupt within the NVIC controller. The problem that it rather vague on how to do this, if this is done by software.
I fails to see any kind of register within the NVIC or such that control the type of the interrupt (to select edge or level by adjusting the register bits). So something must be done by software within handler but again it vague in this field.
I like to hear anyone having a way to make it edge or level trigger interrupt by software.
Please demonstrate within the handler code (if this control it) that the make it detect for level or pulse.
If this is level detect, I can hold interrupt active and disable by the handler, until restore by external code for which it re-excute the interrupt. This is what I'm trying to do, but it will not work if this is pulse detect type.
Thx
A document that describes how the Cortex-M3 NIVC handles level or edge (pulse) triggered interrupts can be found here:
Cortex-M3 Devices Generic User Guide, 4.2.9. Level-sensitive and pulse interrupts
This may well be the document you refer to in your question. Joseph Yiu's book, "The Definitive Guide to the ARM Cortex-M3" also has a pretty good description.
There is no particular configuration of the NVIC for these two interrupt signal types - it handles either kind. Essentially, when an interrupt is asserted (whterh level-based or edge triggered) the NVIC latches that status in the SETPENDx register. When the ISR for that interrupt is vectored to, the corresponding bit in the ACTIVEx register will be set and the bit in the SETPENDx register will be cleared.
While the interrupt is active, if the interrupt line transitions from inactive to active, the pending bit will be turned on again, and upon return from the current active ISR instance, the interrupt will be handled again. This handles the edge triggered interrupt case.
Also, when the ISR returns (and the NVIC clears the 'active' bit), the NIVC will reexamine the state of the interrupt line - if it's still asserted it will set the pending bit again (even if there hasn't been a a transition from inactive to active). This handles the case where an interrupt is level triggered, and the ISR didn't manage to cause the interrupt to be de-asserted (maybe a second device on a shared IRQ line asserted its interrupt at just the critical moment so there was no time when the interrupt line was inactive).
If this is level detect, I can hold interrupt active and disable by the handler, until restore by external code for which it re-execute the interrupt.
I'm not sure I really understand what you're after here, but I think that you might be able to do what you want using the NVIC's SETENAx and CLRENAx registers to enable/disable the interrupt. These work independently of the pending bits, so an interrupt can be pending (or become pending) even if the interrupt is disabled. So you can hold off handling an interrupt for as long as you want.
If that's not quite enough, also note that you can cause an interrupt to pend via software by simply setting the pending bit in the corresponding SETPENDx register - the CPU will vector to the ISR just as if a hardware interrupt were asserted (assuming the interrupt is enabled in the SETENAx register). you can also use the "Software Trigger Interrupt Register" (STIR) to trigger an interrupt by software.