Перейти к содержанию

Поиск сообщества

Показаны результаты для тегов 'rtos'.

  • Поиск по тегам

    Введите теги через запятую.
  • Поиск по автору

Тип контента


Форумы

  • Вопрос-Ответ. Для начинающих
    • Песочница (Q&A)
    • Дайте схему!
    • Школьникам и студентам
    • Начинающим
    • Паяльник TV
    • Обсуждение материалов с сайта
  • Радиоэлектроника для профессионалов
    • Автомобильная электроника
    • Питание
    • Ремонт
    • Системы охраны и наблюдения. Личная безопасность
    • Роботы и модели на ДУ-управлении
    • Световые эффекты и LED
    • Самодельные устройства к компьютеру
    • Программное обеспечение
    • Металлоискатели
    • Автоматика
    • Электрика
    • Промышленная электроника
    • Измерительная техника
    • Мастерская радиолюбителя
    • КВ и УКВ радиосвязь
    • Радиопередатчики
    • Сотовая связь
    • Спутниковое ТВ
    • Телефония и фрикинг
    • Высокое напряжение
    • Идеи и технологии будущего
    • Справочная радиоэлементов
    • Литература
    • Схемотехника для профессионалов
    • Разное
  • Аудио
    • FAQ, Технологии и компоненты
    • Для начинающих
    • Источники звука
    • Предусилители, темброблоки, фильтры
    • Питание аудио аппаратуры
    • Усилители мощности
    • Акустические системы
    • Авто-аудио
    • Ламповая техника
    • Гитарное оборудование
    • Прочее
  • Микроконтроллеры
    • МК для начинающих
    • Arduino, ESP32, ESP8266, Raspberry Pi
    • AVR
    • STM32
    • PIC
    • ПЛИС
    • Другие микроконтроллеры и семейства
    • Алгоритмы
    • Программаторы и отладочные модули
    • Периферия и внешние устройства
    • Разное
  • Товары и услуги
    • Коммерческие предложения
    • Продам-Отдам, Услуги
    • Куплю
    • Уголок потребителя
    • Вакансии и разовая работа
    • Наши обзоры и тесты
  • Разное
    • Курилка
    • Сайт Паяльник и форум
    • FAQ (Архив)
    • Технический английский (English)
    • Личные блоги
    • Наши проекты для Android и Web
    • Корзина
    • Конкурсы сайта с призами
    • Вопросы с VK
  • Переделки ATX->ЛБП
  • Переделки разные темы
  • Киловольты юмора Юмор в youtube

