Archive for the ‘Програмування’ Category.

avr-ld buffer overflow

Дійсно прикра помилка в avr-ld (binutils-avr 2.25) — та, що спонукала мене до перевірки використання Raspberry Pi як комп’ютера для роботи, — виявилася доволі цікавою.

Почала вивалюватися вона у мене доволі давно, але я помилково вважав, що вона притаманна 64-бітній версії Ubuntu 16.04, бо на роботі в 32-бітній все працювало. Думав, що це якісь проблеми невраховування розмірів чи співвідношення розмірів змінних на зразок «подаруночка від FTDI». Чесно кажучи, у повідомлення не особливо і вчитувався — «та хай, це по роботі, то на роботі й зберу» і вдома більше не запускав аж до того, як нещодавно перезібрати знадобилося негайно, бо це зупиняло термінову роботу. Тоді ж ото зібрав на Raspberry й написав про все це.

Ну й на ключову фразу *** buffer overflow detected *** Іван у коментарях пояснив, як із цим можна боротися.
Докладніше читайте » » »

Raspberry Pi як комп’ютер для роботи

Не від хорошого життя довелося провести тест Raspberry Pi як робочого комп’ютера.

Не знаю, після якого оновлення Ubuntu MATE, але на моєму основному комп’ютері перестав працювати avr-ld, валиться з помилкою «*** buffer overflow detected ***» (це на 64-бітній системі, пізніше я перевірив, що на 32-бітній такій же МАТЕ і з тими ж оновленнями все працює — це не так, залежить не від розрядності, докладніше тут).
А мені терміново знадобилося внести маленьку зміну в прошивку ATtiny13A. Мій «червоненький» ноутбук зараз інтенсивно використовує дружина, то щоб їй не заважати, я згадав про Raspberry, на яку оце ж нещодавно ставив (таку ж!) убунту.

Поставив там avr-gcc, все зібрав, перекинув на основний комп, прошив.

Стало цікаво порівняти швидкість. Цей маленький (близько 400 байт прошивки) асемблерний проект на роль такого тесту геть не годиться, тому я вирішив позбирати більший. Поставив, відповідно, arm-none-eabi-gcc, щоб збирати поточний проект для STM32F105. Там десятки файлів, за 40 кілобайт результат, — час вже можна міряти. Збирав на Raspberry, на основному своєму комп’ютері (AMD A8), на «червоненькому» Dell Vostro V130 (Core i3) і на роботі на Pentium D (дохлий, як на нинішні часи, комп’ютер, але його там цілком вистачає). На всіх системах стоїть Ubuntu MATE 16.04 з усіма оновленнями. Лише на AMD A8 64-бітна, всі інші 32-бітні (і на всіх 32-бітних avr-ld свою роботу чесно робить).

Ось що вийшло (time make -j число_ядер, час у секундах).
Воно від збирання до збирання трохи стрибало, але не принципово.

система
(ядер*ГГц)
real user system
Raspberry Pi 3
(4*1.2)
12.2 32.6 3.3
Pentium D
(2*1,8)
9.5 13.3 1.8
Core i3 M380
(4*1,33)
8.2 20.6 2.7
AMD A8-7600
(4*3.1)
3.1 7.7 1.2

Тут у табличці нема ширини і швидкості шини пам’яті, своє слово сказало і те, що Raspberry працює з SD-карти, Pentium-D і AMD A8 з SATA-дисків, а Core-i3 з SSD. Але тут я хочу порівняти все ж таки не кількість зкомпільованих рядків коду на гігагерц-ядро чи DDR-истість пам’яті, а абсолютний час — питання, що турбує: «чи йти заварювати чай, чи воно раніше збере» :-)

Виявилося, що Pi 3, на відміну від перших Raspberry, цілком придатний для роботи з прошивками такого обсягу.
І що ця плата реально набагато швидша, ніж комп’ютер, на якому 10 років тому я запускав альтерівський Quartus-II 9.1 для збирання прошивок альтер (не можу пригадати, що у мене тоді було… якийсь Athlon XP). Та й «мікроконтролерні» компіляції там більше часу займали.

Оболонка Arduino українською

