Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Микропроцессорные системы. Средства разработки программного обеспечения для микроконтроллеров семейства AVR. Учебное пособие
.pdf
61
Рис. 9. Вариант многопоточной архитектуры построения программы
для микроконтроллера
Многопоточная архитектура ПО. В этом случае после инициа-
лизации необходимых программных и аппаратных ресурсов запускается
модуль управления программными потоками, который в свою очередь
запускает первый программный поток. В процессе выполнения алго-
ритма программные потоки могут добавляться и удаляться.
Каждый из программных потоков может производить обращение к
программным модулям управления периферийными устройствами по
мере необходимости. В свою очередь, модули управления периферийными устройствами могут обмениваться данными с процедурами обработки прерываний. Кроме того, потоки могут обмениваться данными
между собой.
Каждый из представленных вариантов архитектуры имеет свои
преимущества и недостатки.

62
Однопоточная архитектура ПО представляет собой, по сути,
цикл обработки событий, в котором по очереди проверяется возникновение определенных событий, таких как срабатывание таймера, появление определенного логического уровня на входной линии микро-
контроллера, получение данных от какого-либо периферийного устройства, окончание передачи данных и т. п.
При обнаружении какого-либо события, программа принимает
решение о дальнейших действиях и переходит к проверке возникнове-
ния следующего события.
Цикл «проверка возникновения события – принятие решения», как
правило, является бесконечным.
Прерывания с точки зрения основного цикла являются просто источником событий.
Например, прерывание, вызываемое при получении данных по по-
следовательному порту, помещает данные из порта в буфер приема и
выставляет специальный флаг, обозначающий «в буфере приема есть
данные». С точки зрения основного цикла не имеет значения, как данные появились в буфере приема. Единственное, что «интересует» алгоритм основного цикла, – это флаг «в буфере приема есть данные» и сами
принятые данные.
Достоинства однопоточной архитектуры – это простота реализации
алгоритма и минимально возможное использование ресурсов памяти.
К недостаткам однопоточной архитектуры можно отнести абсолютно негибкое распределение ресурса процессорного времени.
Многопоточная архитектура гораздо более сложна в реализации,
чем однопоточная, и требует гораздо больших ресурсов оперативной
памяти (или, что то же, памяти данных в семействе микроконтроллеров
AVR). Однако такая архитектура позволяет гибко распределять ресурс
процессорного времени, запуская программные потоки в случае необхо-
димости и останавливая их после выполнения нужных задач.
Попробуем дать оценку того, какие ресурсы необходимы для реа-
лизации многопоточной архитектуры на микроконтроллерах семейства
AVR. Для этого определим, что мы называем «программным потоком»
применительно к программам для микроконтроллеров.
Программный поток – это одна из функций, которая выполняет-
ся одновременно с другими в режиме разделения времени. Каждый поток имеет отдельный программный стек и стек возвратов, а также от-
дельный контекст потока.
Контекст потока – это данные о состоянии потока, позволяющие
полностью восстановить состояние этого потока. Для микроконтроллеров семейства AVR контекст потока состоит из регистров общего назна-

63
чения R0-R31, регистра-указателя стека SP, регистра-счетчика команд
PC и регистра состояния (или флагов) SREG. Кроме того, каждому по-
току нужен программный стек и стек возвратов. Размер программного
стека потока определяет максимальный размер автоматических переменных, которые можно создать в этом потоке. Размер стека возвратов
определяет глубину вызова функций из данного потока.
Оценим, какой расход памяти данных требуется на каждый про-
граммный поток микроконтроллера семейства AVR. Как нетрудно под-
считать, размер контекста равен для AVR 37 байт – 32 байта РОН R0-
R31, 2 байта регистр-указатель стека SP, 2 байта программный счетчик
PC и 1 байт регистр состояния SREG.
Пусть суммарный объем стека возвратов и программного стека ра-
вен 32 байтам. Этого достаточно, чтобы вызвать функции с параметрами
на несколько уровней вложенности.
Таким образом получаем, что оценочно для организации одного
потока на микроконтроллере семейства AVR необходимо 32+37=69 байт
памяти данных.
Это, казалось бы, небольшая величина. Однако, во-первых, объем
памяти данных в микроконтроллерах семейства AVR, даже в старших
моделях, измеряется единицами килобайт. И, во-вторых, реализация более или менее сложного алгоритма в каком-либо потоке может потребовать гораздо большего размера стека для этого потока.
Поскольку микроконтроллер в один момент времени может вы-
полнять только одну машинную команду, то слово «одновременно» не
совсем верно отражает суть многопоточного выполнения программы.
Модуль управления потоками по определенному событию (напри-
мер, по прерыванию от таймера) сохраняет контекст одного потока, восстанавливает контекст другого потока и передает этому потоку управление. Иными словами, модуль управления потоками периодически выполняет переключение потоков. Переключение потоков выполняется
прозрачно. С точки зрения функции-потока, она выполняется так, как
если бы была единственной и не прерывалась.
К достоинствам многопоточной архитектуры относится гибкость
распределения ресурсов микроконтроллера.
К недостаткам многопоточной архитектуры можно отнести гораз-
до большие требования к ресурсам микроконтроллера, таким как память, по сравнению с однопоточной. Следует помнить, что переключе-
ние потоков также требует процессорного времени.
Вопрос выбора архитектуры ПО является одним из главных во-
просов, на которые необходимо ответить на стадии проектирования ПО.

