feat(esp_timer): Support absolute timing APIs

Merges https://github.com/espressif/esp-idf/pull/17807
This commit is contained in:
Huelsenfrucht
2025-10-31 12:46:42 -05:00
committed by Konstantin Kondrashov
parent d18019de5b
commit b3ccc1316d
6 changed files with 280 additions and 83 deletions

View File

@@ -12,13 +12,16 @@ STARTING_TIMERS_REGEX = r'Started timers, time since boot: (\d+) us'
TIMER_DUMP_LINE_REGEX = r'([\w-]+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)'
PERIODIC_TIMER_REGEX = r'Periodic timer called, time since boot: (\d+) us'
TIMED_PERIODIC_TIMER_REGEX = r'Timed periodic timer called, time since boot: (\d+) us'
LIGHT_SLEEP_ENTER_REGEX = r'Entering light sleep for 0\.5s, time since boot: (\d+) us'
LIGHT_SLEEP_EXIT_REGEX = r'Woke up from light sleep, time since boot: (\d+) us'
ONE_SHOT_REGEX = r'One\-shot timer called, time since boot: (\d+) us'
TIMED_ONE_SHOT_REGEX = r'Timed one-shot timer called, time since boot: (\d+) us'
RESTART_REGEX = r'Restarted periodic timer with 1s period, time since boot: (\d+) us'
TIMED_RESTART_REGEX = r'Restarted timed periodic timer with 1s period, time since boot: (\d+) us'
STOP_REGEX = r'Stopped and deleted timers'
@@ -26,6 +29,9 @@ INITIAL_TIMER_PERIOD = 500000
FINAL_TIMER_PERIOD = 1000000
LIGHT_SLEEP_TIME = 500000
ONE_SHOT_TIMER_PERIOD = 5000000
TIMED_PERIODIC_START_TIME = 3000000
TIMED_ONE_SHOT_TIME = 6000000
TIMED_RESTART_TIME = 7000000
@pytest.mark.generic
@@ -40,35 +46,69 @@ ONE_SHOT_TIMER_PERIOD = 5000000
def test_esp_timer(dut: Dut) -> None:
match = dut.expect(STARTING_TIMERS_REGEX)
start_time = int(match.group(1))
logging.info('Start time: {} us'.format(start_time))
logging.info(f'Start time: {start_time} us')
match = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert match.group(1).decode('utf8') == 'periodic' and int(match.group(2)) == INITIAL_TIMER_PERIOD
match = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert match.group(1).decode('utf8') == 'timed_periodic' and int(match.group(2)) == INITIAL_TIMER_PERIOD
match = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert match.group(1).decode('utf8') == 'one-shot' and int(match.group(2)) == 0
match = dut.expect(TIMER_DUMP_LINE_REGEX, timeout=2)
assert match.group(1).decode('utf8') == 'timed_one-shot' and int(match.group(2)) == 0
for i in range(0, 5):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = start_time + (i + 1) * INITIAL_TIMER_PERIOD - cur_time
logging.info('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
logging.info(f'Callback #{i}, time: {cur_time} us, diff: {diff} us')
assert abs(diff) < 100
for i in range(0, 5):
match = dut.expect(TIMED_PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = TIMED_PERIODIC_START_TIME + i * INITIAL_TIMER_PERIOD - cur_time
logging.info(f'Callback #{i}, time: {cur_time} us, diff: {diff} us')
assert abs(diff) < 100
match = dut.expect(ONE_SHOT_REGEX, timeout=3)
one_shot_timer_time = int(match.group(1))
diff = start_time + ONE_SHOT_TIMER_PERIOD - one_shot_timer_time
logging.info('One-shot timer, time: {} us, diff: {}'.format(one_shot_timer_time, diff))
logging.info(f'One-shot timer, time: {one_shot_timer_time} us, diff: {diff}')
assert abs(diff) < 400
match = dut.expect(RESTART_REGEX, timeout=3)
start_time = int(match.group(1))
logging.info('Timer restarted, time: {} us'.format(start_time))
logging.info(f'Timer restarted, time: {start_time} us')
match = dut.expect(TIMED_ONE_SHOT_REGEX, timeout=3)
timed_one_shot_timer_time = int(match.group(1))
diff = TIMED_ONE_SHOT_TIME - timed_one_shot_timer_time
logging.info(f'Timed one-shot timer, time: {timed_one_shot_timer_time} us, diff: {diff}')
match = dut.expect(TIMED_RESTART_REGEX, timeout=3)
timed_start_time = int(match.group(1))
logging.info(f'Timed timer restarted, time: {timed_start_time} us')
# First callback after restart
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = start_time + FINAL_TIMER_PERIOD - cur_time
logging.info(f'Callback #{0}, time: {cur_time} us, diff: {diff} us')
assert abs(diff) < 100
# Callbacks 2 to 5 after restart (now both timers are running)
for i in range(1, 5):
timed_match = dut.expect(TIMED_PERIODIC_TIMER_REGEX, timeout=2)
timed_cur_time = int(timed_match.group(1))
timed_diff = TIMED_RESTART_TIME + (i - 1) * FINAL_TIMER_PERIOD - timed_cur_time
logging.info(f'Timed Callback #{i}, time: {timed_cur_time} us, diff: {timed_diff} us')
assert abs(timed_diff) < 100
for i in range(0, 5):
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = start_time + (i + 1) * FINAL_TIMER_PERIOD - cur_time
logging.info('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
logging.info(f'Callback #{i}, time: {cur_time} us, diff: {diff} us')
assert abs(diff) < 100
if dut.app.sdkconfig.get('SOC_LIGHT_SLEEP_SUPPORTED'):
@@ -78,15 +118,21 @@ def test_esp_timer(dut: Dut) -> None:
sleep_exit_time = int(match.group(1))
sleep_time = sleep_exit_time - sleep_enter_time
logging.info('Enter sleep: {}, exit sleep: {}, slept: {}'.format(sleep_enter_time, sleep_exit_time, sleep_time))
logging.info(f'Enter sleep: {sleep_enter_time}, exit sleep: {sleep_exit_time}, slept: {sleep_time}')
assert -2000 < sleep_time - LIGHT_SLEEP_TIME < 1000
for i in range(5, 7):
timed_match = dut.expect(TIMED_PERIODIC_TIMER_REGEX, timeout=2)
timed_cur_time = int(timed_match.group(1))
timed_diff = TIMED_RESTART_TIME + (i - 1) * FINAL_TIMER_PERIOD - timed_cur_time
logging.info(f'Timed Callback #{i}, time: {timed_cur_time} us, diff: {timed_diff} us')
assert abs(timed_diff) < 100
match = dut.expect(PERIODIC_TIMER_REGEX, timeout=2)
cur_time = int(match.group(1))
diff = abs(start_time + (i + 1) * FINAL_TIMER_PERIOD - cur_time)
logging.info('Callback #{}, time: {} us, diff: {} us'.format(i, cur_time, diff))
logging.info(f'Callback #{i}, time: {cur_time} us, diff: {diff} us')
assert diff < 100
dut.expect(STOP_REGEX, timeout=2)