Last active
March 25, 2016 17:16
-
-
Save AlexanderSavochkin/5f7adedd380eda33a9c3 to your computer and use it in GitHub Desktop.
Simple LED blink program for LPC1114 in assembly
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.syntax unified | |
/*Инструктируем транслятор генерировать 16-битные инструкции Thumb*/ | |
.thumb | |
/*То же самое что ключ командной строки -mcpu=cortex-m0 . | |
Говорим транслятору, что хотим код под архитектуру Cortex-M0*/ | |
.cpu cortex-m0 | |
/* Опрделяем секцию .vectors, в которой описываем таблицу прерываний */ | |
.section .vectors | |
.align 2 /* Выравнивание - 4 байта (1 << 2) */ | |
/* По адресу 0 положим начальное значение указателя стека 0x10002000 */ | |
.long 0x10002000 | |
/* 0x00000004 Адрес, по которому переходим после сброса (Reset_Handler) | |
То, что мы переходим на увеличенный на 1 адрес есть некий трюк архитектуры | |
ARM: на самом деле процессор перейдёт на адрем Reset_Handler, а +1 | |
устанавливает бит, сигнализирующий, что переходим на Thumb-инструкцию*/ | |
.long Reset_Handler + 1 | |
.long 0x0 /*Остальные прерывания не используются, забьём нулями*/ | |
.long 0x0 | |
.long 0x0 | |
.long 0x0 | |
.long 0x0 | |
/*По этому адресу должна лежать контрольная сумма предыдущих векторов, | |
в противном случае контрололер не будет выполнять наш код. | |
Как я понял, утилиты, прошивающие чип должны позабоитися о том, чтобы | |
значение здесь было правильным.*/ | |
.long 0x0 | |
/*Определяем секцию выполняемого кода*/ | |
.text | |
/*Ячейка памяти по адресу 0x00000004 указывает | |
на эту метку, так что после сброса попадаем сюда*/ | |
Reset_Handler: | |
/*Настроим GPIO для мигания светодиодом | |
Определяем константы - адреса и смещения для управления переферией. | |
По адресу 0x40048080 находится регистр, который включает тактирование блоков | |
периферии (SYSAHBCLKCTRL) или System AHB clock control register. | |
AHB - advanced high performance bus | |
https://en.wikipedia.org/wiki/Advanced_Microcontroller_Bus_Architecture#Advanced_High-performance_Bus_.28AHB.29 | |
*/ | |
SYSAHBCLKCTRL = 0x40048080 | |
ENABLE_PERIPH_BITS = 0b00000000000000010000000001000000 /*BIT6 + BIT16*/ | |
/*Адрес регистра, управляющего | |
"направлением работы" GPIO (ввод или вывод)*/ | |
GPIO0DIR = 0x50008000 | |
/*Мы будем работать с 7-м выводом GPIO0. | |
Определим эту константу для адресации | |
7-го вывода*/ | |
BIT7 = 0b10000000 | |
/*Адрес регистра, определяющего уровни | |
на выходах GPIO*/ | |
GPIO0DATA = 0x50003ffc | |
/*В ARM нет инструкции, которая напрямую загружает 32-разрядное число в регистр. | |
Просто потому, что 32-разрядный операнд нельзя положить в 32 разрядную инструкцию | |
ARM или тем более 16-разрядую инструкцию Thumb. Произвольное 32-разрядно число | |
можно загрузить, положив его в память "где-то недалеко" от исполняемого кода и | |
загрузив её по относительному одресу. Хотя и выглядит так, как будто мы загружаем | |
константу непосредственно в регистр, на самом деле LDR - это "псевдоинструкция" | |
Ассемблер положит константу где-то не подалёку и загрузит её по относительному | |
адресу | |
.*/ | |
/*Сначала включим тактирование GPIO и */ | |
LDR R4, =SYSAHBCLKCTRL | |
LDR R1, =ENABLE_PERIPH_BITS | |
LDR R0, [R4] | |
ORRS R0, R1 | |
STR R0, [R4] | |
/*Настроим GPIO0 на вывод*/ | |
LDR R4, =GPIO0DIR | |
LDR R0, =BIT7 | |
STR R0, [R4] | |
/*Мигаем светодиодом в цикле*/ | |
LDR R4, =GPIO0DATA | |
WAIT_LOOPS = 0x100000 | |
LDR R1, =WAIT_LOOPS | |
Blink_loop: | |
/*Включаем светодиод (устанавливаем 7-й бит по адресу GPIO0DATA)*/ | |
LDR R0, =BIT7 | |
STR R0, [R4] | |
/*Вызываем процедуру ожидания*/ | |
BL Wait | |
/*Выключаем светодиод (обнуляем ячейку памяти по адресу GPIO0DATA)*/ | |
EORS R0, R0 /*R0 <- 0*/ | |
STR R0, [R4] | |
/*Вызываем процедуру ожидания*/ | |
BL Wait | |
/*Переход на начало цикла мигания*/ | |
B Blink_loop | |
/*Задержка с помощью пустого цикла | |
Уменьшаем в цикле содержимое R2 до тех | |
пор, пока R2 не станет равным 0*/ | |
Wait: | |
MOV R2, R1 | |
Wait_loop: | |
SUBS R2, R2, #1 | |
BNE Wait_loop | |
BX LR /*Return*/ | |
.END | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment