Системный таймер SysTick предназначен для выдачи прерываний с заданной частотой.
В архитектурах ARMv8-M без основного расширения и ARMv6-M таймер может отсутствовать (это определяется реализацией). В архитектуре ARMv7-M, а также в ARMv8-M с основным расширением, но без расширения безопасности он является обязательным. Наконец, в архитектуре ARMv8-M с основным расширением и расширением безопасности обязательно имеются два таймера: один для безопасного режима работы процессора, а другой – для небезопасного. В ARMv8-M без основного расширения, но с расширением безопасности таймеров в зависимости от реализации может не быть вообще, быть один общий для обоих режимов безопасности или иметься по отдельному таймеру для каждого режима.
Если имеются два таймера, технически они одинаковы, хотя и могут иметь разные альтернативные источники синхронизации. Если имеется один таймер, а процессор располагает расширением безопасности, возможность доступа небезопасного кода к регистрам таймера определяется битом ICSR.STTNS: когда он установлен, доступ имеется, когда он сброшен, любое чтение небезопасным кодом регистров таймера возвращает нуль, а любая запись игнорируется.
В многопроцессорной системе каждый процессор имеет собственный таймер, при этом «чужие» процессоры доступа к нему не имеют.
Принципы работы[]
Таймер ведёт отсчёт, когда его работа разрешена (установлен бит SYST_CSR.ENABLE), а процессор не находится в состоянии отладочного останова.
Из текущего значения счётчика (регистр SYST_CVR) каждый такт вычитается единица. Если в такте, в котором значение счётчика будет уменьшено с 1 до 0, прерывания от таймера были разрешены (установлен бит SYST_CSR.TICKINT), будет выдан запрос прерывания, который приведёт к установке бита ожидающего запроса прерывания от таймера (бит ICSR.PENDSTSET); далее данный запрос обрабатывается, как и любые другие запросы прерываний. В следующем после обнуления счётчика такте в него будет загружено начальное значение, хранящееся в регистре SYST_RVR, после чего он вновь будет каждый такт уменьшаться и т. д.
Текущее значение счётчика может быть программно прочитано из регистра SYST_CVR, что не оказывает никакого влияния на работу таймера.
Помимо возможной выдачи запроса прерывания, каждый раз, когда значение счётчика уменьшается до нуля, производится установка бита SYST_CSR.COUNTFLAG. Этот флаг сбрасывается, когда программа считывает значение регистра SYST_CSR или производит запись в регистр SYST_CVR. Благодаря этому возможна программная проверка истечения периода счёта таймера без использования прерываний. Заметим, что единичное значение бита SYST_CSR.COUNTFLAG не вызывает выдачу запроса прерывания, последний выдаётся лишь в момент перехода значения счётчика из единицы в нуль при разрешённых прерываниях от таймера.
Если регистр перезагружаемого значения SYST_RVR содержит нуль, это эквивалентно запрету работы таймера: в регистре текущего значения всегда будет находиться нуль, а выдача запросов прерываний и установка флага SYST_CSR.COUNTFLAG не производятся, поскольку для этого требуется переход счётчика из единицы в нуль.
Поскольку после сброса состояние регистра SYST_CVR не определено, после установки периода счёта (записи значения в SYST_RVR) необходимо выполнить запись в SYST_CVR, что обнулит счётчик и вызовет его перезагрузку из SYST_RVR.
Для уменьшения значения счётчика всегда может использоваться тактовая частота процессора (или частота, зависящая от частоты процессора; например, в микроконтроллерах серии STM32 ею будет частота процессора, делённая на 8). Кроме того, конкретная реализация процессора может предусматривать другой источник синхронизации; в этом случае выбор источника осуществляется битом SYST_CSR.CLKSOURCE.
Регистры таймера[]
Набор регистров, служащих для управления работой таймера, перечислен в таблице.
Адрес | Обозначение | Доступ | Значение после сброса | Описание |
---|---|---|---|---|
E000E010 | SYST_CSR | Регистр состояния и управления таймера. После сброса содержит либо 0, либо 4 в зависимости от реализации | ||
E000E014 | SYST_RVR | не определено | Регистр перезагружаемого значения счётчика | |
E000E018 | SYST_CVR | не определено | Регистр текущего значения счётчика | |
E000E01C | SYST_CALIB | не определено | Регистр калибровочного значения счётчика |
Регистр состояния и управления SYST_CSR[]
Адрес: E000E010.
Доступ: только привилегированный, полным словом.
Начиная с ARMv8.1-M, в зависимости от реализации отладочная запись в этот регистр может игнорироваться, если процессор не остановлен.
Наличие: в ARMv8-M без основного расширения и в ARMv6-M наличие определяется реализацией; в ARMv8-M с основным расширением и в ARMv7-M является обязательным.
Безопасность: Если процессор имеет расширение безопасности, он может (ARMv8-M без основного расширения) или обязан (ARMv8-M с основным расширением) иметь отдельные таймеры для безопасного и небезопасного режимов.
Если процессор имеет расширение безопасности и реализован лишь один системный таймер, доступность его для небезопасного режима зависит от состояния бита ICSR.STTNS: если этот бит сброшен, небезопасный код считывает из регистра SYST_CSR нулевое значение, а запись в этот регистр игнорируется.
Разряды | Доступ | Обозначение | Функция |
---|---|---|---|
Зарезервировано | |||
COUNTFLAG | Показывает, дошёл ли счётчик до нуля с момента последнего считывания этого регистра:
Этот бит сбрасывается считыванием данного регистра, а также записью значения в регистр SYST_CVR. Его установка производится, когда значение счётчика переходит из 1 в 0. | ||
Зарезервировано | |||
CLKSOURCE | Выбирает источник синхронизации для таймера:
Если конкретная реализация не предусматривает возможности использования внешнего источника синхронизации, этот бит всегда будет равен 1, а попытки записи в него нуля игнорируются | ||
TICKINT | Определяет, вызывает ли достижение счётчиком нулевого значения выдачу запроса прерывания:
Достижением нуля считается только декремент значения счётчика, приводящий к появлению в нём нуля, но не его сброс в результате явной записи в регистр SYST_CVR | ||
ENABLE | Определяет, разрешена ли работа таймера (уменьшение счётчика):
|
Регистр перезагружаемого значения SYST_RVR[]
Адрес: E000E014.
Доступ: только привилегированный, полным словом.
Начиная с ARMv8.1-M, в зависимости от реализации отладочная запись в этот регистр может игнорироваться, если процессор не остановлен.
Наличие: в ARMv8-M без основного расширения и в ARMv6-M наличие определяется реализацией; в ARMv8-M с основным расширением и в ARMv7-M является обязательным.
Безопасность: Если процессор имеет расширение безопасности, он может (ARMv8-M без основного расширения) или обязан (ARMv8-M с основным расширением) иметь отдельные таймеры для безопасного и небезопасного режимов.
Если процессор имеет расширение безопасности и реализован лишь один системный таймер, доступность его для небезопасного режима зависит от состояния бита ICSR.STTNS: если этот бит сброшен, небезопасный код считывает из регистра SYST_RVR нулевое значение, а запись в этот регистр игнорируется.
Разряды | Доступ | Обозначение | Функция |
---|---|---|---|
Зарезервировано | |||
RELOAD | Значение, загружаемое в регистр SYST_CVR, когда в процессе счёта он достигнет нуля |
Регистр текущего значения SYST_CVR[]
Адрес: E000E018.
Доступ: только привилегированный, полным словом.
Начиная с ARMv8.1-M, в зависимости от реализации отладочная запись в этот регистр может игнорироваться, если процессор не остановлен.
Наличие: в ARMv8-M без основного расширения и в ARMv6-M наличие определяется реализацией; в ARMv8-M с основным расширением и в ARMv7-M является обязательным.
Безопасность: Если процессор имеет расширение безопасности, он может (ARMv8-M без основного расширения) или обязан (ARMv8-M с основным расширением) иметь отдельные таймеры для безопасного и небезопасного режимов.
Если процессор имеет расширение безопасности и реализован лишь один системный таймер, доступность его для небезопасного режима зависит от состояния бита ICSR.STTNS: если этот бит сброшен, небезопасный код считывает из регистра SYST_CVR нулевое значение, а запись в этот регистр игнорируется.
Разряды | Доступ | Обозначение | Функция |
---|---|---|---|
CURRENT | Текущее значение счётчика. Неподдерживаемые разряды всегда считываются как 0. Любая запись обнуляет это поле, а также сбрасывает бит SYST_CSR.COUNTFLAG |
Регистр калибровочного значения SYST_CALIB[]
Адрес: E000E01C.
Доступ: только привилегированный, полным словом.
Наличие: в ARMv8-M без основного расширения и в ARMv6-M наличие определяется реализацией; в ARMv8-M с основным расширением и в ARMv7-M является обязательным.
Безопасность: Если процессор имеет расширение безопасности, он может (ARMv8-M без основного расширения) или обязан (ARMv8-M с основным расширением) иметь отдельные таймеры для безопасного и небезопасного режимов.
Если процессор имеет расширение безопасности и реализован лишь один системный таймер, доступность его для небезопасного режима зависит от состояния бита ICSR.STTNS: если этот бит сброшен, небезопасный код считывает из регистра SYST_CALIB нулевое значение, а запись в этот регистр игнорируется.
Разряды | Доступ | Обозначение | Функция |
---|---|---|---|
NOREF | Показывает, реализован ли источник опорной частоты:
Если этот бит равен единице, бит CLKSOURCE регистра SYST_CSR всегда установлен и не может быть обнулён | ||
SKEW | Показывает, является ли калибровочное значение точным:
| ||
Зарезервировано | |||
TENMS | Калибровочное значение, которое, будучи загруженным в регистр SYST_RVR, обеспечивает генерацию прерываний с периодом 10 мс (частота 100 Гц). Если равно нулю, калибровочное значение не задано |