64
Неверный выбор архитектуры влечет за собой массу трудноразрешимых
проблем.
На основе практического опыта можно сказать, что если алгоритм
имеет статическую структуру (в том смысле, что все программные компоненты задействованы всегда во время выполнения программы), то
обычно лучше подходит однопоточная архитектура.
Если структура алгоритма динамическая, т. е. некоторые про-
граммные компоненты могут быть не задействованы при определенных
условиях, то более подходит многопоточная архитектура. Поясним на
примерах.
Допустим, мы проектируем ранее упомянутый полностью авто-
номный интеллектуальный термометр. Нетрудно предположить, что алгоритм его работы будет сводиться к опросу датчиков температуры и
выводу информации на индикатор. Разумеется, что для такого устрой-
ства лучше всего подходит однопоточная архитектура.
Теперь предположим, что нам необходимо снабдить проектируе-
мый интеллектуальный таймер тремя каналами связи – RS485, радиока-
налом и беспроводным каналом Wi-Fi. Причем эти каналы не могут ис-
пользоваться одновременно – из всех каналов связи в каждый момент
используется только один, по желанию пользователя. В этом случае,
программную поддержку каждого из каналов связи будет логично
оформить в виде отдельного потока выполнения и запускать только
один, требуемый, поток из трех. В данном случае многопоточная архитектура позволит сэкономить память данных и ресурс процессорного
времени, который в случае однопоточной архитектуры тратился бы для
обслуживания неиспользуемых устройств.
Как видим, изменение функциональных возможностей устройства
кардинально влияет на соображения выбора архитектуры.
Приведем пример структуры программного обеспечения микропроцессорного устройства (рис. 10).
Данное МПУ предназначено для работы в составе РМПС, поэтому
имеются интерфейсы передачи данных Ethernet и RS232, программные
модули маршрутизации и обработки протоколов передачи данных.
Кроме того, имеются программные модули, реализующие интерфейс пользователя.
Заметим, что сам по себе состав программных модулей ничего не
говорит о типе архитектуры ПО – однопоточной или многопоточной.
Показанная на рис. 10 структура ПО МПУ может быть реализова-
на как на базе однопоточной, так и на базе многопоточной архитектуры.
Все зависит от возможностей микропроцессорной системы и решаемых
этой системой задач.

65
Рис. 10. Пример структуры программного обеспечения МПУ
9.1. Инициализация
Вне зависимости от того, какая архитектура ПО выбрана, первое,
что необходимо сделать при запуске программы (функции main()), – это
провести инициализацию оборудования и программных модулей поль-
зователя.
Во время инициализации оборудования обычно производится:
настройка тактовой частоты микроконтроллера (на тех микро-
контроллерах, где есть такая настройка);
настройка направления передачи данных необходимых линий
портов ввода-вывода;
настройка режимов работы контроллера прерываний;
настройка используемых периферийных устройств;
инициализация основного цикла (в случае однопоточной архи-
тектуры);
инициализация модуля управления программными потоками
(в случае многопоточной архитектуры).
Отметим, что во время инициализации не обязательно произво-
дится настройка всего используемого оборудования и программных модулей. Некоторые программные модули или оборудование могут
настраиваться во время выполнения программы. Как поступить в каж-
дом конкретном случае – решает разработчик.

