Сезон снежных крепостей 2022-2023
Опять и снова :)
Альбом: https://disk.yandex.ru/a/3Gpki_UxTvZXjQ
Фото под катом
Hatred's Log Place
Опять и снова :)
Альбом: https://disk.yandex.ru/a/3Gpki_UxTvZXjQ
Фото под катом
Жжот дурилко. Все помним про вызов функции vs конструирование объекта:
struct foo { foo(int) {} };
int main() {
foo(3); // временный объект
}
vs
void foo(int){}
int main() {
foo(3); // вызов функции
}
Теперь такое:
struct foo {
foo() = default;
foo(int v) : x(v) {}
int x = 1;
static int s;
};
int foo::s; // где храним
int main() {
foo(s);
}
На правах заметки.
В народе этот чип называют “клоном” Atmega328P или “антикризисным Arduino” (ну не сам чип, а те платки, которые доступны на AliExpress).
Даташит смотреть в разделе “Полезные ссылки и документация”.
Клоном оно не является. Это самобытная разработка, которая в некотором отношение по пинам (в некоторых режимах) совместима ATmega328P. При этом, если, к примеру, плату с Али зашить обычным примером я миганием светодиода, собранным для BSP Arduino Nano, то диод будет мигать неадекватно. Т.е. для этого контроллера нужно свой пакет BSP, как, к примеру, для совсем “левых” контроллеров, типа ESP32.
Т.е. из схожего:
Основные особенности LGT8F328P:
Хорошее ревью с примерами кода: Обзор клона меги328 -LGT8F328P
В общем, контроллер новый, самобытный. Для домашнего использования очень интересен, но для промышленного использования я бы поостерёгся использовать.
Для домашнего использования хорош и тем, что можно купить на Али версю платы Нано за ~115 рублей с бесплатной доставкой против 250 рублей за аналогичный Nano v3. Плюс платы с односторонним расположением элементов, что позволяет монтировать на плату в виде модуля.
Статья: LGT8F328P Arduino совместимая плата. Программирование на чистом Си
Ну а инструмент называется: LGTSDK Builder
Теперь про интеграцию в Arduino IDE. Как я писал выше - нужен свой BSP. Как минимум настройки для PLL и EEPROM при старте.
Я нашёл более-менее работающих два:
Рекомендую ознакомиться так же со ссылками на страницах обоих BSP. Можно найти полезного.
Рекомендую именно его на момент 2024.11.26 (актуальная версия: 2.0.7), до этого рекомендовал Nulllab
Ставим через Board Manager в Arduino IDE. В File → Preference, Settings tab добавляем:
https://raw.githubusercontent.com/dbuezas/lgt8fx/master/package_lgt8fx_index.json
На момент первоначального составления заметки была актуальна версия 1.0.5 (оригинальный BSP LGT8fx выглядел заброшенным.) и была доступна неофициальная 1.0.6 (ака v1.0.7 pre release), которая:
Естественно ставить её нужно было вручную. Сейчас же (2023.06.23) актуальная версия - 2.0.6, уже содержит вышеупомянутые доработки.
Для установки в Board Manager вводим:
gt8fx
И ставим “LGT8fx Boards”
В Tools → Board → LGT8fx Board выбираем единственную (2023.06.25) борду: LGT8F328. Собственно на ней и собраны популярные “клоны” Ardunio Nano и Arduino Pro Mini.
После этого выбираем в Tools → Variants выбираем:
Из настроек полезные, по сути, только частота работы и что используется: внутренний клок или внешний кварц.
Внешний кварц понятен, есть три варианта (Tools → Clock Source):
Внутренний клок всегда один (там же, Tools → Clock Source):
А вот нужную частоту работы уже догоняем делителями (Tools → Clock Divider): 1, 2, 4, 8, 16, 32
Я не разбирался, работают ли делители, при выборе внешнего кварца, но для внутреннего клока они точно работают.
Следующие настройки, скорее всего, никогда не придётся менять:
Настроек для размера EEPROM нет, он есть всегда и его размер - 1 кБ. Если нужна гибкость в настройке - используйте Nulllab BSP,
Ну и стоит отдельно упомянуть, что этот BSP - это развитие “официального” оного: https://github.com/LGTMCU/Larduino_HSP. Можете и его попробовать. В некоторых источниках есть и на него ссылка.
В целом можно и его рекомендовать: широкий набор источников клока, делителей (косвенно, через указание конкретной частоты) и возможность настройки EEPROM. Но LGT8fx Boards очень оживился, а этот как был версией 1.0.3 на момент составления заметки (2022.12.04), так и остался на момент правки (2023.06.25).
Ставим через Board Manager в Arduino IDE. В File → Preference, Settings tab добавляем:
https://raw.githubusercontent.com/nulllaborg/arduino_nulllab/master/package_nulllab_boards_index.json
Nullab в Board Manager ищется по словам… nulllab :-) При выборе борды нужно выбрать:
При этом станет доступен полный “тюниг” для всех борд:
Как и LGT8fx Boards - это развитие “официального” BSP: https://github.com/LGTMCU/Larduino_HSP.
Естественно - Aliexpress. Я брал:
Табличка, где сравнивается скорость выполнения в тактах некоторых ассемблерных команд в обычном AVR и в LGT8 (по данным по ссылке 1):
Instruction Function Cycle of AVR Cycle of LGT8XM
ADIW Add immediate to word 2 1
SBIW Subtract immediate to word 2 1
MUL/S/SU 8bit multiply 2 1
FMUL/S/SU Fractional multiply 2 1
RJMP/RCALL Relative jump/call 2/3 1
IJMP/ICALL Indirect jump/call 2/3 2
RET/IRET Return 4 2
CPSE Compare, skip if equal 1/2/3 1/2
SBIS/SBRS Skip if set 1/2/3 1/2
SBIC/SBRC Skip if cleared 1/2/3 1/2
LD/LDD Load indirect 2 1
ST/STD Store indirect 2 1
LPM Load program memory 3 2
PUSH/POP Stack access 2 1
Другие MCU от LGT в платах Arduino и их сравнения:
Вместо вводного слова: начала писать аж 16 сентября, а собрался закончить только 27 ноября (я появилось только 28)…
Короткое интро: на данный ноут больше не выпускают оригинальных батареек и купить, соответственно, их не возможно. А можно купить что-то на Aliexpress или (дороже и, скорее всего, хуже) на локальных площадках.
Но покупка на Ali тоже лотереей: первая батарея нормально себя вела, но кончилась очень быстро. Вторая, пришедшая, буквально недели три назад, прекрасно разряжалась, но отказалась заряжаться в моём нотбуке. Спор не заводил, китаец предложил выслать ещё одну батарейку, правда на 6 ячеек. К слову, прошивка, которая убеждает EC принимать любую батарейку, а не те, что в белом списке, тоже не помогла.
Текущая батарейка, заказанная под видом оригинальной (вот яж лох), ещё дышала (но отрубалась резко на заряде от 10% до 30%), поэтому решил попытаться что-то с ней сделать: у меня были контроллеры от старых, но рабочих батарей.
Кому интересно - под кат.
Они же:
В общем речь о переходных отверстиях по краю платы, которые “разрезаны” пополам и используются для краевого монтажа собранного модуля на другую плату…
Yet another contribution. В общем :)
Зашёл очередной фикс. Поломашка в master, и скорее всего никого пока не задела. Кроме отмороженных, кто сидит на ночных сборках или собирает сам:
Больше фиксов хороших и разных!
UPD: и практически следом:
Наконец-то починили. Джва года ждал:
В Konsole есть такая возможность: при возникновении сигнала в терминале, который генерируется, например, так:
echo -e '\a'
или так:
tput bel
сделать какие-то действия.
Настраивается: Меню (если выключено: Ctrl+Shift+M) → Настройка → Настроить уведомления…
Нас интересуют:
Что бы выделить терминал в панели задач, нужно включить пункт “Выделить программу в панели задач” и нажать Применить или Ок.
Собственно, что это даёт: когда сигнал возникнет, то Konsole выделит, подсветит кнопку приложения в панели задач, примерно так:

При этом сделает это на текущем экране, вне зависимости от того, на каком рабочем столе находится приложение. А если кликнуть по ней, то автоматически активируется окно с переключением на соответствующий рабочий стол.
Плюсом, что сигнал может быть и на удалённом сервере, при подключении через SSH: терминал обрабатывает событие локально.
А удобство в том, что можно запустить длительный процесс сборки и переключиться на чтение документации или кода. Или котиков в интернете смотреть. Не важно, главное, что окно покажет, что процесс завершился и стоит глянуть результат.
Запуск примерно так:
make -j8 ; tput bel
Не стоит ставить &&, или ||: мы же хотим среагировать при любом коде возврата make? Но если нужно именно для успешного или наоборот неуспешного завершения сигнализировать, то карты вам в руки.
На днях поборол жабу, и позволил себе купить на замену стокового системного HDD HGST Travelstart Z7K500 / 500Гб, новый SSD Samsung SSD 870 EVO.
Первое впечатление - систему стероидами накачали. А дальше - увлекательная процедура миграции нужного и не очень в новое окружение.
После неудачного удаления всех точек и треков с навигатора, решил, что автоматический бекап это наше всё.
Сделал средствами Systemd.
Для начала определяемся с местом для бекапа, пусть это будет ~/Documents/GPX и создаём там скрипт ~/Documents/GPX/sync.sh. А внутре… у ней неонка:
#!/bin/sh
#
# Ref:
# https://askubuntu.com/questions/25071/how-to-run-a-script-when-a-specific-flash-drive-is-mounted
#
# `systemctl list-units -t mount`
#
# "~/.local/share/systemd/user/garmin-backup.service"
#
#
# ```
# [Unit]
# Description=Backup GARMIN GPSMAP 64s GPX data
# # Use output from the: `systemctl list-units -t mount`
# Requires=run-media-hatred-GARMIN.mount
# After=run-media-hatred-GARMIN.mount
#
# [Service]
# ExecStart=/home/hatred/Documents/GPX/sync.sh
#
# [Install]
# WantedBy=run-media-hatred-GARMIN.mount
# ```
#
# `systemctl --user start garmin-backup`
# `systemctl --user enable garmin-backup`
#
# Monitor:
#
# ```sh
# journalctl --user --unit garmin-backup -f
# ```
#
prefix="/run/media/hatred/GARMIN/Garmin/GPX"
dir=$(dirname $0)
cd "$dir"
echo "Work dir: " $(pwd)
sleep 2
stat "$prefix" 2> /dev/null && \
rsync -rubv --suffix=.old "$prefix" . && \
touch sync_last.txt && \
notify-send -u normal -a "Garmin Sync" "Garmin GPSMAP 64s" "Backup done"
Да, я не разбирался с переменными для имени пользователя, поэтому указывал полные пути с учётом своего рабочего аккаунта: hatred. Т.е. нужно будет скорректировать под себя.
Следующий шаг: сам юнит. ~/.local/share/systemd/user/garmin-backup.service:
# Ref:
# https://askubuntu.com/questions/25071/how-to-run-a-script-when-a-specific-flash-drive-is-mounted
#
# systemctl list-units -t mount
# systemctl --user start garmin-backup.service
# systemctl --user enable garmin-backup.service
#
# journalctl --user --unit garmin-backup -f
#
[Unit]
Description=Backup GARMIN GPSMAP 64s GPX data
Requires=run-media-hatred-GARMIN.mount
After=run-media-hatred-GARMIN.mount
[Service]
ExecStart=/home/hatred/Documents/GPX/sync.sh
[Install]
WantedBy=run-media-hatred-GARMIN.mount
Тут главное, это запуститься, когда увидим, что нужно устройство примонтировалось. У меня, когда монтируется GARMIN, он использует метку GARMIN для своего внутреннего хранилища (куда и пишутся GPX файлы). Путь для монтирования выходит /run/media/$USER/GARMIN.
Systemd создаёт временный сервис, на который можно сослаться. Если просто, то возьмите путь монтирования, у меня это /run/media/hatred/GARMIN, замените все / на - (кроме первого) и добавьте в конце .mount: run-media-hatred-GARMIN.mount. Ну или смотрим вывод:
systemctl list-units -t mount
после монтирования раздела GARMIN.
А за подробностями по ссылке:
После этого включаем сервис:
systemctl --user enable garmin-backup.service
systemctl --user start garmin-backup.service
Последить за работой:
journalctl --user --unit garmin-backup -f
“Никогда такого не было и вот опять” (с). В этот раз зависание имеет место быть, если воткнуто какое-то USB устройство.
Я уже толком не вспомню ход разбирательства, но меня смущал тот факт, что на 5.10 этой проблемы изначально не было и нет на более ранних LTS ядрах, которые имеют место быть в Manjaro (вот тот самый случай, когда несколько ядер это лютый вин).
Первая мысль: помирает железо. Тем более, что в какой-то момент стало невозможно работать с мышкой Logitech MX Master, подключенный по BT. BT на ThinkPad T530 подключен по USB. Невозможность заключалась в том, что она постоянно отваливалась и подключалась опять. Лаги очень раздражали.
Потом что-то меня навело на мысль, посмотреть на параметры модулей-драйверов USB:
xhci_hcd - USB 3.0 (или по модному: USB 3.2 Gen1)ehci-pci - USB 2.0Больше интересовало второе, так как все проблемные подключенцы были на USB 2.0. Выхлоп примерно такой:
$ modinfo ehci-pci
name: ehci_pci
filename: (builtin)
license: GPL
file: drivers/usb/host/ehci-pci
author: Alan Stern
author: David Brownell
description: EHCI PCI platform driver
И тут меня заинтересовала эта строчка:
filename: (builtin)
Это означает, что модуль встроен в ядро. К слову, даже если он встроен, его параметры и интерфейс доступны через /sys/module/.
Решил глянуть, как обстоят дела на 5.4, а там модуль собран отдельно:
$ find /lib/modules/5.4.176-1-MANJARO/ -name '*ehci*.ko*'
/lib/modules/5.4.176-1-MANJARO/kernel/drivers/usb/host/ehci-pci.ko.xz
/lib/modules/5.4.176-1-MANJARO/kernel/drivers/usb/host/ehci-hcd.ko.xz
/lib/modules/5.4.176-1-MANJARO/kernel/drivers/usb/host/ehci-fsl.ko.xz
/lib/modules/5.4.176-1-MANJARO/kernel/drivers/usb/host/ehci-platform.ko.xz
Что это означает? Всё, что встроено в ядро может инициализировать на самых ранних стадиях старта системы, ещё на этапе работы с RAM-диском (initrd) и даже вообще до подключения корневой файловой системы. А модули уже подгружаются или с initrd образа или уже с основной файловой системы, тут как настроено.
Я уже сталкивался с ситуацией по работе, когда подобное различие влияло на работу системы. Получалось, что модуль, ответственный за работу одной железки стартовал достаточно рано, когда блок, генерирующий тактовый сигнал (“клок”) не неё ещё не был проинициализирован и завершал свою инициализацию с ошибкой. Типичное состояние гонки. Да, на этот случай предусмотрен специальный код возврата EPROBE_DEFER и он не был использован в этот раз чисто по ошибке. Но дело в том, что когда драйвер был собран модулем, то он успешно грузился на более поздних стадиях загрузки системы и клок был проинициализирован и устройство запускалось нормально.
Собственно, на этом месте, у меня, похоже, и зародилась мысль: слишком ранняя инициализация, возможно что-то не стабилизировалось и нужно попытаться как-то переинициализировать железку после старта.
Самый просто способ: вынести драйвера в виде модулей. Но пересобирать ядро не хотелось. Поэтому включил логику: почти все драйвера предлагают функционал bind/unbind. Устройства на PCI шине (по крайней мере на PCIe) могут быть пересканированы (т.е. чисто теоретически PCIe - Hot Plug, но лучше не проверяйте :)). А что станет, если после загрузки, отключить железку от драйвера и потом подключить опять? Почти всё железо содержит функционал Reset настроек в исходное состояяние, что будет если сбросить и сконфигурировать всё, когда система уже готова?
Сказано - сделано. И вы не поверите: после загрузки отключил USB контроллеры, подключил обратно и попытался сделать suspend. И сработало! Ядро 5.15 - resume заработал.
К слову, на 5.16 сломано более сильно. И WA ниже не помогает. Сижу на 5.15.
Более того, вылечился BT и мышка перестала отваливаться при работе (при работе через Logitech Unify Receiver она и так работала хорошо, но теперь и по BT стала - плюс один порт свободен).
Код под катом.
Что текущий основной парсер, что грядущий (или нагрянувший, как посмотреть) парсер на clangd работают поверх libclang и сотоварищи и умеют разбирать то, что умеет собирать clang.
Внезапно, он умеет не всё. И это не всё, к примеру, отлично умеет GCC. Вот то, с чем я столкнулся сам:
Под катом будет хак, который я использовал, что бы запуститься и работать с этим добром. UPD: хак больше не работает, так как этот код вообще удалён из репозитория QtC ветки master на момент 23.05.2022.
Но сейчас не об этом. Просматривая изменения в апстриме, наткнулся на этот коммит:
И визуально это выглядит так:

Похоже, жизнь станет проще. К сожалению, мне сейчас не на чем проверить. Как только дойдут руки, то обязательно это сделаю. Как минимум, есть ещё нюанс с неподдерживаемыми параметрами командной строки, но оно сейчас обходится так:
# Hack QtC Clang:
# https://bugreports.qt.io/browse/QTCREATORBUG-22329
export QTC_CLANG_CMD_OPTIONS_BLACKLIST="-mxl-soft-mul;-mlongcalls;-fstrict-volatile-bitfields"
Данная функциональность, судя по этому списку изменений будет доступна в Qt Creator 7.0, т.е. совсем скоро:
Ну а ниже, как обещал - костыль. Требует пересборки Qt Creator из исходников.
Тут обновлял свой CMakeProjectManager2 и краем глаза заметил добавление файла dist/changes-7.0.0.md. Решил перечитать (с некоторыми изменениями я сталкиваюсь регулярно, так как живу на master-ветке).
Там фигурирует:
### C++
* Switched to Clangd by default (QTCREATORBUG-22917)
И таки да, они переключились на кодовую модель от Clangd. Оно появилось ещё раньше, где-то к версии 6.0, но была выключена. Можно ознакомиться с анонсом из первоисточника: Qt Creator and clangd: An Introduction. Или почитать комментарии к соответствующей новости на Phoronix.
В частности, они там объясняют причины. Основная (как мне кажется): libclang больше активно не развивается и для полноценной навигации, рефакторинга и прочего приходится держать две модели.
Там же они рекомендуют использовать самую последнюю версию clangd. Так что ссылки ниже ваши други:
Ну а теперь мои личные впечатления… Точнее табличка, которую я для себя составил. Плюсы и минусы.
В 2016 году (а в 2020 дошли по Большой Пионерской) уже была попытка добраться до Острой по хребту, пробираясь по “милым Приморским рощам” (они же: “Южный Лес”). В этом году решил закрыть этот гештальт, плюс размять ногу после микротравмы на пробежке.
Встречайте: GeoCrop v2.0
Нового функционала не завезли, но обновил для сборки с современными Proj. Сейчас актуальная версия API - 6. Проверял с Proj 8.0.1.
Итак:
Задача: сделать USB стик с Ubuntu, но так, что бы состояние сохранялось. Между перезагрузкам.
Забегая вперёд, это делается, но с одним ограничением: ядро не меняется. Но под мои задачи этого достаточно.