cstdint, arm-none-eabi- та Ubuntu

Міняв диск, заразом поміняв і Убунту 16.04 на 18.10. Як і минулого разу на шістнадцятій, поставив «рідний» для системи пакет arm-none-eabi-. Мабуть, пора закінчувати з такою практикою, всістися на якусь іншу збірку компілятора, ту ж linaro. Бо проекти перестали збиратися. І на чому, на рівному місці! Компілятор не знаходить файл cstdint.

Короткий пошук показав, що версія компілятора 6.3.1, include-файли лежать в /usr/lib/gcc/arm-none-eabi/6.3.1/include та в /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/include, який, зрештою, вказує на /usr/include/newlib.

А от заголовочні файли C++ лежать в /usr/include/newlib/с++/7.3.1. Звідки взялася сімка — важко сказати. Може це одрук, може дійсно поклали іншу версію, але жодного файлу від C++ cpp не знаходить. Назву 7.3.1 вирішив не чіпати, просто поруч додав лінк 6.3.1->7.3.1. Після цього cpp по -v показав додаткові шляхи до файлів і все стало збиратися.

Недорога плата розробки для STM32L05x

Останнім часом я трохи працюю з мікроконтролерами STM32, зокрема STM32L011 і STM32L051, але то все конкретні плати, на яких виводи задіяно під конкретні функції. І коли раптом хочеться поколупатися із якоюсь ідеєю, то на тих тісних платах то страшенно незручно. А використати їх як носій мікросхеми, прибравши все зайве, так прибирати доведеться майже все і то буде навіть гірше, ніж просто перехідник «TQFP на штирі».

Існують плати STM32L1xxDISCOVERY, але там на найдешевших одна радість — вбудований «фірмовий» ST_LINK. Платити за те під 500 гривень неохота. Та й на них L100 або L152, а мені сподобалися STM32L0xx.

От для STM32F103C8 є декілька варіантів плати, яку називають «синя таблетка» (що викликає деякі застарілі асоціації[1]). Недорого, є необхідний мінімум.
Але то F103…
Тю, так виводи ж у STM32 стандартизовані!
STM32F103C8 і STM32L051C8… Співпадають!
Чудово, вчора син по дорозі зі свого університету заїхав у мікроАмпер і забрав потрібну плату, я ж заїхав у Імрад і взяв STM32L052C8, щоб вже й USB було.

Сьогодні на роботі скористався службовим становищем — попросив похімічити, здути F103 і запаяти на її місце L052:
Створення плати розробки STM32L052 із плати STM32F103

Під дією тепла проведено реакцію, у результаті якої я отримав бажану плату, а STM32F103C8 випала в осад. Залежно від того, чи буде цей мікроконтролер десь використаним, плата розробки для L05x обійшлася у суму від десь 110 до 180 гривень.

p.s. Там ще STM32F303C у такому ж корпусі TQFP48 бувають 😉


1 Колись давно мем про червону і синю таблетки використовували на форумах як вибір між червоним кольором PIC/Microchip і синім AVR/Atmel. Тепер і те і те мірочіпівське, хоч кольори і не помінялися.

Китайський 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 все працює, це точно генетичний дефект клона. Кажуть, його можна перепрошити на інший, кращий програматор, але зараз не до того.

Порти 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, ними б я за хвилину проблему знайшов би…

Порахувати більше, щоб порахувати швидше.

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

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

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

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

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

В моєму випадкові потреба виникла тому, що 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 »»» І що ж я бачу? …

LPC175x and LPC176x Standard Peripheral Firmware Driver Library

Взяв я трохи поколупати платку з мікроконтролером LPC1768.
Спробував використати стандартну бібліотеку lpc17xx cmsis driver library, щоб трохи менше думати. Звісно, документацію на мікроконтролер все одно читати треба. Але здалося простіше викликати функцію для налаштування потрібної периферії, передавши їй кілька парметрів, ніж самому уважно комбінувати ті параметри в кілька регістрів. Та ще й, можливо, про порядок запису треба буде думати.

З часів інтелівського ApBUILDER-а — програми для генерації коду ініціалізації для MCS-51, MCS-196, … — я всю роботу з периферією завжди робив вручну. Тобто, я і до цього робив вручну, а тим ApBUILDER-ом спробував і відмовився. І знову лише вручну. Читаєш собі документацію на потрібний модуль та й потихеньку пишеш всі ці маски/зсуви. Константи для них у файлах від компілятора чи виробника мікроконтролерів є — і то добре.
А тут — на тобі… Вирішив полінуватися…

Читати про покарання за лінощі » » »

Attached Files:

[flagcounter image]