This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Can't access variable in IRQ Handler

Hi,

I'm getting familiar with my nRF52 DK (PCA 10040).

I stumbled on something when I was doing an application that toggles LED1 on every TIMER0 event (200ms). Here is my code

#include "stdint.h"
#include "nrf52.h"

//volatile uint32_t varA;	<POS A>

void initSystem (void) {	
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;	
    while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { }

    NRF_TIMER0->MODE		= 0;
    NRF_TIMER0->BITMODE		= 3;
    NRF_TIMER0->PRESCALER	= 5;
    NRF_TIMER0->CC[0]		= 100000;		// TIMER0_IRQn event each 200ms

    NRF_TIMER0->INTENSET	= (1<<16);

    NRF_TIMER0->TASKS_CLEAR = 1;
    NRF_TIMER0->SHORTS		= 1;
    NRF_TIMER0->TASKS_START = 1;

    NVIC_SetPriority(TIMER0_IRQn, 7);
    NVIC_ClearPendingIRQ(TIMER0_IRQn);
    NVIC_EnableIRQ(TIMER0_IRQn);
}

int main (void) {		
    NRF_P0->DIRSET = (1<<17);
    NRF_P0->OUTSET = (1<<17);

    initSystem();

    while (1) { }
}

void TIMER0_IRQHandler (void) {	
    volatile uint32_t varA;		// <POS B>

    varA = NRF_P0->OUTSET & (1<<17);

    if (varA)
	    NRF_P0->OUTCLR = (1<<17);
    else
	    NRF_P0->OUTSET = (1<<17);	

    NRF_TIMER0->EVENTS_COMPARE[0] = 0;
}

Everything is great. But if I move the declaration of the varA to the top (i.e. in my opinion declaring it as a global variable) it does not work. I don't get a compile or link error. The LED just won't toggle.

Why can't I access global variables inside my IRQ Handler??

NOTE: I'm only using CMSIS: Core and Device startup

Parents
  • Could it be the ARM write cache aka write buffers? See the ARM documents about "write buffers." Also see the terse note in the Nordic docs about migrating from 51 to 52. Briefly, a write to an IO register is buffered, and may not take effect until a read (from another IO register.) In your code, you don't seem to do any reads until the first interrupt. Thus it might be that some (none?) of your writes take effect or take effect a little later than you think, causing a race. I don't believe that myself, since then why would the Timer be started? But you could test it by inserting reads just after writes to flush the cache.

Reply
  • Could it be the ARM write cache aka write buffers? See the ARM documents about "write buffers." Also see the terse note in the Nordic docs about migrating from 51 to 52. Briefly, a write to an IO register is buffered, and may not take effect until a read (from another IO register.) In your code, you don't seem to do any reads until the first interrupt. Thus it might be that some (none?) of your writes take effect or take effect a little later than you think, causing a race. I don't believe that myself, since then why would the Timer be started? But you could test it by inserting reads just after writes to flush the cache.

Children
No Data
Related