Полиморфный квайн

Данный квайн печатает себя в зашифрованном виде. Каждый раз с новым ключом для декодирования. Шифр простой — берём код символа и прибавляем к нему ключ. Далее ключ увеличивается на единицу. И так бесконечно. Пока не кончатся числа. 🙂

Нулевой пациент:

exec(str().join(chr(c) for c in [107, 61, 49, 59, 101, 61, 39, 101, 120, 101, 99, 40, 115, 116, 114, 40, 41, 46, 106, 111, 105, 110, 40, 99, 104, 114, 40, 99, 45, 41, 32, 102, 111, 114, 32, 99, 32, 105, 110, 32, 41, 41, 39, 59, 115, 61, 39, 107, 61, 59, 101, 61, 59, 115, 61, 59, 112, 114, 105, 110, 116, 40, 101, 91, 58, 50, 50, 93, 43, 115, 116, 114, 40, 107, 41, 43, 101, 91, 50, 50, 58, 45, 50, 93, 43, 114, 101, 112, 114, 40, 91, 111, 114, 100, 40, 99, 41, 43, 107, 32, 102, 111, 114, 32, 99, 32, 105, 110, 32, 115, 91, 58, 50, 93, 43, 115, 116, 114, 40, 107, 43, 49, 41, 43, 115, 91, 50, 58, 53, 93, 43, 114, 101, 112, 114, 40, 101, 41, 43, 115, 91, 53, 58, 56, 93, 43, 114, 101, 112, 114, 40, 115, 41, 43, 115, 91, 56, 58, 93, 93, 41, 43, 101, 91, 45, 50, 58, 93, 41, 39, 59, 112, 114, 105, 110, 116, 40, 101, 91, 58, 50, 50, 93, 43, 115, 116, 114, 40, 107, 41, 43, 101, 91, 50, 50, 58, 45, 50, 93, 43, 114, 101, 112, 114, 40, 91, 111, 114, 100, 40, 99, 41, 43, 107, 32, 102, 111, 114, 32, 99, 32, 105, 110, 32, 115, 91, 58, 50, 93, 43, 115, 116, 114, 40, 107, 43, 49, 41, 43, 115, 91, 50, 58, 53, 93, 43, 114, 101, 112, 114, 40, 101, 41, 43, 115, 91, 53, 58, 56, 93, 43, 114, 101, 112, 114, 40, 115, 41, 43, 115, 91, 56, 58, 93, 93, 41, 43, 101, 91, 45, 50, 58, 93, 41]))

Не сложно переделать его для работы с файлами, и тогда может выйти забавный полиморфный вирус.

Итерации разработки:

  1. q="'";s='q="";s=;print(s[:3]+q+s[3:7]+q+s+q+s[7:])';print(s[:3]+q+s[3:7]+q+s+q+s[7:])

    базовый квайн (источник)

  2. s='s=;print(s[:2]+repr(s)+s[2:])';print(s[:2]+repr(s)+s[2:])

    избавления от переменной q

  3. exec('s=\'s=;print("exec("+repr(s[:2]+repr(s)+s[2:])+")")\';print("exec("+repr(s[:2]+repr(s)+s[2:])+")")')

    использование exec

  4. exec("e='exec()';s='e=;s=;print(e[:-1]+repr(s[:2]+repr(e)+s[2:5]+repr(s)+s[5:])+e[-1:])';print(e[:-1]+repr(s[:2]+repr(e)+s[2:5]+repr(s)+s[5:])+e[-1:])")

    вариант без экранирования

  5. e='exec(str().join(chr(c) for c in ))';s='e=;s=;print(e[:-2]+repr([ord(c) for c in s[:2]+repr(e)+s[2:5]+repr(s)+s[5:]])+e[-2:])';print(e[:-2]+repr([ord(c) for c in s[:2]+repr(e)+s[2:5]+repr(s)+s[5:]])+e[-2:])

    добавлено шифрование

  6. k=0;e='exec(str().join(chr(c-) for c in ))';s='k=;e=;s=;print(e[:22]+str(k)+e[22:-2]+repr([ord(c)+k for c in s[:2]+str(k+1)+s[2:5]+repr(e)+s[5:8]+repr(s)+s[8:]])+e[-2:])';print(e[:22]+str(k)+e[22:-2]+repr([ord(c)+k for c in s[:2]+str(k+1)+s[2:5]+repr(e)+s[5:8]+repr(s)+s[8:]])+e[-2:])

    конечный вариант с добавлением ключа


ссылка на оригинал статьи https://habr.com/post/424939/

Digital-мероприятия в Москве c 1 по 7 октября

Подборка ключевых мероприятий в Москве на неделю.

image

EdCrunch

  • 01 октября (понедельник) — 02 октября (вторник)
  • Краснопресненская наб 12
  • 14 900 р.
  • EdCrunch — это одна из крупнейших в Европе конференций в области новых образовательных технологий.

Открытая конференция для бизнеса и ИТ | Accelerate 2018

  • 02 октября (вторник)
  • Краснопресненская наб 14
  • бесплатно
  • Первые лица, топ-менеджеры и эксперты крупнейших организаций России ― ЕВРАЗ, Почта России, IBS, Eqvanta, HeadHunter, АФК Система, Tele2, Банк Центр-инвест, IDS Borjomi Russia, Банк Возрождение, CarPrice, Лукойл-Гарант, Цвет Диванов, CulinaryOn, «МегаФон Таджикистан» и других, ― соберутся в московском Экспоцентре, чтобы поделиться опытом ускорения бизнеса в цифровую эпоху.

День открытых дверей по программам игровой индустрии ВШБИ

  • 03 октября (среда)
  • Трифоновcкая 57с1
  • бесплатно
  • 3 октября 2018 года приглашаем вас на день открытых дверей, где расскажем о программах профессиональной переподготовки «Менеджмент игровых проектов», который запускается в ноябре 2018 года, и «Маркетинг компьютерных и мобильных игр», который стартует в феврале 2019. Это уже 8-й набор слушателей в Высшую школу бизнес-информатики НИУ ВШЭ на программы по игровой индустрии. За 4 года в ВШБИ прошли обучение созданию и продвижению игр более 200 человек, большинство из которых в данный момент успешно работают в крупных игровых компаниях России или создают свои собственные проекты. От обучения можно ожидать уникальный опыт и системные знания по созданию компьютерных и мобильных игр, разработку собственной игры во время обучения, учебу и работу над своим проектом в команде единомышленников, доступ к уникальному учебному материалу и неформальное общение с ведущими представителями игровой индустрии.

Супергерои вашего бизнеса: как управлять кадрами и digital-подрядчиками

  • 03 октября (среда)
  • Ленинградский проспект 39, стр. 79
  • бесплатно
  • Как понять, что пришло время обучать свой штат? Где искать компетентных сотрудников? А может быть, стоит позвать на помощь стороннюю команду? С этими вопросами рано или поздно сталкивается любой бизнес.

QIWI Кухня: ResearchOps, исследования и Impact mapping

  • 04 октября (четверг)
  • Микрорайон северное чертаново 1а к 1
  • бесплатно
  • На этот раз много тем про новое и неизведанное: ResearchOps, Impact mapping и исследования для дизайнеров продуктов.

