Browse Source
Includes an introduction to using the Zephyr port on MicroPython. The quickref details examples of how to use each module the port currently supports. The tutorial provides additional details for Zephyr specific modules. Signed-off-by: Julia Hathaway <julia.hathaway@nxp.com>pull/7644/head
Julia Hathaway
3 years ago
committed by
Damien George
8 changed files with 403 additions and 0 deletions
@ -0,0 +1,22 @@ |
|||
.. _zephyr_general: |
|||
|
|||
General information about the Zephyr port |
|||
========================================= |
|||
|
|||
The Zephyr Project is a Linux Foundation hosted Collaboration Project. It’s an open |
|||
source collaborative effort uniting developers and users in building a |
|||
small, scalable, real-time operating system (RTOS) optimized for resource-constrained |
|||
devices, across multiple architectures. |
|||
|
|||
Multitude of boards |
|||
------------------- |
|||
|
|||
There is a multitude of modules and boards from different sources that are supported |
|||
by the Zephyr OS. All boards supported by Zephyr (with standard level of features |
|||
support, like UART console) should work with MicroPython (but not all were tested). |
|||
The FRDM-K64f board is taken as a reference board for the port for this documentation. |
|||
If you have another board, please make sure you have a datasheet, schematics and other |
|||
reference materials for your board handy to look up various aspects of your board |
|||
functioning. |
|||
|
|||
For a full list of Zephyr supported boards click `here (external link) <https://docs.zephyrproject.org/latest/boards/index.html#boards>`_ |
@ -0,0 +1,157 @@ |
|||
.. _zephyr_quickref: |
|||
|
|||
Quick reference for the Zephyr port |
|||
=================================== |
|||
|
|||
Below is a quick reference for the Zephyr port. If it is your first time working with this port please consider reading the following sections first: |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
|
|||
general.rst |
|||
tutorial/index.rst |
|||
|
|||
Running MicroPython |
|||
------------------- |
|||
|
|||
See the corresponding section of the tutorial: :ref:`intro`. |
|||
|
|||
Delay and timing |
|||
---------------- |
|||
|
|||
Use the :mod:`time <utime>` module:: |
|||
|
|||
import time |
|||
|
|||
time.sleep(1) # sleep for 1 second |
|||
time.sleep_ms(500) # sleep for 500 milliseconds |
|||
time.sleep_us(10) # sleep for 10 microseconds |
|||
start = time.ticks_ms() # get millisecond counter |
|||
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference |
|||
|
|||
Pins and GPIO |
|||
------------- |
|||
|
|||
Use the :ref:`machine.Pin <machine.Pin>` class:: |
|||
|
|||
from machine import Pin |
|||
|
|||
pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1 |
|||
print(pin) # print pin port and number |
|||
|
|||
pin.init(Pin.OUT, Pin.PULL_UP, value=1) # reinitialize pin |
|||
|
|||
pin.value(1) # set pin to high |
|||
pin.value(0) # set pin to low |
|||
|
|||
pin.on() # set pin to high |
|||
pin.off() # set pin to low |
|||
|
|||
pin = Pin(("GPIO_1", 21), Pin.IN) # create input pin on GPIO1 |
|||
|
|||
pin = Pin(("GPIO_1", 21), Pin.OUT, value=1) # set pin high on creation |
|||
|
|||
pin = Pin(("GPIO_1", 21), Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor |
|||
|
|||
switch = Pin(("GPIO_2", 6), Pin.IN) # create input pin for a switch |
|||
switch.irq(lambda t: print("SW2 changed")) # enable an interrupt when switch state is changed |
|||
|
|||
Hardware I2C bus |
|||
---------------- |
|||
|
|||
Hardware I2C is accessed via the :ref:`machine.I2C <machine.I2C>` class:: |
|||
|
|||
from machine import I2C |
|||
|
|||
i2c = I2C("I2C_0") # construct an i2c bus |
|||
print(i2c) # print device name |
|||
|
|||
i2c.scan() # scan the device for available I2C slaves |
|||
|
|||
i2c.readfrom(0x1D, 4) # read 4 bytes from slave 0x1D |
|||
i2c.readfrom_mem(0x1D, 0x0D, 1) # read 1 byte from slave 0x1D at slave memory 0x0D |
|||
|
|||
i2c.writeto(0x1D, b'abcd') # write to slave with address 0x1D |
|||
i2c.writeto_mem(0x1D, 0x0D, b'ab') # write to slave 0x1D at slave memory 0x0D |
|||
|
|||
buf = bytearray(8) # create buffer of size 8 |
|||
i2c.writeto(0x1D, b'abcd') # write buf to slave 0x1D |
|||
|
|||
Hardware SPI bus |
|||
---------------- |
|||
|
|||
Hardware SPI is accessed via the :ref:`machine.SPI <machine.SPI>` class:: |
|||
|
|||
from machine import SPI |
|||
|
|||
spi = SPI("SPI_0") # construct a spi bus with default configuration |
|||
spi.init(baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) # set configuration |
|||
|
|||
# equivalently, construct spi bus and set configuration at the same time |
|||
spi = SPI("SPI_0", baudrate=100000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB) |
|||
print(spi) # print device name and bus configuration |
|||
|
|||
spi.read(4) # read 4 bytes on MISO |
|||
spi.read(4, write=0xF) # read 4 bytes while writing 0xF on MOSI |
|||
|
|||
buf = bytearray(8) # create a buffer of size 8 |
|||
spi.readinto(buf) # read into the buffer (reads number of bytes equal to the buffer size) |
|||
spi.readinto(buf, 0xF) # read into the buffer while writing 0xF on MOSI |
|||
|
|||
spi.write(b'abcd') # write 4 bytes on MOSI |
|||
|
|||
buf = bytearray(4) # create buffer of size 8 |
|||
spi.write_readinto(b'abcd', buf) # write to MOSI and read from MISO into the buffer |
|||
spi.write_readinto(buf, buf) # write buf to MOSI and read back into the buf |
|||
|
|||
Disk Access |
|||
----------- |
|||
|
|||
Use the :ref:`zephyr.DiskAccess <zephyr.DiskAccess>` class to support filesystem:: |
|||
|
|||
import os |
|||
from zephyr import DiskAccess |
|||
|
|||
block_dev = DiskAccess('SDHC') # create a block device object for an SD card |
|||
os.VfsFat.mkfs(block_dev) # create FAT filesystem object using the disk storage block |
|||
os.mount(block_dev, '/sd') # mount the filesystem at the SD card subdirectory |
|||
|
|||
# with the filesystem mounted, files can be manipulated as normal |
|||
with open('/sd/hello.txt','w') as f: # open a new file in the directory |
|||
f.write('Hello world') # write to the file |
|||
print(open('/sd/hello.txt').read()) # print contents of the file |
|||
|
|||
Flash Area |
|||
---------- |
|||
|
|||
Use the :ref:`zephyr.FlashArea <zephyr.FlashArea>` class to support filesystem:: |
|||
|
|||
import os |
|||
from zephyr import FlashArea |
|||
|
|||
block_dev = FlashArea(4, 4096) # creates a block device object in the frdm-k64f flash scratch partition |
|||
os.VfsLfs2.mkfs(block_dev) # create filesystem in lfs2 format using the flash block device |
|||
os.mount(block_dev, '/flash') # mount the filesystem at the flash subdirectory |
|||
|
|||
# with the filesystem mounted, files can be manipulated as normal |
|||
with open('/flash/hello.txt','w') as f: # open a new file in the directory |
|||
f.write('Hello world') # write to the file |
|||
print(open('/flash/hello.txt').read()) # print contents of the file |
|||
|
|||
Sensor |
|||
------ |
|||
|
|||
Use the :ref:`zsensor.Sensor <zsensor.Sensor>` class to access sensor data:: |
|||
|
|||
import zsensor |
|||
from zsensor import Sensor |
|||
|
|||
accel = Sensor("FXOX8700") # create sensor object for the accelerometer |
|||
|
|||
accel.measure() # obtain a measurement reading from the accelerometer |
|||
|
|||
# each of these prints the value taken by measure() |
|||
accel.float(zsensor.ACCEL_X) # print measurement value for accelerometer X-axis sensor channel as float |
|||
accel.millis(zsensor.ACCEL_Y) # print measurement value for accelerometer Y-axis sensor channel in millionths |
|||
accel.micro(zsensor.ACCEL_Z) # print measurement value for accelerometer Z-axis sensor channel in thousandths |
|||
accel.int(zsensor.ACCEL_X) # print measurement integer value only for accelerometer X-axis sensor channel |
@ -0,0 +1,16 @@ |
|||
.. _zephyr_tutorial: |
|||
|
|||
MicroPython tutorial for the Zephyr port |
|||
======================================== |
|||
|
|||
This tutorial is intended to get you started with the Zephyr port. |
|||
|
|||
.. toctree:: |
|||
:maxdepth: 1 |
|||
:numbered: |
|||
|
|||
intro.rst |
|||
repl.rst |
|||
storage.rst |
|||
pins.rst |
|||
|
@ -0,0 +1,30 @@ |
|||
.. _intro_zephyr: |
|||
|
|||
Getting started with MicroPython on the Zephyr port |
|||
=================================================== |
|||
|
|||
Let’s get started! |
|||
|
|||
Requirements |
|||
------------ |
|||
|
|||
To use the MicroPython Zephyr port, you will need a Zephyr supported board (for a list of acceptable |
|||
boards see :ref:`zephyr_general`). |
|||
|
|||
Powering up |
|||
----------- |
|||
|
|||
If your board has a USB connector on it then most likely it is powered |
|||
through this when connected to your PC. Otherwise you will need to power |
|||
it directly. Please refer to the documentation for your board for |
|||
further details. |
|||
|
|||
Getting and deploying the firmware |
|||
---------------------------------- |
|||
|
|||
The first step you will need to do is either clone the `MicroPython repository <https://github.com/micropython/micropython.git>`_ |
|||
or download it from the `MicroPython downloads page <http://micropython.org/download>`_. If you are an end user of MicroPython, |
|||
it is recommended to start with the stable firmware builds. If you would like to work on development, you may follow the daily |
|||
builds on git. |
|||
|
|||
Next, follow the Zephyr port readme document (``ports/zephyr/README.md``) to build and run the application on your board. |
@ -0,0 +1,46 @@ |
|||
.. _pins_zephyr: |
|||
|
|||
GPIO Pins |
|||
========= |
|||
|
|||
Use :ref:`machine.Pin <machine.Pin>` to control I/O pins. |
|||
|
|||
For Zephyr, pins are initialized using a tuple of port and pin number ``(\"GPIO_x\", pin#)`` |
|||
for the ``id`` value. For example to initialize a pin for the red LED on a FRDM-k64 board:: |
|||
|
|||
LED = Pin(("GPIO_1", 22), Pin.OUT) |
|||
|
|||
Reference your board's datasheet or Zephyr documentation for pin numbers, see below for more examples. |
|||
|
|||
.. list-table:: Pin Formatting |
|||
:header-rows: 1 |
|||
|
|||
* - Board |
|||
- Pin |
|||
- Format |
|||
* - frdm_k64f |
|||
- Red LED = PTB22 |
|||
- ("GPIO_1", 22) |
|||
* - 96b_carbon |
|||
- LED1 = PD2 |
|||
- ("GPIOD", 2) |
|||
* - mimxrt685_evk_cm33 |
|||
- Green LED = PIO0_14 |
|||
- ("GPIO0", 14) |
|||
|
|||
Interrupts |
|||
---------- |
|||
|
|||
The Zephyr port also supports interrupt handling for Pins using `machine.Pin.irq() <machine.Pin.irq>`. |
|||
To respond to Pin change IRQs run:: |
|||
|
|||
from machine import Pin |
|||
|
|||
SW2 = Pin(("GPIO_2", 6), Pin.IN) # create Pin object for switch 2 |
|||
SW3 = Pin(("GPIO_0", 4), Pin.IN) # create Pin object for switch 3 |
|||
|
|||
SW2.irq(lambda t: print("SW2 changed")) # print message when SW2 state is changed (triggers change IRQ) |
|||
SW3.irq(lambda t: print("SW3 changed")) # print message when SW3 state is changed (triggers change IRQ) |
|||
|
|||
while True: # wait |
|||
pass |
@ -0,0 +1,75 @@ |
|||
Getting a MicroPython REPL prompt |
|||
================================= |
|||
|
|||
REPL stands for Read Evaluate Print Loop, and is the name given to the |
|||
interactive MicroPython prompt that you can access on your board through |
|||
Zephyr. It is recommended to use REPL to test out your code and run commands. |
|||
|
|||
REPL over the serial port |
|||
------------------------- |
|||
|
|||
The REPL is available on a UART serial peripheral specified for the board by |
|||
the ``zephyr,console`` devicetree node. The baudrate of the REPL is 115200. |
|||
If your board has a USB-serial convertor on it then you should be able to access |
|||
the REPL directly from your PC. |
|||
|
|||
To access the prompt over USB-serial you will need to use a terminal emulator |
|||
program. For a Linux or Mac machine, open a terminal and run:: |
|||
|
|||
screen /dev/ttyACM0 115200 |
|||
|
|||
You can also try ``picocom`` or ``minicom`` instead of screen. You may have to use |
|||
``/dev/ttyACM1`` or a higher number for ``ttyACM``. Additional permissions |
|||
may be necessary to access this device (eg group ``uucp`` or ``dialout``, or use sudo). |
|||
For Windows, get a terminal software, such as puTTY and connect via a serial session |
|||
using the proper COM port. |
|||
|
|||
Using the REPL |
|||
-------------- |
|||
|
|||
With your serial program open (PuTTY, screen, picocom, etc) you may see a |
|||
blank screen with a flashing cursor. Press Enter (or reset the board) and |
|||
you should be presented with the following text:: |
|||
|
|||
*** Booting Zephyr OS build v2.6.0-rc1-416-g3056c5ec30ad *** |
|||
MicroPython v2.6.0-rc1-416-g3056c5ec30 on 2021-06-24; zephyr-frdm_k64f with mk64f12 |
|||
Type "help()" for more information. |
|||
>>> |
|||
|
|||
Now you can try running MicroPython code directly on your board. |
|||
|
|||
Anything you type at the prompt, indicated by ``>>>``, will be executed after you press |
|||
the Enter key. If there is an error with the text that you enter then an error |
|||
message is printed. |
|||
|
|||
Start by typing the following at the prompt to make sure it is working:: |
|||
|
|||
>>> print("hello world!") |
|||
hello world! |
|||
|
|||
If you already know some python you can now try some basic commands here. For |
|||
example:: |
|||
|
|||
>>> 1 + 2 |
|||
3 |
|||
>>> 1 / 2 |
|||
0.5 |
|||
>>> 3 * 'Zephyr' |
|||
ZephyrZephyrZephyr |
|||
|
|||
If your board has an LED, you can blink it using the following code:: |
|||
|
|||
>>>import time |
|||
>>>from machine import Pin |
|||
|
|||
>>>LED = Pin(("GPIO_1", 21), Pin.OUT) |
|||
>>>while True: |
|||
... LED.value(1) |
|||
... time.sleep(0.5) |
|||
... LED.value(0) |
|||
... time.sleep(0.5) |
|||
|
|||
The above code uses an LED location for a FRDM-K64F board (port B, pin 21; |
|||
following Zephyr conventions ports are identified by "GPIO_x", where *x* |
|||
starts from 0). You will need to adjust it for another board using the board's |
|||
reference materials. |
@ -0,0 +1,56 @@ |
|||
.. _storage_zephyr: |
|||
|
|||
Filesystems and Storage |
|||
======================= |
|||
|
|||
Storage modules support virtual filesystem with FAT and littlefs formats, backed by either |
|||
Zephyr DiskAccess or FlashArea (flash map) APIs depending on which the board supports. |
|||
|
|||
See `uos Filesystem Mounting <https://docs.micropython.org/en/latest/library/uos.html?highlight=os#filesystem-mounting>`_. |
|||
|
|||
Disk Access |
|||
----------- |
|||
|
|||
The :ref:`zephyr.DiskAccess <zephyr.DiskAccess>` class can be used to access storage devices, such as SD cards. |
|||
This class uses `Zephyr Disk Access API <https://docs.zephyrproject.org/latest/reference/storage/disk/access.html>`_ and |
|||
implements the `uos.AbstractBlockDev` protocol. |
|||
|
|||
For use with SD card controllers, SD cards must be present at boot & not removed; they will |
|||
be auto detected and initialized by filesystem at boot. Use the disk driver interface and a |
|||
file system to access SD cards via disk access (see below). |
|||
|
|||
Example usage of FatFS with an SD card on the mimxrt1050_evk board:: |
|||
|
|||
import os |
|||
from zephyr import DiskAccess |
|||
bdev = zephyr.DiskAccess('SDHC') # create block device object using DiskAccess |
|||
os.VfsFat.mkfs(bdev) # create FAT filesystem object using the disk storage block |
|||
os.mount(bdev, '/sd') # mount the filesystem at the SD card subdirectory |
|||
with open('/sd/hello.txt','w') as f: # open a new file in the directory |
|||
f.write('Hello world') # write to the file |
|||
print(open('/sd/hello.txt').read()) # print contents of the file |
|||
|
|||
|
|||
Flash Area |
|||
---------- |
|||
|
|||
The :ref:`zephyr.FlashArea <zephyr.FlashArea>` class can be used to implement a low-level storage system or |
|||
customize filesystem configurations. To store persistent data on the device, using a higher-level filesystem |
|||
API is recommended (see below). |
|||
|
|||
This class uses `Zephyr Flash map API <https://docs.zephyrproject.org/latest/reference/storage/flash_map/flash_map.html#>`_ and |
|||
implements the `uos.AbstractBlockDev` protocol. |
|||
|
|||
Example usage with the internal flash on the reel_board or the rv32m1_vega_ri5cy board:: |
|||
|
|||
import os |
|||
from zephyr import FlashArea |
|||
bdev = FlashArea(FlashArea.STORAGE, 4096) # create block device object using FlashArea |
|||
os.VfsLfs2.mkfs(bdev) # create Little filesystem object using the flash area block |
|||
os.mount(bdev, '/flash') # mount the filesystem at the flash storage subdirectory |
|||
with open('/flash/hello.txt','w') as f: # open a new file in the directory |
|||
f.write('Hello world') # write to the file |
|||
print(open('/flash/hello.txt').read()) # print contents of the file |
|||
|
|||
For boards such as the frdm_k64f in which the MicroPython application spills into the default flash storage |
|||
partition, use the scratch partition by replacing ``FlashArea.STORAGE`` with the integer value 4. |
Loading…
Reference in new issue