AVR. Учебный курс. Архитектура Программ. Часть 3.
Автор DI HALT
Опубликовано 31 Янв 2010
Рубрики: AVR. Учебный курс
Метки: RTOS, Алгоритм, Программирование
Приоритетный диспетчер.
Одной из проблем простого диспетчера является то, что все задачи имеют равный приоритет. С одной стороны, это просто и удобно. С другой — какое-либо важное событие можно прошляпить, пока там конвейер перещёлкает все задачи…
Проблему решает введение приоритетов.
В простейшем случае, можно ввести два приоритета — высокий и низкий. Разница между ними будет лишь в том с какой стороны очереди они будут засовываться на конвейер. Высокоприоритетные пихаются сразу в начало, низкоприоритетные с конца.
Разумеется, тут надо следить за тем, чтобы высокоприоритетные задачи не забивали конвейер, блокируя низкоприоритетные. Никакой защиты от этого нет, только думать головой.
Если нужна высокоуровневая система приоритетов, то можно очередь задач превратить в двумерный массив, где вторым этажом будет идти приоритет задачи. Правда при этом увеличиться время обработки конвейера — ведь надо будет сперва прочесать всю очередь в поисках наибольшего элемента. Но тут можно напридумывать кучу оптимизаций. Например, сортировать очередь при постановке задачи на конвейер, либо завести TOP list приоритетов, занося туда значения приоритетов. Тогда диспетчер, обрабатывая очередь, сразу будет искать нужный элемент, ориентируясь по TOP листу. Но вот так, на вскидку, я не берусь сказать какой из приемов будет эффективней/компактней/быстрей.
Читать полностью
AVR. Учебный Курс. Архитектура Программ Часть 2
Автор DI HALT
Опубликовано 20 Янв 2010
Рубрики: AVR. Учебный курс
Метки: RTOS, Алгоритм, Программирование
Диспетчер
Данная организация программы требует чуть большего количества кода чем флаговый автомат (Хотя это еще как посмотреть. С увеличением числа задач служебный код динамического диспетчра не увеличивается, а вот флаговый автомат разрастается за счет большего числа флагов и проверок этих флагов, плюс быстродейтсвие снижается, чего нет в диспетчере) , но зато лишена ряда недостатков.
Во первых тут очередь выполнения задач не жестко заданная, а динамическая, конвеерного типа. То есть у нас есть в памяти массив из указателей на задачи-функции. Диспетчер берет указатель и, если он не указывает на Idle, осуществлет переход по этому адресу. Предварительно удалив его из очереди и подкинув очередь.
Заброс указателей-задач в очередь осуществляется другими задачами и прерываниями, а также программными таймерами. Собственно, принцип передачи управления от задачи к задаче похож на флаговый автомат — работаем через посредника. Только у нас тут отстутствуют проверки флагов, а переход делается диспетчером. За счет этого увеличение числа задач не сказывается на увеличении размера управляющей структуры.
Благодаря такой системе управляющую структуру можно вынести в отдельную библиотеку, сварганить к ней конфиг и таскать за собой ее туда сюда. Очень удобно.
А теперь подробно распишу тот диспетчер который стоит в 90% моих проектов на Си.
Читать полностью
AVR. Учебный Курс. Оценка загрузки контроллера.
Автор DI HALT
Опубликовано 18 июня 2009
Рубрики: AVR. Учебный курс
Метки: AVR, RTOS, Отладка, Трюки, ЦАП
Как оценить загруженность микроконтроллера? С памятью все понятно — размеры занимаемого кода и оперативной памяти показывает компилятор, а что делать с процессорным временем? Конечно, в линейной программе можно взять и посчитать время выполнения каждой процедуры и станет ясно успеет микроконтроллер выполнить все на него повешанное или слажает в каком-нибудь критичном месте.
Куда сложней оценивать время в кооперативной операционной системе реального времени. Тут задачка получается нетривиальной — у нас куча процессов скачут через диспетчер. В ходе программирования задачи навешиваешь одну за другой, как бусинки на нить — каждый процесс обработки чего либо составляет подобную цепочку, а всего их может быть просто тьма. Ядро же у контроллера всего одно, а значит выполнять можно всего одну задачу за раз и если у нас в диспетчере скопится много критичных ко времени процессов (вообще их лучше развешивать на прерывания, но бывает и прерываний на всех не напасешься), то возможно либо переполнение очереди диспетчера, либо превышение времени ожидания, что тоже не праздник.
Самое западло в том, что умозрительно отлаживать такие вещи довольно сложно. Единственный вариант — рисовать временные диаграммы запуска каждой задачи и смотреть где у нас узкие места. Еще можно попробовать в AVR Studio поставить Break Point на переполнение диспетчера, но студия не сэмулирует всю ту прорву периферии, а в пошаговой отладке этого не увидеть — да и момент надо подобрать так, чтобы все навалилось.
В один момент мне пришла в голову одна идея — а почему бы не заставить рисовать временные диаграммы работы задач сам контроллер? Это же просто! Берем и в диспетчере, перед вызовом задачи выставляем бит порта в 1. А когда диспетчер задач опустошается полностью, то есть выполняется переход на Idle — сбрасываем бит в 0. В результате, у нас на выходе будет подобие ШИМ. Если постоянно крутится Idle — будут нули перманентно. Если же проц в поте лица гонит через себя непрерывно код, то будут высокий уровнь сплошняком. А если все прерывисто — что то ШИМообразное. Причем чем больше загрузка процессора тем выше заполнение. Можно поставить интегрирующую RC цепочку и получим аналоговый сигнал. Хоть на стрелочный индикатор заводи :). Сказано — сделано.
Читать полностью
AVR. Учебный Курс. Управляемый вектор прерывания
Автор DI HALT
Опубликовано 12 июня 2009
Рубрики: AVR. Учебный курс
Метки: Assembler, RTOS, Алгоритм, Трюки
Бывает такая ситуация, когда надо на один периферийный девайс повесить много разных задач, а он всего один и что то надо с этим делать.
Простой пример — таймер и его прерывание по переполнению.
Мы можем задавать выдержку и по прерыванию делать какие-нибудь операции. Но если в один момент времени мы хотим чтобы таймер по прерванию сделал одну операцию, а потом другую, третью. Да сколько угодно, в зависимости от состояния. А вектор один.
Или, например, USART. Нам запросто может потребоваться, чтобы в зависимости от режима на прерывание по приходу байта выполнялся разный код. В одном режиме - выдача приветствия, в другом посыл матом в баню. В третьем удар в голову. А вектор один.
Конечно, можно добавить в обработчик прерывания switch-case конструкцию и по выбору режима перейти на нужный участок кода, но это довольно громоздко, а самое главное — время перехода будет разное, в зависимости от того в каком порядке будет идти опрос-сравнение switch-case структуры.
То есть в свитче вида:
1 2 3 4 5 6 7 | switch(x) { 1: Действие 1 2: Действие 2 3: Действие 3 4: Действие 4 } |
Будет последовательное сравнение х вначале с 1, потом с 2, потом с 3 и так до перебора всех вариантов. А в таком случае реакция на Действие 1 будет быстрей чем реакция на Действие 4. Особо важно это при расчете точных временных интервалов на таймере.
Но есть простое решение этой проблемы — индексный переход. Достаточно перед тем как мы начнем ожидать прерывание предварительно загрузить в переменные (а можно и сразу в индексный регистр Z) направление куда нам надо перенаправить наш вектор и воткнуть в обработчик прерывания индексный переход. И вуаля! Переход будет туда куда нужно, без всякого сравнения вариантов.
Читать полностью
М. Дамке “Операционные системы микроЭВМ”
Автор DI HALT
Опубликовано 04 мая 2009
Рубрики: Книги
Метки: RTOS, Алгоритм, Трюки
![]() |
Автор: М. Дамке Название: Операционные системы микроЭВМ Издательство: Финансы и статистика
Старожил сайта и один из самых активных и толковых комментаторов, камрад SWG сделал замечательную вещь– отсканировал и пожал в DejaVu книгу по написанию операционных систем под микро-ЭВМ.
Я пока основательно не врубался, по диагонали пролистал — рулез! Особого грузилова нет, все в виде алгоритмов и концепций. Написано все простым и понятным языком. В частности все разобрано на примере Z80 и i8080 В общем, замечательная книга. Как говорил SWG где то в комментах: “Почитай эту книгу и изобретение велосипедов пойдет куда веселей” :) Надо будет закинуть в принтер бумаги побольше и напечатать этот труд.
AVR. Учебный курс. Операционная система. Пример.
Автор DI HALT
Опубликовано 11 Апр 2009
Рубрики: AVR. Учебный курс
Метки: Assembler, AVR, RTOS, Программирование, Трюки
Отлично, с теорией работы ОС ознакомил. Устанавливать научил, осталось научить использовать весь этот конвеерно таймерный шухер. Чем я сейчас и займусь. Сразу берем быка за рога и формулируем учебно-боевую программу.
Тестовое задание:
Пусть у нас будет ATMega8, с несколькими кнопками. АЦП и подключеним к компу через UART. На меге будет три светодиода.
- Девайс должен при включении начинать мигать зеленым диодом, мол работаю.
- При этом раз в секунду сканировать показания АЦП и если показания ниже порога - Моргать красным диодом.
- По сигналу с UARТ с целью защиты от ошибок сделать по байту ‘R’ установку флага готовности, а потом, в течении 10ms если не придет байт ‘A’ сбросить флаг готовности и игнорировать все входящие байты кроме ‘R’. Если ‘A’ придет в течении 10мс после ‘R’, то отправить в UART ответ и зажечь белый диод на 1 секунду.
Вот так вот, не сильно сложно. Но мне просто лень делать что либо сложней, а для тестовой задачи сгодится. Читать полностью
AVR. Учебный курс. Операционная система. Установка
Автор DI HALT
Опубликовано 09 Апр 2009
Рубрики: AVR. Учебный курс
Метки: Assembler, AVR, RTOS
Ядро у нас есть, теперь осталось это все хозяйство запихать на МК. Для этого всего лишь надо рассовать нужные части кода в исходник. Показывать буду на примере ATmega8. Для других МК разница минимальная. Может быть с таймером что нибудь помудрить придется, но не более того.
Например, недавно, вкорячивал ту же схему на ATmega168, так пришлось подправить иницилизацию таймера - регистры там зовутся по другому. Пришлось изменить макрос OUTI - так как многие привычные уже регистры перестали загружаться через комадну OUT - выпали из диапазона, только через LDS/STS ну и, собственно, все хлопоты. Потратил минут 20 на переименование регистров и заработало.
Читать полностью
AVR. Учебный курс. Операционная система. Таймерная служба
Автор DI HALT
Опубликовано 01 Апр 2009
Рубрики: AVR. Учебный курс
Метки: Assembler, AVR, RTOS, Алгоритм, Операционная система
Третья часть марлезонского балета описалова самопальной операционной системы для AVR.
Итак, у нас есть очередь задач и общая логика работы системы. Но одной очереди задач с диспетчером мало. Нужно распределять задачи по времени, задавать интервалы, запускать отложенные задачи. Всем этим будет заниматься служба таймеров.
В чем ее суть ее работы:
Время разбивается на интервалы, скажем, по 1мс. Такой выдержки хватает для большинства задач. Также у нас должна быть очередь программных таймеров, размещенных в ОЗУ. На каждый таймер отводится три байта:
Первый — идентификатор задачи. Два других — выдержка в миллисекундах.
Два байта позволяют организовать выдержку в 65.5 секунд. Конечно, можно сделать и больше, если отвести на временную выдержку три или даже четыре байта, но такие большие временные интервалы пригождаются редко, поэтому проще перехватиться через дополнительную переменную для конкретной задачи, а не нагружать таймерную службу обсчетом дополнительных байт.
Один из свободных аппаратных таймеров программируем на то, чтобы он генерировал прерывание каждые 0.001с
По прерыванию мы берем из очереди таймеров первый байт и сравниваем его с 0xFF, за 0xFF принято неактивное состояние. Если же там не 0xFF, то значит это идентификатор задачи, а таймер активен. Поэтому берем третий байт, декрементируем его, если он стал равен нулю декрементируем второй байт и если оба байта не стали равны нулю переходим к проверке следующего байта. В случае если время истекло, то идентификатор задачи пихается в очередь задач на исполнение. Читать полностью
AVR. Учебный курс. Операционная система. Диспетчер задач.
Автор DI HALT
Опубликовано 30 марта 2009
Рубрики: AVR. Учебный курс
Метки: Assembler, AVR, RTOS
В прошлой части возник вопрос организации программы по задачам. Чтобы можно было разбить программу на кучу независимых частей и не заморачиваться на тот счет, что где то у нас будет затык.
Затык, конечно может быть, это все же не вытесняющая многозадачность с защищенным режимом, но разрулить все будет гораздо проще.
Общая диаграмма работы ОС
Что из себя представляет задача
Это практически то же самое, что и процедура, вызываемая командой RCALL с тремя отличиями:
- Вызывается она не мгновенно, а в порядке очереди.
- Вызов задачи идет не по ее адресу, а по ее порядковому номеру в таблице переходов.
- Возврат из нее идет не в то же место откуда вызывали, а в цикл диспетчера задач.
Сама задача представляет собой обычную процедуру, записанную без каких либо замудреностей.
Читать полностью
AVR. Учебный курс. Операционная система. Введение.
Автор DI HALT
Опубликовано 14 марта 2009
Рубрики: AVR. Учебный курс
Метки: AVR, RTOS
Рано или поздно наступает момент когда сложность алгоритма становится такой, что дальнейшее развитие и усложнение программы превращается в нетривиальную задачу. Очень легко запутаться и тяжело отлаживать эту портянку. Многие бегут от этих сложностей в языки высокого уровня, впрочем это не особо спасает — разница минимальна на самом деле и проще не становится.
Самое верное решение в данном случае — внедрение в проект операционной системы. Которая бы предоставляла API для решения задач, а также обеспечивала порядок работы всей системы.
В результате было написано микроядро. Камрад Serg2×2 подглядел концепцию в прошивке сотового телефона Motorola и портировал на микроконтроллер АТ89С2051, после ее перенесли на AVR, а я привел все в библиотечный и структурированный вид, обвязал все удобными макросами, а также подробно описал и задокументировал. Так что теперь интеграция ядра операционки в проект под микроконтроллер AVR занимает буквально пару минут работы Copy-Paste.
Ядро обеспечивает очередь задач (пока без приоритетов, но это в планах) и службу таймеров. Многозадачность кооперативная, что накладывает соответствующие ограничения на стиль написания. Фактически, каждую процедуру мы пишем как прерывание, максимально коротко и быстро, все задержки вешая на службу таймеров.
Параметры и системные требования микроядра:
- Занимаемый обьем в Flash - 500 байт, при желании можно ужать до 400 байт, выкинув ненужные функции.
- Рекомендуемый объем RAM - не менее 20 байт+стек, впрочем, можно еще ужать если нагрузка небольшая.
- Крайне желательная поддержка команд STS и LDS, можно и без них, но неудобно. Впрочем, макросы решают.