Fuckup Nights Vol. XIV

  • 04 октября (четверг)
  • Берсеневская набережная 6/3
  • 500 р.
  • Fuckup Nights – это международное движение, возникшее в Мексике в 2012 году, самым неожиданным образом. Однажды трое приятелей в баре выпили достаточно текилы, чтобы признаться в своих неудачах. Выслушав ошибки друг друга, они поняли, что это полезно и решили повторить, пригласив своих друзей. С каждым разом слушателей было всё больше, пришлось рассказывать о своих неудачах со сцены. Так движение Fuckup Nights начало свое путешествие по миру.

Digital Transformation Journey

  • 04 октября (четверг)
  • Google, Балчуг 7
  • бесплатно
  • Цифровые технологии изменили мир и рынок предоставляемых услуг. Ваши решения должны не просто учитывать революцию API, но использовать ее преимущества в каждом бизнес-процессе, который влияет на достижение целей компании.

G8

  • 04 октября (четверг) — 05 октября (пятница)
  • Б. Новодмитровская 36
  • от 1 900 р.
  • Ключевые российские школы высшего и дополнительного офлайн и онлайн образования, которые готовят специалистов в сфере креативных индустрий и креативного мышления, впервые соберутся, чтобы продемонстрировать свои возможности, сильные стороны и проекты студентов.

Frontend Conf

  • 04 октября (четверг) — 05 октября (пятница)
  • 1-й Зачатьевский пер., 4
  • от 12 000 р.
  • Профессиональная конференция Frontend Conf посвящена всем аспектам разработки клиентской части веб-проектов: дизайн, юзабилити, вёрстка, JavaScript, веб-медиа и так далее.

Анализ данных и машинное обучение для менеджеров продуктов

  • 05 октября (пятница)
  • Трифоновcкая 57с1
  • бесплатно
  • Data Driven Product Management – основа работы любого менеджера продукта. Источники данных, воронки, метрики, digital-аналитика, машинное обучение, – инструменты, которые помогают регулярно измерять практически любой аспект бизнеса и принимать решения на основе данных.

VR/AR-Hackathon

  • 05 октября (пятница) — 07 октября (воскресенье)
  • ВДНХ
  • бесплатно
  • Хакатон соберет более 150 разработчиков и менторов в сфере VR- и AR-технологий.

Gaming and Entertainment Startups

  • 05 октября (пятница)
  • Староконюшенный переулок 43
  • бесплатно
  • Присоединяйтесь к первой встречи медиа акселератора 713.media! Кому интересно куда движется мир развлечений, что из технологий будет в нем завтра, как игры и кино сращиваются уже сегодня!

Tutu PHP Meetup#2

  • 06 октября (суббота)
  • 1-й Нагатинский проезд 10с1
  • бесплатно
  • Мы снова приглашаем всех интересующихся php backend-разработкой провести субботу с пользой в приятной обстановке. В программе 3 доклада и дискуссии в перерывах, а в продолжение мероприятия— afterparty. Для тех, кто не в Москве: точно будет трансляция, но ничего не заменит личного присутствия.


ссылка на оригинал статьи https://habr.com/post/424937/

Азиатское чудо Shimano: история легендарного производителя велосипедного оборудования

Имена крупных производителей велосипедов на слуху у многих. Реже люди вспоминают бренды, выпускающие компоненты для этих велосипедов. Еще реже им удается вспомнить какие-то факты о них, кроме названия. Чтобы исправить это, мы решили рассказать об одной из крупнейших компаний в этой нише — японской Shimano, которой три года назад принадлежала половина рынка компонентов и оборудование которой приносит победы лучшим велосипедистам планеты.

Предлагаем вспомнить, как развивалась сама компания и ее технологии, прошедшие почти за век путь от производства муфт до выпуска сложных систем для горных электровелосипедов.


/ Flickr / Glory Cycles / CC

Эволюция оборудования Shimano

В 1921 году 26-летний Сёдзабуро Симано (Shozaburo Shimano) арендовал помещение площадью 40 кв. м в японском Сакаи. Здесь он запустил производство обгонных муфт.

К тому времени в стране уже работали крупные компании, выпускавшие велосипеды для местного рынка и на экспорт. Сейчас сложно сказать, каким из этих компаний поставляла свои первые детали Shimano Iron Works и какие решения принимал Сёдзабуро как руководитель. Однако мы точно знаем, что производство росло и нанимало новых сотрудников.

Основатель компании управлял производством вплоть до своей смерти в 1958 году. За год до этого Shimano выпустила свой первый трехскоростной концентратор, который запустил череду инноваций. Его далеким потомком из нашего времени можно назвать планетарную втулку Nexus Inter-3.

В 1965 году Shimano вышла за пределы Азии и открыла офис в Нью-Йорке. Это произошло незадолго до бума велосипедов в США. Высокий спрос дал шанс азиатским производителям на новом рынке. Этим шансом воспользовалась и Shimano.

На тот момент компания и ее «соотечественники» не выпускали собственные комплекты — их детали дополняло оборудование других производителей. Соглашения с ними не давали азиатским компаниям полного контроля над линейкой продуктов и не позволяли обновлять их так часто, как те считали нужным. Некоторые компании, такие как SunTour, предпочли сохранить свою узкую нишу в те годы, а Shimano выбрала путь конкуренции с бывшими партнерами. Производитель существенно расширил внутренний штат разработчиков и уже в 1973 году представил свой первый комплект — Dura-Ace. Его название одновременно отсылает к сплаву дюралюминий и прочности системы (от английского durability).

Тогда лидером европейского рынка деталей для гоночных велосипедов являлся итальянский производитель Campagnolo. Первый комплект Dura-Ace вышел в один год с комплектом Campagnolo Super Record, который тепло приняли благодаря прошлым заслугам бренда и характеристикам нового оборудования. Несмотря на наличие сильного конкурента, Shimano удалось закрепиться на рынке. Уже через три года компания выпустила обновленный Dura-Ace. С тех пор Shimano вот уже 40 лет поддерживает эту серию.

В 1984 году Shimano представила первую в истории систему индексного переключения передач (Shimano Index System) на Dura-Ace 7400. До этого велосипедистам необходимо было самостоятельно выбирать положение ручки, чтобы контролировать передачу. Индексная система позволяет сделать это по одному щелчку. В 1990 году Shimano представила важное дополнение к ней — двойную систему. В ней манетка совмещена с ручками тормозов.

В 1988 году Энди Хэмпстен (Andy Hampsten) стал победителем гран-при велогонки Джиро д’Италия. На его велосипеде был установлен комплект Dura-Ace. Эта победа стала первым крупным спортивным достижением на оборудовании Shimano. В 1999 году к этому списку прибавилась победа в Тур де Франс на Dura-Ace. К слову, сейчас большая часть спортсменов в этой велогонке использует Shimano, в том числе и победитель Крис Фрум (Chris Froome).

Shimano выпустила первый в истории MTB-комплект — Deore XT — еще в 1982 году. А в 1991 году на рынке появились первые детали серии XTR — компоненты для горных велосипедов. Наряду с XTR у Shimano есть и другие горные комплекты — например, SLX. Тормозами и переключателями этой системы оснащен Twitter MANTIS-E1.

В течение следующих лет параллельно с MTB-комплектами продолжала развиваться флагманская линейка Dura-Ace, а вместе с ней и другие группы шоссейных комплектов. Существенный технологический прорыв для всех последующих моделей произошел в 2009 году с выходом комплекта Dura-Ace 7970. Он был оборудован электронной системой переключения, которая получила название Digital Integrated Intelligence (или Di2).

На трансмиссию нового поколения сразу обрушилась критика — в СМИ Di2 называли «маркетинговой уловкой» и «решением проблемы, которой не существует». Прошли годы, и теперь электронная система переключения стала отраслевым стандартом для велогонок. Несмотря на признание, высококлассные комплекты от Shimano зачастую выходят в механической и электронной версии на выбор велосипедиста.

