• Объявления

    • admin

      Размещайте материалы своей компании БЕСПЛАТНО!   18.04.2018

      Редакционная политика портала позволяет размещать на бесплатной основе различные типы материалов: интересную информацию, наработки, технические решения, аналитические статьи и т.д. Пример такого блога. Взамен мы рекламируем ваш блог в наших группах в соц. сетях, ну и плюс естественная самореклама от пользователей форума и блогов, которые будут читать ваш блог. К примеру охват одного поста только в нашей группе VK составляет более 10 тыс. человек. Т.е. мы предлагаем бартер - вы ведете у нас блог и публикуете какую-то полезную и интересную информацию связанную с вашим производством, а мы рекламируем ваш блог в наших соц. сетях. Блоги можно полностью кастомизировать: поставить изображение шапки, сделать меню или оглавление, также в своем блоге вы будете модератором - сможете удалять комментарии и т.д. Ведение своего блога требует времени и навыков, но рекламный эффект колоссальный, т.к. это живое общение и отклик. Посты не должны быть рекламой, а также должны соответствовать правилам форума. Для тех компаний, которые будут публиковать интересный контент, права в дальнейшем будут расширяться - сможете публиковать больше ссылок, пресс-релизы, новости компании, анонсы и т.д. Ну а если вы хотите размещать платную рекламу: условия и прайс размещения на сайте и форуме, коммерческая тема на форуме, реклама в группе VK.

Гнездо кукушки

  • запись
    1
  • комментариев
    0
  • просмотров
    77

Как перестать волноваться и полюбить... RTOS

ARV

111 просмотр

Вот вы говорите: AVR слишком убоги, чтобы применять на них RTOS... А я рискнул...

Сначала попытался рассмотреть имеющиеся варианты, чтобы сделать предварительные выводы. Поиск вываливает примерно с десяток готовых разработок RTOS разной степени крутости, из которых FreeRTOS, естественно, в лидерах. Однако, я оценил свои силы и решил, что вхождение в эту ОС для меня обернется большими сложностями, в основном, из-за большого количества возможностей API, и англоязычным их описанием. Ну не принимает душа русская языка аглицкого, даже со словарем и гуглопереводчиком в больших количествах. А из осей на великом и могучем нашлось только две: кооперативная OSA и присиплюсплюснатая ScmRTOS.

Опять-таки из-за собственной ограниченности более современная и продвинутая ScmRTOS мне показалась недоступной - С++ пока что понимаю и принимаю исключительно в качестве наказания. Ну, собственно, и вышло, что начать и закончить поиск осей для AVR можно на OSA.

Попробовал - получается. Не без скрипа, но работает. И даже увлекло меня это. Но вот что мне не понравилось в этом варианте.

Главная особенность этой ОС, которую следует учитывать при работе (то есть при написании программ), это отсутствие сохранения контекста при переключении задач. Иными словами, если в текущей задаче вызывается сервис операционной системы, переключающий задачи, то все локальные переменные текущей задачи могу потерять свою актуальность. Это означает, в частности, запрет на вызов сервисов системы в циклах по счетчику (значение счетчика будет потеряно). И единственный способ решить эту проблему - вместо автоматических локальных переменных использовать static или вообще отказаться от локальных в пользу глобальных. Сами понимаете, это совсем не гуд.

Вторая особенность этой ОС, это возможность вызывать сервисы ОС, преключающие задачи, только из тела самой задачи, но не в вызываемых из неё функций. То есть нельзя сделать функцию, например, ожидающую прием символа из USART при помощи системного сервиса OS_Wait, а затем вызывать эту функцию из разных задач, то есть поступать по аналогии с привычным "не-многозадачным" подходом.

Вот представьте себе ситуацию: задачи формируют текстовые сообщения и выводят их в USART. Кажется логичным сделать функцию, которая занимается отправкой в USART строки посимвольно и использовать эту функцию во всех задачах - а нельзя! Более того, не смотря на то, что все задачи ПООЧЕРЕДНО формируют строки (ОС ведь кооперативная), каждая из задач должна иметь собственный промежуточный static-буфер для формирования своей строки - это ведь явно лишний расход памяти! При обычном подходе мы бы работали с локальным буфером в каждой функции, а локальный буфер, как известно, исчезал бы при выходе из функции... 

