Timer capture with gpio

JP5654
Posts: 16
Joined: Fri Jul 07, 2023 11:50 pm

Timer capture with gpio

Postby JP5654 » Fri May 24, 2024 4:42 am

I would like to have a free running hardware timer that gets reset on the the edge of an input gpio. I would like to be able to read this counter at various times during execution to be able to know how much time has elapsed since the last edge. Is this possible with any of the esp32 peripherals? It seemed like I could use the MCPWM capture to do this but I can't seem to be able to configure it to reset the timer. I don't want to use an interrupt to reset the timer.

Thanks

liaifat85
Posts: 200
Joined: Wed Dec 06, 2023 2:46 pm

Re: Timer capture with gpio

Postby liaifat85 » Fri May 24, 2024 4:00 pm

You can use the Input Capture Unit (ICU) or the Pulse Counter Unit (PCNT) to perform this task.

JP5654
Posts: 16
Joined: Fri Jul 07, 2023 11:50 pm

Re: Timer capture with gpio

Postby JP5654 » Fri May 24, 2024 10:43 pm

I'm not sure how I can use the pulse counter to do this. The pulse counter just counts edges, I need to correlate an edge with a time stamp.

I did end up figuring out how to use the mcpwm timer to achieve my goal.

Here's how I did it:

Code: Select all

    //We are using a mcpwm timer in order to be able to query the time in microseconds since the last
    //clock sync falling edge
    mcpwm_timer_handle_t clock_sync_timer;
    const mcpwm_timer_config_t mcpwm_timer_config = {
           .group_id = 0,
           //.clk_src
           .resolution_hz = 1000000,    //1us resolution
           .count_mode = MCPWM_TIMER_COUNT_MODE_UP, //Count up
           .period_ticks = 65536, //Set max period, we should be resetting this timer with the clock sync before we reach this
           //.intr_priority
           .flags.update_period_on_empty = 0,
           .flags.update_period_on_sync = 0,

    };
    assert(ESP_OK == mcpwm_new_timer(&mcpwm_timer_config,&clock_sync_timer));

    mcpwm_sync_handle_t gpio_sync_source;
    const mcpwm_gpio_sync_src_config_t mcpwm_gpio_sync_src_config = {
        .group_id = 0,              // GPIO fault should be in the same group of the above timers
        .gpio_num =GPIO_NUM_15,
        .flags.pull_down = false,
        .flags.active_neg = true,  // negative edge pulse will trigger a sync event to load the timer with the count value
    };
    assert(ESP_OK == mcpwm_new_gpio_sync_src(&mcpwm_gpio_sync_src_config, &gpio_sync_source));

    const mcpwm_timer_sync_phase_config_t mcpwm_timer_sync_phase_config = {
        .sync_src = gpio_sync_source,   //Use our gpio as the sync source for the timer
        .count_value = 0,             //Reset the timer to 0 on the sync
        .direction = MCPWM_TIMER_DIRECTION_UP, //Continue counting up after the sync
    };
    assert(ESP_OK == mcpwm_timer_set_phase_on_sync(clock_sync_timer, &mcpwm_timer_sync_phase_config));

    const mcpwm_timer_event_callbacks_t cbs = {
            .on_empty = mcpwm_on_empty_cb,  //Use this to get an interrupt when the clock sync falling edge occurs
            .on_full = mcpwm_on_full_cb,    //Use this to confirm we have a valid clock sync occuring
    };
    assert(ESP_OK == mcpwm_timer_register_event_callbacks(clock_sync_timer, &cbs, NULL));


    assert(mcpwm_timer_enable(clock_sync_timer) == ESP_OK);  //enable the timer
    assert(mcpwm_timer_start_stop(clock_sync_timer, MCPWM_TIMER_START_NO_STOP) == ESP_OK);   //Start the freerunning timer
    
    uint32_t timer_val = mcpwm_timer_get_value(clock_sync_timer); //get the timer value which shows how many microseconds have elapsed since the last falling edge
Pretty lame though the api doesn't provide a way to read the current timer value (except through an ISR) so I had to modify the driver and add this function:

Code: Select all

uint32_t mcpwm_timer_get_value(mcpwm_timer_handle_t timer_channel)
{
    mcpwm_timer_t *timer = timer_channel;
    mcpwm_group_t *group = timer->group;
    mcpwm_hal_context_t *hal = &group->hal;
    int timer_id = timer->timer_id;

    return mcpwm_ll_timer_get_count_value(hal->dev, timer_id);
}

Who is online

Users browsing this forum: Majestic-12 [Bot], orbitcoms, ThomasSt and 94 guests