66
После того как процедуры инициализации завершены, управление
передается основному циклу (однопоточная архитектура) или модулю
управления программными потоками (многопоточная архитектура).
9.2. Основной цикл
Основной цикл программы (или фоновый цикл) фактически явля-
ется циклом обработки событий и подразделяется на два программных
блока – блок ожидания события и блок обработки событий.
Что такое «событие» применительно к программе?
Событие – в общем случае это действие пользователя, сообщение
от внешнего устройства (например, возникновение прерывания) и т. п.
Пока никаких событий не происходит – основной цикл программы
находится в состоянии ожидания событий.
Как только обнаружено некоторое событие – управление переда-
ется обработчику событий. Обработчик событий определяет, какое
именно событие возникло и как его следует обрабатывать, затем вызы-
вает процедуру обработки конкретного события.
Рассмотрим, каким образом организуется обработка событий в
программах для микроконтроллеров.
Для простоты, считаем, что обработчик событий заведомо успева-
ет обработать все события от всех источников за одну итерацию цикла
обработки событий. Это важно, поскольку позволяет упростить про-
грамму, избежав организации очередей событий.
В этом случае возможно для каждого из событий завести отдель-
ный флаг события. Если событие произошло – то флаг установлен, ес-
ли не произошло – то сброшен.
Как только блок ожидания события обнаруживает, что флаг события установлен – он сбрасывает этот флаг и вызывает процедуруобработчик данного события.
Возможен и другой вариант – проверять возникновение каждого
события путем проверки специфичного для каждого события условия.
В этом случае циклы ожидания события и обработки событий совмещены в один цикл ожидания-обработки.
С точки зрения программиста, оба варианта практически равноправны и могут быть совмещены.
9.3. Модуль управления программными потоками
Модуль управления программными потоками инициализирует си-
стему переключения контекста потоков и запускает первый программ-
ный поток.

67
В случае, когда запущен только один программный поток, многопоточная архитектура работает полностью аналогично однопоточной.
Однако в отличие от однопоточной архитектуры, программист в
любой момент времени может запустить дополнительно другие про-
граммные потоки.
Задача модуля управления потоками, фактически, сводится к переключению контекста потоков по наступлению определенного события.
Рассмотрим вкратце, что представляет собой модуль управления
программными потоками. Модуль управления потоками имеет таблицу
описателей потоков, в которой хранятся сведения по каждому из имею-
щихся потоков:
идентификатор потока (обычно целое число);
контекст потока (описан ранее);
состояние потока;
дополнительную информацию, определяемую разработчиком.
Например, это могут быть: границы стека потока; объем используемой
потоком динамической памяти; сведения об используемых потоком ре-
сурсах микроконтроллера и т. п.
В общем случае можно выделить следующие состояния про-
граммного потока с точки зрения модуля управления программными по-
токами:
инициализация потока: выделение памяти для стека и описателя
потока;
ожидание выполнения потока: поток ждет, пока модуль управ-
ления потоками передаст этому потоку управление;
выполнение потока: состояние непосредственного выполнения
команд программного потока;
состояние сна: поток ждет некоего события;
ожидание завершения потока: модуль управления потоками
освобождает ресурсы, используемые потоком, и уничтожает описатель
потока.
Отметим, что при необходимости могут быть введены и любые
другие состояния программных потоков. Следует учитывать, что чем
больше состояний имеет программный поток, тем сложнее реализовать
алгоритм модуля управления потоками и тем больше вероятность ошибок. Поэтому рекомендуем ограничиться минимально необходимым ко-
личеством состояний программного потока.
В момент создания (инициализации) потока, модуль управления
потока создает в таблице описателей потоков описатель нового потока,
присваивает этому потоку уникальный идентификатор (число) и выде-

