Перейти к содержанию

SysTick — системный таймер

SysTick — простой таймер, встроенный в само ядро Cortex-M. Он одинаков у всех микроконтроллеров на этом ядре, поэтому на нём строят системный тик: счёт миллисекунд в HAL, задержки и переключение задач в операционных системах реального времени.

Обновлено Редакция GAW

SysTick (system tick timer) — 24-битный таймер, входящий в состав ядра ARM Cortex-M. Он считает вниз от значения перезагрузки до нуля; на переходе из 1 в 0 выставляет флаг COUNTFLAG, при разрешении вызывает исключение SysTick и снова загружается. Поскольку таймер одинаков у всех Cortex-M3, операционные системы реального времени и библиотеки берут его для системного тика.

Регистры

Регистр (CMSIS)АдресНазначение
SysTick->CTRL0xE000 E010ENABLE — пуск, TICKINT — запрос исключения, CLKSOURCE — источник такта, COUNTFLAG — дошёл до нуля
SysTick->LOAD0xE000 E014значение перезагрузки, 24 бита
SysTick->VAL0xE000 E018текущее значение; запись обнуляет счётчик
SysTick->CALIB0xE000 E01Cкалибровка: у STM32F1 — 9000 отсчётов, 1 мс при 72 МГц и такте HCLK/8

Период прерываний:

T=LOAD+1fSysTickT = \frac{\text{LOAD} + 1}{f_\text{SysTick}}

Для 1 мс при 72 МГц LOAD = 71 999. Бит CLKSOURCE выбирает частоту ядра (1) или внешний опорный такт (0) — у STM32F1 это HCLK/8 (PM0056, раздел 4.5). Подробнее о ядре, исключениях и приоритетах — в статье об архитектуре Cortex-M3.

SysTick и приоритеты

Функция CMSIS SysTick_Config ставит SysTick самый низкий приоритет. HAL STM32 считает в его прерывании миллисекунды для HAL_GetTick и HAL_Delay, поэтому внутри обработчиков других прерываний с таким же или более высоким приоритетом счётчик стоит. Как HAL раскладывает приоритеты и как поднять приоритет SysTick, разобрано в статье о прерываниях STM32, а значения регистров приоритетов считает калькулятор NVIC.

Частые вопросы

Как настроить SysTick на 1 мс?

Записать в LOAD значение f / 1000 − 1 при тактировании от частоты ядра: при 72 МГц это 71 999. Проще вызвать функцию CMSIS SysTick_Config(SystemCoreClock / 1000): она запишет LOAD, поставит SysTick самый низкий приоритет, обнулит счётчик и запустит его с разрешённым прерыванием.

Какой наибольший период у SysTick?

Счётчик 24-битный, поэтому наибольший период — 2^24 тактов. При частоте ядра 72 МГц это около 0,233 с, при такте HCLK/8, который у STM32F1 выбирается битом CLKSOURCE = 0, — около 1,864 с. Если SysTick_Config получает слишком большое значение, функция возвращает 1 и таймер не трогает.

Почему HAL_Delay не работает в обработчике прерывания?

HAL STM32 считает миллисекунды в обработчике прерывания SysTick, а у него по умолчанию самый низкий приоритет. Пока выполняется обработчик другого прерывания с таким же или более высоким приоритетом, SysTick не может его вытеснить, счётчик миллисекунд стоит, и HAL_Delay ждёт вечно.

Источники

  1. STMicroelectronics. PM0056: STM32F10xxx/20xxx/21xxx/L1xxxx Cortex-M3 programming manual, Rev 7, 2024 — разд. 4.5 — SysTick: регистры CTRL, LOAD, VAL, CALIB, источник такта, STK_CALIB = 9000
  2. Arm. CMSIS-Core (Cortex-M) documentation — функция SysTick_Config: LOAD = ticks − 1, низший приоритет, запуск от частоты ядра с прерыванием
  3. STMicroelectronics. STM32CubeF1 HAL driver (stm32f1xx-hal-driver) — HAL_Init: приоритет SysTick TICK_INT_PRIORITY = 0x0F; HAL_IncTick в обработчике SysTick, HAL_Delay и HAL_GetTick

Нашли ошибку?