Минимально необходимый код для Cortex-M4
С подачей питания или по сигналу сброса, процессорное ядро Cortex-M4 работает от
встроенного RC генератора на частоте ~16 МГц и начинает выполнять программу
с нулевого адреса встроенной флешки.
Это абсолютно штатный режим ядра, можно ничего не трогать и сразу начинать работу.
Потребуются только две строки в начале кода,
которые по сути являются началом таблицы векторов:
.word 0x2001BFFF @ Вершина стека, зависит от размера ОЗУ
.word Start+1 @ Вектор сброса
Start: ....... отсюда начинается код
На этом статью можно было бы закончить. Всё настолько просто, что даже не верится!
Буквально с третьей строки можно вставлять ассемблерный код и он будет выполняться.
Код должен начинаться от метки
Start. Можете придумать своё имя для этой метки, не важно.
Стек настроен, калибровочный байт считан, и это всё делается ядром автоматически.
Помните, как это было в тинках и мегах? Нужно "вручную" установить вершину стека, прописать калибровочный байт,
отрубить пса! А сколько народу на этом отрубилось! Ведь кто-же его поймёт, что по умолчанию пёс всегда включен
и будет сбрасывать процессор до тех пор, пока не вырубишь?
А калибровочный байт - его нужно предварительно считать из камня программатором и где-то сохранить во флешке.
В каждом камне свой уникальный байт. Очень много возни.. По умолчанию 8-битный AVR не был готов к работе..
А вот с кортексами гораздо проще. Я только начал с ними работать. Но уже обратил внимание на более логичную,
укладистую организацию периферии. Например, что бы целиком настроить порт, нужны всего 3 инструкции.
Другая периферия настраивается так же просто, шаг за шагом, путём расталкивания бит и байтов в управляющие регистры.
На основании выше сказанного, мною был написан минимально необходимый код для платы
STM32F4DISCOVERY, который позволяет убедиться, что плата живая и она работает.
Аналогичный код принято считать "Hello world!" для микроконтроллера - подрыгать ножками, поморгать светодиодом.
Наверное в это трудно будет поверить, но размер кода составил 19 ассемблерных инструкций.
А размер прошивки составил умопомрачительные 84 байта. Если вам лень разбираться в кодах, скачайте прошивку и залейте её в камень
через утилиту ST-LINK. Хочу ещё раз обратить ваше внимание, что код написан для отладочной платы STM32F4DISCOVERY.
Скачать прошивку
Конечно, такой маленький код и его простота - заслуга исключительно ассемблера.
Поэтому ниже я приведу листинг программы, которую вы можете использовать в своих проектах.
На что стоит обратить внимание. В начале располагаются несколько полезных макросов. Затем идёт таблица векторов прерываний,
которой по сути нет, потому что прерывания мы не используем и все они по умолчанию в камне отключены.
И ещё, макросы и метки теперь могут быть русскими!
Так что ассемблер в составе GCC обладает хорошим потенциалом. Я только начал с ним работать, понравился!
А через макросы можно исправить ассемблерный синтаксис на более привычный.
@ Синтаксис GCC AS
.syntax unified
.section .text
.macro MOV32 regnum,number
MOVW \regnum,:lower16:\number
MOVT \regnum,:upper16:\number
.endm
.macro MOVLo regnum,number
MOVW \regnum,\number
.endm
.macro MOVUp regnum,number
MOVT \regnum,\number
.endm
.macro CALL address
BL \address
.endm
.macro RET
BX LR
.endm
.macro JMP address
B \address
.endm
.equ RCC_AHB1ENR, 0x40023830
.equ GPIOD_MODER, 0x40020C00
.equ GPIOD_ODR, 0x40020C14
.equ GPIODEN_BB, (RCC_AHB1ENR & 0x00FFFFFF) * 0x20 + 0x42000000 + 3 * 4
@ Это таблица векторов прерываний
@ Если прерывания не используются,
@ таблицу можно сократить до двух строк
.word 0x2001BFFF @ Вершина стека, зависит от размера ОЗУ
.word Start+1 @ Вектор сброса, обязательно +1
Start:
@ Разрешить тактирование PORTD от шины
@ Для настройки используем метод BitBand
MOV32 R0, GPIODEN_BB
MOV R1, 1
STR R1, [R0]
@ Ножки 12, 13, 14, 15 на выход
MOV32 R0, GPIOD_MODER
MOV32 R1, 0x55000000
STR R1, [R0]
@ По умолчанию светодиоды отключены
MOV R1, 0 @ Обнулить регистр
MOV32 R2, GPIOD_ODR @ Выходной порт светодиодов
Моргалка:
MOVLo R1, 0xA000 @ Переключить светодиоды
STR R1, [R2]
CALL Пауза
MOVLo R1, 0x5000 @ Переключить светодиоды
STR R1, [R2]
CALL Пауза
JMP Моргалка
Пауза:
@ Почти 1 секунда на частоте 16 мгц
MOVUp R0, 0x004C
1:
SUBS R0, R0, 1
BNE 1b
RET
.end
Очень сложно, правда?