Потихеньку завершив переклад оболонки Ардуіно українською мовою. Станом на кінець літа там близько третини (із майже шестисот) рядків у .po-файлі було ще не перекладено. Дещо було перекладене, але не потрапляло в оболонку жодною мовою, довелося шукати проблемне місце, виправляти і робити pull-request.

Дещо з перекладеного раніше також довелося виправити. Напевне ж, ще треба виправляти, як старе, так і зроблене мною. Хоча б тому, що в англійській мові нема відмінків, а я сам не пройшов всю оболонку, не викликав усі можливі повідомлення і не знаю контексту, у якому вони виникають. У дуже підозрілих місцях я просто по java-коду оболонки здогадувався про цей контекст.
От цікаво, де виникає повідомлення «Як сюрреалістично!» (в оригіналі «How very Borges of you»), але в код не ліз, такий квест треба проходити чесно ;-)

Зараз з сайту Arduino можна завантажити Arduino IDE «стабільної» версії 1.8.5 від кінця вересня, туди частина перекладу вже увійшла.
У чергову preview-версію 1.8.6 від 30 жовтня (нижче, розділ HOURLY BUILDS) ще не потрапили дві фрази (див. issue), тепер вони є в перекладі. В релізі (чи наступному пре-релізі) 1.8.6 мають бути.

Будь-ласка, хто використовує Arduino, беріть найсвіжішу збірку (зараз ота 30 October 2017) звертайте увагу на меню і всі повідомлення, які трапляються у реальній роботі. Як щось криве побачите — пишіть. Хочу підчистити до релізу. Ну і потім продовжувати підтримувати стан.

Зовнішні відносно Arduino плагіни для роботи з платами/бібліотеками, навіть якщо вони прямо із сайту завантажуються разом з оболонкою, не мають можливості перекладу. Але пишіть про все, а я вже розбиратимуся — то щось нове додали і треба перекласти, чи воно не вміє бути перекладеним.

До речі, довідка в Arduino IDE, на відміну від власне оболонки, існує лише англійською. Так і не зрозумів, чи збираються додавати перемикання. Пізніше питатиму, зараз інша в чомусь близька робота час забрала.

OpenOCD, STM32L011 і всі-всі-всі

Тему так і не закінчено. Доводиться тримати на столі обидва адаптери — і саморобний на FT2232H, і китайський ST-Link.

Мікроконтролери STM32L011, на відміну від інших STM32L0, мають одну особливість. Якщо флеш стерта (точніше, якщо стерте перше слово флеша, у якому початкова адреса стеку сидить), то незалежно від ніжки BOOT0 мікроконтролер стартує у boot-loader. Зроблено це з метою «полегшити початкове прошивання», але мені лише поважчало.

Біди не було б, якби OpenOCD у комбінації з адаптером на FT2232 з цією ситуацією міг упоратися. Але він чомусь не може прошити флеш. Під’єднується по SWD до ядра, показує вміст вказівника команд десь у діапазоні системної пам’яті, каже, який мікроконтролер побачив і обсяг флеш-пам’яті, а от шити відмовляється. Цей же OpenOCD з адаптерами ST-Link, що з «чесним» з плати STM32F3DISCOVERY, що з китайським, — перешиває.

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

p.s. Про всяк випадок повторю: якщо не зупиняти основний генератор (не піднімати біт SLEEPDEEP у регістрі SCB->SCR) і не перепрограмовувати ніжки, потрібні для SWDIO/SWDCLK, то цілком можна обійтися китайським ST-Link-ом. Інакше — доведеться шукати/робити інший програматор або додавати кнопку reset і вчитися її відпускати у потрібний момент :-)

Китайський ST-Link v2 проти STM32F3-Discovery

Щоб вже закінчити вчорашню тему.

Витягнув із шухлядки плату STM32F3-Diіcovery — на ній є вбудований ST-Link, який можна відключити від процесора на платі і використовувати для програмування інших плат. На штирі виведено всі сигнали, включно з RESET і SWO. До речі, перемички розривають лише лінії SWCLK і SWDIO, тому свою плату можна скидати, натиснувши кнопку на платі Discovery.

Ну що — все працює, RESET піднімає мікроконтролер зі Stop-у і перепрошиває. Тобто проблема в тому, що клон ST-Link з Ali-Express-у не вміє виконувати відповідні команди.

