Минимально необходимый код для 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

			

Очень сложно, правда?