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

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: 0x20000000-0x20100000 → 0x22000000-0x24000000
PERIPH: 0x40000000-0x40100000 → 0x42000000-0x44000000

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

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

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

Генерація таблиці синусів

Дивно, я чомусь думав, що про cog я вже писав.

Знадобилася таблична генерація синусоїдальних сигналів — звичайнісінький функціональний генератор. Накопичувач фази та вибірка готового значення з таблиці. Не я перший, не я останній.

Цікаво, який метод отримання таблиці синусів для найпоширеніший?
Пошук в інтернеті готової таблиці з потрібними параметрами (розрядність даних, амплітуда, кількість квадрантів у таблиці та точок)?
Розрахунки у електронній таблиці (OpenOffice calc чи там MS Excel з експортом у .csv та переносом результатів у C-файл?

Не виключаю, що при певних навичках користування гуглом перший варіант дасть найшвидший результат 🙂
Але це не наш метод. Будь-яка зміна параметрів — і заново шукай чи міняй таблицю. Мені ж зазвичай хочеться автоматизувати процеси. Зрештою, «machines should work, people should think».

Як це часто буває, хтось вже все придумав, лише бери і користуйся.
Є такий чудовий генератор cog. Він шукає у вхідному файлі (написаному не обов’язково мовами С/С++) коментарі спеціальної форми, в яких розміщено пітон-скрипти, і породжує вихідний файл, у якому поруч з початковим текстом додається згенерований фрагмент коду. Тобто можна доповнити написаний код фрагментами, згенерованими автоматично. До генерації власне коду я не дійшов, а от таблички іноді генерую.

»»» Якось так…

Calculate more to calculate faster.

Це може звучати дивно, але для того, щоб зменшити час розрахунків, часто слід збільшити загальний обсяг цих розрахунків. Тут я маю на увазі не «написати/згенерувати більше коду», як, наприклад, при розгортанні циклів при оптимізації -O3 у gcc (саме обчислень при цьому може стати менше за рахунок операції з лічильником циклу). Йдеться про отримання більшої кількості результатів обчислень, ніж це потрібно.

Візьмемо для прикладу такий алгоритм: якщо вхідна величина не перевищує заданий поріг, то видати її значення на вихід без змін, інакше взяти напівсуму входу та порогу. Мовою C алгоритм запишеться так:

»»» Читати далі…

Різні версії WinAVR поруч

Коли виходять нові версії компіляторів, у більшості випадків варто спершу спробувати нову версію в роботі, не відмовляючись остаточно від старої. Лише після перевірки перейти на нову версію, можливо навіть попроектно. Бажано залишити можливість повернення до попередньої.
Для цього необхідно встановити поруч кілька версій:

avr-gcc folders

Але ж треба якось вказати своїй системі програмування, яку саме версію використовувати. Звісно, при необхідності замінити версію витирати з кореня диску каталог C:\WinAVR та копіювати у нього один з каталогів компіляторів це «дещо незручно».
»»» Прочитати, як це можна зробити зручніше…

Розвернути біти

Так чи інакше, а ця задачка вилазить.

В моєму випадкові потреба виникла тому, що Altera FPGA при завантаженні по SPI вимагає потік молодшим бітом вперед, а порт SSP мікроконтролерів LPC17 працює лише старшим бітом вперед. Якраз нещодавно на форумі хтось обурювався, що у STM8 USART в режимі SPI працює лише молодшим бітом вперед: «і кому такий SPI потрібен?». Та от, мені…

Як я вже писав у публікації Двійкові дані та програма мікроконтролера (це що, я так довго не повертався до цієї роботи?), можна було б зробити власну програму обробки конфігураційного масиву FPGA, в якій врахувати також і порядок бітів. Але пристрій може отримувати прошивки програмованої логіки ззовні, тому хотілося б приймати файли в такому вигляді, в якому їх видає Quartus. Менше буде плутанини.

На щастя, Cortex-M3 має спеціальну команду розвороту бітів. Ця команда … » » »

extern “C”

Інформація, яку видає OpenOCD при звичайному завантаженні програми у flash-пам’ять мікроконтролера, деколи може допомогти так, як наче це був запущений зневаджувач.

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

Знову висить.

»»» І тут помічаю, що OpenOCD сповістив мене…

Attached Files:

  • h lpc17xx_handlers

    lpc17xx handler prototypes for C/C++ programs (with extern "C" for C++)

Знову LPC17xx та Peripheral Driver Library

Продовжую набігами знайомитися з мікроконтролерами LPC17xx.
При цьому продовжую лізти на кактус: «щоби швидше», підключаю файли зі стандартної периферійної бібліотеки від NXP. І в черговий раз отримую помилку компіляції. На цей раз — з глибин <sys /reent.h>, який включається до <stdio .h>, якого, своєю чергою, потягнув debug_frmwrk.c з LPC1700 Peripheral Driver Library:

--- compiling ./src/NXP/LPC17xx/Drivers/source/debug_frmwrk.c...
In file included from /opt/klen/arm-kgp-eabi/201109/bin/../lib/gcc/arm-kgp-eabi/
                 4.7.0/../../../../arm-kgp-eabi/include/stdio.h:45:0,
        from ./src/NXP/LPC17xx/Drivers/source/debug_frmwrk.c:41:
/opt/klen/arm-kgp-eabi/201109/bin/../lib/gcc/arm-kgp-eabi/4.7.0/../../../
    ../arm-kgp-eabi/include/sys/reent.h:469:10: error: #if без виразу

Причому що в збірці arm-kgp-eabi від Klen, що в CodeSourcery — те саме (the same, як сказали б англомовні). Тільки номери рядків відрізняються та CodeSourcery, на відміну від Klen-ового пакету, зібрано без підтримки локалізацій і він каже #if with no expression а не #if без виразу.

Лізу дивитися sys/reent.h »»» І що ж я бачу? …

OpenOCD, LPC17xx та srec_cat

Boot-loader в мікроконтролерах LPC17xx очікує 32-бітну контрольну суму перших семи слів прошивки (вміст вказівника стеку, та перших шести векторів) на місці не використовуваного вектора по адресі 0x1C. В це слово записується мінус-сума перших семи слів. Схожим чином перевіряє наявність програми і бутлоадер LPC2000.
OpenOCD вміє «на льоту» генерувати таку контрольну суму при програмуванні мікроконтролера, потрібно лишень в команді flash вказати аргумент calc_checksum (ця команда є у файлі target/lpc17xx.cfg пакету).
Але чомусь він не генерує її для звірки вмісту (верифікації). Причому сам він знає, що мені буде незручно, раніше навіть писав щось таке:

Warn : Verification will fail since checksum in image (0x00000000) to be written
    to flash is different from calculated vector checksum (0xeffee33a).
Warn : To remove this warning modify build tools on developer PC to inject
    correct LPC vector checksum.

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

Двійкові дані та програма мікроконтролера

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

У моєму випадку це теж прошивка, але для програмованої логіки (FPGA). Цю прошивку можна отримати у вигляді файлу .ttf (tabular text file, а не true type font :-)), у якому знаходяться десяткові числа, розділені комами.
Колись давно, ще «десь між i87c51FA та AT89C55» я з такого файлу для EPF8282 генерував asm-файл. Програмою sed додавав до та після масиву чисел потрібні заголовки з мітками, на початку кожного рядка директиву .DB і тому подібне. Асемблерний файл згодом компілювався в об’єктний та прилінковувався до програми.
Для ATmega162 та EP1K10 користувався власноруч написаною програмою — основна її робота була стиснути прошивку для альтерини простим, але ефективним алгоритмом, а вже видати назовні C-масив то була проста робота.
Тепер у мене LPC1766 та EP1C3. Циклони вже мають в собі декомпресор і квартус може стискати прошивки. Він це робить гірше, ніж алгоритм від Ivan Mak, але він це робить сам і розпаковує теж без мене. Тому я, принаймні зараз, повертаюся до простого перетворення стороннього файлу прошивки в об’єктний файл з масивом.

Зараз для таких робіт зазвичай пропонують вже готові програми на зразок bin2c для генерації C-шного масиву. До речі, на мою думку, однією з найкращих програм на тему все2всюди є пакет srecord.
Але при роботі з компіляторами gcc (точніше, з набором програм GNU binutils, яким користується і gcc) можна обійтися без додаткових програм, »»» прочитати — яким саме штатним інструментом з пакету та як…

[flagcounter image]