середа, 11 листопада 2015 р.

C++ із ARM GCC + STM32 (+ CoIDE)

Автор С++, Б'ярн Страуструп
Фото взято тут.
Програми практично на будь-якій (*) мові програмування потребує підтримки так-званого коду часу виконання --- runtime. Для С цей код відносно простий, С++ вимагає складнішого --- всілякі там ініціалізації статичних змінних, підтримка роботи із виключеннями, тощо. Зазвичай програмісти не повинні про це турбуватися --- компілятор, разом із операційною системою все забезпечує. Однак, програмуючи мікроконтролери, дуже часто доводиться обходитися без операційних систем (про RTOS всілякі поговоримо іншим разом), а відповідно, без підтримки стандартних бібліотек, які змушені звертатися до ОС для виконання своїх функцій. При тому,  якщо необхідний мінімум підтримки мовних конструкцій С присутній майже завжди, із С++ типова ситуація гірша. Це нікуди не годиться, насправді.
(*) З традиційною обмовкою, що всезагальні твердження про об'єкти реального світу, завжди помилкові -- включаючи це твердження. :-)
Давайте подивимося, яка runtime-підтримка потрібна C++, а потім -- що потрібно "допилювати" вручну, щоб добитися її, працюючи із наступним комплектом інструментів: ARM GCC 4.8 та 4.9 + STM32 CMSIS + CoIDE. Для інших компіляторів -- будуть суттєві відмінності, навіть для інших версій GCC певні відмінності можуть бути. Для інших контролерів -- будуть відмінності. Із середовищем -- як повезе. [Можливо, про Keil поговоримо окремо.]

Розгляд нижче -- достатньо мінімалістичний. І так пост непомірно великий. Про підтримку локалей мова не йде, для контролерів вони просто не вартують затрат. Взагалі, про ціну за використання окремих можливостей С++ буде окремий пост -- сюди воно просто не влазить. Хіба скажу -- зазвичай ця ціна нульова або незначна. Основні винятки описані нижче -- виключення і RTTI.

Вважатимемо, що вже обговорена підтримка стандартної бібліотеки у нас є. Працюватимемо все із тією ж STM32VLDiscovery, обладнаною мікроконтролером STM32F100RB. Сама по собі модель мікроконтролера не є аж такою важливою, але для ясності, орієнтуватимемося на його ресурси -- 128 Кб пам'яті програм, 8Кб оперативної пам'яті.

Так як пост вийшов достатньо великим і трохи плутаним, почну  із короткого огляду:
  • C++ runtime. Огляд задач, які стоять перед кодом часу підтримки, зокрема -- перед його реалізаціями, libstdc++ і libsupc++.
  • Ініціалізація. З чого починає роботу контролер, і як добитися, щоб стандартна для С++ процедура підготовки програми перед входом в main(), зокрема -- виклик конструкторів глобальних об'єктів відбувалася, як очікується. Розглядається процедура ініціалізації контролера, підхід GCC  до ініціалізації програми (зокрема, всілякі там crt0.o) та обробник переривання Reset. Також, для повноти, зачіпається тема "деініціалізації" -- виклику деструкторів по завершенню main(), хоча для контролерів можливість не є особливо цінною.
  • Оператори new, new[], delete, delete[]. Особливості реалізації, вимоги до них, опис цілого зоопарку цих операторів.
  • Виключення. Дуже корисна можливість сучасних мов програмування, яка, на жаль, вимагає складної підтримки часу виконання і помітних ресурсів для своєї роботи (помітних -- в масштабах доступних контролеру ресурсів). Самопальною тут не обійдешся. Тому рекомендується їх просто не використовувати. Якщо ж таки є потреба у них, (чи є просто бажання спробувати), розповідається, як підключити їх підтримку засобами libsupc++, і чого це коштуватиме. Звертається увага на відмінності обробки виключень в GCC  для ARM та його ж для інших архітектур. Є посилання для подальшого заглиблення. Згадується альтернативна реалізація C++ runtime -- libcxxrt, про яку буде окремий пост.
  • RTTI -- RunTime Type Information. Так само, як із виключенням, краще без цієї можливості обійтися, якщо ж таки дуже треба (не вдається прожити без dynamic_cast<> :-), розповідається, як її підключити -- крім компонування із libsupc++ слід додати декілька функцій: __cxa_bad_cast(), __cxa_bad_typeid(), що задають реакцію на відповідні події.
  • Реакція на виклик чисто віртуальних чи видалених функцій. Власне -- воно, пара функцій, що викликатимуться у таких нещасливих випадках. Компілятор вставляє їх виклик в патологічних місцях коду, без надання їх реалізації будуть помилки компонування.
  • Локальні статичні змінні. Для захисту від одночасного доступу, race condition, під час ініціалізації статичних змінних в багатопоточному середовищі, компілятор вставляє спеціальні захисні виклики (таке собі блокування-розблокування мютекса). Написати ці функції коректно відносно складно, тому тут, для початку, описано мінімальні заглушки, які, насправді, не захищають, але дозволяють коду скомпілюватися. (За більш  повною реалізацією див. ту ж libcxxrt).
  • C++11. Більшість мовних засобів мали б працювати зразу, без додаткової підтримки.
  • Стандартна бібліотека С++. Включаючи STL. Огляд того, що вдасться використовувати зразу, що потребує певної підтримки часу виконання, а для чого доведеться тягнути цілу libstdc++. Якщо коротко -- послідовні контейнери (vector<>, deque<>, list<>, array<>, і т.д.) та більшість алгоритмів можна використовувати майже зразу. Асоціативні вимагають компонуватися із libstdc++. Паралельно розглянуті деякі брудні трюки, що дозволяють справитися із дещо непомірними її апетитами щодо RAM. Ілюстрація затрат ресурсів на це все.
  • Керування та відстеження динамічного виділення пам'яті.
  • Опис демонстраційного проекту.
  • Додаток містить прокоментований скрипт лінкера.

