Disclaimer )
Я не агитирую программировать STM32 на ассемблере и даже, наоборот, не советую.
IMHO, ассемблер интересен в трёх случаях:
1) Невозможно сделать на си
2) Разобраться как оно устроено
3) Just for fun
Поскольку первый случай сложный, а третий - тяжёлый, то дальше я излагаю, ориентируясь на второй )
Да, и речь только о Cortex-M{0,3,4}, т.е. о STM32{F|L}{0-4}
Основной мануал по ассемблеру для STM32 - st-шный Programming manual.
Он написан более понятным языком, чем st-шные RM, потому что является по сути пересказом армового Generic User Guide с учётом особенностей STM32.
Вот ссылки на тот и другой, например, для STM32F1
http://www.st.com/content/ccc/resource/ … 228163.pdf
http://infocenter.arm.com/help/topic/co … 3_dgug.pdf
Для других серий STM32 и ядер Cortex есть такие же свои.
Из софта требуются только два файла - две программы: as и objcopy, которые можно взять из любого дистрибутва gcc-arm-none-eabi, например, этого - https://developer.arm.com/open-source/g … /downloads
Ещё нужен какой-то дебаггер, например, Segger Ozone
Первая, самая минимальная программа (для любой серии STM32)
.syntax unified .word 0x20001000 .word Reset+1 .word NMI+1, HardFault+1 .=0x200 Reset: movs r0, 0 10$: adds r0, 1 b 10$ NMI: HardFault: b .
.syntax unified - директива выбора варианта синтаксиса ассемблера (подробнее - https://sourceware.org/binutils/docs/as … 2dSet.html)
.word 0x20001000 - в самое первое слово программы, по нулевому адресу, помещается значение указателя стека (SP), которое будет устанавливаться при ресете (стек растёт в сторону уменьшения адресов, RAM начинается с 0x20000000).
.word Reset+1 - во второе слово программы (по адресу 4) помещается значение счётчика команд (PC), которое будет устанавливаться при ресете.
Младший бит не используется для адресации (реальный счётчик команд всегда чётный), а имеет специальное назначение.
В докортексовых армах использовались два пересекающихся набора инструкций - 32-битный (arm) и 16-битный (thumb), а младший бит значения PC использовался для переключения между ними.
Хотя в кортексах только один набор инструкций - thumb2 (thumb с дополнительными 32-битными инструкциями), а переключение бессмысленно и запрещено, тем не менее в младшем бите остался тот же переключатель и он должен всегда устанавливаться в единицу.
.word NMI+1, HardFault+1 - с третьего слова (с адреса 8) начинается область векторов прерываний (в кортексах вектор прерывания == адрес обработчика).
Минимально необходимы первые два: NMI - немаскируемое и HardFault - фатальный сбой.
Дальше всё просто
.=0x200 - указание ассемблеру размещать остальную программу с адреса 0x200, пропустив область векторов прерываний (просто для приличия, хотя это и не обязательно).
Reset: - сама "программа".
NMI: HardFault: - заглушка для прерываний.
Ассемблирование в объектный файл
as -mcpu=cortex-m{0,3,4} -o test.o test.s
Получение бинарника из объектного файла
objcopy -O binary test.o test.bin