В 2010 году на рынке появился первый комплект Shimano для электровелосипедов — Steps. Он базируется на технологии Di2. Запуск комплекта совпал с новой волной интереса к электротранспорту в Европе и США. Элементы системы Steps, которая наряду со «стандартным» набором компонентов включает двигатель и батарею, установлены на велосипедах от таких брендов, как Kenzel, Panther, Superior.

У комплекта Steps есть специализированное ответвление — серия электронных систем для горных велосипедов. Переключатели с различными режимами передвижения можно встретить на велосипедах от Kelly’s, Bergamont, Wisper.

Классификация современных комплектов Shimano

Комплекты Shimano делятся на две большие группы: шоссейные и горные. Электроприводы можно выделить в отдельную категорию, однако они уже достаточно прочно закрепились и в первой, и во второй группах.

К шоссейным комплектам относятся уже упомянутые Dura-Ace — самые дорогие в группе, — Ultegra, 105, Tiagra, Sora, Claris, 2300. Claris — бюджетная линейка Shimano. Это оборудование, как правило, устанавливают на самых доступных велосипедах. В трансмиссии Claris 8 звезд. Sora и Tiagra близки по классу к Claris. У Tiagra есть много общего с 105-ми комплектами, но все же они остаются более бюджетным вариантом. Tiagra, как правило, оснащают городские прогулочные велосипеды.

105-е комплекты открывают следующий класс оборудования Shimano. В 2018 году линейка R7000 получила серьезное обновление, которое приблизило ее к Ultegra с точки зрения конструктивных особенностей. У 105-х все еще нет Di2, но зато появились дисковые тормоза. Этот комплект позиционируется как доступное предложение, по качеству не сильно уступающее высококлассному оборудованию.

За 105-м следует Ultegra. В некотором смысле это «младший брат» Dura-Ace. Как и на Dura-Ace, на Ultegra доступны электронные переключатели и гидравлические тормоза. В 2017 году обновление комплекта R8000 из этой линейки еще больше приблизило его к флагманскому шоссейному продукту. Ultegra — это универсальный продукт, который подходит и для езды по неровной поверхности благодаря заднему переключателю, помогающему удерживать цепь в экстремальных условиях. Ultegra поставляется и с механическими переключателями.

Dura-Ace — премиальный шоссейный комплект, который совершенствуется уже почти полвека. Его используют профессиональные спортсмены, которые ценят в оборудовании легкий вес и комфорт от плавного переключения как на механике, так и на Di2. Недавно версия с электронным переключателем получила новую функцию — Synchronized Shift. По сути она позволяет «запрогроммировать» езду — установить одновременное переключение задних звезд по щелчку шифтера. Велосипедист может отказаться от этого режима и переключаться привычным образом.

Эта технология заимствована из MTB-линейки компании. Вообще, между флагманским шоссейным комплектом и оборудованием для горной езды Shimano все больше общего — например, технология Shadow. Переключатели Shadow имеют меньший профиль по сравнению с другими моделями — это защищает от повреждений — и обеспечивают прямое положение троса — так он не получает лишние изгибы. Такие переключатели встречаются в горной серии SLX, в том числе на электровелосипеде Twitter AM26-E1 17.


/ twitter-bikes.ru

В горной линейке Shimano за последние 35 лет вышло еще больше комплектных групп, чем в шоссейной, — XTR, Saint, Deore XT, SLX, Zee, Hone, Deore LX, Deore, Alivio, Acera, Altus, Tourney. Как и шоссейные комплекты, горные делятся на классы — от премиального (XTR) к самому доступному. Наряду с классами есть и разделение по применению.

Самому дорогому оборудованию — XTR — отдают предпочтение профессиональные спортсмены. Saint, Zee и Hone подходят для экстремального вождения и фрирайда, SLX и все остальные — для любительских горных прогулок.

От производства некоторых комплектов Shimano отказалась. Речь идет о семействе Hone. Другие компания запустила совсем недавно — например, Tourney. Все действующие серии получают регулярные обновления. Горные комплекты также перенимают конструктивные особенности гоночных — новые поколения 9-скоростных трансмиссий Alivio, Acera и Altus недавно переняли дизайн своих скоростных аналогов, а также технологию MEGA9 LITE, которая обеспечивает улучшенную маневренность при езде.

Среди базовых моделей выделяется комплект Alivio. По аналогии со 105-м шоссейным он принадлежит к «переходному виду». Комплект близок по характеристикам к своим более дорогим аналогам, а по цене — к «соседям» по классу. 9-скоростную трансмиссию за счет цены и надежности считают универсальным решением — ее используют не только для горных восхождений. Недавно Trek выпустил обновленную модель своего классического походного велосипеда, в котором элементы Alivio сочетаются с деталями шоссейного Sora. К горным электровелосипедам с переключателями Alivio относится Twitter VS7.0-EM 17.


/ twitter-bikes.ru

Новые 11-скоростные SLX обладают всеми важными разработками Shimano последних лет, в том числе задними переключателями, выполненными по технологии Shadow Plus, и дисковыми тормозами. При этом комплект просто настроить под собственные предпочтения в езде. Систему SLX устанавливают на горные электровелосипеды по типу Yamaha YDX Torc и Twitter AM26-E1 17.

И среди горных комплектов есть модели, поддерживающие технологию Di2. Это профессиональные компоненты семейства Deore XT (XT M8050) и XTR.

«Изюминка» Shimano

Разнообразие современных комплектов Shimano демонстрирует комплексный подход компании к рынку велосипедов. Это характерный стиль производителя, проявившийся еще в 1960-х, когда Shimano перестала быть поставщиком отдельных компонентов.

Интересно, что компания на протяжении долгих лет эволюции не утратила интерес к узким нишам. Пример этого подхода — проект Coasting для американского рынка. Shimano в 2000-х вместе с несколькими производителями велосипедов изучила предпочтения жителей США — какие велосипеды нужны большинству потребителей.

Выяснилось, что это должны быть простые модели, напоминающие о детских впечатлениях от классических велосипедов. В то время как Shimano уже производила инновационные комплекты для ведущих спортсменов и была близка к выпуску первых систем Di2, дизайнеры компании и привлеченные консультанты разработали серию простейших компонентов для массового рынка. Комплекты Coasting были оснащены 3-скоростной трансмиссией с автоматическим переключением передач и «классической» ножной тормозной системой вместо ручного тормоза.

Хотя проект просуществовал совсем не долго, в свое время он удостоился наград и признания. Shimano последовала своему принципу непрерывного развития и пошла дальше — развивать комплекты для самых разных групп потребителей. Возможно, залогом успеха компании всегда было именно это стремление — угодить не только профессиональным спортсменам, но и обычным любителям велосипедной езды.


Несколько обзоров электровелосипедов Twitter:


ссылка на оригинал статьи https://habr.com/post/424929/

Применение Arm Mbed OS. Тонкая настройка

LNDC1
После того как с помощью Arm Mbed OS удалось помигать светодиодом, настало время протестировать и настроить другие важные сервисы. Далее рассказывается:

  • Технология конфигурирование Mbed
  • Почему сложно перейти на C++ в обычных RTOS
  • Как экономить память в RTOS
  • Как организуются прерывания в Mbed OS
  • Чем удобно отлаживать Mbed OS
  • Как избавиться от лишнего слоя абстракции SDK