Коли вже знову сів за макетку з STM32L051, то перевірив і роботу команд stm32lx lock / stm32lx unlock і швидкість програмування. У клонованого ST-Link тут теж щось в генотипі порушене, бо набагато повільніший. Хоча в ньому стоїть STM32F101, тобто USB зроблене програмно, тому швидким він і не може бути, але ж одиниці кілобайт на секунду не така вже й велика швидкість.

Результати тестування на швидкість (файли для прошивки 2-12kB).
Команда “reset init” перемикає STM32L0x з внутрішнього MSI 2 MHz на HSI 16 MHz і піднімає частоту обміну.

Програматор Fswclk = 300 kHz
(-c “reset halt”)
Fswclk = 2.5 MHz
(-c “reset init”)
Клон ST-Link 1.5-1.7 KiB/s 1.5-1.7 KiB/s
F3-Discovery 4.9-5.0 KiB/s 5.2-5.3 KiB/s
FT2232H 3.8-4.2 KiB/s 8.0-8.3 KiB/s


Платку з FT2232D діставати було ліньки, на цих швидкостях має бути не набагато повільніша за FT2232H, хіба ото не зможе виставити 2.5 MHz частоти SWCLK, буде 2.

Китайський ST-Link v2, STM32L011 і Stop

Точніше, «Stop і не-Reset».
І не STM32L011F4, бо у Імраді їх нема. Граюся на а STM32L051C8T, поки дрібніші кристали їдуть.

Cortex-M, зокрема STM32F10x і трохи раніше LPC176x, я вже трохи помацав у невеликих «одноразових» проектах. У виробах досі йшли ATmega48PA, хоча не все влаштовувало і поглядав на нові можливості нових ATtiny (можна погортати назад, я писав, що мене цікавить). Запитуючи про ціни-доступність цих кристалів, мимоволі роззирався навкруги, як на старіші MSP430 та 8-бітні PIC-и, так і на STM8L, які теж мають цікаві можливості. Та останнім заважає біда — вибір між 16-мегагерцовим RC (забагато, навіть якщо для ядра поділити частоту — багато їсть сам генератор) і низькочастотним low consumption, якого малувато і який має доволі великі початковий розкид і нестабільність частоти.

Так потихеньку доповз і до STM32L0. Аналоговий компаратор, хоч і повільніший, ніж в AVR, але ж пару мікроампер, а не 70, LPTIM1, який може слухати компаратор при зупиненому ядрі і маршевому RC, і, головне, MSI-генератор, який зменшує споживання при зменшенні частоти (привіт, MSP430, я вас ціную, та так до вас і не дійшов). Все, «беру».

Ті «товстіші» Cortex-M я програмував через OpenOCD/JTAG і платки на FT2232D/FT2232H, яких у мене вистачає. Тут же потрібен SWD. Ну що, «досить самому ліпити адаптери», Ali-express, копійчаний клон ST-Link v2, побігли.

І тут вилізла проблема. Якщо програма використовує ніжки SWCLK/SWDIO для себе, або якщо ядро йде у Stop, зупиняючи генератор, то для перепрошивки необхідно смикнути кристал за Reset і потримати на ньому під час з’єднання, параметр connect_assert_srst для OpenOCD. І от чи то всі ці китайські клони, з якими взагалі йдуть 4 дротики (SWDIO, GND, SWCLK, VCC для STM32 і RESET, GND, SWIM, VCC для STM8), не вміють смикати за Reset, чи ще що, але з моїм ST-Link v2 для перепрошивки в потрібний момент необхідно тицяти у кнопку скидання вручну.
Не діло.

Згадав, що опис OpenOCD згадував resistor hack, який дозволяє для FTDI-них адаптерів працювати з SWD. Дописав потрібні рядки у конфіг для своєї плати на FT2232H, спробував — все чудово працює. Ото недаремно мені такі адаптери завжди подобалися ;-)

Десь у мене лежить кілька незапаяних FT2232D і ще 2-4 штуки можна зняти із зоопарку платок, який зібрався за минулі роки. Накидаю я luminary-icdi-подібну плату і притулю її до чергового замовлення експериментальних зразків.


