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

  • Okay, I added "NRF_TIMER1->EVENTS_COMPARE[0] = 0;" and made the IRQ handler modify a boolean which I check constantly in a loop instead. It appears that the variable modification never occurs. On the other hand in the loop which I check that variable I also constantly output text over UART. I noticed that it stops outputting text after a fraction of a second. If I disable the timer it outputs all the time. So I guess it might be still stuck inside the IRQ handler somehow?

  • Can you post the latest code please. It makes it easier to figure out what is really happening.

    Since replies are limited that means editing the original answer (or write a short reply, convert it to an answer and then edit that, I think that works)

  • Another observation: I changed the prescaler to 0 (for milliseconds instead of microseconds) and CC[0] to 2000. After starting the program it fails to output the initial "init" text which brings me to conclusion that it gets stuck much sooner. Is the prescaler not working properly?

  • The prescalar and the timer are all working just fine. Changing it to zero most certainly does not change it from microseconds to milliseconds, at 2000 cycles with a prescalar of 0 you were getting interrupted every 2000/16000000 seconds = 125 microseconds. With your posted code you were getting interrupted about every 30 milliseconds. I'm going to assume for some reason your UART print doesn't like being constantly interrupted. So why don't we try to make the timout LOOONGGGGG, like 1 second.

    max prescaler is 15, so try that, that makes the tick 16,000,000/2^15 ~= 488 a second. So set your counter to 500, which is within the 16 bit range, now you have something like a 1-second timer. If the uart can't keep up with that I have no idea what's wrong with it. So prescalar 15, CC[0] = 500, or 1000 if you like.

Related