Как стать автором
Обновить

Комментарии 45

Программировать STM32 ассемблере это как есть гречневую кашу пинцетом по одному зёрнышку. Если цель просто писать программы для STM32, то вам крайне необходимо осознать ущербность писанины на ассемблере и как можно скорее перейти на С/С++.
Полностью с Вами согласен ! именно пинцетом, и именно по одному зернышку!!!

Я любитель, и написание программ на ассемблере это мое хобби (на жизнь зарабатываю совершенно другим, к программированию, компьютерам, микроконтроллерам отношения не имеющем) Мне очень нравиться ассемблер, тем более с системой команд ARM!
а какая ваша основная работа, если не секрет, если программирование на asm под STM32 только хобби?
Управляющий Закрытыми паевыми фондами недвижимости в Управляющей компании (это из области доверительного управления имуществом)…

В провинции программисты не нужны (нужны только настройщики 1С, администраторы (да и то это все крупные компании админят из Москвы/Питера, удел местных «администраторов» обеспечить канал для настройки), установщики Windows, «сниматели» банеров — и все это вряд ли способно дать более менее заметный доход… ну или дает конечно доход, но единицам и пробиться в эти «круги» не так просто и к сожалению собственный профессионализм при этом роли не играет)
Что ж, достойное хобби! Если вы ещё и Си знаете на достойном уровне то тогда вообще супер.
Статья кстати тоже достойная.
нет, к сожалению в Си я слабак :-(
а вот в асме всегда любил «по извращаться», а сколько исходников было потеряно (у меня тут винда-10 «обновила» комп до состояния нового..:-( а архивы как раз на компьютер сбросил чтобы отсортировать...)
нет, к сожалению в Си я слабак :-(

Вот поэтому я ещё раз вам крайне советую всё таки освоить си (пусть без плюсов), гарантирую после вам уже не будет так нравится ассемблер.
ЗЫ Это из личного опыта… Собственно поэтому и написал слегка «резковатый» первый комментарий.
все это прекрасно понимаю, на си пишу понемногу…

но поскольку у меня это занятие хобби и ничего более (по крайней мере пока) — поэтому пишу и на ассемблере…
с ассемблером я с 1993 года, и честно говоря ни на что его менять не хочу, тем более что ассемблер ARM мне очень нравиться набором инструкций

еще раз повторюсь — у меня не стоит дедлайнов по срокам, не нужно работать в команде, и т.д.
Когда нет дедлайнов это приводит к тому что проект не заканчивается никогда.
Да, и я бы сказал не ассемблер а макро-ассемблер нужен, на голом ассемблере далеко не уедешь, а вот дополнительные уровни абстракции делают ассемблер не хуже С когда въедешь в тему и будут какие-то наработки.

Теперь я понимаю, почему многие не хотят писать на ассемблере под ARM-контроллеры — и система команд довольно громоздкая, и названия самих команд несколько странные и не логичные а тут еще узнал что еще и разные системы команд на одном контроллере применяются(наверно для эффективного использования конвеера для разного рода задач?) — свихнутся можно на раз.
С другой стороны, прикладным программистам больше платят чем системным ибо обхват софта больше, видимая польза и спрос соответственно.

Кстати интересно еще посмотреть на реальных проектах насколько широко используются разные инструкции в случае программы написанной на ассемблере и сгенерированной с ЯВУ.
не знаю как у вас, но у меня дедлайн еще никогда не ускорял проект… скорее даже наоборот — необдуманные решения примененные из-за спешки способны убить проект впоследствии возникающими «родовыми» травмами…
На счет абстракции: на ассемблере вполне можно написать отдельные подпрограммы, с тем или иным функционалом, и потом объединить в каком то алгоритме… да на Си выходит проще, да на СИ проще писать переносимый код (хотя я не видел переносимого кода, кроме случаев когда он состоит из операторов самого языка СИ), проще работать в команде (возможно! но не факт), очень много сред с различными возможностями...
— не хочу холивара, я пояснил свою позицию — я не зарабатываю денег написанием программ, и могу себе позволить разбираться с тем языком который мне нравиться (сегодня придумал способ простой инициализации микроконтроллера, в ближайшее время попробую написать). Если будут люди которым это интересно (именно для этого я здесь) — то с удовольствием объединю усилия (есть у меня пара задач которые нужно решить)… пока (судя по количеству комментариев ко второй части публикации — таковых нет :-(… так что буду «развлекать» вас только собственной персоной…

ну в общем то у каждого семейства процессоров свои команды, мне после Z80 с его LD по всем случаям ассемблер I8080 казался больно мудреным :-) потом ассемблер x86 — опять другие команды, потом AVR — и все более менее знакомо (уже как говориться все повидал, все попробовал) хотя конечно после первых трех уже особо не грузишься, просто запоминаешь новые мнемоники…

а вот ассемблер ARM — это что то действительно новое… на счет сложности — сложно пока не начинаешь разбираться… вообще по моему мнению некоторые вещи очень и очень правильны

На счет разных систем команд — все не так страшно, команды одни и те же, просто есть их 32ух битное и 16ти битное кодирование… в принципе по началу об этом можно не задумываться, при желании потом можно провести оптимизацию кода…
Кстати, различие LD и MOV для Z80 были только в старых книжках, а более новые в т.ч. и зарубежные заменяют всё это одной командой MOV хотя это не отражает сути самих команд, но видимо они там думают чем меньше разнообразия в написании команд тем легче будет студентам выучить их…

Возможно, ассемблер ARM разрабатывался с целью лёгкости машинной оптимизации а не написания программ человеком.
я не видел док по Z80 где команды были бы представлены в формате I8080 (то что первый проработка второго знаю, историю создания читал)…

на счет ассемблера ARM — мне трудно судить почему у вас о нем такое мнение… :-(
Статья получилась хорошая, но на мой взгляд в ней не хватает одной важной вещи.
выясняется, что «гуру не пишут проекты на ассемблере», и в средах ассемблер используется максимум для написания процедур и функций требующих максимального быстродействия, или генерации кода содержащего специфические команды микроконтроллера аналог которых не предлагается языком Си (С++ или библиотеками) in-line вставками.

А в самом деле — зачем писать всю прошивку на ассемблере?
Потом дизассемблировать проще :-)

Довелось мне как-то раскуривать загрузчики PalmOS на несколько древних уже Palm Tungsten T3 и Palm LifeDrive. У первого набортовой оперативки не было, и бóльшая часть загрузчика была весьма читабельным листингом, было видно «поток сознания» автора. У LD процессор был уже поновее, с оперативкой, так что ассемблерный кусок настраивал стек, а дальше начинался страх и ужас оптимизированного кода от g++.
Статья классная, на мой взгляд. Сам некоторое время писал на ассемблере под STM32F103 и К1986ВЕ92QI (Миландр, но ядро то же). Довольно интересно было. Но сейчас на работе пишем исключительно местными обертками основанными на HAL (таковы правила). Так что производительность иногда очень страдает. Зато читабельность многократно выше. Жду продолжения.
Отличная статья, годится не только для контролероа STM. Очень хочу почитать чуть больше о файле линковщика, конечно, в инете есть инфа по этому вопросу, но вы все так хорошо описываете :)
То, что часто не описывают набор инструкций, связано с тем, что programming manual вполне полно это делает и нет никакой необходимости его переписывать.

Про магические адреса около 0x0800 0000, то memory mapping определяется состоянием BOOT0 и BOOT1, что описано в reference manual, 2.4. Загрузка всегда начинается с адреса 0x0000 0000, куда при BOOT0 = 0 маппится flash memory (0x0800 0000 — 0x080F FFFF), а при BOOT0 = 1 и BOOT1 = 0 — system memory (0x1FFF 0000 — 0x1FFF 77FF).

Также, использовать адреса 0x0000 0008 — 0x0000 0040 (т. е. и 0x0800 0008 — 0x0800 0040) не стоит, это адреса векторов exception handler'ов. Если используется NVIC, то таблица прерываний будет продолжаться и после 0x0000 0040 с шагом 4 на каждое прерывание. Рекомендуется не трогать кусок памяти до 0x0000 03FC включительно, см. 2.3.4 в programming manual.
Спасибо за информацию! учту!

К слову, что мне пока не очень удобно в документации ST — так это очень большая фрагментированность документации… не всегда понятно где же все таки будет написано искомое :-) потом, когда найдешь, вроде бы начинаешь логику понимать, но вот с «нуля» — очень не удобно искать иголку в стоге сена…

Про таблицу прерываний в курсе, первая программа в статье — это просто проверка возможности написания и компиляции…
Статья — хороший бочонок меда начинающим для вхождения в тему.
Ложка дёгтя — слова «линковщик»\«линковка» вместо более традиционных «компоновщик»\«компоновка».

Такое особенно вредно для начинающих — в комментариях уже цитируют…
Традиционно — линкер (linker) ;) Мне так привычнее ещё со времён DOS, Borland Turbo Pascal и Turbo C.
Писать всю прошивку на ассемблере наверное нужно очень редко, но вот разобраться в том, как именно создаётся образ прошивки — это безусловно полезно.

Только один комментарий:
В следующей статье будем писать прошивку микроконтроллера чтобы реально проверить его работу — будем мигать светодиодом!
Надеюсь, что исходники прошивки из следующей статьи будут выложены в удобном для скачивания и обновления виде, например, в виде репозитория на github.

в виде ссылки на яндекс.диск подойдет? там не просто обновлять придется — у меня плата отладочная не stm32f4 discovery — так что без желания и активных действий мигать «из коробки» ничего не будет.

p.s. вторая статья уже написана и лежит в черновиках, но еще не вычитал :-( обычно когда печатаю допускаю много оЧеПяток, стыдно такое выкладывать… постараюсь завтра разместить, а там уж как модерацию пройдет (эта статья висела 5 дней на модерации в песочницу, я ее потихоньку правил пока админы собирались смотреть)
Дальше оно без модерации, сразу выкладывается. А так в песочнице иногда и по несколько месяцев статьи висят.
Никаких Я.Дисков! Никаких рарчиков! Освойте уже нормальные процессы разработки о обмена исходниками! Тоже мне, рарчики. У нас 2016 год за бортом, а у вас — рарчики. Стыдобень!
в виде ссылки на яндекс.диск подойдет?
Выкладывать исходные тексты таким образом можно только в случае крайней нужды.

Советую не пожалеть времени и освоить git!
Начать можно с Good Resources for Learning Git and GitHub.
Низкоуровневое программирование контроллеров это интересно, стильно, молодежно. Я как то задался целью написать минимальное приложения для STM32 на С без использования ассемблера и сторонних библиотек. Вот что получилось github.com/anatol/stm32f4-examples/tree/master/native/blink01
какой размер получился? (по файлу binary)
у меня оптимизированная мигалка одним светодиодом заняла 68 байт (та что во второй части статьи, написана «в лоб» для понимания, имеет размер — 116 байт)
:-) прикольный «изврат»
но речь все таки о программе…
кстати, в комментариях правильно написали: программа не из одной инструкции, а из 1024 ! :-) так как первая инструкция включает/выключает светодиод, а остальные служат для организации задержки :-)))
Для STM32 бинарников использую