Доповнення: оскільки через «справжній» ST-LINK v2 на платі STM32F3DISCOVERY все працює, це точно генетичний дефект клона. Кажуть, його можна перепрошити на інший, кращий програматор, але зараз не до того.

Зайві коми в CSV

Зустрівся з ситуацією класу «перестаралися з локалізацією».
Підкинули мені як вхід до симуляції однієї системи лог-файли, про які програма, що їх згенерувала, думала, що вона робить файли CSV. Воно, може, так би й було, якби не те, що та програма подивилася на мову операційної системи і в числах замість «рухомої крапки» втулила «рухому кому». Результат — такі числа сприймаються скрізь як два незалежних поля з цілими числами.

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

Ці файли мають практично вільний формат (рядки мають різну кількість полів), але, на щастя, перед кожним числовим полем йде текстова назва цього поля, маємо набір пар «назва даних», «значення» (значення може бути текстовим, але у випадкові із зайвими комами це не важливо).
Тобто не зустрічаються два цілих числа підряд і якщо вже кома з двох сторін має цифри, то її гарантовано слід замінити крапкою. «Ніколи» — це ніколи там, де є числа з рухомою комою. На початку кожного рядка йде фрагмент фіксованої структури, де є і текстові рядки, і декілька цілих чисел підряд. Рядок розбивається на дві частини, першу слід залишити як була, у другій всі коми, обрамлені цифрами, замінити на крапки.

Тут теж є трішки програмістського щастя — між цим фрагментом і «хвостом» з довільними іменованими даними завжди зустрічається одна й та ж сама послідовність літер, скажімо, vli, що дає можливість не рахувати поля на початку і не сподіватися на фіксовану довжину заголовка, а просто розділити рядок на дві частини по цій комбінації літер.

Все перераховане може зробити коротенький скрипт мовою AWK:

/^.+$/ {
    i = index($0, "vli")
    s0 = substr($0, 1, i)
    s1 = substr($0, 1+i)
    print s0 gensub(/([0-9]),([0-9])/, "\\1.\\2", "g", s1)
}

Статична матрична клавіатура

Матричні клавіатури, на зразок показаної 12-клавішної, зазвичай опитують «динамічно», за допомогою сканування.

Процес опитування складається з послідовного видавання імпульсів на лінії, наприклад, COL0…COL2 і зчитування стану ліній ROW0…ROW3 та, при виявленні натискання, комбінування номерів чи масок цих ліній у скан-код клавіші. Це вимагає наче небагато команд і часу (та енергії) на їх виконання, але…
Якщо у пристрої вже й так використовується динамічна індикація, то таке опитування клавіатури може використовувати той же цикл і ті ж лінії сканування, що використовуються для індикатора, тому опитування клавіатури практично не вимагає додаткових ресурсів.

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

В інших випадках можна обійтися без сканування, «статично», просто зчитуючи стан входів. Нічого не дається надурняк, тут якась кількість внутрішніх ресурсів мікроконтролера розмінюється на декілька транзисторів-резисторів (втім, сумарною вартістю меншою, ніж одна кнопка). Чи вартий того такий розмін, чи ні — вирішувати розробнику, але спочатку треба з ознайомитися з можливістю » » »

Sketch for Scratch

У зв’язку з активізацією інтересу батьків до того, щоб у дітей був інтерес до програмування/електроніки/… у поле мого зору знову потрапив Scratch. Але як людина, яка не вміє налагоджувати програми без осцилографа :-) , я відразу почав шукати можливість підключити до нього якісь зовнішні пристрої.

Перше, що трапилося — плата PicoBorad. Необхідні для роботи з нею блоки інсталюються разом з системою Scratch. Але ціна на неї відлякує (після ознайомлення з можливостями ще й дивує).

На щастя, і сама плата, і програма до неї доступні на GitHub та ще й під вільними ліцензіями, тому ними можна скористатися. Для варіанту «зробити за вечір, щоб увімкнути і подивитися» я вибрав Arduino nano та макетну плату для монтажу дротиками. Змінні резистори з припаяними штирями у мене вже були зроблені раніше, тому паяти не довелося зовсім.