Продолжаем знакомство с технологией программирования микроконтроллеров семейства MKE18F c использованием ARM Mbed OS

Технология конфигурирования Mbed

Важной составляющей проекта Mbed является система автоматического конфигурирования и сборки, как в online режиме так и в offline, т.е. локально на компьютере пользователя. Конфигурировать предлагается путем редактирования файлов в формате .json со специальными именами. Затем находящиеся в проекте Python скрипты преобразуют эти файлы в заголовочные файлы, файлы рабочих пространств выбранной пользователем IDE, командные файлы линкеров и прочие вспомогательные файлы.
Но проблема описанного метода в непрозрачности с точки зрения исходных текстов, так как нам очень трудно отследить где и что в исходниках меняет система конфигурирования. С другой стороны в нашем случае нет никаких мотивов поддерживать способность проекта автоматически переноситься на разные IDE.
Поэтому от такого подхода решено было отказаться. Как писалось в предыдущей статье, был просто сформировали в online проект для IDE IAR, получена неструктурированная куча файлов в рабочем пространстве IDE, затем выполнена их систематизация и отброшено ненужное. В результате больше не нужно делать конфигурирование через .json файлы и осталось только три конкретных места где находятся параметры влияющие на конфигурацию Mbed:

  • Опции компилятора в среде IDE
  • Командный файл MKE18F512xxx16_flash.icf линкера
  • Заголовочный файл mbed_config.h

В файле mbed_config.h можно насчитать около 130 дефайнов, что поначалу очень напрягает. Но к счастью большинство из них относится к стекам беспроводных протоколов, которые к данному моменту в проекте не используются. Для удобства записи были отсортированы чтобы актуальные разместились вверху. Исходно дефайны для разных модулей в файле mbed_config.h расположены хаотично, но после сортировки он выглядит так:

Открыть

#ifndef __MBED_CONFIG_DATA__ #define __MBED_CONFIG_DATA__  // Configuration parameters #define MBED_CONF_RTOS_PRESENT                                                1                                                                                                // set by library:rtos #define MBED_ALL_STATS_ENABLED                                                1  //#define DEVICE_SLEEP=1 Снять комментарий если нужно переводить в SLEEP в случае отсутствия активных задач #define MBED_CONF_APP_MAIN_STACK_SIZE                                         1024 #define MBED_CONF_APP_TIMER_THREAD_STACK_SIZE                                 512 #define MBED_CONF_APP_IDLE_THREAD_STACK_SIZE                                  512  #define MBED_CONF_PLATFORM_DEFAULT_SERIAL_BAUD_RATE                           3000000                                                                                             // set by library:platform #define MBED_CONF_PLATFORM_ERROR_ALL_THREADS_INFO                             0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED                     0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_ERROR_HIST_ENABLED                                 0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_ERROR_HIST_SIZE                                    4                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR                           0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_MAX_ERROR_FILENAME_LEN                             16                                                                                               // set by library:platform #define MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER                            0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_STDIO_BAUD_RATE                                    3000000                                                                                           // set by library:platform #define MBED_CONF_PLATFORM_STDIO_BUFFERED_SERIAL                              0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_STDIO_CONVERT_NEWLINES                             1                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_STDIO_CONVERT_TTY_NEWLINES                         0                                                                                                // set by library:platform #define MBED_CONF_PLATFORM_STDIO_FLUSH_AT_EXIT                                1                                                                                                // set by library:platform #define MBED_CONF_DRIVERS_UART_SERIAL_RXBUF_SIZE                              256                                                                                              // set by library:drivers #define MBED_CONF_DRIVERS_UART_SERIAL_TXBUF_SIZE                              256                                                                                              // set by library:drivers  #define MBED_CONF_EVENTS_PRESENT                                              1                                                                                                // set by library:events #define MBED_CONF_EVENTS_SHARED_DISPATCH_FROM_APPLICATION                     0                                                                                                // set by library:events #define MBED_CONF_EVENTS_SHARED_EVENTSIZE                                     256                                                                                              // set by library:events #define MBED_CONF_EVENTS_SHARED_HIGHPRIO_EVENTSIZE                            256                                                                                              // set by library:events #define MBED_CONF_EVENTS_SHARED_HIGHPRIO_STACKSIZE                            1024                                                                                             // set by library:events #define MBED_CONF_EVENTS_SHARED_STACKSIZE                                     1024                                                                                             // set by library:events #define MBED_CONF_EVENTS_USE_LOWPOWER_TIMER_TICKER                            0                                                                                                // set by library:events  #define MBED_CONF_CELLULAR_DEBUG_AT                                           0                                                                                                // set by library:cellular #define MBED_CONF_CELLULAR_RANDOM_MAX_START_DELAY                             0                                                                                                // set by library:cellular #define MBED_CONF_CELLULAR_USE_APN_LOOKUP                                     1                                                                                                // set by library:cellular #define MBED_CONF_FILESYSTEM_PRESENT                                          1                                                                                                // set by library:filesystem #define MBED_CONF_KINETIS_EMAC_RX_RING_LEN                                    16                                                                                               // set by library:kinetis-emac #define MBED_CONF_KINETIS_EMAC_TX_RING_LEN                                    8                                                                                                // set by library:kinetis-emac  #define MBED_CONF_LORA_ADR_ON                                                 1                                                                                                // set by library:lora #define MBED_CONF_LORA_APP_PORT                                               15                                                                                               // set by library:lora #define MBED_CONF_LORA_APPLICATION_EUI                                        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}                                                 // set by library:lora #define MBED_CONF_LORA_APPLICATION_KEY                                        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // set by library:lora #define MBED_CONF_LORA_APPSKEY                                                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // set by library:lora #define MBED_CONF_LORA_AUTOMATIC_UPLINK_MESSAGE                               1                                                                                                // set by library:lora #define MBED_CONF_LORA_DEVICE_ADDRESS                                         0x00000000                                                                                       // set by library:lora #define MBED_CONF_LORA_DEVICE_EUI                                             {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}                                                 // set by library:lora #define MBED_CONF_LORA_DUTY_CYCLE_ON                                          1                                                                                                // set by library:lora #define MBED_CONF_LORA_LBT_ON                                                 0                                                                                                // set by library:lora #define MBED_CONF_LORA_NB_TRIALS                                              12                                                                                               // set by library:lora #define MBED_CONF_LORA_NWKSKEY                                                {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // set by library:lora #define MBED_CONF_LORA_OVER_THE_AIR_ACTIVATION                                1                                                                                                // set by library:lora #define MBED_CONF_LORA_PHY                                                    EU868                                                                                            // set by library:lora #define MBED_CONF_LORA_PUBLIC_NETWORK                                         1                                                                                                // set by library:lora #define MBED_CONF_LORA_TX_MAX_SIZE                                            64                                                                                               // set by library:lora  #define MBED_CONF_LWIP_ADDR_TIMEOUT                                           5                                                                                                // set by library:lwip #define MBED_CONF_LWIP_ADDR_TIMEOUT_MODE                                      1                                                                                                // set by library:lwip #define MBED_CONF_LWIP_DEBUG_ENABLED                                          0                                                                                                // set by library:lwip #define MBED_CONF_LWIP_DEFAULT_THREAD_STACKSIZE                               512                                                                                              // set by library:lwip #define MBED_CONF_LWIP_ENABLE_PPP_TRACE                                       0                                                                                                // set by library:lwip #define MBED_CONF_LWIP_ETHERNET_ENABLED                                       1                                                                                                // set by library:lwip #define MBED_CONF_LWIP_IP_VER_PREF                                            4                                                                                                // set by library:lwip #define MBED_CONF_LWIP_IPV4_ENABLED                                           1                                                                                                // set by library:lwip #define MBED_CONF_LWIP_IPV6_ENABLED                                           0                                                                                                // set by library:lwip #define MBED_CONF_LWIP_MEM_SIZE                                               36560                                                                                            // set by library:lwip[Freescale] #define MBED_CONF_LWIP_PPP_THREAD_STACKSIZE                                   768                                                                                              // set by library:lwip #define MBED_CONF_LWIP_SOCKET_MAX                                             4                                                                                                // set by library:lwip #define MBED_CONF_LWIP_TCP_ENABLED                                            1                                                                                                // set by library:lwip #define MBED_CONF_LWIP_TCP_SERVER_MAX                                         4                                                                                                // set by library:lwip #define MBED_CONF_LWIP_TCP_SOCKET_MAX                                         4                                                                                                // set by library:lwip #define MBED_CONF_LWIP_TCPIP_THREAD_STACKSIZE                                 1200                                                                                             // set by library:lwip #define MBED_CONF_LWIP_UDP_SOCKET_MAX                                         4                                                                                                // set by library:lwip #define MBED_CONF_LWIP_USE_MBED_TRACE                                         0                                                                                                // set by library:lwip  #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL                            0                                                                                                // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL_MASK                       0x7fff800                                                                                        // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_CHANNEL_PAGE                       0                                                                                                // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_DEVICE_TYPE                        NET_6LOWPAN_ROUTER                                                                               // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_PANID_FILTER                       0xffff                                                                                           // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_PSK_KEY                            {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf} // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_PSK_KEY_ID                         1                                                                                                // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_SEC_LEVEL                          5                                                                                                // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_6LOWPAN_ND_SECURITY_MODE                      NONE                                                                                             // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_HEAP_SIZE                                     32500                                                                                            // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL                         22                                                                                               // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_MASK                    0x7fff800                                                                                        // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_CHANNEL_PAGE                    0                                                                                                // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_COMMISSIONING_DATASET_TIMESTAMP 0x10000                                                                                          // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_EXTENDED_PANID                  {0xf1, 0xb5, 0xa1, 0xb2,0xc4, 0xd5, 0xa1, 0xbd }                                                 // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_ML_PREFIX                       {0xfd, 0x0, 0x0d, 0xb8, 0x0, 0x0, 0x0, 0x0}                                                      // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_NETWORK_NAME                    "Thread Network"                                                                                 // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PANID                           0x0700                                                                                           // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_CONFIG_PSKC                            {0xc8, 0xa6, 0x2e, 0xae, 0xf3, 0x68, 0xf3, 0x46, 0xa9, 0x9e, 0x57, 0x85, 0x98, 0x9d, 0x1c, 0xd0} // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_DEVICE_TYPE                            MESH_DEVICE_TYPE_THREAD_ROUTER                                                                   // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_MASTER_KEY                             {0x10, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff} // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_PSKD                                   "ABCDEFGH"                                                                                       // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_SECURITY_POLICY                        255                                                                                              // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_THREAD_USE_STATIC_LINK_CONFIG                 1                                                                                                // set by library:mbed-mesh-api #define MBED_CONF_MBED_MESH_API_USE_MALLOC_FOR_HEAP                           0                                                                                                // set by library:mbed-mesh-api  #define MBED_CONF_NANOSTACK_CONFIGURATION                                     nanostack_full                                                                                   // set by library:nanostack #define MBED_CONF_NANOSTACK_HAL_CRITICAL_SECTION_USABLE_FROM_INTERRUPT        0                                                                                                // set by library:nanostack-hal #define MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_DISPATCH_FROM_APPLICATION          0                                                                                                // set by library:nanostack-hal #define MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_THREAD_STACK_SIZE                  6144                                                                                             // set by library:nanostack-hal #define MBED_CONF_NANOSTACK_HAL_EVENT_LOOP_USE_MBED_EVENTS                    0                                                                                                // set by library:nanostack-hal #define MBED_CONF_NANOSTACK_HAL_NVM_CFSTORE                                   0                                                                                                // set by library:nanostack-hal  #define MBED_CONF_NSAPI_DEFAULT_MESH_TYPE                                     THREAD                                                                                           // set by library:nsapi #define MBED_CONF_NSAPI_DEFAULT_STACK                                         LWIP                                                                                             // set by library:nsapi #define MBED_CONF_NSAPI_DEFAULT_WIFI_SECURITY                                 NONE                                                                                             // set by library:nsapi #define MBED_CONF_NSAPI_DNS_CACHE_SIZE                                        3                                                                                                // set by library:nsapi #define MBED_CONF_NSAPI_DNS_RESPONSE_WAIT_TIME                                5000                                                                                             // set by library:nsapi #define MBED_CONF_NSAPI_DNS_RETRIES                                           0                                                                                                // set by library:nsapi #define MBED_CONF_NSAPI_DNS_TOTAL_ATTEMPTS                                    3                                                                                                // set by library:nsapi #define MBED_CONF_NSAPI_PRESENT                                               1                                                                                                // set by library:nsapi  #define MBED_CONF_PPP_CELL_IFACE_APN_LOOKUP                                   1                                                                                                // set by library:ppp-cell-iface #define MBED_CONF_PPP_CELL_IFACE_AT_PARSER_BUFFER_SIZE                        256                                                                                              // set by library:ppp-cell-iface #define MBED_CONF_PPP_CELL_IFACE_AT_PARSER_TIMEOUT                            8000                                                                                             // set by library:ppp-cell-iface #define MBED_CONF_PPP_CELL_IFACE_BAUD_RATE                                    115200                                                                                           // set by library:ppp-cell-iface  #define MBED_CONF_TARGET_NETWORK_DEFAULT_INTERFACE_TYPE                       ETHERNET                                                                                         // set by target:K66F  #define MBED_LFS_BLOCK_SIZE                                                   512                                                                                              // set by library:littlefs #define MBED_LFS_ENABLE_INFO                                                  0                                                                                                // set by library:littlefs #define MBED_LFS_INTRINSICS                                                   1                                                                                                // set by library:littlefs #define MBED_LFS_LOOKAHEAD                                                    512                                                                                              // set by library:littlefs #define MBED_LFS_PROG_SIZE                                                    64                                                                                               // set by library:littlefs #define MBED_LFS_READ_SIZE                                                    64                                                                                               // set by library:littlefs  #define NSAPI_PPP_AVAILABLE                                                   0                                                                                                // set by library:lwip #define NSAPI_PPP_IPV4_AVAILABLE                                              1                                                                                                // set by library:lwip #define NSAPI_PPP_IPV6_AVAILABLE                                              0                                                                                                // set by library:lwip  #define NVSTORE_ENABLED                                                       1                                                                                                // set by library:nvstore #define NVSTORE_MAX_KEYS                                                      16                                                                                               // set by library:nvstore // Macros #define _RTE_                                                                                                                                                                  // defined by library:rtos #define NS_USE_EXTERNAL_MBED_TLS                                                                                                                                               // defined by library:nanostack #define UNITY_INCLUDE_CONFIG_H                                                                                                                                                 // defined by library:utest  #endif

Особенности перехода на C++ в применении к RTOS

API верхнего уровня в Mbed написано на C++, поэтому этот язык приходится использовать и в прикладном коде. Но тут есть нюансы о которых необходимо знать.
Использование C++ для RTOS в малых встраиваемых системах еще сравнительная редкость. Проблема здесь в том, что успешные проекты RTOS стремятся быть мультиплатформенными, а С++ предъявляет повышенные требования к менеджменту ресурсов платформы по сравнению с С. Причина в стремлении скрыть от пользователя детали низкоуровневого управления ресурсами. Речь прежде всего о ресурсах памяти. Конструкторы, деструкторы, потоки, исключения c автоматической деструкцией, шаблоны объектов структур данных и др. используют неявные операции с динамической памятью. Но ресурс оперативной памяти RAM в малых системах очень ограничен. Оперативная память — самый дефицитный ресурс в таких системах и особенно в RTOS. В RTOS каждой задаче выделяется стек, его точный размер разработчик заранее спрогнозировать не может и поэтому выбирает с запасом. Таким образом наличие RTOS с десятком задач сразу вызывает необходимость в RAM размером от 10 до 30 кБ. Еще много памяти нужно для различных парсеров и протоколов (HTTP, HTML…) и файловых систем. Если применяется дисплей, то еще более увеличиваются требования к свободной RAM.
Библиотеки сред разработки типа IAR оснащаются неплохими менеджерами динамической памяти, но они рассчитаны на однопоточную среду исполнения. Чтобы они начали работать в RTOS нужно написать дополнительный код. Этот процесс называется retargeting.
В RTOS написанных на C ретаргетинг как правило не производится. Поскольку там нет неявных операций с динамической памятью на уровне языка, то все операции выполняются явно вызовом собственных потокобезопасных вариантов функций malloc и free. Программист имеет полный контроль над операциями с динамической памятью и легко может применять все возможные меры по ее экономии.
В случае C++ если мы хотим использовать все возможности этого языка нам придется делать retargeting. Но retargeting в каждой среде разработки процесс сугубо индивидуальный. Это и усложняет жизнь разработчикам RTOS.
На рисунке ниже пример структуры вызовов с ретаргетингом. Функции __write, __lseek, __read могут пользователем и не реализовываться, но тогда их функциональность остается на усмотрение IDE. И уж точно printf и scanf не будут многопоточными.

Mbed одна из немногих если не единственная RTOS, которая предоставляет исходники с уже проделанным ретаргетингом под триаду известных средств разработки: GCC, IAR, Keil
Несмотря на все сказанное выше можно встретить статьи о портировании RTOS на C++ без выполнения ретаргетинга, например решая проблему простой заменой некоторых распространненных стандартных функций на свои. Это работать может, но программисту тогда нужно помнить о разных неявных и недокументированных ограничениях при использовании конструкций C++ в IAR(только статические конструкторы, проверять все шаблоны на использование new, отказаться от исключений и т.д.). Это уже будет сложно назвать C++. Mbed как система дружелюбная к пользователю снимает многие такие ограничения приближаясь по простоте к Arduino.

Помимо всего в свежих версиях IAR есть трудности перехода на C11 и C++14 о чем написано здесь — https://www.iar.com/support/resources/articles/exploring-c11-and-c14/

Как организуются прерывания в Mbed

Как ни странно, но найти класс или функцию или что-то подходящее для организации обслуживания прерываний в API Mbed не удастся. Можно обнаружить только класс InterruptIn, который предначзначен только для внешних портов.
Ответы на такие вопросы надо искать в CMSIS-RTOS, а именно в хидерах CMSIS Cortex-M4 Core Peripheral Access Layer. Там определены макросы:

  • NVIC_SetVector — устанавливает для заданного вектора процедуру обслуживания прерываний (interrupt service routine, ISR)
  • NVIC_SetPriority — устанавливает приоритет для заданного вектора прерываний.
  • NVIC_EnableIRQ — разрешает вызов прерываний по заданному вектору

Вот как инициализируется организация прерыванияй от таймера SysTick:

    NVIC_SetVector(mbed_get_m0_tick_irqn(), (uint32_t)SysTick_Handler);     // Здесь функция mbed_get_m0_tick_irqn возвращает номер вектора прерывания от таймера SysTick.     // Тут можно было бы сразу вставить имя SysTick_IRQn их заголовочного файла MKE18F16.h     // Функция SysTick_Handler является обработчиком прерывания.     NVIC_SetPriority(mbed_get_m0_tick_irqn(), 0xFF); // 0xFF здесь назначает минимальный приоритет. Чем больше число тем меньше приоритет. В контроллере NVIC реализованном в семействые MKE18F16 возможны только 16 уровней приоритетов. Т.е. значащими будут 4-е младших бита.     NVIC_EnableIRQ(mbed_get_m0_tick_irqn()); // Разрешает вызов обработчика прерывания.

Нельзя путать приоритеты задач Mbed и приоритеты прерываний.
Если приоритет не назначается, то по умолчанию он устанавливается максимальным.
Из назначенных таким образом обработчиков прерываний можно вызывать любые сервисы RTOS, которые не вызывают ожиданий. Т.е. передавать флаги, семафоры, сообщения, майлбоксы и проч. Сервисы вызываются однако не из самого ISR, а путем вызова программного прерываний установкой бита PENDSVSET в регистре Interrupt Control and State Register (ICSR) блока System control block (SCB) ядра Cortex-M. Т.е. после завершения текущего обработчика прерываний если нет других приоритетных прерываний произойдет вызов системного обработчика по вектору PendSV где и будет проведено обслуживание.

Как в Mbed происходит работа с динамической памятью

Динамическая память или иначе куча или heap — обязательный компонент при программировании на C++. В нашем проекте Mbed под IAR определение размера этой области памяти производится в файле настроек линкера MKE18F512xxx16_flash.icf с помощью записи в переменную __size_heap__. Размер ставим так чтобы он занял всю оставшуюся свободную память. Сколько осталось свободной памяти узнаем из .map файла после компиляции, т.е. определение размера heap — процесс итеративный.

Вызов статических конструкторов объектов C++

Важным вопросом при использовании C++ является где и как вызываются конструкторы глобальных объектов. Даже в RTOS претендующих на серьезность, например МАКС, это обойдено вниманием, т.е. пущено на самотек. Там конструкторами занимается стандартная однопоточная библиотека среды разработки с обычным однопоточным механизмом выделения памяти. Но после старта распространенные RTOS создают свой механизм управления динамической памятью, а память занятая глобальными объектами остается забытой. Это дыра в наших усилиях по экономии памяти и контролю над всем.
В Mbed к данному вопросу подошли гораздо серьезней. Там для каждой среды разработки имеется собственный подход. В IAR это делается так:

  • поток инициализации еще до вызова конструкторов перехватывается пользовательским кодом
  • в стандартную библиотеку подставляются методы блокировки потоков из API RTOS
  • перенаправляются стандартные функции new, delete, malloc, free… на обращения к API работы с динамической памятью RTOS.

Mbed использует адаптеры библиотек IAR для работы в много-поточном режиме
Об адаптации IAR под многопоточность можно почитать здесь — http://supp.iar.com/FilesPublic/UPDINFO/005691/arm/doc/infocenter/DLIBThreadSupport.html
В Mbed адаптированы как системные блокировки (System locks) так и поточные блокировки (File stream locks) библиотеки IAR. Они реализованы в файле mbed_boot.c и используют мьютексы OS.
В функции __iar_program_start исполняемой в первых же строчках файла startup_MKE18F16.s происходит инициализация стека и динамической памяти OS с помощью вызова mbed_set_stack_heap

Назначение размеров стеков задач

