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

Issues with using Timer1 in counter mode after SDK migration.

Hi!

I have inherited a large codebase that I'm trying to migrate to SDKv10 from SDKv6.

The project also uses an A4960 BLDC motor controller. To bring the motor up to speed, we count the number of rising edges on the TACHO pin of the controller, but for some reason this no longer works as it used to.

The following piece of code initializes the counter.

void freqcntr_init() {
    uint8_t softdevice_enabled;
    uint32_t err_code;

    /* Stop and clear the timer */
    NRF_TIMER1->TASKS_STOP = 1;
    NRF_TIMER1->TASKS_CLEAR = 1;

    /* Disable the TIMER1 interrupt vector */
    NVIC_DisableIRQ(TIMER1_IRQn);

    /* Disable interrupts on all compare channels */
    NRF_TIMER1->INTENCLR = TIMER_INTENCLR_COMPARE0_Msk
            | TIMER_INTENCLR_COMPARE1_Msk
            | TIMER_INTENCLR_COMPARE2_Msk
            | TIMER_INTENCLR_COMPARE3_Msk;

    NVIC_ClearPendingIRQ(TIMER1_IRQn);

    /* Select counter mode */
    NRF_TIMER1->MODE = (TIMER_MODE_MODE_Counter << TIMER_MODE_MODE_Pos);

    /* 32-bit width so that we minimize risk of overflowing counter. */
    NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos);

    /* Make the BLDCTACHO pin an input will a pull-down resistor to keep it
     * from floating unpredictably. */
    nrf_gpio_cfg_input(BLDCTACHO_PIN_NO, NRF_GPIO_PIN_PULLDOWN);

    /* Configure GPIO task/event block to generate an event for every low-to-
     * high transition of the input signal. */
    nrf_gpiote_event_configure(FREQCNTR_GPIOTE_CHANNEL, BLDCTACHO_PIN_NO, NRF_GPIOTE_POLARITY_LOTOHI);

    /* Whether or not the soft device is enabled determines how we configure
     * the PPI block. */
    err_code = sd_softdevice_is_enabled(&softdevice_enabled);
    APP_ERROR_CHECK(err_code);

    /* Connect the rising-edge GPIOTE event to the counter's count task so that
     * we count the number of rising edges and then enable the PPI channel. */
    if (softdevice_enabled) {
        err_code = sd_ppi_channel_assign(FREQCNTR_PPI_CHANNEL,
                &(NRF_GPIOTE->EVENTS_IN[FREQCNTR_GPIOTE_CHANNEL]),
                &(NRF_TIMER1->TASKS_COUNT));
        APP_ERROR_CHECK(err_code);

        err_code = sd_ppi_channel_enable_set(FREQCNTR_PPI_CHENSET_MASK);
        APP_ERROR_CHECK(err_code);
    } else {
        NRF_PPI->CH[FREQCNTR_PPI_CHANNEL].EEP = (uint32_t)&(NRF_GPIOTE->EVENTS_IN[FREQCNTR_GPIOTE_CHANNEL]);
        NRF_PPI->CH[FREQCNTR_PPI_CHANNEL].TEP = (uint32_t)&(NRF_TIMER1->TASKS_COUNT);
        NRF_PPI->CHENSET = FREQCNTR_PPI_CHENSET_MASK;
    }

    /* Enable counting */
    NRF_TIMER1->TASKS_START = 1;
}

And this function is called every once in a while to get the count:

void freqcntr_updateFreq() {
    /* Capture the count */
    NRF_TIMER1->TASKS_CAPTURE[0] = 1;

    SEGGER_RTT_printf("Count: %lu\r\n", NRF_TIMER1->CC[0]);

    /* Reset the count as soon as we have saved the old count */
    NRF_TIMER1->TASKS_CLEAR = 1;
}

Unfortunately, this always prints 0 for the counter value. I know that the problem can be from somewhere else, but wanted to check if there is anything glaringly wrong with the code above.

Thanks!

Parents
  • Don't see anything which wouldn't work. Couple of general points, TIMER1 isn't 32 bit, it's max 16 bit, but it should still count. If you're moving to a more recent softdevice, the PPI peripheral is no-longer restricted, so no need for the sd_enabled check, you can just set up the PPI directly saving the softdevice overhead.

    I'd enable the GPIOTE interrupt and ensure that event is being correctly triggered by breaking in the handler and check the PPI registers at that point to make sure the channel you're using is still set up and enabled.

Reply
  • Don't see anything which wouldn't work. Couple of general points, TIMER1 isn't 32 bit, it's max 16 bit, but it should still count. If you're moving to a more recent softdevice, the PPI peripheral is no-longer restricted, so no need for the sd_enabled check, you can just set up the PPI directly saving the softdevice overhead.

    I'd enable the GPIOTE interrupt and ensure that event is being correctly triggered by breaking in the handler and check the PPI registers at that point to make sure the channel you're using is still set up and enabled.

Children
No Data
Related