10. 内联汇编器¶
在这里,您将学习如何在 MicroPython 中编写内联汇编程序。
注意:这是一个高级教程,适用于那些已经对微控制器和汇编语言有所了解的人。
MicroPython 包括一个内联汇编器。它允许您将汇编例程编写为 Python 函数,您可以像调用普通 Python 函数一样调用它们。
10.1. 返回值¶
内联汇编函数由一个特殊的函数装饰器表示。让我们从最简单的例子开始:
@micropython.asm_thumb
def fun():
movw(r0, 42)
您可以在脚本中或在 REPL 中输入它。这个函数不带参数,返回数字42。r0
是一个寄存器,函数返回时这个寄存器中的值就是返回的值。MicroPython 始终将 解释 r0
为整数,并将其转换为调用者的整数对象。
如果您运行,print(fun())
您将看到它打印出 42。
10.2. 访问外围设备¶
对于更复杂的事情,让我们打开一个 LED:
@micropython.asm_thumb
def led_on():
movwt(r0, stm.GPIOA)
movw(r1, 1 << 13)
strh(r1, [r0, stm.GPIO_BSRRL])
这段代码使用了一些新概念:
stm
是一个模块,它提供了一组常量,以便于访问 pyboard 微控制器的寄存器。尝试运行,然后在 REPL。它将为您提供所有可用常量的列表。import stm
help(stm)
stm.GPIOA
是 GPIOA 外设在内存中的地址。在 pyboard 上,红色 LED 位于端口 A、引脚 PA13 上。
movwt
将 32 位数字移动到寄存器中。这是一个方便的功能,变成了 2 条拇指指令:movw
后跟movt
. . 该movt
还了16位转移的直接价值的权利。
strh
存储一个半字(16 位)。上面的指令将 的低 16 位r1
存储到内存位置。这具有将端口 A 上所有设置了相应位 in 的引脚设置为高电平的效果。在我们上面的例子中,第 13 位 in被设置,所以 PA13 被拉高。这会打开红色 LED。r0 + stm.GPIO_BSRRL
.r0
r0
.
10.3. 接受参数¶
内联汇编器函数最多可以接受 4 个参数。如果它们时,它们必须被命名为 r0
, r1
, r2
和r3
反映寄存器和调用约定。
这是一个添加参数的函数:
@micropython.asm_thumb
def asm_add(r0, r1):
add(r0, r0, r1)
这将执行计算。由于结果被放入,这就是返回的内容。尝试,它应该返回 3。
r0 = r0 + r1
r0
asm_add(1, 2)
10.4. 循环¶
我们可以使用 分配标签 label(my_label)
,并使用
b(my_label)
或条件分支(如 bgt(my_label)
.
以下示例使绿色 LED 闪烁。它闪烁它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)