diff options
Diffstat (limited to 'docs/tutorial/assembler.rst')
-rw-r--r-- | docs/tutorial/assembler.rst | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/docs/tutorial/assembler.rst b/docs/tutorial/assembler.rst new file mode 100644 index 0000000000..777600fc86 --- /dev/null +++ b/docs/tutorial/assembler.rst @@ -0,0 +1,123 @@ +Inline assembler +================ + +Here you will learn how to write inline assembler in Micro Python. + +**Note**: this is an advanced tutorial, intended for those who already +know a bit about microcontrollers and assembly language. + +Micro Python includes an inline assembler. It allows you to write +assembly routines as a Python function, and you can call them as you would +a normal Python function. + +Returning a value +----------------- + +Inline assembler functions are denoted by a special function decorator. +Let's start with the simplest example:: + + @micropython.asm_thumb + def fun(): + movw(r0, 42) + +You can enter this in a script or at the REPL. This function takes no +arguments and returns the number 42. ``r0`` is a register, and the value +in this register when the function returns is the value that is returned. +Micro Python always interprets the ``r0`` as an integer, and converts it to an +integer object for the caller. + +If you run ``print(fun())`` you will see it print out 42. + +Accessing peripherals +--------------------- + +For something a bit more complicated, let's turn on an LED:: + + @micropython.asm_thumb + def led_on(): + movwt(r0, stm.GPIOA) + movw(r1, 1 << 13) + strh(r1, [r0, stm.GPIO_BSRRL]) + +This code uses a few new concepts: + + - ``stm`` is a module which provides a set of constants for easy + access to the registers of the pyboard's microcontroller. Try + running ``import stm`` and then ``help(stm)`` at the REPL. It will + give you a list of all the available constants. + + - ``stm.GPIOA`` is the address in memory of the GPIOA peripheral. + On the pyboard, the red LED is on port A, pin PA13. + + - ``movwt`` moves a 32-bit number into a register. It is a convenience + function that turns into 2 thumb instructions: ``movw`` followed by ``movt``. + The ``movt`` also shifts the immediate value right by 16 bits. + + - ``strh`` stores a half-word (16 bits). The instruction above stores + the lower 16-bits of ``r1`` into the memory location ``r0 + stm.GPIO_BSRRL``. + This has the effect of setting high all those pins on port A for which + the corresponding bit in ``r0`` is set. In our example above, the 13th + bit in ``r0`` is set, so PA13 is pulled high. This turns on the red LED. + +Accepting arguments +------------------- + +Inline assembler functions can accept up to 3 arguments. If they are +used, they must be named ``r0``, ``r1`` and ``r2`` to reflect the registers +and the calling conventions. + +Here is a function that adds its arguments:: + + @micropython.asm_thumb + def asm_add(r0, r1): + add(r0, r0, r1) + +This performs the computation ``r0 = r0 + r1``. Since the result is put +in ``r0``, that is what is returned. Try ``asm_add(1, 2)``, it should return +3. + +Loops +----- + +We can assign labels with ``label(my_label)``, and branch to them using +``b(my_label)``, or a conditional branch like ``bgt(my_label)``. + +The following example flashes the green LED. It flashes it ``r0`` times. :: + + @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) |