Skip to content

Ticker interrupt not scheduled when interrupt has been set in the past #6054

Closed
@mprse

Description

@mprse

Description

  • Type: Bug/Question
  • Priority: Major

Bug

Target
ALL

Toolchain:
ALL

Description:
While working with PR #6052 I debug the ticker interrupt scheduling process on K64F board and found that interrupt is not fired when interrupt has been scheduled in the past. Please see the following part of code:

static void schedule_interrupt(const ticker_data_t *const ticker)
{
    ticker_event_queue_t *queue = ticker->queue;
    update_present_time(ticker);

    if (ticker->queue->head) {
        us_timestamp_t present = ticker->queue->present_time;
        us_timestamp_t match_time = ticker->queue->head->timestamp;

        // if the event at the head of the queue is in the past then schedule
        // it immediately.
        if (match_time <= present) {
            ticker->interface->fire_interrupt();
            return;
        }

        timestamp_t match_tick = compute_tick(ticker, match_time);
        ticker->interface->set_interrupt(match_tick);
        timestamp_t cur_tick = ticker->interface->read();

        if (_ticker_match_interval_passed(queue->tick_last_read, cur_tick, match_tick)) {   <----- ISSUE
            ticker->interface->fire_interrupt();
        }
    } else {
        uint32_t match_tick =
                (queue->tick_last_read + queue->max_delta) & queue->bitmask;
        ticker->interface->set_interrupt(match_tick);
    }
}

Expected behavior

In case when interrupt has been scheduled in the past _ticker_match_interval_passed() function should return true and interrupt should be fired by means of ticker->interface->fire_interrupt();.

I found in my debug log the following case:

  • timestamp in ticks passed to set_interrupt() function: 020394758.
  • current time in ticks reported by set_interrupt() function: 020394759.
  • last tick read (queue->tick_last_read): 020394758.

It looks like this is the case when interrupt has been set in the past (one tick), so _ticker_match_interval_passed() routine should return true and interrupt should be fired by means of ticker->interface->fire_interrupt();.

Actual behavior

Interrupt is not fired by means of ticker->interface->fire_interrupt();.

Analysis

Please see the _ticker_match_interval_passed() function:

int _ticker_match_interval_passed(timestamp_t prev_tick, timestamp_t cur_tick, timestamp_t match_tick)
{
    if (match_tick > prev_tick) {
        return (cur_tick >= match_tick) || (cur_tick < prev_tick);
    } else {
        return (cur_tick < prev_tick) && (cur_tick >= match_tick);
    }
}

In our case:

  • cur_tick > match_tick
  • match_tick == prev_tick

Result: false

Question

@c1728p9
The logic of this function is quite complicated and I'm not sure if I correctly understand entire flow, but it looks like in mentioned case _ticker_match_interval_passed() function should return true.
Is logic of this function valid?

In our case (cur_tick >= match_tick) condition is fulfilled, so maybe (match_tick > prev_tick) should be changed to (match_tick >= prev_tick)?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions