Автор: bevice

MacOS QuickLook и всякие файлы

ставим QLColorCode (brew install qlcolorcode), снимаем метку карантина, сраная макось бережет нас, даже когда не нужно:

sudo xattr -d com.apple.quarantine ~/Library/QuickLook/QLColorCode.qlgenerator

получаем MD-ContentType, для чего есть команда mdls (man mdls)

mdls -name kMDItemContentType some.file.ext

которая выдаст что-то вроде:

kMDItemContentType = "dyn.ah62d4rv4ge80s52"

запихиваем в Info.plist QLColorCode, ~/Library/QuickLook/QLColorCode.qlgenerator/Contents/Info.plist в массив открываемых типов, найти просто, куча строк со знакомыми названиями, вроде:

<string>public.ruby-script</string>
<string>public.yaml</string>

Добавляем свой:

<string>dyn.ah62d4rv4ge80s52</string>

перезапускаем Finder, все должно взлететь

P.S.

Еще крутые QL невозбранно подглядываются на:

Quick Look Plugins Awesome

Rocky Linux 8.4 Open vSwitch

Прикручивать к системе буду через network-scripts, хоть и legacy, но просто, быстро и без бубна. А NetworkManager вообще выключу к х.ям. И вообще это заметка для себя, потому что OVSDHCPINTERFACES и OVSBOOTPROTO как-то не сразу обнаружилось, а надо было.

Устанавливаем пакеты, в два этапа

dnf install -y centos-release-nfv-openvswitch
dnf install -y network-scripts openvswitch2.13

Запускаем OpenVSwitch

systemctl enable --now openvswitch

Добавляем OVS свитч ovs-br0, порт в него добавим позже, иначе отвалится сеть

ovs-vsctl add-br ovs-br0

Создаем файлы конфигурации свитча

cat > /etc/sysconfig/network-scripts/ifcfg-ovs-br0 << EOF
DEVICE=ovs-br0
BOOTPROTO=dhcp 
ONBOOT=yes
TYPE=OVSBridge
PEERDNS=yes
IPV6INIT=no
# Static IP
IPADDR=192.168.0.2
NETMASK=255.255.255.0
GATEWAY=192.168.0.1
DNS1=192.168.0.1
DNS2=1.1.1.1
#Or DHCP Config, BOOTPROTO должно быть none
OVSBOOTPROTO=dhcp
OVSDHCPINTERFACES=enp0s3
EOF

И его порта,

cat > /etc/sysconfig/network-scripts/ifcfg-enp0s3 << EOF
DEVICE=enp0s3
ONBOOT=yes
TYPE=OVSPort
DEVICETYPE=ovs
OVS_BRIDGE=ovs-br0
EOF

Выключаем NetworkManager и заводим sys-v скрипты

systemctl disable NetworkManager
systemctl enable network

Вот тут кончится сеть или перезагружать компьютер через минутку (shutdown -r +1)

ovs-vsctl add-port ovs-br0 enp0s3

или выполнить в скрипте

systemctl stop NetworkManager
systemctl start network

Ну а дальше:
https://habr.com/ru/post/242741/

ARM Without Magic. Урок 1.2 Линковка

Пришла пора привести в понятный вид скрипт линковки для прошивки под STM32 (или любой другой ARM Cortex-M).
Прошлый раз мы писали как попало и не очень понятно было, где и что лежит. Будем устранять непонятности.
Я все время говорю – символы, секции. Давайте займемся терминологией.
Первое и главное – это символ. Для компоновщика символ это именованный адрес не более того. (правда похоже на переменную в любом языке программирования?). Причем не важно, что скрывается под этим символом – адрес переменной, код функции, все что угодно. Плюс некоторые «атрибуты», такие как принадлежность к секции, размер. Когда в коде написано uint32_t var_a = 12345;, при компиляции создается символ var_a, в атрибуты помещается размер в 4 байта и принадлежность к секции .data (мы уже говорили, что инициализированные переменные попадают в эту секцию). Для функций – примерно тоже самое, только секция будет .text, ну и размер нельзя вот прямо так сразу назвать, но после компиляции он конечно же будет известен.
Читать далее

ARM Without Magic. Урок 1.1 Переменные и инициализация.