arm-none-eabi-objdump -D -marm --disassembler-options=force-thumb --target binary $INPUT > $OUTPUT
он показывает информацию по секциям…
в этой публикации цель простота и понятность (до сложного дойдем еще), а так вы правы, например, может быть такая «конструкция»:
:: Отдельно информация о каждой секции в файл (вывод в файлы)
bin\arm-none-eabi-objdump.exe  -j .vectors -t -w compile\temp\sys.o > compile\temp\main_vect.lst
bin\arm-none-eabi-objdump.exe  -j .text -d -t -w compile\temp\sys.o > compile\temp\main_text.lst
bin\arm-none-eabi-objdump.exe  -j .rodata -d -t -w compile\temp\sys.o > compile\temp\main_rodata.lst
bin\arm-none-eabi-objdump.exe  -j .bss  -d -t -w compile\temp\sys.o > compile\temp\main_bss.lst
bin\arm-none-eabi-objdump.exe  -j .ccmdataram -d -t -w compile\temp\sys.o > compile\temp\main_ccm.lst
bin\arm-none-eabi-objdump.exe  -j .bkpsram -d -t -w compile\temp\sys.o > compile\temp\main_bkpm.lst
Каждый, кто писал свой бутлоадер для STM32, по-любому должен был столкнуться с асмом. Немножко так, но достаточно для того, что бы запомнить как начинает работать STM32, откуда берет стек, откуда загружает PC, и как называется команда перехода на ассемблере. Ну и немножко потанцевать с бубном вокруг таблицы векторов прерываний, особенно на младших семействах типа stm32f030. А дальше быстро уйти обратно в Си.

