10. Ассемблерная вставка¶
Здесь вы узнаете как сделать ассемблерную вставку в код Micro Python.
Примечание: эта часть учебника для опытных программистов, для тех, кто уже немного знаком с микроконтроллерами и ассемблером.
С помощью ассемблерных вставок вы можете писать процедуры ассемблера и вызывать их как обычные функции в Python.
10.1. Возвращение значения¶
Ассемблерные вставки обозначаются специальным символом. Начнём с простого примера:
@micropython.asm_thumb
def fun():
movw(r0, 42)
Вы можете написать этот скрипт в REPL. Эта функция не принемает никаких аргументов и возвращает число 42. r0
- это регистр, значение этого регистра вернётся вместе с 42.
Micro Python всегда распознаёт r0
как integer и конвертирует его в объект для получателя.
Если мы запустим print(fun())
- то увидим как на экране появится 42.
10.2. Доступ к периферийным устройствам¶
Для того, чтобы немного усложнить задачу, давайте включим светодиод:
@micropython.asm_thumb
def led_on():
movwt(r0, stm.GPIOA)
movw(r1, 1 << 13)
strh(r1, [r0, stm.GPIO_BSRRL])
Здесь есть несколько новых элементов:
stm
- это модуль, который предоставляет множество констант для простого доступа к регистрам микроконтроллера. Попытайтесь импортировать stm (import stm
) и затем вызовитеhelp(stm)
в REPL. Должен появиться список всевозможных конастант.stm.GPIOA
- это адресс в памяти периферийного устройства GPIOA. На pyboard красный светодиод на порт A, пин PA13.movwt
перемещает 32-разрядное число в регистр. Это удобная функция, которая превращается в две отличные инструкции:movw
следует заmovt
. Также,movt
немедленно сдвигает значение вправо на 16 бит.strh
хранит полу-слова (16 бит). Инструкция выше сохраняет нижние 16 бит изr1
в ячейку памятиr0 + stm.GPIO_BSRRL
. This has the effect of setting high all those pins on port A for which the corresponding bit inr0
is set. In our example above, the 13th bit inr0
is set, so PA13 is pulled high. Это включает красный светодиод.
10.3. Получение аргументов¶
Встроенные ассемблерные функции могут принемать до 3-х аргументов. Если они используются, то должны быть названы r0
, r1
и r2
для отображения регистров и вызова соглашения(???).
Ниже функция, которая добавляет эти аргументы:
@micropython.asm_thumb
def asm_add(r0, r1):
add(r0, r0, r1)
Эта функция выполняет вычисление r0 = r0 + r1
. Результат помещается в r0
и возвращается.
Попробуйте asm_add(1,2)
- это должно вернуть 3ю
10.4. Циклы¶
Мы можем назначать метки label(my_label)
и ветвить их, используя, b(my_label)
или условно ветвить как bgt(my_label)
.
В следующем примере мигает залёный светодиод. Он мигает r0
раз.
@micropython.asm_thumb
def flash_led(r0):
# get the GPIOA address in r1
movwt(r1, stm.GPIOA)
# get the bit mask for PA14 (the pin LED #2 is on)
movw(r2, 1 << 14)
b(loop_entry)
label(loop1)
# turn LED on
strh(r2, [r1, stm.GPIO_BSRRL])
# delay for a bit
movwt(r4, 5599900)
label(delay_on)
sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_on)
# turn LED off
strh(r2, [r1, stm.GPIO_BSRRH])
# delay for a bit
movwt(r4, 5599900)
label(delay_off)
sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_off)
# loop r0 times
sub(r0, r0, 1)
label(loop_entry)
cmp(r0, 0)
bgt(loop1)