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“是一个提供一组常量的模块,访问TPYBoard微控制器的寄存器。 尝试在REPL上运行“import stm“然后“help(stm)“,它会给你列出所有可用的常量。
- “stm.GPIOA“是GPIOA外设的内存地址。
在TPYBoard上,红色LED指示灯位于端口A,引脚PA13上。
- “movwt“将32位数字移入一个寄存器。这是一个方便功能变成两个拇指指令:“movw“,后跟“movt“。
“movt“也把立即数值右移16位。
- “strh“存储一个半字(16位),上面的说明书“r1”的低16位进入内存位置“r0 + stm.GPIO_BSRRL“。 这具有将端口A上的所有引脚设置为高的效果,“r0”中的相应位置为1。在上面的例子中,第13个“r0”中的位被设置,所以PA13被拉高,这将打开红色LED指示灯。
10.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。
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. 进一步阅读¶
有关内联汇编程序支持的指令的更多信息, 请参阅:ref:reference documentation <asm_thumb2_index>。