Оскільки і у платі PicoBoard, і в Arduino nano стоїть однаковий процесор, не було потреби навіть перепризначати ніжки і можна було б просто зашити готовий .hex. Але то було б зовсім нецікаво і я вирішив переписати ту коротку програму як arduino-sketch. Ну сподобалася мені назва Sketch for Scratch :-) Заради цього я навіть встановив оболонку Arduino і відновив у платі стертий раніше bootloader.

Вийшов коротенький скетч, який можна подивитися тут » » »

Порти STM32F30x

От не чекав такого.

Є у Cortex-ів M0/M3/M4 така зручна штука, як bit-band, призначена для атомарної роботи з однісіньким бітом IO або пам’яті.
Коротко, для тих, хто не знає — два одномегабайтних регіони адресного простору, в яких цей механізм працює, мають поставлені їм у відповідність 32-мегабайтні регіони bit-band. Кожна адреса 32-бітного слова у цих регіонах відображається на один біт відповідного 1-мегабайтного, тобто старші 20 біт адреси всередині bit-band регіону вибирають слово у відповідному 1-мегабайтному, а молодші 5 —вибирають біт у цьому слові. Звертання на запис десь на апаратному рівні контролера пам’яті призводить до циклу читання-модифікація-запис зі зміною одного біту.

Ну так от, чому я саме про F30x. Попросили тут організувати одному студентові робоче місце з STM32F3DISCOVERY — компілятор-те-се, допомогти стартувати. Вирішив відразу показати scmRTOS як просту-швидку і практично дармову по ресурсах та нескладну в освоєнні міні-RTOS. Порт для Cortex-M4F є, прикладів для STM32F4xx вистачає. Вирішив почати з найпростішого 1-EventFlag (він зовсім простий майже у всіх портах scmRTOS, ускладений я зробив колись для AVR та STM8). Поліз модифікувати startup.c з таблицею векторів, у sysinit.cpp переписав ініціалізацію PLL.
Ну і ще pin.h, C++-ний аналог «Волковських» макросів на препроцесорі мови C для роботи з портами.
Все так наче нормально, GPIO у STM32F30x по організації такі ж, як у STM32F2xx та STM32F4xx — той же принцип, такі ж регістри (практично такі — у F3 повернули назад регістр BRR, який був у STM32F1xx, а у F2 та F4 пропав, скинути біт порту можна лише через верхню половину BSRR).
Підправив базові адреси портів, компілюю, зашиваю… Висить.
Ну, думаю, десь щось або в ініціалізації PLL, або десь у векторах чи в самій rtos щось таки треба міняти. Вирішив мигнути кілька разів світлодіодами до OS::run(), тобто до дозволу переривань під час запуску ОС.
Не мигають.
Перевірив код ініціалізації PLL. Все нормально.
І тут… І тут… І тут до мене доходить, що базові адреси портів дещо незвичні після STM32F1xx та тих, що були у старому pin_stm32F4xx.h у прикладах.

Лізу знову у документацію. Отже:

У кортексів два 1-мегабайтних регіони з відображенням на bit-band
SRAM: 0×20000000-0×20100000 → 0×22000000-0×24000000
PERIPH: 0×40000000-0×40100000 → 0×42000000-0×44000000

У STM32F1xx GPIO на APB2, діапазон 0×40010800-0x400123FF, потрапляє у bit-band
STM32F2xx, STM32F4xx — на AHB1, діапазон 0×40020000-0x400223FF, потрапляє у bit-band
STM32F30x — на AHB2, діапазон 0×48000000-0x480017FF, НЕ потрапляє у bit-band

Таймери-АЦП потрапляють, а це – ні! У таймерів з різних місць атомарно клацати бітиками дозволу/заборони переривань на CC-каналах теж приємно, але ж місця там валом, все б влізло, навіщо було GPIO закидати так далеко?
Довелося переписати весь цей pin.h у стилі «прочитали, наклали маску, врізали біти, записали». Для роботи з виходом атомарність залишається завдяки старим-добрим BRR/BSRR, з усім іншим (перемикання вхід/вихід/альтернативна функція, pull-up/pull-down) тепер треба буде уважно.

p.s. Пора розбиратися з GDB через OpenOCD, ними б я за хвилину проблему знайшов би…

[flagcounter image]