Параллелизм и прерывания в микроконтроллерах и встраиваемых системах
Данная статья знакомит с идеей параллелизма и механизмом, который многие компьютеры предоставляют для работы с параллелизмом, называемым прерываниями.
Данная статья является первой в серии, в которой рассматриваются понятия параллелизма и прерываний. Основная часть серии будет посвящена непосредственно микроконтроллерам и прерываниям входов/выходов общего назначения (GPIO).
В этой начальной части мы рассмотрим основные определения этих концепций, и насколько они актуальны для написания кода для микроконтроллера.
Что такое параллелизм?
Давайте поговорим о параллелизме на примере, с которым мы все знакомы. Обычно, когда вы ложитесь спать, вы хотите проснуться в определенное время. Здесь у вас две цели: лечь спать, чтобы вы могли отдохнуть, а также удостовериться, что вы не спите после необходимого времени пробуждения.
Один из способов убедиться в том, что вы не пропустите время пробуждения, – это не спать и смотреть на часы, но это аннулирует вашу цель – выспаться. Чтобы исправить это, мы обычно используем будильник (устройство или доверенное лицо, которое к тому времени уже не спит), чтобы разбудить нас в определенное время, чтобы мы могли сосредоточиться на сне и при этом достичь своей цели – вовремя проснуться.
Параллелизм – это термин, который мы используем для описания сценария, когда у вас есть два или более процессов для одновременного выполнения, но в любой момент времени вы способны физически работать только с одним из процессов.
В приведенном выше примере двумя процессами, которые необходимо учитывать, являются сон и отслеживание времени (поэтому мы просыпаемся в нужное время). Физически невозможно, чтобы один и тот же человек выполнял оба этих дела одновременно.
Обычно нас интересуют только конкретные события, связанные с процессами, которыми мы занимаемся. Как вы заметили выше, единственное событие, о котором мы заботимся с точки зрения времени, – это время пробуждения. Типовой способ решения проблемы параллелизма заключается в том, чтобы другой физический ресурс (будильник или человек) отслеживал интересующее нас событие, а затем оповещал (или прерывал) нас о том, что событие произошло, чтобы мы могли заняться ним.
На рисунке 1 показана временная диаграмма этого.
Параллелизм во встраиваемых и киберфизических системах
Встраиваемые и киберфизические системы обычно имеют дело с параллелизмом.
Примером этой концепции в действии является микроволновая печь. Устройство должно быть в состоянии обрабатывать нажатия кнопок или определять, когда вы открываете дверцу, пока еда нагревается. Нажатие кнопки паузы или отмены или открытие дверцы приведет к тому, что еда перестанет подогреваться.
Микроконтроллеры – компьютеры, которые вы обычно программируете, чтобы быть «мозгом» системы, – разработаны с учетом параллелизма.
В дополнение к универсальному центральному процессору (CPU) для взаимодействия с внешним миром они содержат ряд специализированных аппаратных устройств (называемых периферийными устройствами), поэтому вы можете подключать такие вещи, как кнопки и дисплеи, и другое внешнее оборудование, необходимое для реализации вашей системы. Обычно эти периферийные устройства обладают механизмом прерывания, поэтому CPU может попросить их отслеживать определенное событие, а затем, при возникновении этого события, прерывать работу CPU.
Обзор высокоуровневых программ с прерываниями и параллелизмом
Прерывания в микроконтроллере работают так же, как пример со сном и будильником, который я обсуждал ранее.
Вы можете написать программу, которая конфигурирует периферийное устройство для отслеживания определенного события и прерывания CPU, когда это событие происходит. Например, когда значение на входе GPIO изменяется с 0 на 1. Когда ваша программа выполняется, CPU выполняет фрагменты вашей основной программы. Когда происходит ожидаемое событие, периферийные устройства сигнализируют CPU о том, что событие произошло. Если всё настроено правильно, CPU остановит всё, что он делал в основной программе, выполнит специальную функцию, называемую процедурой обработки прерывания (ISR, interrupt service routine) или обработчиком прерывания, и затем вернется к основной программе, чтобы продолжить с того места, где он прервался.
В своем коде вы должны написать обработчик прерывания. Предполагая, что вы используете C для написания своей программы, это означает, что вы должны объявить и определить его где-нибудь в исходном коде, который будет скомпилирован как часть исполняемого кода, который будет запускать микроконтроллер.
Тем не менее, сами вы никогда не вызываете обработчик прерывания. Все инструменты разработки для микроконтроллеров имеют особый способ сообщить компилятору C, что определенная функция является ISR, и с каким конкретным прерыванием она связана. Если вы сделали всё правильно, когда произойдет конкретное прерывание, CPU автоматически перейдет к этой функции и выполнит ее.
Пример прерывания в коде C
Из-за того, как работают прерывания, обработка параллелизма в программировании может поначалу показаться немного неинтуитивной.
Чтобы помочь лучше понять параллельные программы, на следующем рисунке показано, как будет работать код, написанный на C и содержащий обработчик прерывания. Предполагается, что все настройки прерываний выполнены правильно.
- Процессор выполняет код в цикле
while
основной функции. - На выводе, который настроен для прерывания, происходит интересующее нас событие (изменение с 1 на 0).
- CPU прекращает выполнение кода в цикле
while
и выполняет процедуру обработки прерывания. - После завершения выполнения процедуры обработки прерывания процессор возобновляет выполнение основного цикла с того места, на котором он остановился.
- Процессор выполняет код в цикле
while
. - Интересующее нас событие происходит снова.
- CPU прекращает выполнение кода в цикле
while
и выполняет процедуру обработки прерывания. - После завершения выполнения процедуры обработки прерывания процессор возобновляет выполнение основного цикла с того места, на котором он остановился.
Прерывания для периферии и выводов GPIO
Большая часть этой серии будет посвящена концепциям параллелизма и прерываний применительно к микроконтроллерам. Далее мы поговорим о прерываниях выводов GPIO и о том, как они работают.