Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Python on bare metal

Python on bare metal

Fast & efficient MicroPython

348cfd39887a39d65a7a99cd849d1d12?s=128

Jessica Greene

February 23, 2019
Tweet

Transcript

  1. Python on bare metal fast & efficient code with MicroPython

    Jessica Greene @sleepypioneer
  2. MicroPython  A complete reimplementation of Python  Designed to

    be efficient with resources  Designed to run bare metal Includes:  A compiler, runtime & familiar REPL  Support for basic libraries  Extra modules to control hardware
  3. PyBoard, ESP32, ESP8266 & more...

  4. Challenges of working on microcontrollers BATTERY POWERED VERY LITTLE MEMORY

    (RAM, ROM) NORMALLY REQUIRE LOW LEVEL LANGUAGE
  5. How does MicroPython solve the issue of having a low

    amount of RAM? Interned strings, most already in ROM Small integers stuffed in a pointer to avoid using heap (trick from lisp) Optimised method calls to not use heap Garbage collection
  6. Normal python uses megabytes RAM if not 100s MicroPython can

    run with only 8 kilobytes & it runs without an OS, so on bare metal Python Vs MicroPython
  7. How you can impact this with your code?

  8. Tips: Memory allocation Doesn’t use heap Uses Heap Expressions Importing

    If, while, for and try statements Defining functions & classes Local variables Assigning global variables for the first time Small integer arithmetic Creating data structures Inplace operations on existing data structures Calling functions/ methods with positional or keyword args
  9. Tips: CPU time USE FUNCTIONS TO AVOID GLOBAL SCOPES USE

    LOCAL VARIABLES CACHE MODULE FUNCTIONS & OBJECT METHODS AS LOCALS PREFER LONGER EXPRESSIONS NOT SPLIT UP ONES RUNTIME IS FAST! E.G. STR.STARTSWITH
  10. Tips: RAM usage DON'T USE HEAP WHEN POSSIBLE SHORTER VARIABLE

    NAMES, REUSE THEM; EG X,Y,I, LEN, VAR DON'T USE * OR ** ARGS SCRIPT MINIFICATION ULTIMATE SOLUTION: FREEZE SCRIPTS INTO THE FIRMWARE (AT COMPILE TIME)
  11. Code example

  12. LED Blink script import time, machine led = machine.Pin('LED_BLUE') for

    i in range(N): led.on() led.off() 50kHz @dpgeorge
  13. Inside a function - removes global variables 60kHz import time,

    machine led = machine.Pin('LED_BLUE') def blink_simple(n): for i in range(n): led.on() led.off() @dpgeorge
  14. Preload methods & range() optimisation def blink_preload(n): on = led.on

    # returns a bound method off = led.off r = range(n) # optimise the range for i in r: on() off() 180kHz @dpgeorge
  15. Loop unrolling def blink_preload_unrolled8(n): n //= 8 on = led.on

    off = led.off r = range(n) for i in r: on() off() on() off() .... 220kHz @dpgeorge
  16. Native mode @micropython.native def blink_preload_unrolled8_native(n:int): n //= 4 on =

    led.on off = led.off r = range(n) for i in r: on() off() on() off() .... 290kHz @dpgeorge
  17. Viper mode @micropython.viper def blink_unrolled8_viper(n:int): n //= 8 p =

    ptr16(stm.GPIOB + stm.GPIO_BSRR) for i in range(n): p[0] = 1 << 4 # high p[1] = 1 << 4 # low p[0] = 1 << 4 # high p[1] = 1 << 4 # low .... 12890kHz @dpgeorge
  18. In assembler @micropython.asm_thumb def blink_asm(r0): lsr(r0, r0, 3) movwt(r1, stm.GPIOB

    + stm.GPIO_BSRR) mov(r2, 1 << 4) label(loop) strh(r2, [r1, 0]) # high strh(r2, [r1, 2]) # low strh(r2, [r1, 0]) # high strh(r2, [r1, 2]) # low .... 27359.25kHz @dpgeorge
  19. Takeaways ◦ If your code runs faster it can sleep

    for longer and that saves battery! ◦ ROM everything that you can ◦ Use runtime methods! ◦ Local not global variables!
  20. THANK YOU! www.github.com/sleepypioneer/fast_and_efficient_micropython www.micropython.org www.github.com/micropython