Имхо — ARM не доставляет много фана в программировании на ассемблере. Потому что много за чем нужно следить, много периферии, много настроек — внимание распыляется по пустякам, а когда дело доходит до кодинга, то уже и кодить не хочется, потому что замучался тонны строк инициализации копипастить, да еще и ошибся при копипасте и сидишь разбираешься в какой бит положил 1 вместо 0 в одном из сотен 32-битных регистров.

Другое дело 8-битки, да. Меня «прет» иногда покодить что-то для PIC16… А сколько вообще интересных винтажных платформ — 6502, 6809, 8080б 8041… Взять какую-нибудь денди (6502) и закодить для нее демку — вот это было бы здорово. Или из АОН на 8035 сделать часики и термометр. Ну или просто добавть в прошивку поддержку CallerID -)
то есть вы тоже сторонник SPL?
года два назад когда я писал программы с использованием SPL мне постоянно говорили что это как то по детски и профессионалы всегда пишут в регистры напрямую без всяких прокладок :-)))

а на счет инициализации — у меня она вообще теперь выглядит как список, для мигалки так:
Настройка GPIOH PH2/3
@ ***************************************************************************
@ * Список конфигурации для мигалки *
@ ***************************************************************************
@ * для порта GPIOH выводов PH2, PH3 *
@ ***************************************************************************
.word 0x00000011 @ Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_AHB1ENR)*32+RCC_AHB1ENR_GPIOHEN_N*4

