ГЛАВА 5
ВДОХНИТЕ В РОБОТА ЖИЗНЬ
В предыдущей главе мы рассмотрели достаточно много примеров реализации функций двух нижних (механического и электронного) уровней в виде обработ- чика прерываний от таймера, формируемых каждую миллисекунду. Что касается функций верхнего (биологического) уровня, то представленный код выполнял пока лишь только тестовые функции, позволяя проверить работу интерфейсов нижнего уровня. Одновременно мы обсудили методы совмещения нескольких интерфейсов в одной процедуре обработки прерываний.
В этой главе, наконец, будет как реализуется выполнение функций уровня. Другими словами, мы обсудим методы принятия решений, ко- торые и определяют функциональность робота. Для этого применяются самые различные подходы, и здесь будут рассмотрены только самые популярные из них.
Большинство подходов базируется на методе нелинейного программирования,
с помощью которого удается реализовывать достаточно сложные функции и ко- торый в большинстве случаев не требует больших объемов памяти или трудоем- ких вычислений. Именно эти достоинства становятся определяющими, когда речь идет о программировании микроконтроллеров, поскольку, в отличие от персо- нальных компьютеров или, тем более, больших ЭВМ, здесь очень жестко задают- ся ограничения на время реакции программы и объем аппаратных ресурсов.
Еще одно преимущество описываемого здесь подхода состоит в том, что он позволяет свести достаточно сложный процесс проектирования программного обеспечения к более простой задаче, которая решается оптимальным подбором нескольких параметров. Это не означает, что мы больше не будем программиро- вать (будем, насколько вы сможете выдержать), но после написания программы,
которое теперь уже не осуществляется столь хаотично и неформально, понадобит- ся выполнить настройку значений нескольких параметров, пока мы не добьемся нужного поведения робота. При этом настройка параметров в идеале не должна потребовать внесения изменений в текст программы.
При создании биологического кода необходимо помнить, что поведение робо- та кажется осмысленным только в том случае, если оно является детерминиро-
ванным. Это значит, что любая реакция управляющей программы на то или иное входное воздействие не должна быть случайной. Только строго запланированные и предсказуемые (то есть повторяющиеся при одних и тех же условиях) реакции на изменения внешней обстановки можно считать проявлениями искусственного интеллекта.
Вдохните в робота жизнь 325
5.1. ОПЕРАЦИОННЫЕ СИСТЕМЫ РЕАЛЬНОГО ВРЕМЕНИОперационной системой времени (ОСРВ, Real Time Operating System -
RTOS) называется программная среда, которая обеспечивает поддержку выпол- нения
прикладных программ (tasks - задач), выступая, таким образом, в качестве своеобразного интерфейса между программным обеспечением и аппаратными средствами. ОСРВ предоставляет прикладным программам необходимый набор стандартных
сервисов функций), позволяющий программам наи- более простым способом взаимодействовать друг с другом и с аппаратурой. Бла- годаря тому что часто
используемые функции реализуются с помощью ОСРВ,
программы становятся менее объемными и сложными, а сам процесс программи- рования - менее трудоемким. От обычных
операционных систем (ОС) операци- онные системы реального времени отличаются тем, что обеспечивают поддержку выполнения задач, в которых большую роль играет соблюдение заданного време- ни реакции на то или иное внешнее событие.
Многие микроконтроллеры имеют встроенную поддержку какой-либо опера- ционной системы. К сожалению, этого нельзя сказать о микроконтроллерах среднего семейства. Поэтому в следующем разделе при обсуждении методов работы с ОСРВ мы будем вынуждены иметь дело больше с теоретичес- кими концепциями, чем с конкретными примерами.
Лучшая формулировка, которую я предложить для определения ОСРВ,
такова:
операционная система времени - это фоновая программа, кото-рая управляет выполнением множества прикладных задач и облегчает их взаимо-действие.Напомним, что операционная система, способная поддерживать выполнение сразу нескольких прикладных задач, называется
многозадачной. При этом для выполнения каждой задачи обычно отводится малый промежуток (квант) процес- сорного времени, по истечении которого управление передается следующей зада- че; данный процесс повторяется по кругу, создавая иллюзию одновременного выполнения многих задач.
Если вы знакомы с системным программным обеспечением персональных компьютеров, то, возможно, слышали что-то о процессах и потоках, а также различ- ных методах планирования задач (в том числе и реального времени), используемых в современных операционных системах. Здесь мы не будем вдаваться во все эти тон- кости, так как большинство из них оказывается совершенно не нужно, когда речь за- ходит о программировании микроконтроллеров. Даже различия между ОС и ОСРВ
не будут нас волновать, так как ядро (kernel) тех и других устроено одинаково. Разу- меется, при более пристальном рассмотрении могут быть выделены некоторые отли- чия, в частности касающиеся начальной загрузки системы. При запуске ОС персо- нальных компьютеров вместе с ядром загружаются:
базовая система ввода-вывода(Basic Input/Output System - BIOS), осуществляющая поддержку ввода информа- ции с клавиатуры и вывода ее на экран, а также работу с файлами на диске; 2) ин- терпретатор команд, которые вводит пользователь.
326 Устройства управления роботами
В ОСРВ вместе с ядром загружаются наиболее приоритетные задачи, выпол- нение которых жизненно необходимо для поддержания работоспособности всей системы.
Важная особенность ОСРВ,
используемых в робототехнике, заключается в том, что они должны требовать минимально возможных аппаратных ресурсов,
то есть экономно расходовать память программ и данных, а также процессорное время. Объем памяти микроконтроллеров сильно ограничен, и весьма накладно было бы хранить в ней, как это обычно бывает в ОС, код для поддержки всего набора возможных функций (в том числе и сетевых), даже если многие из них
в данный момент не требуются.
Все задачи в ОСРВ (как и в ОС) имеют свой приоритет. В первую очередь процессорное время отводится самым приоритетным задачам. Планировщик ис- пользует так называемые
очереди, в которых задачи ожидают своего выполнения.
Обычно для имеющих один и тот же уровень приоритета, используется отдельная очередь.
В каждый момент времени может выполняться только одна задача. Она будет приостановлена, когда истечет отведенный для нее квант времени, или произой- дет какое-либо особое внешнее событие, или эта задача завершится сама по себе либо перейдет в режим ожидания некоторого события (например, запроса на пре- рывание от внешнего устройства). После этого из наиболее приоритетной очере- ди будет выбрана для выполнения следующая задача, и так будет повторяться снова и снова. Длительность кванта времени должна быть не слишком велика,
чтобы все задачи могли получать процессорное время достаточно часто и тем са- мым имели возможность своевременно реагировать на все внешние события. В то же время длительность кванта не должна быть слишком маленькой, иначе боль- шую часть времени микроконтроллер или микропроцессор будет занят переклю- чением задач, а не их выполнением.
В каждом конкретном случае при разработке того или иного автоматического устройства в процессе его. испытания может потребоваться индивидуальная на- стройка длительности кванта времени. Все зависит от тех функций, которые дол- жна выполнять система.
Уровни приоритета назначаются задачам в зависимости от того, как быстро они должны уметь реагировать на запрос, поступивший от внешнего устройства.
Вас может удивить тот факт, что вроде бы наиболее важный по значимости код верхнего (биологического) уровня обычно имеет самый низкий уровень приори- тета, в то время как менее важным механическим и электронным интерфейсам,
обслуживающим
различные периферийные устройства, зачастую присваивается наивысший уровень. Все дело в том, что робот должен быстро реагировать на за- просы, поступающие от внешних устройств. Если какое-либо внешнее устройство формирует запрос на обслуживание, необходимо как можно быстрее выполнить его. Если никаких запросов нет, то может выполняться наименее приоритетный биологический код, определяющий поведение робота. Для успешного выполне- ния биологического кода должны вовремя выполняться все обеспечивающие его работу функции, а это в первую очередь функции нижних уровней.
Вдохните в робота жизнь 327
При распределении приоритетов важно понимать, как протекают все процес- сы в системе и как они взаимодействуют. Очень просто попасть в ловушку, когда какая-либо важная задача ожидает результата выполнения менее приоритетной,
которая, в свою очередь, не может завершиться из-за того, что ей мешает эта более приоритетная задача. Также возможны ситуации, когда какая-либо задача с низ- ким приоритетом (но в данный момент необходимая) вообще не может начать свое выполнение, потому что ей все время мешает более приоритетная задача.
Очень часто в системах реального времени некоторые задачи не могут начать свое выполнение, потому что ждут определенного внешнего события (обычно за- проса на прерывание от какого-то известного устройства). В ожидании внешнего события такие задачи размещаются в специальной очереди. ОСРВ должна уметь при наступлении события сообщить о нем всем ожидающим его задачам и пере- местить их в очередь задач, готовых к выполнению.
При этом ОСРВ должна распознать источник запроса на прерывание и передать управление соответствующему обработчику, который выполнит все необходимые действия по обработке этого запроса, в том числе не забудет сбросить контроллер прерываний и оповестит внешнее устройство, что его запрос уже обрабатывается.
Следует помнить, что в больших и сложных системах во многих случаях не- возможно обеспечить немедленную обработку запроса на прерывание, и может пройти не одна сотня микросекунд, пока запрос действительно будет обработан
(даже если процедура обработки имеет достаточно высокий приоритет).
Чтобы минимизировать эту задержку, необходимо весьма тщательно проекти-
ровать код обработчика прерываний, стараясь выполнить все необходимые дей- ствия как можно быстрее. Иногда хороший результат может быть достигнут толь- ко ценой усложнения аппаратных средств, берущих на себя те функции, которые программное обеспечение не может выполнить достаточно быстро.
Хороший пример такого рода - модулятор, который мы рассматривали в прошлых главах. Он может быть реализован программно, но более эффективна его аппаратная реализация.
Разумеется, в любой ОСВР должен быть какой-то механизм, который позво- ляет через определенные промежутки времени выполнять те или иные действия,
подобно тому как это было у нас при разработке интерфейсов, основанных на прерывании от таймера TMRO.
Часто требуется, чтобы задачи, выполняемые под управлением ОСРВ, взаи- модействовали, обмениваясь необходимыми данными. Такое взаимодействие может быть организовано напрямую, с помощью глобальных (доступных всем за- дачам) переменных, но в большинстве случаев лучше использовать поддержива- емый операционной системой
механизм передачи сообщений. Тогда не требуется принимать специальных мер по синхронизации доступа к глобальным перемен- ным, следя за тем, чтобы значение любой из них, записанное одной задачей, не изменилось раньше времени другой.
Процесс передачи сообщений состоит фаз: сначала одна задача посы- лает сообщение другой, а затем помещается в специальную очередь, где ожидает от второй задачи подтверждения того, что сообщение получено.
328 Устройства управления роботами
С другой стороны, вторая задача посылает первой запрос на пересылку оче- редного блока данных и ожидает его прихода. Это может быть сделано или до того,
как первая задача пошлет свое сообщение, или после. После получения сообще- ния вторая задача высылает первой подтверждение, а
сама переводится в очередь задач, готовых к выполнению, ожидая, когда планировщик задач выделит ей квант рабочего времени. После прихода подтверждения первая задача также переводит- ся в эту
Для разграничения доступа задач к общим системным ресурсам используются так называемые
семафоры - специальные флажки.
ресурсу (переменной или порту ввода-вывода) соответствует свой флажок. Когда какая-либо задача хочет использовать общий ресурс, она проверяет состояние его флажка. Если он сброшен, значит, ресурс свободен. Задача занимает этот ресурс (то есть читает или изменяет значение переменной либо регистра ввода-вывода), но предвари- тельно устанавливает флажок, таким образом сообщая остальным задачам, что данный ресурс занят. Все другие задачи, которые захотят работать с тем же ресур- сом, запросив состояние флажка, будут помещены в очередь ожидания. По вы- полнении операции задача освобождает ресурс, снова сбрасывая его флажок и давая другим задачам возможность использовать его.
Например, если одна задача начинает вывод текстового сообщения на экран жидкокристаллического дисплея, то до окончания этого процесса никакая другая задача не может получить доступ к этому дисплею — в противном случае мы уви- дели бы на экране начало другой строки вместо продолжения предыдущей. По- этому вывод информации на дисплей должен регулироваться с помощью семафо- ра, и все задачи, прежде чем начать запись, должны проверять его состояние.
Если программист по окончании работы с общим ресурсом забудет освободить семафор, то заблокирует выполнение всех других задач, которым требуется тот же ресурс, и даже задача, вызвавшая ошибку при необходимости повторного об- ращения ресурсу, не сможет получить к нему доступ.
В табл. 5.1 перечислены основные типы запросов к ОСРВ; там же указаны параметры этих запросов и формат ответа. В зависимости от используемых ин- струментальных средств, типа операционной системы и процессора для обращения к ОСРВ и посылки запросов могут использоваться макросы или подпрограммы.
Для идентификации задач, выполняемых в системе, используются номера или специальные метки — адресные ссылки. С их помощью операционная система узнает, кому надо послать то или иное сообщение.
Номера занимают меньше ме- ста, чем адреса, поэтому последние реже используются в микроконтроллерах.
Заметим, что в табл. 5.1 не указаны обращения к процедурам обработки пре- рываний. Они весьма специфичны, и мнения разных разработчиков по поводу того, как должен быть реализован обработчик прерываний в ОСРВ, иногда диа- метрально противоположны. Зато имеется функция задержки на заданное число миллисекунд, формируемой с помощью аппаратного таймера (в многозадачной среде реализовать задержку программно без использования таймера и системы прерываний не удастся, если только не заблокировать все остальные задачи).
Вдохните в робота жизнь 329
Таблица
Запуск задачи
Завершение
задачи
Переход
к следующей
задаче
Посылка
сообщения
сообщений
Ожидание
сообщения
Чтение
полученного
сообщения
Подтверждение
получения
сообщения
Захват ресурса
Проверка
ресурса
Освобождение
ресурса
Задержка
Основные сервисы
Формат вызова
StartTask
End ()
Message)
OCPB
Возвращаемые
параметры
Дескриптор
задачи или ошибка
-
"
Номер сообщения
Номер сообщения
Текст сообщения
(или ошибка)
Нет (или
—
Нет (или ошибка,
если ресурс уже
Нет (или ошибка,
если этот семафор
не был занят данной
задачей)
—
Комментарии
Запустить указанную задачу начиная
с
адреса
Удалить выполнявшуюся задачу из
памяти
Перейти к выполнению следующей
задачи, не дожидаясь окончания или
приостановления текущей
Послать заданное сообщение указанной
задаче и ждать подтверждения его
получения
Проверить очередь задач, ожидающих
подтверждения получения посланных
сообщений
Поместить задачу в очередь ожидания,
где она будет находиться до тех пор,
пока не получит сообщение от другой
задачи
Получить данные, посланные другой
задачей
Послать уведомление о получении
сообщения с указанным номером
Если ресурс свободен, то занять его;
в противном
ждать освобождения
Проверить состояние ресурса по его
семафору
Освободить ресурс, сбросив его
семафор
Выполнить задержку на указанное
количество миллисекунд
Работа операционной системы реального времени осуществляется следующим образом. После включения питания и загрузки ОСРВ обычно запускается специ- альная задача - назовем ее
Она выполняет двойную функцию. Во-пер- вых, с ее помощью осуществляется запуск других программ (задач). Для выпол- нения этой функции используется системный вызов StartTask (см. табл. 5.1):
void
{
StartTask(Task1, 1);
1);
// Постоянно выполняемая задача.
// Запускается задача
// Выполняется цикл.
В приведенном фрагменте кода происходит запуск задачи Taskl, причем ей назначается уровень приоритета 1.
330 Устройства управления роботами
Заметим, что приоритет фоновой задачи AllTask равен 0, поэтому тело бес- конечного цикла выполняется,
только если нет какой-либо другой задачи, кото- рая в любом случае будет более приоритетной.
При разработке программного обеспечения для управления роботами надо учитывать следующие правила:
• существует три типа задач:
управляемые оператором (вручную),
биологичес-кие (код верхнего уровня по нашей классификации) и
периферийные (обслу- живающие внешние устройства). Задачи первого типа используют различные средства ввода информации — кнопки на боковой панели робота, интерфейс с компьютером, приемник команд дистанционного управления, - которые позволяют человеку вмешиваться в процесс выполнения программы. Задачи второго типа (биологический код) обычно заняты опросом датчиков, обра- боткой поступающих с них данных и выработкой команд для исполнитель- ных устройств. Как правило, в ОСРВ должна выполняться только одна зада- ча данного уровня. Каждая задача третьего типа предназначена для работы с каким-то одним (и только одним) внешним устройством. Эти задачи не способны инициировать обмен данными с внешними устройствами - они только могут обслужить запросы, сформированные биологическим кодом;
• если задача биологического уровня в настоящий момент не активна, то про- изводится вызов функции задержки на некоторое количество миллисекунд.
Пока длится задержка, могут выполняться другие задачи;
• в некоторых ОСРВ не требуется в явном виде использовать оператор цикла:
дойдя до конца, задача сама продолжает свое выполнение с самого начала. В дру- гих системах все может оказаться совершенно наоборот: завершенная задача удаляется из памяти. Поэтому лучше использовать явный цикл для продолже- ния выполнения и явный системный вызов End для завершения задачи.