Урезание стеков задач до минимума — самый привлекательный вариант экономии RAM.
Чтобы задачи требовали меньше стека применяются разные техники. Например, на стек сильно влияют библиотечные функции для вывода и форматирования строк printf, sprintf, scanf и т.д. Они имеют особенность выделять в стеке большие временные области для хранения данных. Если мы откажемся в задаче использовать эти функции, то сможем сократить стек задачи на каких-нибудь добрых пару сотен байт.

Mbed OS при старте сразу создает три задачи с именами: «main_thread», «timer_thread», «idle_thread». Размер стека по умолчанию для них определялся макросами в заголовочном файле mbed_rtx_conf.h. Мы перенесли объявления этих стеков в файл конфигурации mbed_config.h и сократили размер стеков. Теперь определения выглядят так:

  • Стек задачи «main_thread» определяется макросом MBED_CONF_APP_MAIN_STACK_SIZE = 1024 байт
  • Стек задачи «timer_thread» определяется макросом MBED_CONF_APP_TIMER_THREAD_STACK_SIZE = 512 байт
  • Стек задачи «idle_thread» определяется макросом MBED_CONF_APP_IDLE_THREAD_STACK_SIZE = 512 байт

Средства контроля за использованием ресурсов памяти в Mbed

Динамическая память равно как и стек — это ресурсы требующие постоянного внимания. Чтобы видеть насколько использована динамическая память и какова интенсивность запросов к ней, сколько осталось стека у каждой задачи и какова была пиковая загрузка стеков в Mbed есть специальные счетчики. По умолчанию они отключены директивой условной компиляции, для их включения надо объявить дефайн MBED_ALL_STATS_ENABLED. Когда дефайн объявлен, нужно написать свою процедуру для вывода информации пользователю. Мы написали специальную процедуру для вывода статистики в эмулятор терминала VT100, о чем будет рассказано позже.

Помимо средств предоставляемых OS среда разработки IAR в последних версиях добавляет новую возможность — стековые канарейки. Прочитать о них можно здесь — https://www.iar.com/support/resources/articles/stack-protection-in-iar-embedded-workbench-for-arm/
Общие вопросы защиты стека от переполнения рассмотрены здесь — https://www.iar.com/support/resources/articles/detecting-and-avoiding-stack-overflow-in-embedded-systems/
и здесь — https://www.iar.com/support/resources/articles/mastering-stack-and-heap-for-system-reliability/

Средства отладки и анализа кода Mbed

По настоящему глубоко изучить работу Mbed на новой платформе можно только с использованием JTAG/SWD отладчика.

Исходники Mbed насыщены многоуровневыми макросами и инструкциями условной компиляции. Просто рассматривая исходники нельзя сказать какие функции работают, а какие нет, куда выполнение программы заходит, а куда не заходит. Единственным выходом остается подключить отладчик и по шагам анализировать путь выполнения программы. Уже на этапе портирования практически невозможно обойтись без пошаговой отладки.
Я рекомендовал бы отладчики фирмы Segger версии J-Link Pro и J-Link Ultra. Их отличает высокая пропускная способность, в несколько раз выше чем у распространенных дешевых моделей. Для отладки систем с жестким реальным временем это немаловажно. При трассировке быстрых событий такие отладчики меньше подвержены переполнениям и требуют меньше отладочных итераций. Помимо пошаговой отладки они способны выполнять лог прерываний, вести статистику прерываний, включая их длительности выполнения, поддерживают технологии отладки RTT и ITM, перехватывают аппаратные исключения и другие функции.

Ниже вид окна отладчика IAR при работе через адаптер J-Link.

Экономить не стоит, 90% времени разработки уходит на отладку. Хотя более дорогие трассировщики J-Trace от Segger уже не дают большого преимущества, поскольку серия MKE18F не оснащена специальным трассировочным интерфейсом.
Вторым средством отладки, конечно, является ввод-вывод через UART. В Mbed реализовано как минимум четыре разных технологии доступа к последовательному каналу обмена данными через UART,
Это:

  • перенаправление через класс DirectSerial стандартных функций ввода-вывода языка C/C++
  • класс RawSerial
  • класс Serial
  • класс UARTSerial

Довольно необычное разнообразие. Все четыре могут быть использованы одновременно для вывода в один и тот же порт. Какие-то из них более функциональны, какие-то менее, какие-то документированы, а какие-то нет. В дальнейшем в нашем проекте будем использовать RawSerial, как наименее затратный по ресурсам класс.

Сколько мы теряем таймеров портировав Mbed

Для мигания светодиодом использовалась функция wait из API Mbed OS. В прошлой статье было рассказано о проблемах ее портирования. Но это не все, кроме этого Mbed ведет счетчик своей работы ( его можно прочитать функцией mbed_stats_cpu_get ) и есть API таймера. Эти сервисы используют низкоуровневые функции из файла lp_ticker.c. В этом файле для организации счета времени используется таймер LPTMR из набора периферии Kinetis. В процессе портирования этот файл был отредактирован для соответствия способам тактирования примененным в микроконтроллере MKE18F512VLL16.
Таким образом порт Mbed полностью захватывает два модуля счетчиков — PIT и LPTMR и таймер ядра SysTick. Об этом надо помнить планируя ресурсы для прикладной задачи.

Особенности начальной загрузки MKE18F

Чипы семейства MKE18F имеют встроенный ROM с начальным загрузчиком через последовательные интерфейсы: UART, CAN, SPI, I2C. Но на нашей плате планируется использовать свой защищенный загрузчик, поэтому работа штатного загрузчика нежелательна.
В этом случае у чипов Kinetis надо обращать внимание на содержимое области Program Flash по адресу 0x040D. Там хранится константа определяющая порядок начальной загрузки. В нашем случае там должна быть записана константа 0x7B, указывающая на старт из Flash памяти, а не из ROM и отключающая функцию NMI на внешнем выводе. При ином значении этой константы программа может зависнуть в случайно вызванном из ROM встроенном загрузчике.
Еще важно помнить, что запись во Flash память контроллера возможна только на частоте ядра 120 МГц и не выше, т.е. в режиме HRUN запись во Flash невозможна.

Активизируем Watchdog

Плата нашего контроллера предназначена для промышленного применения и значит без Watchdog-а обойтись нельзя.
Изначально макрос DISABLE_WDOG в файле system_MKE18F16.h был установлен для отключения watchdog-а. Чтобы исправить ситуацию этот макрос был стерт и реализована своя инициализация WDOG.
Инициализация Watchdog-а производится в функции SystemInit. Обновление счетчика watchdog-а сделано в задаче IDLE.
Такой подход требует чтобы более высокоприоритетные задачи не захватывали монопольно процессор более чем на 100 мс. Но это легко может произойти, например, при выводе на терминал больших дампов данных. Поэтому везде разбиваем длительные процедуры в задачах с приоритетом больше чем у IDLE на короткие фрагменты перемежаемые паузами c использованием функции wait.

Вопрос драйверов из поставки SDK