.word 0x00000003 @ value ORR (mask AND [adress])
.word PERIPH_BASE + GPIOH_BASE + GPIO_MODER
.word ~(GPIO_MODER_MODER3+GPIO_MODER_MODER2)
.word GPIO_MODER_MODER2_0 + GPIO_MODER_MODER3_0

.word 0x000000FF @ конфигурация завершенa

а например для настройки тактирования так:
Тактирование STM32F4 168 мгц
@ ***************************************************************************
@ * Список конфигурации SYSCLK 168 MHz Standard *
@ ***************************************************************************
@ * Конфигурация HSE ( 8Мгц) + PLL, со стандартными значениями множителей *
@ ***************************************************************************
@ * НАСТРОЙКИ *
@ * — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - — - *
@ * значения делителей и множителей *
@ * *
@ * PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N *

.equ MOD_INIT_SYSCLK_168STD_PLL_M, 8
.equ MOD_INIT_SYSCLK_168STD_PLL_N, 336

@ * Частота тактирования процессора (AHB), документированная 168 мгц *
@ * SYSCLK = PLL_VCO / PLL_P *
@
.equ MOD_INIT_SYSCLK_168STD_PLL_P, 2

@ * Такт для USB (должен быть 48 мгц для нормальной работы) *
@ * USB OTG FS, SDIO and RNG Clock = PLL_VCO / PLLQ *
@
.equ MOD_INIT_SYSCLK_168STD_PLL_Q, 7

@ ***************************************************************************

@ — Дальше настроек нет!!! — @ значение для загрузки в RCC_PLLCFGR
.equ MOD_INIT_SYSCLK_168STD_PLLCFGR, MOD_INIT_SYSCLK_168STD_PLL_M|(MOD_INIT_SYSCLK_168STD_PLL_N<<6)+(((MOD_INIT_SYSCLK_168STD_PLL_P>>1)-1)<<16)+RCC_PLLCFGR_PLLSRC_HSE+(MOD_INIT_SYSCLK_168STD_PLL_Q<<24)


@ включение HSE
.word 0x00000011 @ Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_CR)*0x20+RCC_CR_HSEON_N*4

@ ожидаем стабилизации частоты кварца
.word 0x00000021 @ Wait Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_CR)*0x20+RCC_CR_HSERDY_N*4

@ включаем Power control
.word 0x00000011 @ Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_APB1ENR)*0x20+RCC_APB1ENR_PWREN_N*4