В прошлый раз мы оформили только две секции в прошивке, для таблицы векторов прерываний и кода. Поморгать светодиодом таким образом можно, а вот для работы с переменными нужно еще чуть-чуть допилить.
Но для начала неплохо бы разобраться, где и как хранятся переменные. Из учебника по C мы помним, что переменные бывают: локальные, статические и динамические. Напомню, что из себя они представляют.

  • Переменные локальные, которые объявляются внутри функций хранятся в стеке, всю работу по выделению памяти, инициализации и последующему удалению берет на себя компилятор, нам никаких действий предпринимать не нужно.
  • Статические переменные хранятся в специальных секциях в области оперативной памяти, память под них выделяется на этапе линковки, а инициализация должна быть выполнена при загрузке микроконтроллера.
  • Память под динамические переменные выделяется во время работы программы, они так же хранятся в специально отведенном регионе памяти. Но с точки зрения линковщика нужно только сообщить системным вызовам размер этого региона, все остальное остается на совести программиста. В основном считается, что использование динамической памяти на микроконтроллерах — это плохо (почему?). Поэтому пока мы не будем их использовать, оставим этот вопрос открытым на потом.

А сегодня мы займемся статическими переменными.
Читать далее

ARM Without Magic. Урок 1.0 Самое начало.

Небольшое предисловие.
Этот урок, как и последующие, написан прежде всего для новичков в прошивко-строении и не совсем новичков программировании. Для людей, которые хотят разобраться, как все устроено и почему работает именно так. После вдумчивого прочтения этого курса не должно остаться никаких вопросов, о том, что делает та или иная строка в любом файле, какие команды для сборки и отладки прошивки вызываются, для чего они нужны и как работают. Я постараюсь избавиться от ассемблерных вставок (в паре мест они будут, но не более), все что нужно знать – это язык программирования C на каком-то начальном уровне, сложные места постараюсь разъяснять. Ну и конечно для чтения документации потребуется хоть немного знать английский язык, к документации мы будем обращаться часто.
Я не буду особо заострять внимание на работу с блоками периферии, во-первых, потому что они все время разные, а во-вторых, по этой теме написаны тысячи статей и отснято тысячи бестолковых видеоуроков, что я вряд ли смогу сказать что-то новое и полезное. Я склоняюсь к тому, что лучший учебник по управлению светодиодом и отправке несколько байт через USART — это документация на соответствующий процессор. Она правильная и полная. В общем этакий экскурс в BareMetal для прикладных программистов. И основное отличие прошивки МК от прикладной программы в том, что все приходится делать самому. Инициализировать переменные, раскидывать секции по правильным адресам. Обычно это скрыто под капотом всяких IDE и их шаблонов, да так хорошо спрятано, что многие относятся к этим процессам как к магии: поставил волшебных галочек или произнес страшное заклятие — и прошивка собралась. Само по себе это не плохо, я тоже уже не первый год пользуюсь шаблоном для создания новых проектов, но мне нравится знать как оно работает и где подкрутить, чтобы получить требуемый результат.

Мы не будем привязываться к какой-то особенной среде разработки, мы не будем пользоваться генераторами проектов типа STM32 CubeMX, мы на первом этапе вообще прошивку руками соберем, без всяких систем сборок, и отлаживать будем тоже руками.

Ориентироваться я буду на процессоры STM32, так как с ними мне приходится работать чуть ли не каждый день, они дешевые и доступные. Из приборов для начала потребуется отладочная плата на процессоре STM32F103C8 (например Blue-pill) и отладчик ST-Link v2. Все это доступно для покупки на AliExpress за сущие копейки. Но все что будет написано довольно легко адаптировать к любому ARM Cortex-M процессору. Собственно цель курса в том, чтобы, используя полученные знания можно было без труда использовать любой доступный процессор.

Читать далее

Еще немного про Core-Coupled Memory (CCM) на STM32

В дополнение к прошлой заметке
Как я уже говорил, у CCM есть некоторые особенности, чтобы их понять и не наступать на грабли, по каждому чипу лучше всего сверяться с документацией. Например для STM32F407, CCM подключена только к D-BUS (шине данных), поэтому на этих чипах нет никакой возможности выполнять код лежащий в CCM.
Для STM32F3xx наоборот, ST вполне даже рекомендует оптимизировать быстродействие переместим код в CCM, обещая при этом +43% к производительности. Но опять же, согласно RM0316 CCM не имеет подключения к шинам DMA S3,S4 поэтому DMA работать откажутся.

