понеділок, 22 лютого 2016 р.

Далекомір HC-SR04 -- використовуючи GPIO/SPL

Ієрархія засобів програмування, орієнтована на SPL.
Клікабельно. (c) STMicroelectronics
CMSIS, про яку йшла мова минулого разу, штука потужна, але дуже вже низькорівнева. (Кожен раз себе так відчуваю, ніби попав у кабіну авіалайнера -- ті сотні бітиків, які треба правильно сконфігурувати, інакше нічого не працюватиме.) В STMicroelectronics теж розуміли, що користуватися нею, в більшості випадків, не дуже зручно. Першою спробою надати більш високий рівень абстракції для роботи із їхніми мікроконтролерами, була SPL -- Standard Peripherals Library. (Нагадую, основа CMSIS універсальна, від розробника ядра ARM Cortex-M, ARM Inc., виробники конкретних мікроконтролерів її хіба розширяють, а ось SPL -- специфічна для STM32). 
Зауваження -- не плутайте SPL із STL з С++ -- стандартною бібліотекою шаблонів. ;-)
Повторимо те ж, що і в попередньому пості, засобами  Standard Peripherals Library, SPL. Апаратна конфігурація та ж:
  • PB1 -- Trig
  • PB2 -- Echo
  • PC8 -- синій світлодіод
  • PC9 -- зелений світлодіод

неділя, 21 лютого 2016 р.

Далекомір HC-SR04 -- використовуючи GPIO/CMSIS

Структура GPIO-піна, з
офіційної документації.
Клікабельно.
В попередньому пості було описано цікавий пристрій -- ультразвуковий далекомір, HC-SR04. Він може служити хорошим демонстраційним прикладом для багатьох технік роботи із мікроконтролерами. 

Подальші пости використовуватимуть плату STM32VLDiscovery із її мікроконтролером  STM32F100RB, архітектури ARM Cortex M3, котрий має 128Кб пам'яті програм та 8Кб RAM. Для інших споріднених мікроконтролерів відмінності будуть мінімальними. 

Спершу розглянемо найбільш базову (але, відповідно, і найбільш низькорівневу) методику -- із використанням CMSIS. Також, буде використано найбільш примітивну техніку роботи із пристроєм -- безпосереднє смикання ніжок мікроконтролера та читання рівнів на них (іншими словами, самим GPIO, без використання переривань).

CMSIS -- GPIO


субота, 20 лютого 2016 р.

Далекомір HC-SR04 -- огляд

Купив я колись, багато років тому, собі таку штуку, як на фото -- ультразвуковий далекомір-"ехолокатор", HC-SR04. (Взагалі, перша моя покупка на e-bay. Купляв по 2.5 бкс, зараз менше 2. Та й продавець той, "Чіп партнер", як показала практика,  цілком приємний).

Пристрій простий, як двері. Datasheet -- аж дві сторінки крупним шрифтом із малюнками. 

четвер, 31 грудня 2015 р.

Эндрю Шульман - Неофициальная Windows 95

Трапилася мені книжечка із далекого минулого, "Неофициальная Windows 95", проглядав її останні місяці, на пару із Таненбаумом, про якого пізніше. Такої "ніжності" та "ностальгії" як до FCB та DOS я до неї аж ніяк не відчуваю, тому детальної рецензії, як до "Extending DOS" by Ray Duncan et. al  не писатиму. Однак, дечим із неї поділитися хотілося б.

пʼятниця, 13 листопада 2015 р.

Мікро-реалізація стандартної бібліотеки C++ -- uClibc++

Саморобна амфібія. (c) wiki
Якщо libcxxrt підміняє собою libsupc++, то uClibc++ намагається бути всім решта із libstdc++, що не входить в libsupc++. Тобто, для свого функціонування вона потребує libsupc++ (або libcxxrt) -- бібліотеку низькорівневої підтримки.

Подивимося, що це за звір. Скачати її можна на офіційному сайті. В архіві є файл INSTALL, в якому описана процедура інсталяції. На жаль, вона доволі нетривіальна і сильно зав'язана на Linux (хоча, перенесення під Windows видається можливим). Перший етап -- "make menuconfig", генерує конфігурацію бібліотеки -- можливості, які слід включити. Результатом його буде файл system_configuration.h, із купою макросів виду "#define __UCLIBCXX_STL_BUFFER_SIZE__ 32". Після чого слід виконати хитрі магічні процедури, в результаті яких буде отримано незалежний lib-файл.

Для економії часу, я схитрував --- критично важливий system_configuration.h згенерував на доступній мені Linux-машині, а решту операцій уник, додавши файли бібліотеки до проекту. Для ясності, це може виглядати так -- в директорії проекту створюється директорія uclibcxx, до неї копіюється вміст директорій src та include із архіву текстів бібліотеки, крім Makefile-ів та піддиректорії src/abi -- вона буде зайвою. В include кладемо і system_configuration.h. В середовищі створюємо відповідні групи, додаємо до них файли із цих директорій. (Готовий демонстраційний проект CoIDE, як завжди, можна скачати тут).

Додаємо libsupc++ до списку бібліотек (як це робити, не раз згадувалося в попередніх постах) -- uClibc++ покладається на неї. (libstdc++, навпаки, повністю самодостатня, фактично є "два-в-одному"). Також, вважаємо, що С-ний runtime, про який говорили раніше, присутній. "Свій" С++-ний runtime не додаємо --- цим займається libsupc++.

Пробуємо компілювати. Халяви немає -- купа помилок.

четвер, 12 листопада 2015 р.

libcxxrt в ролі libsupc++ -- бібліотеки підтримки мовних засобів часу виконання


Клікабельно. :-)
Розглядаючи підтримку С++ на "голому залізі", в попередньому пості, ми орієнтувалися на штатні засоби --- мінімальний набір із libsupc++, яка підтримує синтаксичні засоби мови (зокрема, виключення та RTTI) та повну libstdc++, що дозволяє, принаймні -- в теорії, користуватися всіма засобами стандартної бібліотеки мови. Однак, і одна і друга страждають певною громіздкістю, тому іноді хотілося б мати більш компактну альтернативу, навіть якщо її можливості будуть дещо урізаними. В ролі альтернативи до libsupc++ часто пропонують libcxxrt, для повної бібліотеки можна подивитися на uClibc++.

Почнемо із розгляду libcxxrt. Вона прийшла із світу FreeBSD/x86, потім модифікувалася і для інших платформ. Потребує окрему бібліотеку розкрутки стеку, в ролі якої підходять як libgcc_s так і libunwind (якщо просто --- одна із них мала б бути з GCC, детальніше -- див. попередні пости або тут чи тут). Крім того, вона, все ж, розрахована на великі системи, де не потрібно економити кожен кілобайт, що проявляється в коді.

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

При тому, завдяки своїй простоті (відносній), бібліотека виявилася неоціненим джерелом подробиць про роботу C++ runtime, допомігши розібратися в нюансах для попереднього поста. У свою чергу, цінні підказки по перенесенню libcxxrt знайдено тут: "C++ Exception Support".

Попередивши, можна починати. Розгляд проводиться на прикладі все тієї ж STM32VLDiscovery, але для інших мікроконтролерів сімейства особливих відмінностей (крім доступного розміру RAM) бути не мало б.

середа, 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 в цьому блозі чомусь дуже капризно поводяться, тому, щоб не витрачати додаткового часу (даний пост його спожив неміряно!), не використовую їх для посилання на розділи нижче (може потім додам, під настрій).

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