Наконец, архитектура этой ОС (под архитектурой я подразумеваю набор файлов-модулей и порядок работы с ними) такова, что почти все файлы инклюдятся друг в друга, что очень сильно нарушает модульный подход при программировании. Напомню, что модульный подход означает, в частности, возможность компиляции каждого Сишного файла отдельно от других сишных файтов. А в OSA системные сишники "вставляются" в один большой "общий" сишник, который затем и компилируется. В итоге я потратил немало времени, чтобы разобраться, как же настроить проект в Eclipse, чтобы можно было комфортно работать. Eclipse очень привык считать все сишники отдельными модулями проекта, и страстно стремится компилировать их отдельно.

В общем, знакомство с OSA было увлекательным, недолгим, интересным, но разочаровывающим.

Другие же ОС, найденные мной, были не кооперативными, а вытесняющими. Вытесняющие ОС имеют много преимуществ перед кооперативными, но один их недостаток сильно ограничивает применение на AVR: они весьма требовательны к объемам ОЗУ. Именно отсюда растут ноги у паникерских мнений, что AVR и "нормальная" RTOS - понятия несовместимые. И это на самом деле так, если мы говорим о микроконтроллерах младше (т.е. слабее) atmega32. Для справки: OSA вполне себе способна быть полезной не только на atmega8, но даже и на attiny2313! 

Но, к счастью для меня, не одной atmega32 ограничен мир AVR, и, кроме прочего, не ограничен и я сам. У меня в загашнике есть и at90can128, и даже atmega2560! И, спросил я себя, почему я должен переживать по поводу вытесняющей ОС при таких-то ресурсах? В at90can128 целых 4К ОЗУ, а уж flash-памяти по 8-битным меркам просто немеряно - 128К, а у монстра atmega2560 вдвое больше всего! Правда, если первый МК паять вполне комфортно (TQFP64), то второй без микроскопа уже сложно (TQFP100 c шагом выводов 0,5 мм). А тут еще у меня завалялась отладочная платка DVK90CAN1... Ну, вы поняли...

Итак, решающим теперь для меня стал поиск максимально простой операционки - чтобы мне по силам.

Их не так мало, как может показаться, но самой простой, по моему мнению, является YAVRTOS (скачать архив с исходниками, примерами и документацией можно по ссылке, но сайт автора уже не существует) - это практически такой же малоизвестный, как OSA, продукт примерно тех же времен (видимо, тогда было можно каждому мастерить свою собственную ОС с блекджеком и девушками низкой социальной ответственности).

Не смотря на инглиш, эта ось оказалась мне по силам: всего два файла и с полтора десятка системных функций! За один вечер легко расщелкал все необходимое для первого старта.

Плюсы этой RTOS перед OSA неоспоримы: не надо предпринимать практически никаких усилий по оформлению кода - пишется точно так же, как всегда, с локальными переменными, с вложенными вызовами функций и т.д. Разумеется, надо следить за общими ресурсами и блокировать к ним доступ, если необходимо - но это вообще всегда необходимо в многозадачных системах, и даже в ОSA частично так. Минусы, правда, тоже заметны: минимальное приложение, тупо мигающее двумя светодиодами (каждый в своей задаче) занимает почти 2К flash и порядка 400 байт ОЗУ. На просторах выбранного мной МК это даже и не заметно, но для atmega8 может быть близким к техническому пределу.

YAVRTOS написана на 99,9% на Си (только сохранение/восстановление контекста реализовано в виде ассемблерной вставки из трех десятков push-pop), всего два файла (task.c и task.h) - все это явный плюс в плане изучения и модификации под себя, если надо (и если хватает ума). Косвенным плюсом (или минусом, если продолжать переживать о ресурсах) является массовое применение malloc в ядре ОС, а значит, и в пользовательском приложении уже вполне оправдано динамическое распределение памяти. 

И мой энтузиазм просто на взлете от первого опыта! Например, вот как выглядит код задачи и вспомогательных функций для извлечения точного времени из GPS-приемника, подключенному к USART1, и вывода этих показаний на стандартный вывод (stdout, связанный с USART0):

const __flash char gps_msg[] = "RMC,";
#define GPS_MSG_SZ (sizeof(gps_msg)-1)

// поллинг 1 символа от GPS
static uint8_t get_char(void){
	while(bit_is_clear(UCSR1A, RXC)) wait_for_increment_of(&tick, 1);
	return UDR1;
}

// получение 1 цифры из символа
static uint8_t get_dig(void){
	return (get_char() - '0');
}

