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

TASKS_CAPTURE cannot read the correct value

Hello!

I compare the timer every 1ms and process it.
In order to check whether it can be executed every 1ms, I am going to refer to the register value by "TASKS_CAPTURE".
The description of the timer itself is as follows.

Timer 1 is used.

nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
err_code = nrf_drv_timer_init(&TIMER, &timer_cfg, timer_twi_event_handler);
APP_ERROR_CHECK(err_code);

time_ticks = nrf_drv_timer_us_to_ticks(&TIMER, time_us);

nrf_drv_timer_extended_compare(
    &TIMER, NRF_TIMER_CC_CHANNEL1, time_ticks, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK, true);

nrf_drv_timer_enable(&TIMER);



The description of "TASKS_CAPTURE" is as follows.

void timer_twi_event_handler(nrf_timer_event_t event_type, void* p_context)
{

    switch (event_type)
    {
        case NRF_TIMER_EVENT_COMPARE1:
            if(j == 48){
                j = 0;
            }
					
            NRF_TIMER1 -> TASKS_CAPTURE[0] = 1;
            uint8_t caputured_value = NRF_TIMER1 -> CC[0];

            flags = true;
            time++;
            //receive_data();
            ret_code_t ret = nrf_drv_spi_xfer(&spi,&xfer_spi,flags);//Function for starting the SPI data transfer with additional option flags
            if(ret == NRF_SUCCESS)
            {
                uint32_t start_tsk_addr = nrf_drv_spi_start_task_get(&spi);
            }

            if(j < 24){
              //put_in_array(buf);
              for(int a = 0; a < 20; a++){
                  buf[j*21+a] = mpu_buf[a];
              }
              buf[j*21+20] = caputured_value;
            }else if(j >= 24){
              //put_in_array(buf2);
              for(int a = 0; a < 20; a++){
                  buf[j*21+a+8] = mpu_buf[a];
              }
              buf[j*21+20+8] = caputured_value;
            }
            j++;
            //data_handler();
					
            break;

        default:
            //Do nothing.
            break;
    }
}

The captured value is confirmed by writing to the SD card.
The values are always as follows:

253.00000
253.00000
253.00000
253.00000
253.00000
253.00000
255.00000
255.00000
228.00000
228.00000
255.00000
75.00000
255.00000
252.00000
252.00000
252.00000
252.00000
252.00000
252.00000
252.00000

This will be repeated.
Is my code something wrong?
Since "NRF_TIMER_CC_CHANNEL1" is used in the comparison, cc [0] is used when reading the register. Is this correct?

Please give me an answer.

Parents
  • Hi,

    I found thiese DevZone threads quite useful regarding need to update CC register og clear the time in order to be ready  https://devzone.nordicsemi.com/f/nordic-q-a/2010/setting-timer2-interval and https://devzone.nordicsemi.com/f/nordic-q-a/18237/timer-with-two-compared-values/70428#70428

    I see you set up your device to use TIMER1 CHANNEL1 to call your callback every 1ms. The function nrf_drv_timer_extended_compare makes sure the time in CHANNEL1 is cleared upon every compare (1ms). 
    However, I cannot find a similar mechanism in your callback clearing the time in CHANNEL0 which you use to verify the frequency of CHANNEL1 callback.
    I would suggest to capture the value in CC[0] then clear the CHANNEL0, or store the captured value in a static variable and subtract the current value to the old value to find the delta. 


    One thing I see right away, the variable captured_value should be of type uint32_t to not overflow at value 255. 

    Another thing I wonder about.
    Is it possible that the next timer event is ready before you exit the timer callback?
    Looking trough your code it seems the there are some data dependencies, which gives the execution path different length from time to time. 

    I'll look more into this tomorrow to see if I can verify this on my desk.

Reply
  • Hi,

    I found thiese DevZone threads quite useful regarding need to update CC register og clear the time in order to be ready  https://devzone.nordicsemi.com/f/nordic-q-a/2010/setting-timer2-interval and https://devzone.nordicsemi.com/f/nordic-q-a/18237/timer-with-two-compared-values/70428#70428

    I see you set up your device to use TIMER1 CHANNEL1 to call your callback every 1ms. The function nrf_drv_timer_extended_compare makes sure the time in CHANNEL1 is cleared upon every compare (1ms). 
    However, I cannot find a similar mechanism in your callback clearing the time in CHANNEL0 which you use to verify the frequency of CHANNEL1 callback.
    I would suggest to capture the value in CC[0] then clear the CHANNEL0, or store the captured value in a static variable and subtract the current value to the old value to find the delta. 


    One thing I see right away, the variable captured_value should be of type uint32_t to not overflow at value 255. 

    Another thing I wonder about.
    Is it possible that the next timer event is ready before you exit the timer callback?
    Looking trough your code it seems the there are some data dependencies, which gives the execution path different length from time to time. 

    I'll look more into this tomorrow to see if I can verify this on my desk.

Children
  • Thank you for your reply!

    The link seems useful
    Thank you

    Is the correct way to capture with CC [0] instead of capturing CC [1]?

    I do not know how to clear after capture

    In "store the captured value in a static variable and subtract the current value to the old value to find the delta", I don't feel like checking 1ms every time.

    The variable capture_calue is set to uint8_t for SD card writing. Therefore,
    NRF_TIMER1-> BITMODE
    Should be set to

    "Is it possible that the next timer event is ready before you exit the timer callback?"
    Since the contents of the call are being executed, we think it will be finished by the next call.

    I prepared a variable time that was not capture_value and wrote it to the SD card so that it is incremented by 1 each time. However, I want to read the timer register instead of this method.

Related