Я хочу реализовать функцию отметки времени для моей платформы на базе msp430.
Моя цель — использовать аппаратный таймер и подсчитать, сколько раз он переполняется, чтобы сгенерировать длинное значение метки времени (обычно это uint32 для счетчика переполнения в сочетании со значением uint16 аппаратного таймера).
Вот что у меня есть:
- Счетчик переполнения увеличивается при прерывании,
- его значение проверяется каждый раз, когда запрашивается метка времени (это защищено блокировкой прерывания).
- значение счетчика переполнения объединяется с текущим значением аппаратного таймера в большую отметку времени.
У меня возникают проблемы, когда я принимаю во внимание время прерываний.
Первая наивная реализация у меня была:
uint16_t timer_value = timer_value_get();
__istate_t istate = interrupt_disable();
uint64_t overflow_count_local = overflow_count; // the volatile incremented on interrupt
interrupt_restore(istate);
return (overflow_count_local << 16u) + timer_value;
Это приведет к сбою, когда переполнение произойдет после получения значения таймера, но до того, как прерывания будут отключены. overflow_count_local
тогда будет на 1 больше, чем при присвоении timer_value
.
Я попытался добавить другие проверки для обнаружения этого возможного прерывания.
uint16_t timer_value = timer_value_get();
__istate_t istate = interrupt_disable();
uint16_t second_timer_value = timer_value_get();
uint64_t overflow_count_local = overflow_count; // the volatile incremented on interrupt
interrupt_restore(istate);
if (second_timer_value < timer_value) {
// A HW timer overflow occured just before disabling interrupts.
overflow_count_local--;
}
return (overflow_count_local << 16u) + timer_value;
Это тоже не сработает, на этот раз потому, что таймер мог переполниться после отключения прерываний, но до назначения second_timer_value
. Тогда overflow_count_local
будет слишком мало.
Как бы я ни пытался изменить это, кажется, всегда есть случай, который не охвачен. Есть ли известный способ сделать эту работу?
Некоторые ограничения:
- Таймер используется и для других функций (с захватом/сравнением) и не может быть остановлен.
- Модуль RTC в msp430 нельзя использовать для этой цели, поскольку он используется для сохранения фактического времени суток.
- Нет 32-битного таймера.