Atmel SAM3X / SAM3A, handle interrupts from Parallel Input/Output Controller (PIO) - arm

I want to enable the PA8 pin in a processor (Atmel SAM3X / SAM3A). I have set PIOA_MDERp[7]=0 and PIOA_MDDR[7]=0 and PIO_OER[7]=0 and PIO_ODR[7]=1, so that the tri-state buffer will no longer send data out of the pin, and the pin is enabled to receive data from the environment and to send interrupts if needed. I also want to set my interrupt to rising edge, so I also did PIOA_RHLSR[7]=1 and PIOA_FELLSR[7]=0 and also PIO_ESR[7]=1 and PIOA_LSR[7]=0.
My problem now is how to modify NVIC registers so that this interrupt is enabled. I mean, on a rising edge on this pin, the state of this pin is pending, and then the changes I will apply to NVIC causes this pending state to active state.
My interrupt group priority and subgroup priority are both 3.
I know how to modify Interrupt set-enable register, interrupt clear-enable register, application interrupt and reset control register, and interrupt priority register. Still, my problem is that now I don't have any number for interrupts from this specific pin (PIOA8), so it is different from the time I had my interrupt number (from 1 to 240), and so I could know which register in the NVIC I should modify.
Thanks for your help.

Related

Clearing or preventing pending interrupts in an ISR

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.

How to setup the interrupt handler in stm32?

void EXTI4_15_IRQHandler()
{
if(EXTI->PR & EXTI_PR_PR8)
{
EXTI->PR |= EXTI_PR_PR8;
// handle interrupt here
GPIOA->BSRR |= GPIO_BSRR_BS_10;
Delay(500);
GPIOA->BSRR |= GPIO_BSRR_BR_10;
Delay(500);
}
}
the interrupt init is initialized in the main.c and the setup is correct.
Is there anything that i am missing in the handler function?
You have posted only interrupt handler function, which is not a big help on its own. Basically, your MCU either enters it and executes it entirely or not. So if it (the interrupt handler) doesn't run, it means, the interrupt is not triggered. It means, the problem is somewhere else, so I will go over the entire logic of getting EXTI interrupt on STM32, make sure you have all of that done.
In order to get EXTI interrupts working, we need to connect 3 internal peripherals together: GPIO, EXTI and NVIC. You haven't indicated a specific microcontroller, but they all (STM32) do it in the same/similar way, so I will use STM32F746 as an example, since I have it here on my table.
First, you need to set up EXTI. If you want an interrupt on pin GPIOx8, you need to set bits 8 in the appropriate places in the EXTI registers depending on the event you want to trigger an interrupt.
Second of all, you need to connect GPIO port to EXTI. Do you want an interrupt on PA8? Or PB8? Or PC8? EXTI only understands that it's "Pin 8". It doesn't know if it's PA8 or PB8. That you do in SYSCFG peripheral. In the register EXTI->EXTICR3 you need to set port for EXTI8. This is where you decide that it's PB8 and not PA8 that triggers the interrupt, or whatever port you have.
Now, upon the GPIO behavior event defined in EXTI, the EXTI will report an EXTI9_5 event to NVIC. For now, NVIC will set pending bit if EXTI interrupt event occurs, but it will not execute the interrupt, because it's not activated. So we need to configure NVIC and activate EXTI9_5 interrupt there. At this point your interrupt should work.
To recap, the sequence of actions is the following:
Configure EXTI with the number of pin, on which you want interrupt. Number of pin, but not a GPIO port. For you, it will be pin 8.
Configure SYSCFG to select GPIO port for that EXTI pin. Configure pin 8 to be pin PB8 and not PA8 (or whatever port the interrupt is on).
Activate the corresponding NVIC interrupt.
From this also follows, that you can't have interrupts on PA8 and PB8 at the same time.
EDIT: having delays in the ISR is highly inadvisable. Also, make sure your input signal on the interrupt pin is debounced.
EDIT2: I assumed it goes without saying that every peripheral you use requires clock to be supplied to it.

need to use delay in a interrupt function using an STM32F4

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.

ARM Cortex M NonMaskable Interrupt is NonClearable also?

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...

LPC17XX SPI: Implementing pulse-sensitive(edge-triggered) interrupts

I would like to implement a pulse-sensitive, aka edge-triggered, interrupt on an LPC1759 microcontroller. In the UM10360.pdf datasheet and ARM Cortex-M3 user guide, it says that interrupts can be triggered based on level- or pulse-sensitive behavior, but I am unable to find how to set this to be pulse-sensitive. Can someone please tell me where to set this?
For my particular application(interfacing the LPC1759 with an AD7794 ADC), I would like to trigger an interrupt based on the falling edge of the MISO pin. Although it is not explicitly stated that the interrupt is trigger on the MISO value, I am assuming this based on the fact that, of the four SPI signals, the MISO is the only input to the microcontroller. Please let me know if this is not correct.
See UM10360.pdf, chapter 9.5.6: "GPIO interrupt registers". You can enable rising and falling edge interrupts only on port 0 and 2 pins. The interrupt vector is the same as external interrupt 3.

Resources