11. 内联汇编¶
在这里,您将学习如何用MicroPython编写内联汇编程序.
注意:这是一个高级教程,适用于那些已经对微控制器和汇编语言有一定了解的人。
MicroPython包括一个内联汇编程序。它允许您将汇编操作编写为Python函数,并且可以像调用普通Python函数那样调用它们。
11.1. 返回一个值¶
内联汇编函数由一个特殊的函数修饰符来表示。让我们认识一下:
@micropython.asm_thumb
def fun():
movw(r0, 42)
您可以在脚本中或REPL中输入这个。这个函数无需参数,返回一个数字42, r0
表示一个寄存器,这个数就是这个寄存器的值。
Micorpython总是将 r0
定义为整数,将其以整数想形式呈现给调用者。
如果你打印这个值 print(fun())
将返42这个值.
11.2. 访问外设¶
更复杂一点,我们点亮LED
@micropython.asm_thumb
def led_on():
movwt(r0, stm.GPIOA)
movw(r1, 1 << 13)
strh(r1, [r0, stm.GPIO_BSRRL])
T这段代码使用了一些新概念:
stm
是一个模块,它提供了一组容易的常量访问pyboard的微控制器的寄存器。试一试在REPL上运行import stm
和’help(stm)
。它将给出所有可用常量的列表.stm.GPIOA
是GPIOA的外设地址.在pyborad上,红灯的是使用了port A,pin PA13.movwt
将一个32位的数字移动到寄存器中。这个指令相对于两条thumb指令movw
和movt
,MOVW把16位立即数放到寄存器的底16位,高16位清0,MOVT把 16 位立即数放到寄存器的高16位,低 16位不影响.-
strh
半字节数据存储指令.上述指令存储将r1
存储到r0 + stm.GPIO_BSRRL
.这个操作将影响port A所有寄存器数值,在上一步我们设置了PA13那个寄存器置1,PA13这个引脚就被拉高了,这时候红灯就亮了.
11.3. 接受参数¶
内联汇编函数最多可以接受4个参数。如果使用它们,则必须将它们命名为 r0
、 r1
、 r2
和 r3
,来映射到寄存器或调用。
下面是一个添加参数的函数:
@micropython.asm_thumb
def asm_add(r0, r1):
add(r0, r0, r1)
执行计算 r0 = r0 + r1
. 把结果放到 r0
,它将当做结果返回.试着执行 asm_add(1, 2)
, 将会返回3.
11.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)
11.5. 延伸阅读¶
有关内联函数的更多知识请阅读:ref:reference documentation.