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

Parents
  • So the only thing I instantly see wrong there is TIMER1 and 2 don't support anything other than 16 bit mode (it's documented but it's hard to find). I'm not entirely sure what happens when you put them into 24 or 32 bit mode, it may well be that they set up the target count as 2,000,000, compare it on a 24-bit basis but never get there because the counter rolls over after 16 bits.

    So I'd try using a smaller number for a start see if that works.

    I see you said you tried it with TIMER0, that should work, are you sure when you tried it that you changed every instance of TIMER1 to TIMER0, including the IRQ handler, and the interrupt enable, it's very easy to miss one?

    You could run that code and hit break after a few seconds to see where you are, hopefully in the while() loop. Then take a look at the TIMER registers and see what they're giving you.

    You need to clear the COMPARE event or else the IRQ will keep firing, which isn't your problem yet.

    And just for testing purposes whilst doing other things, comment out the short, I'm fairly sure that doesn't affect the COMPARE event but getting down to the bare minimum is always a good idea.

    I don't think you need to start the HF Clock, but it's ok to do so.

    For consistency and to get into good habits I'd do

    NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos;
    

    It's zero anyway but I try to use this pattern every time so I don't get tripped up one day.

    The rest looks fine - I would expect that code, when restricted to 16 bit mode, to work.

    Please post what you find - if it doesn't work I'll compile and run it myself, it should do.

    EDIT:

    Actually I was bored this afternoon and did try it out and it works fine. Setting the 2,000,000 compare into TIMER1 just sets the lower 16 bits and setting it to 24bit mode doesn't seem to matter. I get (very) regular interrupts.

    I cut n' pasted your code directly into a new project, changing only log() to a Segger RTT log and adding the header imports I needed. I made no other changes, it works.

    Changing everything to TIMER0 I get the 2 second ticks you'd expect in 24 bit mode.

    So are you sure it's not working? What makes you think it's not, not logging? Are you sure log() does what you think it does and isn't just linking in the log() function from the math library? Have you put a breakpoint in the IRQ handler to see if it goes in there?

  • Well as I said, if that's all your code then you haven't actually set the uart up, there's no app_uart_init there so app_uart_put() won't do anything, well it won't do anything useful. You need to call the initialization function before you try using the UART, from reset the chip isn't going to know what pins you're using for UART comms or enable the UART irq or do anything else.

    If that isn't all your code and you are initializing the uart somewhere then I'll tell you one more time, you need to clear the event in the IRQ handler. Now I'm back home I can see that app_uart is interrupt driven, I have no idea what priority you gave it when you initialise it, if you initialise it, if it's lower than the default TIMER1 priority which is 0, the highest there is, then you will never get out of the timer interrupt unless you clear the event and the uart will never get to send anything.

Reply
  • Well as I said, if that's all your code then you haven't actually set the uart up, there's no app_uart_init there so app_uart_put() won't do anything, well it won't do anything useful. You need to call the initialization function before you try using the UART, from reset the chip isn't going to know what pins you're using for UART comms or enable the UART irq or do anything else.

    If that isn't all your code and you are initializing the uart somewhere then I'll tell you one more time, you need to clear the event in the IRQ handler. Now I'm back home I can see that app_uart is interrupt driven, I have no idea what priority you gave it when you initialise it, if you initialise it, if it's lower than the default TIMER1 priority which is 0, the highest there is, then you will never get out of the timer interrupt unless you clear the event and the uart will never get to send anything.

Children
No Data
Related