Блоги

  • Твори, выдумывай, пробуй.
  • fant's блог
  • Ток покоя
  • Где купить велпатасвир, epclusa, velpanat, velasof, софосбувир в России по лучшей цене.
  • Китайские бренды видеокамер
  • Создание Маленькой Мастерской
  • Блог администрации
  • STEN50's блог
  • Изучение, наладка, исследование
  • MiSol62's блог
  • короткие записки по ходу дела
  • Программирование AVR и PIC блог
  • Стабилизированный выпрямитель тока ТЕС 12-3-НТ
  • Блог getshket
  • ТНПА
  • welder's блог
  • blog cheloveka loshadi
  • OPeX3's блог
  • Подводная робототехника
  • Сабвуфер и акустика.
  • Радиоуправляемая машина
  • Консультация психолога сексолога онлайн, психолог онлайн
  • Nokian блог
  • Оповещения Dermabellix Scam !! Не покупайте это !!!
  • Cheerful Boss' блог
  • Cheerful Boss' блог
  • VLAD1996B's блог
  • "Коллективное увеличение продаж"
  • Dudok's блог
  • "Коллективное увеличение продаж"
  • Goluboglazyi's блог
  • Прибор определяющий электролитический конденсатор на работоспособность.
  • Mosfet@'s блог
  • mazzi's блог
  • Лучшие компьютерные игры 2017
  • Marchenkokerya's блог
  • Заметки начинаущего аудиофила
  • Почти бесполезные проги
  • Светлый блог.
  • дядюшка Филин's блог
  • Дневники нуба
  • satyrn's блог
  • Люк. В погреб.
  • Фильм Дом Солнца
  • Светодиодная лента B-LED 2835-120 W белая негерметичная
  • Само-Реплицируещиеся Производственные Системы
  • Блог от Eknous
  • РВС's блог
  • Den_R's blog
  • РВС's блог
  • Чтото крутое и про криворукость
  • ekadom's блог
  • Проектирование любых чертежей
  • Lisovic's блог
  • Блог уже не юного радиогубителя
  • денди
  • eHouse
  • zaregan's блог
  • Схемотехника УНЧ с низковольтным питанием на примере приёмников фирмы Grundig
  • То, что в руки попало.
  • Блок питания водородного генератора и все что с ним связано
  • slava_va@mail.ru's блог
  • Блог alex123al97
  • slava_va@mail.ru's блог
  • параленое соединение КРЕНок или как сделать стабилизатор напряжения 24-12в
  • Свободная генерация Андрея Мельниченко
  • реобас
  • Модернизации системы впрыска на 555
  • помощь
  • Копии схем и печатных плат устройств попавшие ко мне
  • MBM75's блог
  • Буду
  • lagutai's блог
  • Мои проекты.
  • lagutai's блог
  • Трудовик
  • vOVK@'s блог
  • токарь-радиолюбитель
  • azlk3000's блог
  • Коллизия сингулярности
  • SmallAlex's блог
  • Вопрос по Цифровому усилителю мощности звука 2x12 Вт YDA138-E
  • bebulo's блог
  • Простейший макет станка термо-вакуумной формовки
  • Блог им. pryanic
  • peratronika
  • Zer's блог
  • MEDBEDb's
  • Гнездо кукушки
  • hiMiческий блог
  • luna_kamen's блог
  • Изучаем USI на основе сверхэкономичного прототипа
  • Алекс-Юстасу
  • SUBWOOFER.RU
  • kot sansher's блог
  • Поделки стареющего пионера
  • доброжелатель2's блог
  • Grig96. Полезные заметки.
  • Attiny 0-ой и 1-ой серии (Attiny817, 1614 и прочие)
  • pavlo's блог
  • MSP430FR
  • viper2's блог
  • Моя Электро Чинильня
  • Selyk's блог
  • VoltServis.ru
  • kpush's блог
  • OM3 на новых платах.
  • конни's блог
  • Электронный экстазёр "MASHKA".
  • ptimai's блог
  • noc functionalities
  • Sun kapitane's blog
  • ODEON AV-500
  • Sun kapitane's blog
  • Логика на транзисторах,диодах, счетние тригери на транзисторах
  • AleksandrBulchuck's блог
  • Качественные окна от производителя
  • KRALEX's блог
  • Javaman's projects
  • SeVeR36's блог
  • 3232
  • Пять копеек.
  • Az@t's блог
  • Индукционный нагрев
  • Схемы разных устройств
  • Кардшаринг SAT ТВ блог
  • PENTAGRID SAYS
  • Ещо раз о "Кощее 5И"
  • Игровые автоматы на официальном сайте
  • коллекционер
  • дямон's блог
  • Ламповый усилитель и акустика для озвучки семейных мероприятий
  • дямон's блог
  • tiosmutoutrup1971
  • Светомузыкальная установка для новачков
  • Лучшие игры для ПК скачать бесплатно
  • sqait's блог
  • Блокнотик
  • Gubernator's блог
  • Записки электрика
  • Полстакана
  • Vrednyuka
  • Интегральные микросхемы
  • grigorik's блог
  • Интегральные микросхемы
  • VMWare удобство и безопастность
  • Профсоюз обычных пользователей
  • rtfcnf's блог
  • Гидроэнергетика в России: отечественные гидроэлектростанции, типы и характеристики
  • VMWare удобство и безопастность
  • Лайфхаки от Кати
  • Kinh chong anh sang xanh gia re
  • ukabumaga's блог
  • АО "Диполь Технологии"
  • artos5's блог
  • блог
  • Kraftwerk's блог
  • 1
  • Kraftwerk's блог
  • Как выбрать точечный светильник?
  • мастерская ky3ne4ik'а
  • Работа с микроконтроллером Atmega8
  • Aronsky
  • Игорь Камский
  • Диммеры
  • 5В = 1,5+3
  • vitiv' блог
  • Ремонт цифровой панели прибора тойоты марк 100. Замена транзистора 36 ( SOT- 23 )PNP
  • Все СРО России
  • 300writers
  • Металлоискатель Tracker FM-1D3
  • Былое
  • Создание монстра "Blaster 8920"
  • 2Smart Cloud Blog
  • EmmGold's блог
  • 2Smart Cloud Blog
  • ivan15961596's блог
  • Кумир у-001
  • ivan15961596's блог
  • My blog
  • Интернет радио в машину
  • SamON
  • Помогите люди добрые
  • AI
  • Помогите подключить маяк 231 стерео.
  • Гаусс-пушки
  • Название
  • 7400's блог
  • Как я собирал свой первый импульсный источник питания
  • Віталік Приходько_130349's блог
  • Lithium ECAD - российская САПР печатных плат
  • Евгений Малюта's блог
  • ПИшу свои мысли
  • werekpro
  • Venera Electronica
  • afurgon's блог
  • Выбросьте это в парашу!
  • odaplus' блог
  • Zvik's блог
  • Smart overload protection power amplifier «Zita (Z) ThermalTrak™»
  • радиоэлектоника
  • BoBka777's блог
  • МиУЗР - Модернизация и Усовершенствование Звуковой Радиотехники .
  • aleksey9900's блог
  • Лабораторная блок питания
  • Нашел статью о пайке проводов к светодиодов
  • Китайский городовой
  • Костик0's блог
  • УФ лампа для маникюра SK-818
  • 8 Contrasts Between Web Servers and Application Servers
  • Конденсатор
  • Новости, обзоры и другая полезная информация от ИМ "Радиодар"
  • Цветомузыка
  • OPeX3's блог
  • Sem2012's блог
  • это не хлам – это часть моей жизни
  • Контроллер на базе ПК (OS Win LTSC)
  • OdiS' блог
  • Хитрости строителя
  • aleksfil's блог
  • Color Preamp - предусилитель на лампах 12AU7
  • Проблема с зарядкой литиевого аккумулятора для шуруповерта 21 вольт
  • EmmGold's блог; AVR
  • Микроэлектроника
  • З
  • CH32V
  • Блог Плотникова Ильи
  • Бесплатные радиодетали с Алиэкспресс
  • Повышение качества и снижение временных затрат при испытаниях электронных компонентов с помощью отечественного испытательного оборудования
  • Источники питания MEAN WELL
  • Жизнь и рыбалка
  • yureika's блог
  • Глушитель спутникогого интернета
  • Всякая всячина
  • Для начинающих
  • Ignite your senses with the grace and allure of female escorts near Laguna Niguel
  • Fumitox's блог
  • Наш-RXT6 топ-10 на январь 2023: Лучшие сайты онлайн казино в России
  • Лицензионные казино онлайн в 2024 году на реальные деньги
  • Самоделки блог
  • Домашняя автоматика
  • Интересное и полезное
  • Ремонт Амфитон 35у-101с
  • ульян's блог
  • Свет в грузовой газели
  • Блок питания 0-12В для начинающих
  • Dimko's блог
  • Иван Самец's блог
  • SolomonVR's блог
  • gendzz's блог
  • fleh138's блог
  • Электроника forever!
  • aleksejhozhenets' блог
  • aleksejhozhenets' блог
  • diserver блог
  • aleksey290476 блог
  • ВАРГ's блог
  • Люстра Чижевского
  • wanes101's блог
  • voldemar2009's блог
  • Jana's блог
  • Jana's блог
  • Рена Искужин's блог
  • abduraxman7's блог
  • Kuzumba's блог
  • Самопальник
  • заработок через интернет на запчасти!!!
  • electric.kiev's блог
  • lolo's блог
  • leravalera's блог
  • ideomatic's блог
  • приглашаем на работу инженера-радиоэлектронщика
  • FREEMAN_77's блог
  • Блог автоэлектрика
  • Блог начинающего электронщика
  • Dersu's блог
  • Электроэнергия и её экономия!
  • Электроэнергия и её экономия!
  • Семён Ковалёв's блог
  • piligrim-666's блог
  • помогите с партотивной калонкой
  • помогите с партотивной калонкой
  • Музыка в стене.
  • m-a-r-i-k-a's блог
  • cosmos44's блог
  • oyama14's блог
  • блог Виталика!
  • ciornii's блог
  • Великий и Ужастный блог
  • Denis__Ricov's блог
  • Universal12's блог
  • Sprut's блог
  • Alexeyslav's блог
  • cosmosemo's блог
  • Заметки радиолюбителя
  • Falconist. Мемуары
  • Блог MillyVolt
  • усилитель импульсов
  • Panasonic sa-ak 18
  • Простое радиоуправление из того, что было.
  • 35house
  • Блог Радиочайника
  • Блохи iiiytnik'a
  • Хороший сервис- Бяка
  • Аудиолаборатория "Философия Звука"
  • ОколоCADовое
  • Блог KVLADS
  • Короп блог
  • Автоматизация котла Protherm MTV
  • Бложиг Касянича
  • Обо всём
  • Эксперимент
  • No electronics
  • ПРИРОДА СВЕТА и ЕГО ВОЗМОЖНОСТИ
  • Генератор на xr2206
  • HTPOWLASER
  • Когда-то были очень популярны у радиолюбителей
  • AVR - микроконтроллеры
  • Микроконтроллер
  • Самодельный автосимулятор
  • Интернет-магазин керамической плитки «Боярская Плитка»
  • Разработка электронных метрических мишеней IPSC для мягкой пневматики (страйкбол)
  • ,