68
ляет потоку участок памяти данных под хранение стека и контекста потока, после чего поток переходит в состояние ожидания выполнения по-
тока.
Из состояния ожидания выполнения потока, поток переходит в со-
стояние выполнения потока. Далее, по определенному событию или по
специальному программному вызову, поток переходит в одно из трех
состояний: в состояние ожидания выполнения потока (т. е. передает
управление другим потокам); в состояние сна (ожидание определенного
события); в состояние завершения потока.
Модуль управления потоками может реализовывать различные ал-
горитмы – алгоритмы вытесняющей многозадачности; кооперативной
многозадачности; выделять равные кванты времени выполнения всем
потокам; выделять кванты времени выполнения согласно приоритету
потоков и т. п.
В настоящем издании нет возможности подробно рассмотреть во-
просы управления потоками и построения многозадачных ОС, поэтому
отсылаем читателя к соответствующей литературе [12, 13].
9.4. Обработка прерываний
Прерывание – это сигнал, сообщающий процессору о наступле-
нии какого-либо события. При этом выполнение текущей последова-
тельности команд приостанавливается и управление передается обработчику прерывания, который реагирует на событие и обслуживает его,
после чего возвращает управление в прерванный код.
Один из вариантов классификации типов прерываний приведен на
рис. 11.
Рис. 11. Классификация типов прерываний

69
Аппаратные прерывания – это прерывания, формируемые при
поступлении определенного электрического сигнала от внешнего
устройства. Аппаратные прерывания подразделяются на маскируемые и
немаскируемые.
Маскируемые прерывания – это аппаратные прерывания, кото-
рые можно запрещать установкой соответствующих битов в соответствующих регистрах маскирования прерываний. В микроконтроллерах с
архитектурой AVR все прерывания, кроме прерывания по рестарту си-
стемы, являются маскируемыми.
Немаскируемые прерывания – это аппаратные прерывания, ко-
торые обрабатываются всегда, независимо от запретов на другие (маскируемые) прерывания. В микроконтроллерах с архитектурой AVR не-
маскируемым является только одно прерывание – по рестарту системы.
Программные прерывания – это прерывания, которые может
осуществить программа с помощью специальной инструкции. В некоторых микропроцессорах программные прерывания служат для перехода в
привилегированный режим работы процессора. В микроконтроллерах
архитектуры AVR нет специальных инструкций для вызова программ-
ных прерываний.
Общий алгоритм обработки прерываний микроконтроллерами се-
мейства AVR показан на рис. 12. Предположим, что все регистры управления внешним устройством, от которого мы ожидаем прерывание, –
настроены. Для каждого из устройств эти регистры специфичны и опи-
саны в документации на конкретный тип микроконтроллера.
Процедура обработки прерывания начинается с возникновения
события, генерирующего прерывание. Это может быть, например, установка линии ввода в определенное состояние, получение данных по ин-
терфейсу связи и т. п.
Чтобы прерывание произошло, необходимо выполнение следующих условий:
флаг глобальной маски прерываний (бит I регистра SREG) дол-
жен быть установлен в единицу;
флаг локальной маски прерываний от прерывающего устрой-
ства должен быть установлен в единицу;
произошло событие, вызывающее прерывание от данного
устройства.
Если все условия соблюдены, то после возникновения события,
на контроллер прерываний подается электрический сигнал, извещающий о том, что необходимо обработать прерывание от внешнего устрой-
ства с определенным вектором.

70
Рис. 12. Общий алгоритм обработки прерываний
микроконтроллерами семейства AVR
После этого ядро процессора дожидается завершения текущей
машинной команды. Вызов обработчика прерывания не может произой-
ти между этапами выполнения машинной команды.
На стеке запоминается адрес следующей выполняемой команды
(адрес возврата), полностью аналогично с вызовом подпрограммы командой CALL. Флаг глобального разрешения прерываний I регистра
SREG сбрасывается, т. е. все маскируемые прерывания запрещаются.
Затем происходит переход по адресу обработчика прерывания,
расположенному в таблице векторов прерывания (см. ниже) и соответ-
ствующему прерывающему устройству.
После того, как процедура обработки прерывания завершит свою
работу, возврат из нее в прерванную программу происходит с помощью
команды RETI. Данная команда полностью аналогична команде RET, но,
кроме возврата из подпрограммы, команда RETI устанавливает флаг
глобального разрешения прерываний I регистра SREG, т. е. разрешает
все маскируемые прерывания.
С точки зрения программиста, обработчик прерывания почти ни-
чем не отличается от любой другой подпрограммы, за исключением того, что она может быть вызвана в произвольный момент времени, и того,
что во время ее выполнения запрещены все маскируемые прерывания.
В микроконтроллерах семейства AVR имеется таблица векторов
прерываний, расположенная с адреса 0 в программной памяти.
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
