This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Timers not working when using C++?

So. After countless hours of messing around, reading SDK, examples and stuff I'm begginning to feel kind of frustrated. I want a microsecond timer. For that I tried a number of different approaches: app_timer, timer driver API and accessing the timers directly. So far app_timer seems to be the only one that worked, but it lacks in resolution I need.

Approach 1:

nrf_drv_timer_t timerThing = NRF_DRV_TIMER_INSTANCE(1);

void timerHandler(nrf_timer_events_t event)
{
	if(event == NRF_TIMER_EVENTS_COMPARE0) log("time!\r\n");
}

void main()
{
	log("init\r\n");
	uint32_t ticks, ms = 2000;
	
	nrf_drv_timer_init(&timerThing, NULL, timerHandler);
	ticks = nrf_drv_timer_ms_to_ticks(&timerThing, ms);
	nrf_drv_timer_extended_compare(&timerThing, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORTS_COMPARE0_CLEAR_MASK, true);
	nrf_drv_timer_enable(&timerThing);
	
	while(1);
	return 0;
}

I looked into 'examples/peripheral/timer', basically copied the code just to get it running. Well.. The handler IS called just fine, the problem however is the fact that it's being called constantly. It doesn't matter what value I set for 'ms' variable. I checked the value returned by ms to ticks conversion function and it appears to be correct.

So I started to look around the devzone and I noticed that people were usually using these timers directly (if what I'm saying makes any sense).

volatile bool foobar = false;

void TIMER1_IRQHandler()
{
    if(NRF_TIMER1->EVENTS_COMPARE[0])
    {
        NRF_TIMER1->EVENTS_COMPARE[0] = 0;
        foobar = true;
    }
}

void uartEventHandler(app_uart_evt_t *event) {}

int main()
{
    uint32_t errorCode;
    
    app_uart_comm_params_t uartParams =
    {
        RX_PIN_NUMBER,
        TX_PIN_NUMBER,
        RTS_PIN_NUMBER,
        CTS_PIN_NUMBER,
        APP_UART_FLOW_CONTROL_DISABLED,
        false,
        UART_BAUDRATE_BAUDRATE_Baud115200 // 57600 // 115200
    };

    APP_UART_FIFO_INIT(&uartParams, 32, 256, uartEventHandler, APP_IRQ_PRIORITY_LOW, errorCode);
    
    debugOut("Hello World!\r\n");
    
    NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    NRF_TIMER1->EVENTS_COMPARE[1] = 0;
    NRF_TIMER1->EVENTS_COMPARE[2] = 0;
    NRF_TIMER1->EVENTS_COMPARE[3] = 0;
    
    NRF_TIMER1->TASKS_STOP  = 1;
    NRF_TIMER1->MODE        = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;
    NRF_TIMER1->BITMODE     = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos;
    NRF_TIMER1->PRESCALER   = 9;
    NRF_TIMER1->TASKS_CLEAR = 1;
    NRF_TIMER1->CC[0] = 31250;
    NRF_TIMER1->INTENSET    = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos;
    NRF_TIMER1->SHORTS      = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
    NVIC_EnableIRQ(TIMER1_IRQn);
    NRF_TIMER1->TASKS_START = 1;
    
    while(1)
    {
        if(foobar)
        {
            debugOut("foo\r\n");
            foobar = false;
        }
        else debugOut("no\r\n");
    }
    
    return 0;
}

This at first wasn't working. It appeared as if it got stuck inside the interrupt or something. After compiling it with Keil it worked at first but then I did something that made it stop. Now I can't get it to work again:

image description

I'm obviously doing something very wrong, I'm just unable to find out what exactly it is. What am I missing here? Please forgive me if it's something rather silly, I'm still trying to learn the way everything works here.

EDIT:

I found something interesting. This is the code that orginally worked: http://pastebin.com/CGGxRLhs

It's C. After putting in in a .cpp file (compiling as C++) it doesn't work. Putting in in a .c file makes it work just fine...

  • you disable it with the same code you enabled it with, just use NVIC_DisableIRQ() and/or INTENCLR instead of INTENSET.

    I'll copy paste your latest code into a project later but I know it's going to work just fine.

  • No luck http://pastebin.com/Yf9jT22v Perhaps I should report it somewhere else?

  • My last attempt then I give up.. set the timer up in this order after you set timer mode and bit mode.

    NRF_TIMER1->INTENSET = .. the thing you have ...
    NRF_TIMER1->PRESCALER=15;
    NRF_TIMER1->CC[0]=65535;
    NRF_TIMER1->TASKS_CLEAR=1;
    NRF_TIMER1->EVENTS_COMPARE[0] = 0;
    NVIC_ClearPendingIRQ( TIMER1_IRQ );
    NRF_TIMER1->TASKS_START = 1;
    

    That timer should not fire for 136 seconds.

    If that doesn't work then you really need to get a debugger on it to convince yourself that it does, because this absolutely totally works.

  • So. It seems like it DOES work. But only when compiled with Keil. It simply refuses to work when compiled using GCC ARM. Not sure what's up with that... It also appears that the value of 65000 with the prescaler of 15 equates to around 2 seconds. I don't think that's expected, is it?

    EDIT: 9 is the max prescaler here, values any higher don't change anything. So 32000ish is 1 second. That really doesn't look right.

    EDIT2: Actually, I think I got it. 16000000 / 2^9 = 31250 So 1 tick with that pescaler is 1/31250 of a second. Yup, makes sense. Thank you very much for your assistance! I should be able to manage all this now.

  • Yeah, nevermind. After stiching the code together it stopped working. sigh Now I can't get it to work again. Here's how it looks in the debugger: http://i.imgur.com/8GPwmpY.png

    EDIT: See my edited question

Related