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, r2r3反映寄存器和调用约定。

这是一个添加参数的函数:

@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)

10.5. 进一步阅读

有关内联汇编器支持的指令的更多信息,请参阅参考文档