@ выходим из режима энергосбережения
.word 0x00000011 @ Bitband 1
.word PERIPH_BB_BASE+(PWR_BASE + PWR_CR)*0x20+PWR_CR_VOS_N*4

@ Установим делитель шины APB2
.word 0x00000011 @ Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_CFGR)*0x20+RCC_CFGR_PPRE2_DIV2_N*4

@ Установим делитель шины APB1
.word 0x00000002 @ str value, ORR [adress]
.word PERIPH_BASE+RCC_BASE+RCC_CFGR
.word RCC_CFGR_PPRE1_DIV4

@ Установка коэффициентов PLL
.word 0x00000001 @ str value, [adress]
.word PERIPH_BASE+RCC_BASE+RCC_PLLCFGR
.word MOD_INIT_SYSCLK_168STD_PLLCFGR

@ Включаем PLL
.word 0x00000011 @ Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_CR)*0x20+RCC_CR_PLLON_N*4

@ Ожидаем готовности PLL
.word 0x00000021 @ Wait Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_CR)*0x20+RCC_CR_PLLRDY_N*4

@ Настройки конвейера
.word 0x00000001 @ str value, [adress]
.word PERIPH_BASE + FLASH_R_BASE + FLASH_ACR
.word FLASH_ACR_ICEN + FLASH_ACR_DCEN + FLASH_ACR_LATENCY_5WS + FLASH_ACR_PRFTEN

@ Выбираем PLL источником тактирования
.word 0x00000003 @ str value, ( ORR ( MASK[adress] ) )
.word PERIPH_BASE+RCC_BASE+RCC_CFGR
.word ~(RCC_CFGR_SW)
.word RCC_CFGR_SW_PLL

@ Ожидаем переключения на PLL
.word 0x00000021 @ Wait Bitband 1
.word PERIPH_BB_BASE+(RCC_BASE+RCC_CFGR)*0x20+RCC_CFGR_SWS_PLL_N*4

.word 0x000000FF @ выход

один раз написана, сохранена как модуль. При необходимости вызываю настройку с указанием адреса списка и все готово… сейчас все используемые иниты периферии перевожу в этот формат…

p.s. как в первом сообщении верно указал Dark purple: «это как гречневую кашу пинцетом по одному зёрнышку», и если есть правильно, то каша очень вкусная получается :-)
А кто запрещает на С писать прямо в регистры? Просто на ЯВУ проще строить уровни абстракции чем на ассемблере, SPL — это уже некое готовое дерево абстракций которое сделали до тебя. Можно вырастить и своё дерево, только боюсь плоды не будут совместимы с метаболизмом других проектов — и это реальная проблема велосипедов.
мы падаем в холивар относительно языков программирования… :-(
почему все тогда не используют бейсик? :-)

я не призываю всех сменить язык программирования, я пишу на том языке что мне интересен, и делюсь опытом с теми кто захочет попробовать…
В бейсике не доступно всё дерево абстракций, а те ветви что доступны довольно высокоуровневые и довольно неуклюжие из-за необходимости обеспечить совместимость несовместимых вещей.
просто развитие бейсика фактически остановилось после того как юникс написали на си и он стал языком на котором написана операционная система и одновременно единственным простым способом писать программы под ОС…
А дальше свое взяла мода… — стал не модным и просто умер в развитии… примерно как дельфи… неплохой в общем то язык, но пара просчетов — и в результате обочина…
Бейсик вобщем-то не умер, как и делфи. Просто они нынче не популярны из-за второстепенных проблем. Не так давно приходилось бейсиком пользоваться, и на делфи написано корпоративное приложеньице купленное пару лет назад.
Статья супер, автор, респект за дотошность и инженерный энтузиазм)
На мой взгляд, статья не потеряла актуальность даже через 5 лет. Спасибо автору!
ну если интересно, то можете попробовать редактор ассемблера, ссылка на него в группе ВК.
он еще пишется, но уже может многое
Да-да, я видел. Ещё раз спасибо!

Главное — чтобы со временем Вы не забросили этот проект, как это сделал, например, автор FASMARM (последнее обновление 26.12.2017).

Поддержал Вас плюсом в карму ;-)
ну проекты в одного тяжко вести… нельзя объять необъятное
спасибо за карму… я уже привык что мне ее минусуют :-))
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации