При работе с реальными движущимися устройствами (чем, по сути, и является робот) мы сталкиваемся с необходимостью как можно скорее реагировать на внешние события. Для решения этой задачи существует специализированный класс операционных систем.
Операционные системы реального времени (ОСРВ) предназначены для обеспечения интерфейса к ресурсам критических по времени систем реального времени. Основной задачей в таких системах является своевременность (timeliness) выполнения обработки данных.
В качестве основного требования к ОСРВ выдвигается требование обеспечения предсказуемости или детерминированности поведения системы в наихудших внешних условиях, что резко отличается от требований к производительности и быстродействию универсальных ОС. Хорошая ОСРВ имеет предсказуемое поведение при всех сценариях системной загрузки (одновременные прерывания и выполнение потоков).
Существует некое различие между системами реального времени и встроенными системами. От встроенной системы не всегда требуется, чтобы она имела предсказуемое поведение, и в таком случае она не является системой реального времени. Однако даже беглый взгляд на возможные встроенные системы позволяет утверждать, что большинство встроенных систем нуждается в предсказуемом поведении, по крайней мере, для некоторой функциональности, и таким образом, эти системы можно отнести к системам реального времени.
Принято различать системы мягкого (soft) и жесткого (hard) реального времени. В системах жесткого реального времени неспособность обеспечить реакцию на какие-либо события в заданное время ведет к отказам и невозможности выполнения поставленной задачи. В большинстве русскоязычной литературы такие системы называют системами с детерминированным временем. При практическом применении время реакции должно быть минимальным. Системами мягкого реального времени называются системы, не попадающие под определение "жесткие", т.к. в литературе четкого определения для них пока нет. Системы мягкого реального времени могут не успевать решать задачу, но это не приводит к отказу системы в целом. В системах реального времени необходимо введение некоторого директивного срока (в англоязычной литературе - deadline), до истечения которого задача должна обязательно (для систем мягкого реального времени - желательно) выполниться. Этот директивный срок используется планировщиком задач как для назначения приоритета задачи при ее запу ске, так и при выборе задачи на выполнение.
Мартин Тиммерман сформулировал следующие необходимые требования для ОСРВ:
В течение последних 25-30 лет структура операционных систем эволюционировала от монолитной к многослойной структуре ОС и далее к архитектуре клиент-сервер. При монолитной структуре ОС состоит из набора модулей, и изменения одного модуля влияют на другие модули. Чем больше модулей, тем больше хаоса при эксплуатации такой системы. Кроме того, невозможно распределить ОС в многопроцессорной системе. В многослойной структуре изменения одного слоя влияют на соседние слои; кроме того, обращение через слой невозможно. Для систем реального времени должно быть обеспечено прямое обращение к каждому слою ОС, а иногда напрямую к аппаратуре.
Основной идеей клиент-серверной технологии в ОС является сведение базиса ОС к минимуму (планировщик и примитивы синхронизации). Вся остальная функциональность выносится на другой уровень и реализуется через потоки или задачи. Совокупность таких серверных задач отвечает за системные вызовы. Приложения являются клиентами, которые запрашивают сервисы через системные вызовы.
Клиент-серверная технология позволяет создавать масштабируемые ОС и упрощает распределение в многопроцессорной системе. При эксплуатации системы замена одного модуля не вызывает эффекта "снежного кома"; кроме того, сбой модуля не всегда влечет за собой отказ системы в целом. Появилась возможность динамической загрузки и отгрузки модулей. Главной проблемой в этой модели является защита памяти, поскольку серверные процессы должны быть защищены. При каждом запросе сервиса система должна переключаться с контекста приложения на контекст сервера. При поддержке защиты памяти время переключения с одного процесса на другой увеличивается.
Как правило, большинство современных ОСРВ построено на основе микроядра (kernel или nucleus), которое обеспечивает планирование и диспетчеризацию задач, а также осуществляет их взаимодействие. Несмотря на сведение к минимуму в ядре абстракций ОС, микроядро все же должно иметь представление об абстракции процесса. Все остальные концептуальные абстракции операционных систем вынесены за пределы ядра, вызываются по запросу и выполняются как приложения.
Рассмотрим концептуальные абстракции операционной системы через призму требований к системам реального времени.
Концепция многозадачности (псевдопараллелизм) является существенной для системы реального времени с одним процессором, приложения которой должны быть способны обрабатывать многочисленные внешние события, происходящие практически одновременно. Концепция процесса, пришедшая из мира UNIX, плохо реализуется в многозадачной системе, поскольку процесс имеет тяжелый контекст. Возникает понятие потока (thread), который понимается как подпроцесс, или легковесный процесс (light-weight process). Потоки существуют в одном контексте процесса, поэтому переключение между потоками происходит очень быстро, а вопросы безопасности не принимаются во внимание. Потоки являются легковесными, потому что их регистровый контекст меньше, т.е. их управляющие блоки намного компактнее. Уменьшаются накладные расходы, вызванные сохранением и восстановлением управляющих блоков прерываемых потоков. Объем управляющих блоков зависит от конфигурации памяти. Если потоки выполняются в разных адресных пространствах, система должна поддерживать отображение памяти для каждого набора потоков.
Итак, в системах реального времени процесс распадается на задачи или потоки. В любом случае каждый процесс рассматривается как приложение. Между этими приложениями не должно быть слишком много взаимодействий, и в большинстве случаев они имеют различную природу - жесткого реального времени, мягкого реального времени, не реального времени.
В связи с проблемой дедлайнов главной проблемой в ОСРВ становится планирование задач (scheduling), которое обеспечивало бы предсказуемое поведение системы при всех обстоятельствах. Процесс с дедлайнами должен стартовать и выполняться так, чтобы он не пропустил ни одного своего дедлайна. Если это невозможно, процесс должен быть отклонен.
В связи с проблемами планирования в ОСРВ изучаются и развиваются два подхода - статические алгоритмы планирования (RMS - Rate Monotonic Scheduling) и динамические алгоритмы планирования (EDF - Earliest Deadline First).
RMS используется для формального доказательства условий предсказуемости системы. Для реализации этой теории необходимо планирование на основе приоритетов, прерывающих обслуживание (preemptive priority scheduling). В теории RMS приоритет заранее назначается каждому процессу. Процессы должны удовлетворять следующим условиям:
Процессы выполняются в соответствии с приоритетами. При планировании RMS предпочтение отдается задачам с самыми короткими периодами выполнения.
В EDF приоритет присваивается динамически, и наибольший приоритет выставляется процессу, у которого осталось наименьшее время выполнения. При больших загрузках системы у EDF имеются преимущества перед RMS.
Во всех системах реального времени требуется политика планирования, управляемая дедлайнами (deadline-driven scheduling). Однако этот подход находится в стадии разработки.
Обычно в ОСРВ используется планирование с приоритетами, прерывающими обслуживание, которое основано на RMS. Приоритетное прерывание обслуживания (preemption) является неотъемлемой составляющей ОСРВ, т.к. в системе реального времени должны существовать гарантии того, что событие с высоким приоритетом будет обработано перед событием более низкого приоритета. Все это ведет к тому, что ОСРВ нуждается не только в механизме планирования на основе приоритетов, прерывающих обслуживание, но также и в соответствующем механизме управления прерываниями. Более того, ОСРВ должна быть способна запрещать прерывания, когда необходимо выполнить критический код, который нельзя прерывать. Длительность обработки прерываний должна быть сведена к минимуму.
ОСРВ должна обладать развитой системой приоритетов. Во-первых, это требуется потому, что система сама может рассматриваться как набор серверных приложений, подразделяющихся на потоки, и несколько высоких уровней приоритетов должно быть выделено системным процессам и потокам. Во-вторых, в сложных приложениях необходимо все потоки реального времени помещать на разные приоритетные уровни, а потоки не реального времени помещать на один уровень (ниже, чем любые потоки реального времени). При этом потоки не реального времени можно обрабатывать в режиме циклического планирования (RRS - round-robin scheduling), при котором каждому процессу предоставляется квант времени процессора, а когда квант заканчивается, контекст процесса сохраняется, и он ставится в конец очереди. Во многих ОСРВ для планирования задач на одном уровне используется RRS. Приоритетный уровень 0 обычно используется для холостого режима.
При планировании на основе приоритетов необходимо решить две обязательные проблемы:
Для борьбы с инверсией приоритетов в ОСРВ часто используется механизм наследования приоритетов, однако при этом приходится отказываться от планирования на основе RMS, поскольку приоритеты становятся динамическими.
При описании управления прерываниями обычно различают две процедуры, а именно:
Обычно ISR реализуются производителем аппаратуры, а драйверы устройств выполняют управление прерываниями с помощью IST. Потоки обработки прерываний действуют как любые другие потоки и используют ту же самую систему приоритетов. Это означает, что проектировщик системы может придать IST более низкий приоритет, чем приоритет потока приложения.
В ОСРВ используются различные службы времени. Операционная система отслеживает текущее время, в определенное время запускает задачи и потоки и приостанавливает их на определенные интервалы. В службах времени ОСРВ используются часы реального времени. Обычно используются высокоточные аппаратные часы. Для отсчета временных интервалов на основе часов реального времени создаются таймеры.
Для каждого процесса и потока определяются часы процессорного времени. На базе этих часов создаются таймеры; которые измеряют перерасход времени процессом или потоком, позволяя динамически выявлять программные ошибки или ошибки вычисления максимально возможного времени выполнения. В высоконадежных, критичных ко времени системах важно выявление ситуаций, при которых задача превышает максимально возможное время своего выполнения, т.к. при этом работа системы может выйти за рамки допустимого времени отклика. Часы времени выполнения позволяют выявить возникновение перерасхода времени и активизировать соответствующие действия по обработке ошибок.
Большинство ОСРВ оперируют относительным временем. Что-то происходит "до" и "после" некоторого другого события. В системе, полностью управляемой событиями, необходим часовой механизм (ticker), т.к. там нет квантования времени (time slicing). Однако, если нужны временные метки для некоторых событий или необходим системный вызов типа "ждать одну секунду", то нужен тактовый генератор и/или таймер.
Синхронизация в ОСРВ осуществляется с помощью механизма блокирования (или ожидания) до наступления некоторого события. Абсолютное время не используется.
Реализации в ОСРВ других концептуальных абстракций подобны их реализациям в традиционных ОС.
Большие различия в спецификациях ОСРВ и огромное количество существующих микроконтроллеров выдвигают на передний план проблему стандартизации в области систем реального времени.
Наиболее ранним и распространенным стандартом ОСРВ является стандарт POSIX (IEEE Portable Operating System Interface for Computer Environments, IEEE 1003.1). Первоначальный вариант стандарта POSIX появился в 1990 г. и был предназначен для UNIX-систем, первые версии которых появились в 70-х годах прошлого века. Спецификации POSIX определяют стандартный механизм взаимодействия прикладной программы и операционной системы и в настоящее время включают набор более чем из 30 стандартов. Для ОСРВ наиболее важны семь из них (1003.1a, 1003.1b, 1003.1c, 1003.1d, 1003.1j, 1003.21, 1003.2h), но широкую поддержку в коммерческих ОС получили только три первых.
Несмотря на явно устаревшие положения стандарта POSIX и большую востребованность обновлений стандартизации для ОСРВ, заметного продвижения в этом направлении не наблюдается.
Некоторые наиболее успешные компании в области систем реального времени объявляют о своем решении принять в качестве стандарта спецификации одной из своих продвинутых ОСРВ. Так поступила компания TRON (the RTOS Nucleus), которая в 1987г. выпустила в свет первые ITRON спецификации - ITRON1. Далее в 1989г. она разработала и выпустила спецификации µITRON для 8- и 16- битовых микроконтроллеров, а также спецификации ITRON2 для 32-битовых процессоров. ОСРВ ITRON описывается ниже в соответствующем разделе. Этот стандарт является очень распространенным в Японии.
Военная и аэрокосмическая отрасли предъявляют жесткие требования к вычислительным средствам, влияющим на степень безопасности целевой системы. В настоящее время имеются следующие стандарты для ОСРВ в авиации - стандарт DO-178B и стандарт ARINC-653. Поскольку эти стандарты разработаны в США, стоит отметить еще европейский стандарт ED-12B, который является аналогом DO-178B.
Распространенным также является стандарт OSEK/VDX, который первоначально развивался для систем автомобильной индустрии.
Стандарт OSEK/VDX является комбинацией стандартов, которые изначально разрабатывались в двух отдельных консорциумах, впоследствии слившихся. OSEK берет свое название от немецкого акронима консорциума, в состав которого входили ведущие немецкие производители автомобилей - BMW, Bosch, Daimler Benz (теперь Daimler Chrysler), Opel, Siemens и Volkswagen, а также университет в Карлсруэ (Германия). Проект VDX (Vehicle Distributed eXecutive) развивался совместными усилиями французских компаний PSA и Renault. Команды OSEK и VDX слились в 1994г.
Первоначально проект OSEK/VDX предназначался для разработки стандарта открытой архитектуры ОС и стандарта API для систем, применяющихся в автомобильной промышленности. Однако разработанный стандарт получился более абстрактным и не ограничивается использованием только в автомобильной индустрии.
Стандарт OSEK/VDX состоит из трех частей - стандарт для операционной системы (OS), коммуникационный стандарт (COM) и стандарт для сетевого менеджера (NM). В дополнение к этим стандартам определяется некий реализационный язык (OIL). Первым компонентом стандарта OSEK является стандарт для ОС, поэтому часто стандарт OSEK ошибочно воспринимается как стандарт ОСРВ. Хотя ОС и есть большая порция данного стандарта, мощность его состоит в интеграции всех его компонент.
ОС OSEK оперирует такими объектами, как задачи, события, ресурсы. Кроме того, обеспечиваются такие возможности, как управление ошибками и средства для пользовательских функций отслеживания изменений в состоянии системы.
ОС OSEK обеспечивает определенный набор интерфейсов для пользователя. Интерфейсы используются сущностями, конкурирующими за центральный процессор. ОС OSEK оперирует двумя типами таких сущностей - задачи и прерывания - и определяет три уровня обработки - уровень прерываний, логический уровень планировщика и уровень задач. Задачи выбираются на выполнение в соответствии с присвоенными им приоритетами.
Задача в ОС OSEK может быть
Главное различие между базовой и расширенной задачами заключается в том, может ли задача впасть в состояние ожидания (в котором она ждет появления события). Только расширенная задача может ожидать события. Вытесняемая задача может быть вытеснена задачей более высокого приоритета или прервана прерыванием. Невытесняемая задача может быть вытеснена только с помощью прерывания (когда прерывания не запрещены).
(рис 7.1)
Концепция двух типов задач потребовала введения нового понятия - класс соответствия (conformance class) для описания своеобразной реализации ОС OSEK и системных сервисов. Определяются четыре класса соответствия - два для базового соответствия (BCC1 и BCC2 - Basic conformance Classes 1 и 2) и два для расширенного (ECC1 и ECC2 - Extended Conformance Classes 1 и 2). Реализации, которые соответствуют базовым классам, требуют использования только базовых задач, в то время как для расширенных классов нужны как расширенные, так и базовые задачи. Числа 1 и 2 в именах классов указывают количество запросов на задачу для базовых задач и количество задач на приоритет для всех задач. Таким образом, в BCC1 и ECC1 имеется только одна задача на приоритет, и базовые задачи могут быть запрошены только один раз. В BCC2 и ECC2 допускается множественность задач на приоритет и множественное запрашивание базовых задач.
Каждая задача должна находиться в одном из четырех состояний
(рис 7.2) Модель состояний задачи в ОС OSEK
Каждая задача имеет приоритет. Стандарт ОС OSEK не ограничивает максимальное количество приоритетов - это определяет реализация.
ОС OSEK определяет два уровня программ управления прерываниями, которые различаются возможностями вызова системных сервисов. Прерывания уровня 1 выполняются независимо от ОС очень быстро. Уровень 2 обеспечивает выполнение функций приложений, которые содержат вызовы ОС.
События в ОС OSEK используются для синхронизации различных задач. События являются собственностью задач. Любая задача, в том числе и базовая, может установить событие, и только собственник события может ожидать или снять его.
Управление ресурсами обеспечивает доступ к разделяемым ресурсам, таким как память, аппаратура и т.п. Планировщик также считается специальным ресурсом, который может быть захвачен задачами. Чтобы избежать инверсии приоритетов и тупиковых ситуаций, OSEK применяет потолочный протокол приоритетов. Согласно этому протоколу задаче, захватившей ресурс, временно повышается приоритет, и, таким образом, никакие другие задачи, обращающиеся к данному ресурсу, не смогут выполняться до тех пор, пока ресурс остается захваченным. Однако, все задачи с более высоким приоритетом, чем приоритет задачи, захватившей ресурс, все еще могут выполняться.
Аварийные сигналы и счетчики в OSEK используются для синхронизации активации задач с повторяющимися событиями. Аварийный сигнал статически присваивается счетчику, задаче и воздействию. Воздействие может либо активировать задачу, либо установить событие. Счетчики оперируют тактами и могут представлять время, количество принятых импульсов и т.п. Каждая реализация обеспечивает один временной счетчик, который используется для планирования периодических событий. Все другие счетчики управляются через API, являются специфическими для конкретной реализации и не могут быть переносимыми.
В OSEK существует два типа аварийных сигналов: циклические и одинарные. Циклические аварийные сигналы применяются для диспетчеризации задачи, которая должна запускаться периодически. Счетчик аварийного сигнала может быть установлен в относительное или абсолютное значение. Параметры цикла и значение счетчика могут переустанавливаться динамически.
ОС OSEK обеспечивает минимальные средства для управления ошибками времени выполнения. Однако имеется возможность дополнительного управления ошибками во время разработки благодаря расширенной функциональности возврата управления. Причина такого решения состоит в том, что после того как продукт запущен в производство, большинство возможных ошибок может быть выявлено во время тестирования (такие как "неверный идентификатор задачи", "ресурс занят", "непредусмотренный вызов с уровня прерываний" и т.д.). Во время выполнения большинство системных сервисов не возвращает коды ошибок, но некоторые сервисы, такие как аварийные сигналы, которые могут стартовать и останавливаться динамически, возвращают код ошибки, если данный аварийный сигнал уже использовался.
ОС OSEK определяет два типа ошибок - ошибки приложения и фатальные ошибки. При ошибке приложения, когда приложение пытается выполнить несанкционированную операцию (например, активизировать несуществующую задачу), целостность внутренних данных все еще сохраняется. Фатальные ошибки возникают, если ОС обнаруживает нарушение целостности внутренних данных. При выявлении таких ошибок вызывается сервис завершения работы ОС.
ОС РВ nxtOSEK имеет программный интерфейс для С и С++, который используется в пакете ECRobot . Изначально программный интерфейс для С разрабатывался исключительно для автоматической генерации кода пакетом Simulink® (в рамках реализации модельно-ориентированного подхода пакета ECRobot), и, как следствие, его не очень удобно использовать при написании программы на чистом С. Другое дело интерфейс для С++, его структура и имена более приспособлены для написания программ вручную. Ниже приведен пример программы HelloWorld на С++, после знакомства с API для C будет очевидно, что эта программа реализована проще, чем ее аналог на C.
/* sample.cpp для TOPPERS/ATK(OSEK) */
//nxtOSEK C++ API
#include "Lcd.h" //подключаем класс работы с дисплеем
using namespace ecrobot;
extern "C"
{
//стандартные заголовочные файлы
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"
// nxtOSEK обработчик прерываний
void user_1ms_isr_type2(void){}
//точка входа
TASK(TaskMain)
{
Lcd lcd; //создаем объект lсd
lcd.clear(); //очищаем дисплей
lcd.putf("s", "Hello World"); //вывод Hello World
lcd.disp(); //перерисовываем картинку на дисплее
while(1);
}
}
Сама система nxtOSEK базируется на ОС TOPPERS ATK1, которая очень похожа на версию ОС OSEK OS/OIL, используемую в проекте TOPPERS. Подробное описание API OSEK можно найти на сайте OSEK/VDX (см. OSEK OS Version 2.2.1, OSEK OIL Version 2.5). Однако в ОС РВ nxtOSEK не реализована некоторая функциональность TOPPERS ATK1 из-за особенностей архитектуры системы. Например, не следует использовать объявления процедур обработки прерываний (ISR) и API обработки прерываний.
К сожалению, подробная документация TOPPERS ATK1 доступна только на японском языке, тем не менее, желающие смогут найти ее в папке nxtOSEK\toppers_osek\doc.
Программный интерфейс ОС РВ nxtOSEK содержит низкоуровневые функции доступа к устройствам и функции-обертки (wrapper) для пакета ECRobot (последние имеют префикс ecrobot_) которые разработаны для создания программ управления устройствами в режиме реального времени.
При описании программного интерфейса отдельно помечались функции, которые являются надстройками над низкоуровневыми функциями (функции-обертки). Чтобы не иметь лишних потерь времени при выполнении программы, лучше воздержаться от их использования. Для использования программного интерфейса необходимо подключить в исходном коде заголовочный файл ecrobot_interface.h
В программе, написанной для ОС РВ nxtOSEK, должны быть описаны три специальные процедуры, так называемые функции-обработчики или функции-ловушки (hook routines): ecrobot_device_initialize, ecrobot_device_terminate, user_1ms_isr_type2. Их определение и описание должны быть в главном с-файле программы. Система вызывает их автоматически, первую в начале работы программы, вторую в конце, а третью периодически каждую миллисекунду. Что бы легче было понять, как правильно их использовать, рассмотрим примеры этих процедур из файла ecrobot_main.c программы NXTway.
void ecrobot_device_initialize(void): Эта процедура вызывается в самом начале работы программы. В ней нужно помещать вызовы функций инициализации датчиков и моторов.
void ecrobot_device_initialize(void)
{
/* Инициализировать используемые устройства */
ecrobot_set_light_sensor_active(NXT_PORT_S1);
ecrobot_set_light_sensor_active(NXT_PORT_S3);
ecrobot_init_sonar_sensor(NXT_PORT_S2);
ecrobot_set_motor_speed(NXT_PORT_B, 0);
ecrobot_set_motor_speed(NXT_PORT_C, 0);
ecrobot_init_bt_connection();
}
void ecrobot_device_terminate(void): Эта процедура вызывается в случае, если нажали кнопку STOP или EXIT. В ней нужно помещать вызовы функций, корректно завершающих работу датчиков и моторов.
void ecrobot_device_terminate(void)
{
/* Завершить работу датчиков, остановить моторы */
ecrobot_set_light_sensor_inactive(NXT_PORT_S1);
ecrobot_set_light_sensor_inactive(NXT_PORT_S3);
ecrobot_set_motor_speed(NXT_PORT_B, 0);
ecrobot_set_motor_speed(NXT_PORT_C, 0);
ecrobot_term_sonar_sensor(NXT_PORT_S2);
ecrobot_term_bt_connection();
}
void user_1ms_isr_type2(void): Эта процедура вызывается процедурой обработки прерываний второго типа, работающей с периодом 1 мсек. В ней, например, можно реализовать счетчик системных тактов подсистемы запуска задач (OSEK Alarm) для реализации Планировщика Периодических Вызовов Задач.
#include "kernel.h"
#include "kernel_id.h"
void user_1ms_isr_type2(void)
{
StatusType ercd;
/* Увеличить счетчик системного времени */
ercd = SignalCounter(SysTimerCnt);
if (ercd != E_OK)
{
ShutdownOS(ercd);
}
}
Опишем простой пример для демонстрации общих принцпов построения программ с использованием API для С nxtOSEK. Текст примера предоставил студент математико- механического факультета Михаил Липкович. В этом примере реализована управляющая программа для робота, движущегося вдоль стенки.
Прежде всего рассмотрим файл описания OSEK Implementation Language (OIL). Подробную справку по синтаксису OIL-файла можно найти на сайте концерна VXD/OSEK.
/* wall_osek.oil*/
#include "implementation.oil"
CPU ATMEL_AT91SAM7S256
{
OS LEJOS_OSEK
{
STATUS = EXTENDED;
STARTUPHOOK = FALSE;
ERRORHOOK = FALSE;
SHUTDOWNHOOK = FALSE;
PRETASKHOOK = FALSE;
POSTTASKHOOK = FALSE;
USEGETSERVICEID = FALSE;
USEPARAMETERACCESS = FALSE;
USERESSCHEDULER = FALSE;
};
APPMODE appmode1{};
TASK Motion //определение свойств задачи Motion
{
AUTOSTART = FALSE; //не запускаться самой при запуске //программы
PRIORITY = 2; //приоритет. чем больше число, тем //выше приоритет
ACTIVATION = 1; //максимально число одновременно //работающих задач Motion
SCHEDULE = FULL; //возможность вытеснять эту задачу //задачами более высокого приоритета
STACKSIZE = 512; //размер стека
};
ALARM cyclic_alarm1 //определение будильника (генератора //событий запуска задачи)
{
COUNTER = SysTimerCnt; //счетчик SysTimerCnt
ACTION = ACTIVATETASK //при запуске будильника вызвать //задачу Motion
{
TASK = Motion;
};
AUTOSTART = TRUE //автоазапуск будильника
{
ALARMTIME = 1; //время запуска будильника впервый //раз
CYCLETIME = 50; //период последующих запусков
APPMODE = appmode1;
};
};
COUNTER SysTimerCnt //определение счетчика
{
MINCYCLE = 1; //минимально возможное число тиков //счетчика для использования //будильником
MAXALLOWEDVALUE = 10000; //максимально
//возможноезначение счетчика
TICKSPERBASE = 1; //размер тика (в миллисекундах)
};
};
Сам текст программы находится в файле wall_osek.c. Точкой входа этой программы (места с которого начинается выполнение программы) является задача task(Motion), как следует из файла wall_osek.oil, эта задача вызывается раз в 50 миллисекунд. Не следует забывать, что необходимо реализовать еще три процедуры ecrobot_device_initialize, ecrobot_device_terminate, user_1ms_isr_type2, которые формально нигде не используются, но система вызывает их автоматически.
/* wall_osek.c*/
#include "kernel.h"
#include "kernel_id.h"
#include "ecrobot_interface.h"
//определение констант
#define MOTOR_R NXT_PORT_C
#define MOTOR_L NXT_PORT_A
#define SONAR NXT_PORT_S1
#define K 1.2 //коэффициент //пропорционального регулятора
#define D 20 //расстояние до стены
DeclareTask(Motion);
DeclareCounter(SysTimerCnt);
//инициализация моторов и ультразвукового датчика
//(выполняется перед всеми задачами)
void ecrobot_device_initialize()
{
ecrobot_set_motor_speed(MOTOR_R, 0);
ecrobot_set_motor_speed(MOTOR_L, 0);
ecrobot_init_sonar_sensor(SONAR);
}
//выполняется после завершения всех задач
void ecrobot_device_terminate()
{
ecrobot_set_motor_speed(MOTOR_R, 0);
ecrobot_set_motor_speed(MOTOR_L, 0);
ecrobot_term_sonar_sensor(SONAR);
}
//процедура обработки прерываний. необходима для получения //доступа к датчикам и сервомоторам
void user_1ms_isr_type2(void) {
(void)SignalCounter(SysTimerCnt); //увеличить счетчик //SysTimerCnt для вызова периодических задач
}
TASK(Motion) //задача, реализующая движение
{
S8 base_speed = 25, u = 0;
u = (ecrobot_get_sonar_sensor(SONAR)-D)*K;
ecrobot_set_motor_speed(MOTOR_L, (base_speed + u)%100);
ecrobot_set_motor_speed(MOTOR_R, (base_speed - u)%100);
TerminateTask(); //завершение задачи
}
Конечно, текст самой задачи, реализующей логику работы регулятора, существенно меньше описания технической части программы. С одной стороны, это делает даже маленькую по содержанию программу объемной, но с другой, дает пространство для тонкой настройки параметров. Эта настройка, по сути, шаблонная и ее легко скопировать из другой задачи.
Более удобный программный интерфейс реализован для C++. Каждый датчик и мотор является экземпляром соответствующего класса, а это перекладывает работу по инициализации и завершения работы переферийных устройств на конструкторы и деструкторы соответствующих классов, инкапсуирует методы, деля синтаксии интуитивно понятным. Хоть необходимость использования процедур ecrobot_device_initialize, ecrobot_device_terminate пропадает, тем не менее, для того что бы согласовать обектно ориентированный подход с функционалом ОС РВ nxtOSEK и предоставлять классам взаимодействие с процедурами обработки прерываний, все же необходимо использовать процедуру user_1ms_isr_type2 и описать событие ОС РВ.
Как правило, в процедуре user_1ms_isr_type2 достаточно вызывать одну функцию SleeperMonitor() которая необходима для корректной работы класса Clock и корректного взаимодействия с устройвами через I2C интерфейс.
Так же необходимо указать в описании основной задачи в OIL файле события EventSleepI2C и EventSleep. Это может выглядеть, например, так:
//событие EventSleepI2C
EVENT EventSleepI2C
{
MASK = AUTO;
};
//событие EventSleepI
EVENT EventSleep
{
MASK = AUTO;
};
//описание основной задачи с названием, например, TaskMain
TASK TaskMain
{
AUTOSTART = TRUE
{
APPMODE = appmode1;
};
PRIORITY = 1;
ACTIVATION = 1;
SCHEDULE = FULL;
STACKSIZE = 512;
EVENT = EventSleepI2C; //добавили событие EventSleepI2C
EVENT = EventSleep; //добавили событие EventSleepI2C
};
Надо помнить, что так как объектам 18ти классов (датчикам, соединениям, моторам) требуется инициализация и корректное завершение работы, их необходимо определять как глобальные объекты. В противном случае на дисплее появится сообщение об ошибке и для корректной работы устройство надо будет перезапустить. Глобальными должны быть экземпляры следующих классов: AccelSensor, Bluetooth, Camera, ColorSensor, CompassSensor, SonarSensor, IrSeeker, LegoLight, Motor, NxtColorSensor, PSPNx, Rs485, GyroSensor, LightSensor, RcxLightSensor, SoundSensor, TouchSensor.
В этом параграфе приведен список классов в алавитном порядке с учетом наследования. Многие методы классов созвучны функциям С интерфейса, поэтому подробно их описывать здесь не будем.
Все классы находятся в пространстве имен (namespace) "ecrobot", что бы использовать классы без приставки ecrobot:: необходимо указасть в начале программы using namespace ecrobot. Так же, что бы генерировался корректный машинный код, необходимо сделать указание компановщику (linker) компановать программу в стиле С, т.е. код программы должен быть заключен между extern "C"{ …код программы… }(см. пример в начале главы).
ecrobot::AccelSensor
Клаcс работы с датчиком ускорения HiTechnic.
ecrobot::Bluetooth
Класс работы с Bluetooth.
ecrobot::BTConnection
Устанавливает соединение через Bluetooth.
ecrobot::Camera
Класс работы с камерой NXTCamv2.
ecrobot::Clock
Класс работы с системными часами.
ecrobot::ColorSensor
Класс работы с датчиком цвета NXT.
ecrobot::CompassSensor
Класс работы с компасом HiTechnic
ecrobot::Daq
Класс для отправки внутренних данных NXT программе NXT GamePad.
ecrobot::GamePad
Класс для дистанционного управления с помощью джойстика GamePad.
ecrobot::I2cecrobot::SonarSensor
Класс работы с ультразвуковым датчиком.
ecrobot::IrSeeker
Класс работы с инфракрасным датчиком.
ecrobot::Lcd
Класс работы с дисплеем устройства NXT.
ecrobot::LegoLight
Класс работы с датчиком освещенности NXT.
ecrobot::Motor
Класс работы с серводвигателями NXT.
ecrobot::Nxt
Класс работы с внутренними функциями устройства NXT (работа с кнопками, получение уровня заряда батареи).
ecrobot::NxtColorSensor
Класс работы с датчиком цвета NXT.
ecrobot::PSPNx
Класс работы с портом расширения для Sony Play Station.
ecrobot::Camera::Rectangle_T
Вспомогательный класс для работы с камерой NXTCamv2.
ecrobot::Rs485
Класс работы с интрфейсом RS485.
ecrobot::Sensorecrobot::GyroSensor
Класс работы с гироскопом.
ecrobot::LightSensor
Класс работы с датчиком освещенности.
ecrobot::RcxLightSensor
Класс работы с датчиком освещенности RCX.
ecrobot::SoundSensor
Класс работы со звуковым датчиком.
ecrobot::TouchSensor
Класс работы с датчиком касания.
ecrobot::Speaker
Класс работы с воспроизведением звука.
ecrobot::Usb
Класс работы с USB.
ecrobot::VectorT < T >
Класс, реализующий вектор из двух компонент.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.