Quick Aside to debug GPIO ISRs
Problem: It is seen that the GPIO ISR was getting called more than once for every button press. Diagnosis: The last instruction in the GPIO Interrupt handler is a write to the ICR register which clears the interrupt. However, this write takes multiple cycles, depending on the caching involved. As a result, after the instruction to write to ICR, the microcontroller exits from the ISR function but the write has not yet completed. The controller sees this as a pending interrupt and goes into the ISR again. However, by the time the controller enters the ISR this second time the ICR write has indeed happened, and it appears to be a spurious interrupt call. If the code is run in single-step debug mode, it gives the code enough time to write to the ICR register and therefore the ISR is not called a second time. Solution: Wait for a few cycles *after* the ICR write instruction and before exiting from the ISR. The official documentation recommends a DSB instruction but that may not be enough to account for vendor-specific write-caching. In such a case a simple write to a register location should be enough. Additional Info: https://developer.arm.com/documentation/ka003795/latest/
This commit is contained in:
parent
dd679556d5
commit
85a2491634
21
Blink/main.c
21
Blink/main.c
|
@ -31,15 +31,15 @@ x GPIODEN -- GPIO Digital Enable -- 0x00011111 >> 0x1F
|
|||
register uint32_t x = ZERO_DEF;
|
||||
|
||||
|
||||
GPIO_PORTF_DATA_R = 0xE;
|
||||
while(1)
|
||||
{
|
||||
GPIO_PORTF_DATA_R = 0x0;
|
||||
GPIO_PORTF_DATA_R = 0x2;
|
||||
GPIO_PORTF_DATA_R = 0x4;
|
||||
GPIO_PORTF_DATA_R = 0x8;
|
||||
GPIO_PORTF_DATA_R = 0xE;
|
||||
}
|
||||
GPIO_PORTF_DATA_R = 0x4;
|
||||
// while(1)
|
||||
// {
|
||||
// GPIO_PORTF_DATA_R = 0x0;
|
||||
// GPIO_PORTF_DATA_R = 0x2;
|
||||
// GPIO_PORTF_DATA_R = 0x4;
|
||||
// GPIO_PORTF_DATA_R = 0x8;
|
||||
// GPIO_PORTF_DATA_R = 0xE;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
@ -47,6 +47,7 @@ x GPIODEN -- GPIO Digital Enable -- 0x00011111 >> 0x1F
|
|||
{
|
||||
x++;
|
||||
counter_loop();
|
||||
GPIO_PORTF_DATA_R ^= 0x2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ void GPIO_PORTF_Init(void)
|
|||
|
||||
void counter_loop (void)
|
||||
{
|
||||
register uint32_t count=10;
|
||||
uint32_t count = 0xFFFFFF;
|
||||
while(count>0)
|
||||
count--;
|
||||
|
||||
|
|
|
@ -10,14 +10,12 @@ void SystickHandler(void);
|
|||
void Systick_Init(void);
|
||||
|
||||
volatile uint32_t systick_count = 1;
|
||||
|
||||
volatile uint32_t global_counter = 0;
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
|
||||
|
||||
GPIO_PORTF_Init();
|
||||
//Systick_Init();
|
||||
while(1);
|
||||
|
@ -26,8 +24,13 @@ int main(void)
|
|||
|
||||
void SW2_Handler(void)
|
||||
{
|
||||
GPIO_PORTF_DATA_R ^= 0x8;
|
||||
GPIO_PORTF_ICR_R = 0xff;
|
||||
//Start with some nops and then try some dela
|
||||
|
||||
//GPIO_PORTF_DATA_R ^= 0x2;
|
||||
global_counter ++;
|
||||
//GPIO_PORTF_ICR_R = 0x10;
|
||||
GPIO_PORTF_ICR_R = 0x10;
|
||||
__asm(" DSB");
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,7 +79,7 @@ void GPIO_PORTF_Init(void)
|
|||
//GPIOIEV -- Interropt Event --> 0 for falling edge --> 0x00
|
||||
GPIO_PORTF_IEV_R = 0x0;
|
||||
|
||||
//GPIOICR -- INterrpt clear -- must be cleared by writing 1 to corresponding bit --> 0xff
|
||||
//GPIOICR -- Interript clear -- must be cleared by writing 1 to corresponding bit --> 0xff
|
||||
GPIO_PORTF_ICR_R = 0xff;
|
||||
|
||||
//GPIOIM -- Interrupt Mask --> 1 for unmasked (enabled)--> 0x01
|
||||
|
|
Loading…
Reference in New Issue