Для лінивих, демонстраційний проект тут.

На жаль, якорі HTML в цьому блозі чомусь дуже капризно поводяться, тому, щоб не витрачати додаткового часу (даний пост його спожив неміряно!), не використовую їх для посилання на розділи нижче (може потім додам, під настрій).

Перш ніж перейти до тексту, див. заголовок блогу --- виклад не всюди робиться із повним розумінням процесів, іноді -- емпіричний, тому ніяких гарантій. Звичайно, буду вдячний за уточнення та виправлення!

вівторок, 10 листопада 2015 р.

Retargetable printf з CoIDE та порівняння розмірів ROM/RAM для різних способів виводу

Ілюстрація з Вікі до
теми саморобок (DIY)
В попередньому пості було розглянуто, як забезпечити мінімалістичну підтримку стандартної бібліотеки С для мікроконтролерів сімейства STM32F1, (для контролерів інших сімейств, крім, власне, особливостей SemiHosting, відмінності будуть мінімальними, якщо взагалі будуть), працюючи з-під CoIDE. Однак, повноцінна підтримка цієї бібліотеки не завжди потрібна, а витрати пам'яті програм та RAM її printf(), в деяких ситуаціях можуть бути неприйнятними. На такий випадок CoIDE пропонує ще один варіант -- скористатися урізаною, мініатюрною реалізацією, яку воно називає Retargetable printf (Retarget_printf). (Взагалі, всі такі бібліотеки, де реалізувавши пару-другу функцій, можна "перенацілити" на роботу із іншим залізом, називають retargetable.)

Подивимося, що вона вміє, для чого може бути і як її подружити із SemiHosting --- виведенням повідомлень із використанням дебаггера.

понеділок, 9 листопада 2015 р.

Стандартна бібліотека C та SemiHosting (на прикладі STM32 і CoIDE)

Роль LibC в Linux. Зауважте, що
glibc надає значно більше інструментів,
ніж стандартна бібліотека С -- зокрема,
засоби POSIX. Нижче мови про них не буде.
(c) wiki
В попередньому пості було показано, як викристовувати CoIDE, програмуючи мікроконтролери (на прикладі плати STM32VLDiscovery). Розглянемо тепер, деякі загальні практичні питання програмування із використанням С. (В порівнянні із давнішими попередніми (1, 2) постами, тут більше подробиць, виправлено деякі помилки, і т.д.)

Увага (як часто буває в  embedded!), багато що із написаного нижче дуже сильно прив'язано до особливостей конкретного компілятора, GCC та конкретних його версій! Про Keil, можливо, колись напишу окремо. З іншого боку, особливої прив'язки до IDE немає, CoIDE згадується лише як конкретний приклад, котру галочку в котрому меню слід поставити для досягнення якогось результату. Розгляд ведеться для ARM-GCC 4.8 та 4.9, для новіших чи старіших версій можуть бути відмінності.