// собственно сама задача
void p2p_usart(void *p){
	uint8_t i;
	uint8_t h,m,s;
	while(1){
		i = 0;
      // ждем прихода сообщения с точным временем
		while((i < GPS_MSG_SZ) && (get_char() == gps_msg[i])) i++;
		if(i == GPS_MSG_SZ){
          // разбираем сообщение по символам
			h = get_dig()*10 + get_dig() + 3; // +3 - это часовой пояс
			h %= 24;
			m = get_dig()*10 + get_dig();
			s = get_dig()*10 + get_dig();
          // пропускаем сотые доли секунды
			get_char(); // '.'
			get_char(); // 's'
			get_char(); // 's'
			get_char(); // ','
          // проверка корректности времени и его вывод
			if(get_char() == 'A'){
				printf_P(PSTR("GPS Time %02d:%02d.%02d\r"),h,m,s);
			} else {
				printf_P(PSTR("No GPS, wait...  \r"));
			}
		}
	}
}

Как видите, код крайне "тупой", то есть прямолинейный, как лом: сплошные ожидания и никакой заботы о том, что параллельно должно что-то еще работать. В моем случае просто мигают 2 светодиода - один с длительностью импульса/паузы в 500 тиков, а второй в 501 (кстати, 1 тик = 1 мс, тактовая частота МК = 8 МГц). Но вместо светодиодов может быть еще две (или сколько надо) аналогично прямолинейно написанных задач, и можно быть уверенным, что все будет работать! Приведу данные по итогам компиляции проекта, чтобы продемонстрировать израсходованные ресурсы:

Цитата

AVR Memory Usage
----------------
Device: at90can128

Program:    5544 bytes (4.2% Full)
(.text + .data + .bootloader)

Data:         47 bytes (1.1% Full)
(.data + .bss + .noinit)

Не так уж и плохо, учитывая свободное применение printf. В активном режиме используется дополнительно 380 байт ОЗУ под стеки задач и ОС, т.е. примерно 10% всего объема - еще много остается.

Есть, кроме YAVRTOS, и другие альтернативы, например, FemtoOS, которая поддерживает даже (!!!) attiny25, и при этом тоже является вытесняющей операционкой. Но она существенно "богаче" в плане API, и разобраться с нею будет посложнее, т.к. документирована она явно менее детально. Возможно, я и её попробую на вкус...

И, скорее всего, теперь это станет для меня основным способом написания программ. RTOS позволяет сильно упростить себе жизнь. Имхо.

  • Одобряю 2


0 комментариев


Рекомендуемые комментарии

