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指令 movwmovt,MOVW把16位立即数放到寄存器的底16位,高16位清0,MOVT把 16 位立即数放到寄存器的高16位,低 16位不影响.

-strh 半字节数据存储指令.上述指令存储将 r1 存储到 r0 + stm.GPIO_BSRRL .这个操作将影响port A所有寄存器数值,在上一步我们设置了PA13那个寄存器置1,PA13这个引脚就被拉高了,这时候红灯就亮了.

11.3. 接受参数

内联汇编函数最多可以接受4个参数。如果使用它们,则必须将它们命名为 r0r1r2r3 ,来映射到寄存器或调用。

下面是一个添加参数的函数:

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