assembler.rst 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. .. _pyboard_tutorial_assembler:
  2. Inline assembler
  3. ================
  4. Here you will learn how to write inline assembler in MicroPython.
  5. **Note**: this is an advanced tutorial, intended for those who already
  6. know a bit about microcontrollers and assembly language.
  7. MicroPython includes an inline assembler. It allows you to write
  8. assembly routines as a Python function, and you can call them as you would
  9. a normal Python function.
  10. Returning a value
  11. -----------------
  12. Inline assembler functions are denoted by a special function decorator.
  13. Let's start with the simplest example::
  14. @micropython.asm_thumb
  15. def fun():
  16. movw(r0, 42)
  17. You can enter this in a script or at the REPL. This function takes no
  18. arguments and returns the number 42. ``r0`` is a register, and the value
  19. in this register when the function returns is the value that is returned.
  20. MicroPython always interprets the ``r0`` as an integer, and converts it to an
  21. integer object for the caller.
  22. If you run ``print(fun())`` you will see it print out 42.
  23. Accessing peripherals
  24. ---------------------
  25. For something a bit more complicated, let's turn on an LED::
  26. @micropython.asm_thumb
  27. def led_on():
  28. movwt(r0, stm.GPIOA)
  29. movw(r1, 1 << 13)
  30. strh(r1, [r0, stm.GPIO_BSRRL])
  31. This code uses a few new concepts:
  32. - ``stm`` is a module which provides a set of constants for easy
  33. access to the registers of the pyboard's microcontroller. Try
  34. running ``import stm`` and then ``help(stm)`` at the REPL. It will
  35. give you a list of all the available constants.
  36. - ``stm.GPIOA`` is the address in memory of the GPIOA peripheral.
  37. On the pyboard, the red LED is on port A, pin PA13.
  38. - ``movwt`` moves a 32-bit number into a register. It is a convenience
  39. function that turns into 2 thumb instructions: ``movw`` followed by ``movt``.
  40. The ``movt`` also shifts the immediate value right by 16 bits.
  41. - ``strh`` stores a half-word (16 bits). The instruction above stores
  42. the lower 16-bits of ``r1`` into the memory location ``r0 + stm.GPIO_BSRRL``.
  43. This has the effect of setting high all those pins on port A for which
  44. the corresponding bit in ``r0`` is set. In our example above, the 13th
  45. bit in ``r0`` is set, so PA13 is pulled high. This turns on the red LED.
  46. Accepting arguments
  47. -------------------
  48. Inline assembler functions can accept up to 4 arguments. If they are
  49. used, they must be named ``r0``, ``r1``, ``r2`` and ``r3`` to reflect the registers
  50. and the calling conventions.
  51. Here is a function that adds its arguments::
  52. @micropython.asm_thumb
  53. def asm_add(r0, r1):
  54. add(r0, r0, r1)
  55. This performs the computation ``r0 = r0 + r1``. Since the result is put
  56. in ``r0``, that is what is returned. Try ``asm_add(1, 2)``, it should return
  57. 3.
  58. Loops
  59. -----
  60. We can assign labels with ``label(my_label)``, and branch to them using
  61. ``b(my_label)``, or a conditional branch like ``bgt(my_label)``.
  62. The following example flashes the green LED. It flashes it ``r0`` times. ::
  63. @micropython.asm_thumb
  64. def flash_led(r0):
  65. # get the GPIOA address in r1
  66. movwt(r1, stm.GPIOA)
  67. # get the bit mask for PA14 (the pin LED #2 is on)
  68. movw(r2, 1 << 14)
  69. b(loop_entry)
  70. label(loop1)
  71. # turn LED on
  72. strh(r2, [r1, stm.GPIO_BSRRL])
  73. # delay for a bit
  74. movwt(r4, 5599900)
  75. label(delay_on)
  76. sub(r4, r4, 1)
  77. cmp(r4, 0)
  78. bgt(delay_on)
  79. # turn LED off
  80. strh(r2, [r1, stm.GPIO_BSRRH])
  81. # delay for a bit
  82. movwt(r4, 5599900)
  83. label(delay_off)
  84. sub(r4, r4, 1)
  85. cmp(r4, 0)
  86. bgt(delay_off)
  87. # loop r0 times
  88. sub(r0, r0, 1)
  89. label(loop_entry)
  90. cmp(r0, 0)
  91. bgt(loop1)
  92. Further reading
  93. ---------------
  94. For further information about supported instructions of the inline assembler,
  95. see the :ref:`reference documentation <asm_thumb2_index>`.