Нет комментариев для отображения

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас

  • Комментарии блога

    • На данной автоматике были неисправны один светодиод LD 2 и подстроечник Р1.
    • Запуск платы на столе.
      Устанавливаем перемычке согласно документации на Ваш котел. 1. Подключаем неоновые лампочки на 220В на разъемы J2 (треходовой кран), J3 (Насос), J1 выводы 1 и 2 (Запуск розжига.)  2. На разъем J1 выводы 5 и 6 подаем 220В, Сеть. 3. Восле подачи питания щелкнуло реле К2 и включился насос. Загорелся светодиод LD1 (DHW) 4. На разъем J4 выводы 5 и 6 (DHW.S) подключаем терморезистор на 10к. Температура бойлера.
      При нагревании данного датчика до 60 градусов происходит отключения реле К1 и К2.
      Напряжение на модуляционной катушке изчезает. 5. Реле К2 сразу отключилось. 6. Если сейчас установить перемычку Комнатного термостата, разъем J1 выводы 3 и 4 (ROOMST.), тогда заработает Насос и Треходовой клапан, так как напряжение на данный разъемы J2 и J3 будет ити через комнатный термостат, разумеется если он замкнутый. Так-же если установить резистор, постоянный, на 10к (от 8к2 до 10к) на разъем J5 выводы 3 и 4 (DHW SET), тогда включится реле К2. 7. Устанавливаю на разъем J5 выводы 3 и 4 (DHW SET), установка температуры бойлера постоянно поддерживает 60 градусов, резистор, постоянный, на 10к, см. докуменацию на объвязку платы. Плата реагирует только на его отсутствие, при его замыкании плата продолжает работать, как ни вчем не бывало. 8. Включилось реле К2, запустился насос. 9. Устанавливаю лампочку на 28В мощностью 4,8 Ватт на разъем J4 выводы 1 и 2 (MOD), модуляционная катушка. 10. Устанавливаю перемычку на разъем J4 выводы 7 и 8 (FLOW SW.), согласно документации на объвязку платы.
      Без этой перемычки запуск розжига не произойдет, так как входы ОУ буду привязаны к земле через резистор R33 и защитные диоды D12-14. 11. Через 15 сек. появилось на модулляционной катушке  напряжение 13,5В,(Пусковая мощность, ее можно регулировать резистором Р2). Произошел запуск платы на розжиг. Нагрев Бойлера. 12. Подключаю переменный резистор на 10к к разъему J5 выводы 1 и 2 (CH SET), температура системы отопления от +30 до 85 градусом, можно устанавливать.
      Какой в оригинале стоит я не знаю.
      При его обрыве автоматика не будет нагревать контур отопления. При возобновлении соединения автоматика может сразу не запуститься, это нормально, так как идет отсчет Антицикличности (Устанавливается JP2), по истечении времени автоматика запуститься.
      13. Подключаю терморезистор на 10к к разъемы J4 к выводам 3 и 4 (СN S.), датчик температуры отопления. Отключение автоматики при 1к1 и включение ее при 1к2. Если данный резистор будет в обрыви или в КЗ, розжиг не произойдет пока не будет устранена неисправность, реле К1 не включится. При КЗ датчика отключается реле К1 и снимается напряжение с модуляционной катушки. Если обрыв датчика, то отключается реле К1, но напряжение на модуляционной катушке остается.
      При нагревании данного датчика плавно уменьшается напряжение на модуляционной катушке и при достижении установленной температуры отключает реле К1 и обесточивается модуляционная катушка. НА данной автоматике этот датчик приоритетный, лубое его повреждение и плата не запустится на розжиг ни на каком из режимов. 14. После этого светодиод LD2 (BURNER ON), начал тускленько блымать, это не правильно светодиоды должны ярко гореть, он был в обрыве, хотя по истечению некоторого временем он все начинал работать. Ни когда бы не подумал, что может выйти из строя светодиод. Начал проверять транзисторы Q4 и Q6, полностью рабочие, ну думаю сдох электролит С4, выпаял проверил все отлично, но все-же решил поменять, но проблема так и осталась. Решил просто замкнуть Коллектор Q4 с Анодом D8, в обход светодиода и сразу все заработало, как положенно.
      Светодиод с падение 1,95В и емкостью 15pF, диаметром 5 мм., красного свечения/матовый. Целый вечер провозился с ним. Р2 настройка пусковой мощности. Если даный регулятор выкручен на максимум к реле, то при запуске розжига на модулятор не будет (Вернеее 0В) поступать в течении 15 сек. напряжение, потом оно плавно подымится до 14В и таким останется. Если регулятор выкрутить на минимум от реле, то на модулятор после запуска розжига поступит 10В. Если после розжига, когда щелкнуло реле К1, начать крутить Р2 в сторону реле, то напряжение можно уменьшать до 0В, но как только Вы дойдете до середины положения переменника, напряжение перескочить на 14В и не будет уже изменятся. На регулировку пусковой можности у Вас есть ровно 10-15 сек. после запуска розжига. Регуляторы Р1 и Р2 настраиваются единожды под мощность котла и больше не трогаются.
      Р1 можно настраивать только в режиме отопления, после 15сек. как произошел розжиг. Если крутить от реле то напряжение на модуляционной катушке будет рости от 0В до 14В. Если нагреть диоды, пальцем, D9, D12 то напряжение на модуляционую катушку сказу станет 21В. Так-же если установить перемычку LPG (JP1), то напряжение сразу подымится до 21В. У данной автоматике приоритет Бойлер, а не отопление. После того, как произошел розжиг платы (после 15 сек. от запуска) на выводе 9 U4.3 поставить щуп мультиметра, то напряжение покажет 10.6В и начнет медленно падать, так и должно быть, а то Вы можете подумать что конденсатор С9 не исправен. Данные измерения проводились с отключеным резистором на 10к DHW SET разъем J5 выводы 4 и 5. Чтобы себе облегчить измерения.
      В случае обрыва Регулятора температуры отопления, напряжение на U4.4 на выводе 13 в  упадет до 0 и на 14-выводе появится 10В. 
      После этого на выводе 13 плавно будет подыматся до 12В, как только подымется до 7.5В, напряжение на 14-выводе изменется с 10В на 0.
      Так-же жестко установится напряжение на микросхеме U4.3 вывод 8=10В, а вывод 9=0В. И сохранится до тех пор пока не будет восстановленно соединение переменника. Фото
       
       
    • 1. На схеме 6Н6П, а в тексте  6Н23П. Что используется реально ? Ну и как быть с внутренним сопротивлением триода ? Может катодный повторитель был бы лучше
    • @Олег Л хм, буду знать.
  • Записи блога