I'm trying to enable interrupts and timer 2 on Allwinner A20 (User Manual).
cpsr reads 0x60000113. GICD_CTRL reads 1. GICC_CTRL reads 1. GICD_ITARGETSR0 reads 0x01010101. And GICD_IIDR reads 0x0100143b.
IRQ_ENABLE_REG of the timer was enabled. STATUS_REG also changed after the timer counted down once.
But I still cannot get it running into IRQ handler. What did I miss?
What I've ignored is to check the base address of exception vectors, which was written in pre-booting. IRQ behaves normally after resetting.
Related
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.
Is there any way to disable all irq from Cortex M3 MCU except one ?
My issue is that I have a system running several kinds of irq with various priority levels and I want to disable all irq except one in a particular state.
I know I can disable all irq by using "__disable_irq()" instruction but I can't enable one irq after calling this instruction if I didn't call "__enable_irq()" before.
Thanks for your help,
Regards
Use the BASEPRI register to disable all interrupts below the specified priority level.
This is a core register, described in the Cortex-M3 Programming Manual.
CMSIS provides the __get_BASEPRI() and __set_BASEPRI() functions to manipulate its value.
Note that bits 7-4 are used, the priority value must be shifted left by 4. To disable all interrupts with priority 1 or lower, use
__set_BASEPRI(1 << 4);
and to enable all, set it to 0
__set_BASEPRI(0);
You should of course set interrupt priorities accordingly, ensuring that no other interrupt has priority 0.
Other than by disabling all the enabled interrupts you don't want, no.
__disable_irq() is implemented as CPSID I, which turns off all exceptions which can have a priority set (those configured in the NVIC), it achieves this by changing the PRIMASK register (setting bit 0) within the CPU. There is no way to tell this to only enable a specific interrupt.
Is it a feature of Cortex-M series MCUs to be able to wake from a low power mode (sleep or deepsleep or other MCU specific modes) with interrupts configured but disabled?
The mechanism for entering the low power mode is executing WFI instruction.
The MCUs I have used from STM and Renesas, wake from the low power mode via an interrupt if the interrupt is configured correctly and even if all interrupts are disabled via the cpsid instruction.
I am trying to determine is this is what I should expect on all Cortex M series based MCUs or just specific to certain MCU vendors.
Every ARM Cortex-M will work this way as long as you use PRIMASK to disable ALL interrupts. This is what __disable_irq() from CMSIS does. According to the docs, raising priority with BASEPRI will not cause an interrupt with insufficient priority to wake the chip.
See here - http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABFEFIG.html
Operation
WFI is a hint instruction that suspends execution until one of the following events occurs:
a non-masked interrupt occurs and is taken
an interrupt masked by PRIMASK becomes pending
a Debug Entry request.
Context
on i.MX6Quad board, when the system running, I found that Core3 can not deal with any interrupt.
view the GIC interface registers by Trace32, the GICC_RPR is always 0, which means the highest priority event is running, so it explain the uppon question: lower priority event cannot be processed.
Question
I have insert a instruction : write 0 to GICC_EOI , which can change GICC_RPR to idle priority(0xFF), but it doesn't work, keep 0.
Goal
I want to do priority drop and deactivate success.
References
gic arch specf : 3.2.1 Priority drop and interrupt deactivation
Priority drop is the drop in the Running priority that occurs on a valid write > to an EOIR, either the
GICC_EOIR or the GICC_AEOIR.
On priority drop, the running priority is reduced from the priority of the
interrupt referenced by the
EOIR write to either
Writing Zero to EOI does not help. When an interrupt fires, you have to read GICC_IAR register. The value you get is the interrupt number that fired. If you are in legacy mode, you have to write this interrupt number to EOI to retire this interrupt. If you are in priority drop mode, writing this number to EOI decreases the priority, writing the same value to DI will retire the interrupt (check GICC_CTLR to confirm your mode). Hope this clears up the confusion with RPR and EOI.
Some pointers to debug your issue:
1. Check the GICD_ITARGET registers to see there are interrupts pointed at CPU3.
2. Ensure the interrupts that you are expecting in CPU3 (if anything specific) is not masked in the distributor
3. Check GICC_PMR for CPU3 to see that the priority is not too high. An interrupt is forwarded from distributor to cpu interface only if its priority is higher than the value in this register
4. Check CPU interface for CPU3 is enabled
5. Check GICD_ISPEND to see if the interrupt in question is pending
NOTE: Be careful when using T32 to debug GIC. T32 works by reading values from registers/memory. This has undesired effects on some GIC registers, for eg GICC_IAR register can only read once to acknowledge the interrupt. Further reads will return spurious interrupt numbers. When T32 is connected and a window is opened to read GICC registers, this will cause an 'orphan' interrupt that no one can take care of. I would suggest putting in logs in the interrupt handling logic to debug issues.