Поиск результатов в...

Поиск контента, содержащего...


Дата создания

  • Начало

    Конец


Дата обновления

  • Начало

    Конец


Фильтр по количеству...

Регистрация

  • Начало

    Конец


Группа


Skype


ICQ


Интересы


Город


Сфера радиоэлектроники


Оборудование

Найдено: 4 результата

  1. ARV

    Минималистическая RTOS

    В моём гнезде прибавление. В смысле, алгоритм вылупился. Не скажу, чтобы исключительно новый, вряд ли гениальный, но, мне кажется, заслуживающий внимания. Преамбула. Что мы понимаем под понятием "таймер"? Ну, не в смысле задатчика времени варки яиц всмятку, а в программировании? Это некая функция, которая "сама по себе" выполняется через заданные интервалы времени. Или же чуть иначе: функция выполнится через заданный интервал времени однократно. Наконец, и третья интерпретация тоже имеет место быть: таймер - это некий счетчик, который сам по себе считает, а мы можем время от времени поглядывать на его значение и принимать какие-то решения. Амбула. Как обычно реализуются таймеры в микроконтроллерном программировании? Безусловно, наиболее удобно - с задействованием аппаратных таймеров-счетчиков и прерываний от них. Существует вариант реализации и без этого, но сие удовольствие надо оставить пациентам более строгого режима лечения. С прерыванием от аппаратного таймера все понятно, но их количество (аппаратных счетчиков я имею ввиду) ограничено. И поэтому в общем случае используется модель "программных" таймеров на основе одного прерывания от аппаратного. Вот как, например, выглядит один из простейших вариантов: #define TIMER_CNT 5 static volatile uint8_t timer[TIMER_CNT]; // обработчик прерывания от таймера, вызывается каждую миллисекунду ISR(TIMER_vect){ for(uint8_t i=0; i<TIMER_CNT; i++){ if(timer[i]) timer[i]--; } } // вот так можно ограничить длительность цикла интервалом времени в 100 мс timer[0] = 100; while(timer[0]){ // что-то длительное if(какое-то-условие-неизвестно-когда-возникающее) break; } if(!timer[0]){ // из цикла вышли по таймауту } else { // из цикла вышли по условию } Вроде бы, все просто и понятно. И даже удобно. Я сам 100 раз так делал! Но есть и неприятности. Во-первых, надо постоянно следить за тем, какой "номер" таймера задействован в том или ином участке кода. Когда таймеров два или три - проблемы нет, а когда в разных функциях в разных модлях их по нескольку штук, можно и запутаться. Во-вторых, массив timer должен быть глобальным, что само по себе не страшно, но как-то не комильфо... В-третьих, сделать таймер не однобайтным, а двухбайтным, чтобы иметь возможность отсчитывать большие интервалы времени, уже так красиво не выйдет - следует обеспечивать атомарный доступ к значению счетчика... И главное: этот подход реализует только последний вариант таймера из числа рассмотренных в преамбуле, т.е. гибкость его ограничена. Путем нехитрых манипуляций можно заметно улучшить ситуацию. Хотя и несколько усложнив код: #include <util/atomic.h> #define TIMER_CNT 5 typedef uint8_t (*tmr_func)(void); typedef struct{ uint16_t counter; uint16_t duration; tmr_func func; } timer_t; static volatile timer_t timer[TIMER_CNT]; ISR(TIMER_vect){ for(uint8_t i=0; i<TIMER_CNT; i++){ if(timer[i].counter){ timer[i].counter--; if((timer[i].counter == 0) && (timer[i].func != NULL)) if(timer[i].func()) timer[i].counter = timer[i].duration; } } } void timer_start(uint8_t t, uint16_t duration, tmr_func f){ ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ timer[t].counter = duration; timer[t].duration = duration; timer[t].func = f; } } uint8_t timer_out(uint8_t t){ ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ return timer[t].counter == 0; } } // вот так можно заставить светодиоды мигать с разной частотой static uint8_t blink_led1(void){ PORTB ^= 1<<0; // светодиод на нулевой линии порта return 1; // для перезапуска функции } static uint8_t blink_led2(void){ PORTB ^= 1<<1; // светодиод на первой линии порта return 1; // для перезапуска функции } timer_start(0, 500, blink_led1); timer_start(0, 300, blink_led2); while(1){ // тут что-то делаем, а светодиоды тем временем мигают каждый по-своему } Разумеется, здесь уже и атомарность доступа к значению счетчика реализована (ценой вызова отдельной функции), и все вариаты из преамбулы тоже. Надеюсь, очевидно, что если переданная в таймер функция вернет 0, она больше не будет вызываться после того, как таймер истечет? Чем вам не RTOS в минимальном виде? Главное условие в применимости такого подхода - предельно быстрое исполнение таймерной функции. Но при использовании автоматов состояний этим способом можно решать большой спектр практических задач. Но проблема с "учетом" таймеров осталась. Да и если вы вдруг станете нуждаться в бОльшем количестве таймеров, чем TIMER_CNT, вам придется эту константу менять. И в случае, если вы модифицируете старый проект, и старое количество таймеров вам не нужно, то тоже надо это вручную менять. Мелочь, а неприятно. Хорошо было бы, если бы в любом месте кода описал свой отдельный static (т.е. невидимый другим) таймер, и пользуешься им. Не нужен -удалил его описание, и не пользуешься. А "система" сама заботится о том, чтобы таймер "тикал" или не "тикал", если не нужен. И обычно для этого используют возможности RTOS. Хотя... Хотя максимальное количество выделяемых RTOS таймеров позапросу пользователя тоже ограничено значением какой-то константы... Но и из этого исхода есть выход! Только об этом в следующий раз. Т.е. о самом главном я и не сказал...
  2. Нельзя полюбить RTOS и избавиться от волнений. Любовь - это штука, волнующая кровь по определению, так что... Стихли первые эмоции на основе эйфории, появилась тревога. Отладка RTOS - та еще песня! Никогда не знаешь точно, что и как происходит не так, если оно не так. Когда одна задача посылает команды по USART в устройство, другая задача принимает от него ответы, а третья занимается управлением, понять, почему третья задача работает не правильно, очень не просто. Непросто потому, что запросы и ответы разделены во времени и в пространстве, и если управляющая задача ждет готовности, надо выснить, из-за неотправленного запроса или же из-за не полученного ответа. А если на все это накладывается еще и не совсем разумное поведение устройства, то вообще все становится загадочно и сташно. Пытаюсь совместить модуль плейера MP3-файлов с RTOS. Написал две функции-задачи для приема ответов и отправки команд. Вроде бы все правильно, все корректно. /** * задача приема сообщений от других задач и выдачи команд в плейер * @param p не используется */ static void control_task(void *p){ static int16_t ver; static player_msg_t *msg; ver = get_current_mbox_version(&player_mailbox); while(1){ wait_for_increment_of(&tick, 10); // обработка сообщений if((msg = read_mbox_min_version(&player_mailbox, &ver)) != NULL){ // новое в ящике // разбор сообщения switch(msg->cmd){ case PCMD_RESET: // сброс status = P_NOT_READY; mp3_cmd(MP3_CMD_RESET,0,0); break; case PCMD_SET_VOL: // громкость mp3_cmd(MP3_CMD_SET_VOL, 0, msg->bparam > MP3_MAX_VOL ? MP3_MAX_VOL : msg->bparam); break; case PCMD_STOP: // остановка воспроизведения if(status != P_READY){ mp3_cmd(MP3_CMD_STOP, 0, 0); status = P_READY; } break; case PCMD_S_MSG_QUEUE: // воспроизвести сообщение с ожиданием while((status != P_READY)) yield(); //continue; case PCMD_S_MSG_NOW: // немедленно воспроизвести сообщение // если папка не указана - ищем трек в корне if(msg->bparam) mp3_cmd(MP3_CMD_PLAY_FOLDER, msg->bparam, msg->wparam); else mp3_cmd(MP3_CMD_PLAY, msg->wparam >> 8, msg->wparam & 0xFF); status = P_PLAY; break; case PCMD_L_MSG_QUEUE: // воспроизвести трек из "большой" папки с ожиданием while(status != P_READY) yield(); //continue; case PCMD_L_MSG_NOW: // воспроизвести из "большой" папки немедленно status = P_PLAY; mp3_cmd(MP3_CMD_PLAY_3000, ((msg->bparam & 0x0F) << 4) | ((msg->wparam>>8) & 0x0F),msg->wparam & 0xFF); break; case PCMD_USER: // любая иная команда mp3_cmd(msg->bparam, msg->wparam>>8, msg->wparam & 0xFF); break; } } release_mbox_read(); ver++; } } #include <util/delay.h> /** * Задача приема сообщений от модуля плейера. Осуществляет управление статусом * плейера в зависимости от принятых команд. * @param p не используется */ static void reseive_task(void *p){ static mp3_buf_t packet; static uint8_t old; static uint8_t d; while(1){ // обработка ответов модуля d = 0; // ждем время, достаточное для приема пакета (10 мс) wait_for_increment_of(&tick,10); // ищем стартовый байт if(data_reseived()) d = data_get(); if(d != MP3_START_BYTE) continue; // считываем пакет for(uint8_t i=0; i < (MP3_PACKET_SZ-1); i++){ packet.bytes[i] = d; while(!data_reseived()) to_os(); d = data_get(); } // обрабатываем пакет switch(packet.command){ case MP3_ERROR: // ошибка mprintf("\nError %02X st=%d", packet.param_lo, status); if(status == P_PLAY) status = P_READY; break; case MP3_STAY_USB:// конец воспроизведения case MP3_STAY_SD: // STAY приходит дважды!!!, один раз надо игнорировать //dbg_packet(&packet); if(old != packet.param_lo) status = P_READY; old = packet.param_lo; break; case MP3_DEV_STATUS: // инициализация закончена if((status == P_NOT_READY) && (packet.param_lo == DEV_SD)) status = P_READY; break; case MP3_PLUG_IN: // подключение источника status = P_READY; break; case MP3_PULL_OUT: // отключение источника status = P_NOT_READY; break; default: // все прочие пакеты break; } } } Проверяю функционирование при помощи простой функции, "говорящей время": void say_time(uint8_t h, uint8_t m){ player_send_msg(PCMD_S_MSG_QUEUE, FOLDER_MSG, SAY_TIME); if(h==0) h=24; if(m==0) m=60; player_send_msg(PCMD_S_MSG_QUEUE, FOLDER_HOUR, h); player_send_msg(PCMD_S_MSG_QUEUE, FOLDER_MIN, m); } Вызываю эту функцию каждые 5 секунд, имитируя минуты, в отдельной задаче. В итоге система говорит время некоторое количество раз, после чего состояние модуля становится P_PLAY и не исчезает. Если посмотреть на код функций управления и приема ответов, то можно понять, что такая ситуация возможна, если модуль не ответил о том, что файл проигран до конца. НО ОН ОТВЕЧАЕТ! И отвечает 2 раза на каждый файл, о чем в документации нет ни слова! Что происходит, как выяснить? Самое удивительное, что если снять ремарку с отладочного вывода содержимого принятого ответа, то все начинает работать! И в терминале я вижу, что на каждый файл приходит подтверждение окончания воспроизведения... И, значит, состояние P_PLAY обязано сбрасываться в P_READY! Но если отладочный вывод в терминал заремарить - рано или поздно все виснет. А я-то думал, волноваться больше не придется...
  3. Вот вы говорите: 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 МГц). Но вместо светодиодов может быть еще две (или сколько надо) аналогично прямолинейно написанных задач, и можно быть уверенным, что все будет работать! Приведу данные по итогам компиляции проекта, чтобы продемонстрировать израсходованные ресурсы: Не так уж и плохо, учитывая свободное применение printf. В активном режиме используется дополнительно 380 байт ОЗУ под стеки задач и ОС, т.е. примерно 10% всего объема - еще много остается. Есть, кроме YAVRTOS, и другие альтернативы, например, FemtoOS, которая поддерживает даже (!!!) attiny25, и при этом тоже является вытесняющей операционкой. Но она существенно "богаче" в плане API, и разобраться с нею будет посложнее, т.к. документирована она явно менее детально. Возможно, я и её попробую на вкус... И, скорее всего, теперь это станет для меня основным способом написания программ. RTOS позволяет сильно упростить себе жизнь. Имхо.
  4. Вливаюсь в среду программирования MBED OS с платой STM32F429I-DISC1 и вот что заметил: 1) Почему-то PWM у меня нормально заработал только на ножке PF_6. Я перебрал, конечно, не все порты, которые поддерживают работу с PWM, но другие, которые я попробовал, не заработали. 2) Пытался сконфигурировать некоторые порты в качестве цифрового выходи и тоже фигушки. Нормально заработали только те, что подключены к зеленому и красному светодиодам (PG_13 и PG_14). На некоторых ножках был какой-то неведомый мне меандр, какие-то не захотели переходить в низкоомное состояние. В качестве базы я использовал код DISCO-F429ZI_LCDTS_demo (это из примеров по этой плате с работой ЖК индикатора и тачскрина). Что может быть не так? Может быть какие-нибудь библиотеки, подключаемые при работе тачскрина и/или дисплея занимают большую часть портов и не позволяют их использовать по усмотрению программиста? Или я еще что-то не понимаю в архитектуре ARM? (Сам я прихожу из AVR-ов)
×
×
  • Создать...