Стандартна бібліотека C

субота, 7 листопада 2015 р.

CoIDE 2

Давненько я про CoIDE не писав. Воно потроху розвивався, виходили нові версії, фіксилися старі баги, вносилися нові. З'явилася підтримка STM32F3 -- тих, що в STM32F3Discovery, з'явилася, в значній мірі -- формальна (див. наступні пости) підтримка C++. Остання доступна версія - 1.7.8. Однак, попередні рік-два, не зважаючи на вихід згаданої 1.7.8, основні зусилля були зосереджені на новій версії, CoIDE-2. Перші його випуски видалися мені претензійним, але мало-юзабельним. Однак, минав час, випала нагода з ним знову попрацювати, і виявилося, що версія 2.0.3, все ще бета, але вже цілком придатна для повсякденної роботи. 

Так як і в самому CoIDE, і в CMSIS (*) з часу попередніх постів ("CooCox CoIDE [1.5.1]", "CoIDE 1.7.1"), багато що змінилося, вирішив написати знову. Спочатку планувався один пост, потім він переріс у цілу серію, але, як би там не було, серія ця запланована як незалежна від попередніх матеріалів, але абсолютної гарантії не дам -- у них може бути щось важливе, що я забув згадати тут. Буду вдячний за bug-report-и. :-)

(*) CMSIS -- "стандартна бібліотека" для ARM-івських контролерів, основу якої, для спільного у всіх них ядра, випускає ARM Inc, а кожен розробник конкретних мікроконтролерів доповнює підтримкою своїх "фіч" --- реалізованих ними периферійних засобів та можливостей, див [1], [2].

субота, 18 липня 2015 р.

Новини з Плутона (оновлюється)

Отож, новини із системи Плутона. 

Почнемо з того місця, де ми станцію залишили [на жаль, через технічні обмеження, це було досить давно]. Найкраще фото здалеку:
Останні навігаційні фото Плутона та Харона, 12 липня 2015, 08:45 і 08:50 UTC, відповідно, віддаль -- 2.5 млн км.
(c) NASA / JHUAPL / SwRI

На прес-конференції від наземної команди, разом із цією фото було опубліковано попередні наукові результати:

вівторок, 14 липня 2015 р.

Місія New Horizons

"New Horizons". (c) NASA
Плутон давно приваблює дослідників, особливо після того, як в 1989 Voyager-2 відвідав Нептун і Плутон залишився останньою планетою, де не бували земні роботи. Звичайно, первинним тут було не "колекціонування", а науковий (і трішки -- технічний) інтерес. Детальніше про останній -- див. "Плутон, до "New Horizons"", розділ "Фото".

Однак, дорога до нього була тернистою --- місії багато раз відміняли, навіть переможця, "наш" New Horizons, довелося відстоювати не раз. Детальніше на цій сторінці історії не зупинятимуся, за подробицями див. там же, посилання у виносці "(**)", а також вступ та історію на Вікі.

Тут зосередимося на тому, що це за Автоматична міжпланетна станція (АМС), що вона може і на які результати можна очікувати.

Спочатку --- про віддалі.  Станцію запущено в 2006 році, при запуску вона стала найшвидшим запущеним землянами об'єктом, по дорозі отримала "копняка" від Юпітера, тому змогла досягнути Плутона всього лиш за дев'ять з половиною років. А Плутон знаходиться всього лиш на внутрішній межі поясу Койпера

Тепер детальніше:

неділя, 12 липня 2015 р.

Ще один таємничий світ -- Плутон

Кращі, на момент публікації, фото. Подробиці - нижче.
(c) NASA / JHUAPL / SwRI
Є, все таки, щось магічне у тому, як нова земля вперше проявляється на горизонті. Вчетверте пишу про це в цьому блозі. Раніше була Веста, Церера, комета Чурюмова-Герасименко. А тепер -- Плутон. Як відомо, повз нього, через лічені десятки годин, 14 липня 2015 р, пролетить АМС New Horizons, вперше показавши його нам зблизька. Але вже зараз вона достатньо близько, щоб кожного дня постачати все більш якісні фото. І поки -- все більш загадкові.