По поводу производительности, по тестам для STM32F407 выходит такой результат, в таблице время выполнения теста относительно FLASH/RAM (больше — хуже):

Код в FLASH Код в SRAM
Данные в SRAM 0% +14.53%
Данные в CCM +2.4% +15.73%

А вот результаты того же теста для STM32F303:

Код в FLASH Код в SRAM Код в CCM
Данные в SRAM 0% 0% -16.93%
Данные в CCM +4.6% +10.77% -12.32%

Читать далее

Проблема со сбросом stm32F7xx в OpenOCD

Симптомы проблемы такие: на версии Open On-Chip Debugger 0.10.0+dev-00924-g16496488 выглядело как ошибка:
in procedure 'program'
in procedure 'program_error' called at file "embedded:startup.tcl", line 474

на Open On-Chip Debugger 0.10.0+dev-00973-g80f1a92b
ошибки нет, но чипу мозг выносит, вместо резета он прыгает в какую-нибудь функцию и там умирает

Вроде как решается правкой stm32f7x.cfg

reset_config srst_only srst_nogate
на
reset_config srst_nogate

STM32 CCM

Есть у некоторых взрослых STM-ок такая дурная штука, как CCM (core coupled memory). Это отдельный регион памяти, не шуточного размера в 64K (для F4xx), который по-умолчанию вообще не используется. Выделена эта память в отдельный регион, потому что имеет подключение только к D-BUS ядра, что накладывает кое-какие ограничения. Главное — это невозможно использовать вместе с DMA и DMA2D и выполнять код (примечание: это для F40x, но вообще неплохо заглянуть в PDF, раздел «Архитектура системы»), а в остальном — память как память.
Есть несколько способов хоть как-то его начать использовать, самый простой способ — это положить туда стек.
Для этого нужно модифицировать всего одну строку скрипта линковки, ту что задает адрес _estack и положить в этот символ адрес конца CCM (0x10010000):

_estack = 0x10010000;    /* end of CCMRAM */

При этом весь стек переедет в CCM и как следствие все локальные переменные, аргументы функции итд.
Второй не менее простой, но довольно ручной способ — это указание секции при описании переменной:

__attribute__((section(".ccmram"))) int ccmvar;

однако, стоит при этом помнить, что без модификации startup-скрипта при инициализации там будет мусор, заполним нулями, добавив где-нибудь после FillZeroBSS

/* Zero fill the CCM segment. */
ldr  r2, =_sccmram
FillZeroCCM:
  movs  r3, #0
  str  r3, [r2], #4
 
LoopFillZeroCCM:
  ldr  r3, = _eccmram
  cmp  r2, r3
  bcc  FillZeroCCM

а заодно уберем в скрипте линковки из описания секции .ccmram запись инициализации во FLASH:

  .ccmram (NOLOAD):
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)
 
    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
   } >CCMRAM

теперь все переменные с attribute((section(«.ccmram»))) будут стартовать с нулевыми значениями.

Подробнее про переменные, секции и инициализацию можно почитать тут: ARM Without Magic. Урок 1.1 Переменные и инициализация.

PJSIP отладка

А вот что сделали удобно, так это отладку.
Вместо грязного sip set debug on, теперь есть история пакетов. Включается запись истории командой

pjsip set history on

выключается соответственно:

pjsip set history off

Посмотреть, что записалось в историю поможет команда

pjsip show history

которая в удобном формате покажет, какие сообщения sip пробежали за время записи, а команда

pjsip show history entry 1

покажет полностью сообщение (пакет) номер 1 (как не сложно догадаться)
В общем, удобно.

Asterisk PJSIP и voip.domru.ru

В догонку к предыдущему, подключение телефонии Дом.Ру к Asterisk pjsip. Поскольку voip.domru.ru желает видеть в регистрации длинный номер (UserID), а идентифицирует по короткому (AuthID) использовать pjsip_wizard не получится, о чем мелким шрифтом сообщает документация придется писать полный конфиг. Впрочем, ничего сложного. Пример конфигурации ниже.
Да, в бумажке по астериску, которую они присылают непонятно зачем устанавливается CallerID, делать этого не стоит — он подменит все входящие звонки.
Читать далее