Драйвера SDK имеют префикс fsl находятся в директории NXP_MKE18F_drivers и являются своеобразным слоем абстракции периферии. Они по идее, должны облегчать программирование сложной для изучения периферии, но к сожалению минимально документированы. Вернее их документирование ограничивается комментариями в заголовках функций. Возникает недоумении для кого тогда они написаны, и как они могут освободить нас от изучения мануалов на периферию микроконтроллере. Мой ответ — никак. Драйвера всего лишь помогают легче переносить программы на разные микроконтроллеры в пределах одного семейства. Но чтобы их эффективно применять нужно очень хорошо разобраться с документацией на периферию. Таким образом драйвера SDK решают довольно частную проблему разработчиков самих драйверов, далекую от нужд пользователей начинающих изучать Kinetis.
Драйвера также предназначены для работы на всех чипах семейства т.е. быть универсальными и поэтому насыщены условными макросами и проверками которые для каждого конкретного чипа не несут никакой полезной функции.
Драйвера еще некоторым образом могут помочь лучше понять как следует обращаться с периферией, но после прихода понимания драйвера можно смело игнорировать.
В связи со сказанным не должно удивлять, что в данном проекте обращение к периферии не затронутой портом Mbed идет напрямую минуя драйвера.
Могут однако возникнуть опасения по поводу зависимостей работы той или иной периферии от наличия драйверов SDK. Тут приходится исследовать исходный код драйверов. Главная опасность зависимостей исходит от разделения функций DMA драйверами. Чтобы этого не случилось нужно отследить и запретить штатным сервисам Mbed использовать DMA при работе с периферией. Если DMA остается нетронутым драйверами SDK, то практически все, что не касается 2-х упомянутых модулей таймеров (PIT и LPTMR) и отладочного UART-а можно из директории NXP_MKE18F_drivers выкинуть или игнорировать.
Меньшая опасность, но тоже существенная может исходить от назначения приоритетов задействованной через драйвера SDK периферии. Например надо знать какой приоритет назначен прерываниям SysTick, отладочного UART-а, и таймеров. В ситуации когда их приоритет равен или больше приоритету периферии используемой в realtime управлении это может привести к деградации качества управления.
Помним, что порт Mbed для MKE18F инициализирует прерывания UART и таймеров без назначения приоритета, т.е. они по умолчанию получают максимальный уровень.


ссылка на оригинал статьи https://habr.com/post/422413/

Разработка гексапода своими руками с нуля (часть 2)

Всем привет! Подошло время для второй части разработки гексапода SKYNET. В данной статье я расскажу как я собрал корпус и об ошибках при его проектировании. Так же будет демонстрация работы конечности и первый самостоятельный подъем с брюха.

ALARM: Будет много картинок.


Корпус будет немного отличаться от модели из первой части, так как модель является улучшенной версией собираемого корпуса.

Как упоминалось в первой части, в качестве материала будет использоваться фанера 3мм. Сделал заказ лазерной резки по чертежам из и спустя 2 дня модель из экрана перешла ко мне на стол, правда по частям.

Меня это не остановило и начался длительный процесс сборки, который занял приблизительно часа 3 — 4. Перед сборкой лучше сделать сортировку деталей, так намного удобнее собирать.

Сборка конечностей
for (uint32_t i = 0; i < 6; ++i) {

Звено 1
Начать я решил со сборки 1 звена конечности. Для этого потребуются следующие детали:

Ах да, нам еще понадобится сервопривод. На него необходимо установить 2 «подушки», которыми он будет фиксироваться в корпусе. Перепутать стороны очень сложно, в подушках есть специальный вырез под уголок на ушках сервопривода.

Далее ставим полученную сборку на нижнюю часть звена в специальный вырез и устанавливаем остальные детали в соответствии с моделью. Ось сервопривода должна совпадать с осью винта на другой стороне. Установку необходимо делать очень аккуратно без особых усилий, чтобы не испортить пазы. Получился следующий результат:

В конце ставим верхнюю часть звена, затягиваем винты и звено готово.

Звено 2
После поглощения пары кружек с чаем пришло время сборки второго звена. С виду собрать легко, но это самая рутиная часть. Для сборки понадобятся детали, показанные ниже. Кстати самая рутиная часть уже сделана — прикручены качалки для сервоприводов. И да, небольшой совет: закручивать саморезы быстрее всего плоскогубцами, крутя при этом саму деталь.

Дальше по сборке проблем быть не должно. Делаем все в соответствии с моделью и должно получится так:

Звено 3
Наконец-то мы подошли к последнему звену будущей конечности. Необходимые детали для сборки набираем в соответствии с моделью и начинаем сборку каркаса:

Теперь нам понадобится сервопривод и подушки для него. Установить их необходимо следующим образом (для второго ушка сервопривода делаем так же).

Далее устанавливаем сервопривод в каркас и крепим его при помощи винтов. Так же устанавливаем вторую часть звена и затягиваем все винты. В данном случае я решил установить ось сервопривода ближе к центру звена — так лучше смотрится.

Наконец-то сборка всех деталей конечности i завершена
}

После завершения цикла сборки деталей конечностей, нужно соединить всё вместе. Думаю процесс надевания качалок на оси сервоприводов не нужно описывать. Должно получиться так:

Видео работы одной из конечностей:

Сборка рамы
Данная часть является самой простой и в подробных комментариях думаю не нуждается. Для сборки рамы нам понадобятся все оставшиеся детали. Сборку я решил начать с крышек, так как они собираются с участием клея и пока я буду собирать раму, клей уже высохнет (надеюсь).

Крышки собираются очень просто и перепутать там что-либо трудно. Должно получится так (нижняя крышка):

Как видно я залил клеем все места соединения деталей, чтобы вся эта конструкция не развалилась. Кстати, на удивление она оказалась довольно прочной. Верхняя крышка собирается аналогично, только при её сборки главное не перевернуть название гексапода.

После сборки крышек пора приступать к сборке рамы. Сервоприводы к верхней части крепятся на прямую без подушек и затягиваются моими любимыми винтами и гайками М3. Далее ставим широкие и узкие стойки в пазы и цепляем нижнюю часть. Потом затягиваем все это дело винтами и радуемся результату (не смейтесь над отверткой, она многое пережила).
В раме стоят сервоприводы S3003, так как партия MG996R из 6 штук пока, что в пути, но размеры у них одинаковые.

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

И теперь момент истины — установка всех ног на свои места. Думаю установить их на оси сервоприводов не составит труда. Результат ну просто шикарен:

Да, он умеет вставать. Радости в этот момент было крайне много. Код писался на скорою руку, чтобы понять сможет ли он хотя бы встать. В сборке на видео везде стоят сервоприводы S3003, так как оно было снято до перехода на MG996R.

Грабли, тяпки и мотыги на которые я наступил
1. Сервоприводы. Решил взять самые дешевые S3003 по 100 руб на шутку и пожалел об этом. Усилия хватает с запасом, но вот люфт это ужас. Ось сервопривода можно спокойно повернуть примерно на 10 градусов в любую сторону, при этом он не делает никаких попыток удержать положение. Если крутить больше, то он будет сопротивляться. И никаких плавных движений с ними реализовать невозможно.
Решение: MG996R решают все эти проблемы, да и стоят они на 50р дороже.

2. Неверное расположение опор. В результате этого в некоторых местах детали прогибаются при затяжке, особенно это заметно на 3 звене конечности.
Решение: переместил точки крепления и добавил пару опор

3. Чем больше кусок фанеры, тем сильнее он деформирован, особенно это заметно в раме. В итоге некоторых местах наблюдаются щели.
Решение: добавил по краям пару отверстий под винты

4. Подшипники. Да, нужно было поставить подшипники. Эта мотыга черенком по ноге пока не стукнула, но я чувствую, что она приближается. Осевые отверстия быстро изотрутся под нагрузкой и будут люфтить.

Планы
В следующих статьях планирую рассказать про электронику робота и его базовую математику


ссылка на оригинал статьи https://habr.com/post/424905/