Update Micropython

This commit is contained in:
Amir Gonnen 2021-06-15 01:07:36 +03:00
commit 377068c5f2
488 changed files with 12459 additions and 1752 deletions

View File

@ -1,3 +1,6 @@
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
0f78c36c5aa458a954eed39a46942209107a553e
# tests/run-tests.py: Reformat with Black.
2a38d7103672580882fb621a5b76e8d26805d593

23
.github/workflows/ports_mimxrt.yml vendored Normal file
View File

@ -0,0 +1,23 @@
name: mimxrt port
on:
push:
pull_request:
paths:
- '.github/workflows/*.yml'
- 'tools/**'
- 'py/**'
- 'extmod/**'
- 'lib/**'
- 'drivers/**'
- 'ports/mimxrt/**'
jobs:
build:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- name: Install packages
run: source tools/ci.sh && ci_mimxrt_setup
- name: Build
run: source tools/ci.sh && ci_mimxrt_build

8
.gitignore vendored
View File

@ -9,6 +9,9 @@
*.dis
*.exe
lextab.py
yacctab.py
# Packages
############
@ -55,5 +58,6 @@ ports/javascript/node_modules
######################
genrst/
lextab.py
yacctab.py
# MacOS desktop metadata files
######################
.DS_Store

2
.gitmodules vendored
View File

@ -7,7 +7,7 @@
url = https://github.com/atgreen/libffi
[submodule "lib/lwip"]
path = lib/lwip
url = https://git.savannah.gnu.org/r/lwip.git
url = https://github.com/lwip-tcpip/lwip.git
[submodule "lib/berkeley-db-1.xx"]
path = lib/berkeley-db-1.xx
url = https://github.com/pfalcon/berkeley-db-1.xx

View File

@ -91,7 +91,7 @@ This simple module named ``cexample`` provides a single function
``cexample.add_ints(a, b)`` which adds the two integer args together and returns
the result. It can be found in the MicroPython source tree
`in the examples directory <https://github.com/micropython/micropython/tree/master/examples/usercmodule/cexample>`_
and has a source file and a Makefile fragment with content as descibed above::
and has a source file and a Makefile fragment with content as described above::
micropython/
└──examples/

View File

@ -58,7 +58,7 @@ The :mod:`esp32` module::
import esp32
esp32.hall_sensor() # read the internal hall sensor
esp32.raw_temperature() # read the internal temperature of the MCU, in Farenheit
esp32.raw_temperature() # read the internal temperature of the MCU, in Fahrenheit
esp32.ULP() # access to the Ultra-Low-Power Co-processor
Note that the temperature sensor in the ESP32 will typically read higher than
@ -171,6 +171,37 @@ Notes:
* The pull value of some pins can be set to ``Pin.PULL_HOLD`` to reduce power
consumption during deepsleep.
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
which can be used to invert a pin. Useful for illuminating active-low LEDs
using ``on()`` or ``value(1)``.
UART (serial bus)
-----------------
See :ref:`machine.UART <machine.UART>`. ::
from machine import UART
uart1 = UART(1, baudrate=9600, tx=33, rx=32)
uart1.write('hello') # write 5 bytes
uart1.read(5) # read up to 5 bytes
The ESP32 has three hardware UARTs: UART0, UART1 and UART2.
They each have default GPIO assigned to them, however depending on your
ESP32 variant and board, these pins may conflict with embedded flash,
onboard PSRAM or peripherals.
Any GPIO can be used for hardware UARTs using the GPIO matrix, so to avoid
conflicts simply provide ``tx`` and ``rx`` pins when constructing. The default
pins listed below.
===== ===== ===== =====
\ UART0 UART1 UART2
===== ===== ===== =====
tx 1 10 17
rx 3 9 16
===== ===== ===== =====
PWM (pulse width modulation)
----------------------------
@ -357,6 +388,17 @@ See :ref:`machine.RTC <machine.RTC>` ::
rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
rtc.datetime() # get date and time
WDT (Watchdog timer)
--------------------
See :ref:`machine.WDT <machine.WDT>`. ::
from machine import WDT
# enable the WDT with a timeout of 5s (1s is the minimum)
wdt = WDT(timeout=5000)
wdt.feed()
Deep-sleep mode
---------------
@ -386,6 +428,21 @@ Notes:
p1 = Pin(4, Pin.OUT, None)
SD card
-------
See :ref:`machine.SDCard <machine.SDCard>`. ::
import machine, uos
# Slot 2 uses pins sck=18, cs=5, miso=19, mosi=23
sd = machine.SDCard(slot=2)
uos.mount(sd, "/sd") # mount
uos.listdir('/sd') # list directory contents
uos.umount('/sd') # eject
RMT
---
@ -430,10 +487,10 @@ Be sure to put a 4.7k pull-up resistor on the data line. Note that
the ``convert_temp()`` method must be called each time you want to
sample the temperature.
NeoPixel driver
---------------
NeoPixel and APA106 driver
--------------------------
Use the ``neopixel`` module::
Use the ``neopixel`` and ``apa106`` modules::
from machine import Pin
from neopixel import NeoPixel
@ -444,6 +501,13 @@ Use the ``neopixel`` module::
np.write() # write data to all pixels
r, g, b = np[0] # get first pixel colour
The APA106 driver extends NeoPixel, but internally uses a different colour order::
from apa106 import APA106
ap = APA106(pin, 8)
r, g, b = ap[0]
For low-level driving of a NeoPixel::
import esp
@ -455,6 +519,7 @@ For low-level driving of a NeoPixel::
400kHz) devices by passing ``timing=0`` when constructing the
``NeoPixel`` object.
APA102 (DotStar) uses a different driver as it has an additional clock pin.
Capacitive touch
----------------

View File

@ -125,6 +125,16 @@ will overflow every 7:45h. If a long-term working RTC time is required then
``time()`` or ``localtime()`` must be called at least once within 7 hours.
MicroPython will then handle the overflow.
Simultaneous operation of STA_IF and AP_IF
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Simultaneous operation of STA_IF and AP_IF interfaces is supported.
However, due to restrictions of the hardware, there may be performance
issues in the AP_IF, if the STA_IF is not connected and searching.
An application should manage these interfaces and for example
deactivate the STA_IF in environments where only the AP_IF is used.
Sockets and WiFi buffers overflow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -153,25 +163,26 @@ SSL/TLS limitations
~~~~~~~~~~~~~~~~~~~
ESP8266 uses `axTLS <http://axtls.sourceforge.net/>`_ library, which is one
of the smallest TLS libraries with the compatible licensing. However, it
of the smallest TLS libraries with compatible licensing. However, it
also has some known issues/limitations:
1. No support for Diffie-Hellman (DH) key exchange and Elliptic-curve
cryptography (ECC). This means it can't work with sites which force
the use of these features (it works ok with classic RSA certificates).
cryptography (ECC). This means it can't work with sites which require
the use of these features (it works ok with the typical sites that use
RSA certificates).
2. Half-duplex communication nature. axTLS uses a single buffer for both
sending and receiving, which leads to considerable memory saving and
works well with protocols like HTTP. But there may be problems with
protocols which don't follow classic request-response model.
Besides axTLS own limitations, the configuration used for MicroPython is
Besides axTLS's own limitations, the configuration used for MicroPython is
highly optimized for code size, which leads to additional limitations
(these may be lifted in the future):
3. Optimized RSA algorithms are not enabled, which may lead to slow
SSL handshakes.
4. Stored sessions are not supported (may allow faster repeated connections
to the same site in some circumstances).
4. Session Reuse is not enabled, which means every connection must undergo
the full, expensive SSL handshake.
Besides axTLS specific limitations described above, there's another generic
limitation with usage of TLS on the low-memory devices:
@ -185,13 +196,16 @@ limitation with usage of TLS on the low-memory devices:
accessing various REST APIs, which usually require much smaller messages.
The buffers size is on the order of 5KB, and is adjusted from time to
time, taking as a reference being able to access https://google.com .
The smaller buffer hower means that some sites can't be accessed using
it, and it's not possible to stream large amounts of data.
The smaller buffer however means that some sites can't be accessed using
it, and it's not possible to stream large amounts of data. axTLS does
have support for TLS's Max Fragment Size extension, but no HTTPS website
does, so use of the extension is really only effective for local
communication with other devices.
There are also some not implemented features specifically in MicroPython's
``ussl`` module based on axTLS:
6. Certificates are not validated (this may make connections susceptible
6. Certificates are not validated (this makes connections susceptible
to man-in-the-middle attacks).
7. There is no support for client certificates (scheduled to be fixed in
1.9.4 release).

View File

@ -58,7 +58,7 @@ The :mod:`network` module::
wlan.scan() # scan for access points
wlan.isconnected() # check if the station is connected to an AP
wlan.connect('essid', 'password') # connect to an AP
wlan.config('mac') # get the interface's MAC adddress
wlan.config('mac') # get the interface's MAC address
wlan.ifconfig() # get the interface's IP/netmask/gw/DNS addresses
ap = network.WLAN(network.AP_IF) # create access-point interface
@ -138,6 +138,10 @@ Also note that Pin(16) is a special pin (used for wakeup from deepsleep
mode) and may be not available for use with higher-level classes like
``Neopixel``.
There's a higher-level abstraction :ref:`machine.Signal <machine.Signal>`
which can be used to invert a pin. Useful for illuminating active-low LEDs
using ``on()`` or ``value(1)``.
UART (serial bus)
-----------------
@ -293,6 +297,17 @@ See :ref:`machine.RTC <machine.RTC>` ::
(using a custom handler), `RTC.init()` and `RTC.deinit()` are
currently not supported.
WDT (Watchdog timer)
--------------------
See :ref:`machine.WDT <machine.WDT>`. ::
from machine import WDT
# enable the WDT
wdt = WDT()
wdt.feed()
Deep-sleep mode
---------------
@ -409,6 +424,20 @@ The DHT driver is implemented in software and works on all pins::
d.temperature() # eg. 23.6 (°C)
d.humidity() # eg. 41.3 (% RH)
SSD1306 driver
--------------
Driver for SSD1306 monochrome OLED displays. See tutorial :ref:`ssd1306`. ::
from machine import Pin, I2C
import ssd1306
i2c = I2C(scl=Pin(5), sda=Pin(4), freq=100000)
display = ssd1306.SSD1306_I2C(128, 64, i2c)
display.text('Hello World', 0, 0, 1)
display.show()
WebREPL (web browser interactive prompt)
----------------------------------------

View File

@ -31,4 +31,5 @@ to `<https://www.python.org>`__.
neopixel.rst
apa102.rst
dht.rst
ssd1306.rst
nextsteps.rst

View File

@ -75,6 +75,10 @@ the DTR and RTS pins wired in a special way then deploying the firmware should
be easy as all steps can be done automatically. Boards that have such features
include the Adafruit Feather HUZZAH and NodeMCU boards.
If you do not have such a board, you need keep GPIO0 pulled to ground and reset
the device by pulling the reset pin to ground and releasing it again to enter
programming mode.
For best results it is recommended to first erase the entire flash of your
device before putting on new MicroPython firmware.
@ -113,6 +117,10 @@ the firmware (note the ``-fm dio`` option)::
If the above commands run without error then MicroPython should be installed on
your board!
If you pulled GPIO0 manually to ground to enter programming mode, release it
now and reset the device by again pulling the reset pin to ground for a short
duration.
Serial prompt
-------------

View File

@ -0,0 +1,93 @@
.. _ssd1306:
Using a SSD1306 OLED display
============================
The SSD1306 OLED display uses either a SPI or I2C interface and comes in a variety of
sizes (128x64, 128x32, 72x40, 64x48) and colours (white, yellow, blue, yellow + blue).
Hardware SPI interface::
from machine import Pin, SPI
import ssd1306
hspi = SPI(1) # sck=14 (scl), mosi=13 (sda), miso=12 (unused)
dc = Pin(4) # data/command
rst = Pin(5) # reset
cs = Pin(15) # chip select, some modules do not have a pin for this
display = ssd1306.SSD1306_SPI(128, 64, hspi, dc, rst, cs)
Software SPI interface::
from machine import Pin, SoftSPI
import ssd1306
spi = SoftSPI(baudrate=500000, polarity=1, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
dc = Pin(4) # data/command
rst = Pin(5) # reset
cs = Pin(15) # chip select, some modules do not have a pin for this
display = ssd1306.SSD1306_SPI(128, 64, spi, dc, rst, cs)
I2C interface::
from machine import Pin, I2C
import ssd1306
# using default address 0x3C
i2c = I2C(sda=Pin(4), scl=Pin(5))
display = ssd1306.SSD1306_I2C(128, 64, i2c)
Print Hello World on the first line::
display.text('Hello, World!', 0, 0, 1)
display.show()
Basic functions::
display.poweroff() # power off the display, pixels persist in memory
display.poweron() # power on the display, pixels redrawn
display.contrast(0) # dim
display.contrast(255) # bright
display.invert(1) # display inverted
display.invert(0) # display normal
display.rotate(True) # rotate 180 degrees
display.rotate(False) # rotate 0 degrees
display.show() # write the contents of the FrameBuffer to display memory
Subclassing FrameBuffer provides support for graphics primitives::
display.fill(0) # fill entire screen with colour=0
display.pixel(0, 10) # get pixel at x=0, y=10
display.pixel(0, 10, 1) # set pixel at x=0, y=10 to colour=1
display.hline(0, 8, 4, 1) # draw horizontal line x=0, y=8, width=4, colour=1
display.vline(0, 8, 4, 1) # draw vertical line x=0, y=8, height=4, colour=1
display.line(0, 0, 127, 63, 1) # draw a line from 0,0 to 127,63
display.rect(10, 10, 107, 43, 1) # draw a rectangle outline 10,10 to 107,43, colour=1
display.fill_rect(10, 10, 107, 43, 1) # draw a solid rectangle 10,10 to 107,43, colour=1
display.text('Hello World', 0, 0, 1) # draw some text at x=0, y=0, colour=1
display.scroll(20, 0) # scroll 20 pixels to the right
# draw another FrameBuffer on top of the current one at the given coordinates
import framebuf
fbuf = framebuf.FrameBuffer(bytearray(8 * 8 * 1), 8, 8, framebuf.MONO_VLSB)
fbuf.line(0, 0, 7, 7, 1)
display.blit(fbuf, 10, 10, 0) # draw on top at x=10, y=10, key=0
display.show()
Draw the MicroPython logo and print some text::
display.fill(0)
display.fill_rect(0, 0, 32, 32, 1)
display.fill_rect(2, 2, 28, 28, 0)
display.vline(9, 8, 22, 1)
display.vline(16, 2, 22, 1)
display.vline(23, 8, 22, 1)
display.fill_rect(26, 24, 2, 4, 1)
display.text('MicroPython', 40, 0, 1)
display.text('SSD1306', 40, 12, 1)
display.text('OLED 128x64', 40, 24, 1)
display.show()

View File

@ -11,5 +11,6 @@ MicroPython documentation and references
pyboard/quickref.rst
esp8266/quickref.rst
esp32/quickref.rst
rp2/quickref.rst
wipy/quickref.rst
unix/quickref.rst

View File

@ -176,10 +176,6 @@ Exceptions
.. exception:: OSError
|see_cpython| `python:OSError`. MicroPython doesn't implement ``errno``
attribute, instead use the standard way to access exception arguments:
``exc.args[0]``.
.. exception:: RuntimeError
.. exception:: StopIteration

View File

@ -162,7 +162,7 @@ used to transmit or receive many other types of digital signals::
The input to the RMT module is an 80MHz clock (in the future it may be able to
configure the input clock but, for now, it's fixed). ``clock_div`` *divides*
the clock input which determines the resolution of the RMT channel. The
numbers specificed in ``write_pulses`` are multiplied by the resolution to
numbers specified in ``write_pulses`` are multiplied by the resolution to
define the pulses.
``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by

View File

@ -165,3 +165,14 @@ The following libraries are specific to the ESP8266 and ESP32.
esp.rst
esp32.rst
Libraries specific to the RP2040
--------------------------------
The following libraries are specific to the RP2040, as used in the Raspberry Pi Pico.
.. toctree::
:maxdepth: 2
rp2.rst

View File

@ -0,0 +1,79 @@
.. currentmodule:: machine
.. _machine.PWM:
class PWM -- pulse width modulation
===================================
This class provides pulse width modulation output.
Example usage::
from machine import PWM
pwm = PWM(pin) # create a PWM object on a pin
pwm.duty_u16(32768) # set duty to 50%
# reinitialise with a period of 200us, duty of 5us
pwm.init(freq=5000, duty_ns=5000)
pwm.duty_ns(3000) # set pulse width to 3us
pwm.deinit()
Constructors
------------
.. class:: PWM(dest, \*, freq, duty_u16, duty_ns)
Construct and return a new PWM object using the following parameters:
- *dest* is the entity on which the PWM is output, which is usually a
:ref:`machine.Pin <machine.Pin>` object, but a port may allow other values,
like integers.
- *freq* should be an integer which sets the frequency in Hz for the
PWM cycle.
- *duty_u16* sets the duty cycle as a ratio ``duty_u16 / 65535``.
- *duty_ns* sets the pulse width in nanoseconds.
Setting *freq* may affect other PWM objects if the objects share the same
underlying PWM generator (this is hardware specific).
Only one of *duty_u16* and *duty_ns* should be specified at a time.
Methods
-------
.. method:: PWM.init(\*, freq, duty_u16, duty_ns)
Modify settings for the PWM object. See the above constructor for details
about the parameters.
.. method:: PWM.deinit()
Disable the PWM output.
.. method:: PWM.freq([value])
Get or set the current frequency of the PWM output.
With no arguments the frequency in Hz is returned.
With a single *value* argument the frequency is set to that value in Hz. The
method may raise a ``ValueError`` if the frequency is outside the valid range.
.. method:: PWM.duty_u16([value])
Get or set the current duty cycle of the PWM output, as an unsigned 16-bit
value in the range 0 to 65535 inclusive.
With no arguments the duty cycle is returned.
With a single *value* argument the duty cycle is set to that value, measured
as the ratio ``value / 65535``.
.. method:: PWM.duty_ns([value])
Get or set the current pulse width of the PWM output, as a value in nanoseconds.
With no arguments the pulse width in nanoseconds is returned.
With a single *value* argument the pulse width is set to that value.

View File

@ -9,7 +9,7 @@ the most flexible and heterogeneous kind of hardware in MCUs and SoCs,
differently greatly from a model to a model. MicroPython's Timer class
defines a baseline operation of executing a callback with a given period
(or once after some delay), and allow specific boards to define more
non-standard behavior (which thus won't be portable to other boards).
non-standard behaviour (which thus won't be portable to other boards).
See discussion of :ref:`important constraints <machine_callbacks>` on
Timer callbacks.

View File

@ -16,7 +16,7 @@ the most flexible and heterogeneous kind of hardware in MCUs and SoCs,
differently greatly from a model to a model. MicroPython's Timer class
defines a baseline operation of executing a callback with a given period
(or once after some delay), and allow specific boards to define more
non-standard behavior (which thus won't be portable to other boards).
non-standard behaviour (which thus won't be portable to other boards).
See discussion of :ref:`important constraints <machine_callbacks>` on
Timer callbacks.
@ -115,7 +115,7 @@ Methods
.. method:: timerchannel.irq(*, trigger, priority=1, handler=None)
The behavior of this callback is heavily dependent on the operating
The behaviour of this callback is heavily dependent on the operating
mode of the timer channel:
- If mode is ``TimerWiPy.PERIODIC`` the callback is executed periodically

View File

@ -37,6 +37,14 @@ Reset related functions
Get the reset cause. See :ref:`constants <machine_constants>` for the possible return values.
.. function:: bootloader([value])
Reset the device and enter its bootloader. This is typically used to put the
device into a state where it can be programmed with new firmware.
Some ports support passing in an optional *value* argument which can control
which bootloader to enter, what to pass to it, or other things.
Interrupt related functions
---------------------------
@ -56,9 +64,11 @@ Interrupt related functions
Power related functions
-----------------------
.. function:: freq()
.. function:: freq([hz])
Returns CPU frequency in hertz.
Returns the CPU frequency in hertz.
On some ports this can also be used to set the CPU frequency by passing in *hz*.
.. function:: idle()
@ -167,6 +177,7 @@ Classes
machine.Pin.rst
machine.Signal.rst
machine.ADC.rst
machine.PWM.rst
machine.UART.rst
machine.SPI.rst
machine.I2C.rst

View File

@ -25,7 +25,7 @@ For this example to work the CC3000 module must have the following connections:
- VBEN connected to Y4
- IRQ connected to Y3
It is possible to use other SPI busses and other pins for CS, VBEN and IRQ.
It is possible to use other SPI buses and other pins for CS, VBEN and IRQ.
Constructors
------------

View File

@ -26,7 +26,7 @@ For this example to work the WIZnet5x00 module must have the following connectio
- nSS connected to X5
- nRESET connected to X4
It is possible to use other SPI busses and other pins for nSS and nRESET.
It is possible to use other SPI buses and other pins for nSS and nRESET.
Constructors
------------

View File

@ -55,7 +55,7 @@ parameter should be `id`.
Activate ("up") or deactivate ("down") the network interface, if
a boolean argument is passed. Otherwise, query current state if
no argument is provided. Most other methods require an active
interface (behavior of calling them on inactive interface is
interface (behaviour of calling them on inactive interface is
undefined).
.. method:: AbstractNIC.connect([service_id, key=None, *, ...])

View File

@ -30,7 +30,7 @@ Constructors
the bus, if any). If extra arguments are given, the bus is initialised.
See :meth:`CAN.init` for parameters of initialisation.
The physical pins of the CAN busses are:
The physical pins of the CAN buses are:
- ``CAN(1)`` is on ``YA``: ``(RX, TX) = (Y3, Y4) = (PB8, PB9)``
- ``CAN(2)`` is on ``YB``: ``(RX, TX) = (Y5, Y6) = (PB12, PB13)``

View File

@ -64,7 +64,7 @@ Constructors
the bus, if any). If extra arguments are given, the bus is initialised.
See ``init`` for parameters of initialisation.
The physical pins of the I2C busses on Pyboards V1.0 and V1.1 are:
The physical pins of the I2C buses on Pyboards V1.0 and V1.1 are:
- ``I2C(1)`` is on the X position: ``(SCL, SDA) = (X9, X10) = (PB6, PB7)``
- ``I2C(2)`` is on the Y position: ``(SCL, SDA) = (Y9, Y10) = (PB10, PB11)``

View File

@ -98,11 +98,11 @@ Class methods
Methods
-------
.. method:: Pin.init(mode, pull=Pin.PULL_NONE, af=-1)
.. method:: Pin.init(mode, pull=Pin.PULL_NONE, \*, value=None, alt=-1)
Initialise the pin:
- ``mode`` can be one of:
- *mode* can be one of:
- ``Pin.IN`` - configure the pin for input;
- ``Pin.OUT_PP`` - configure the pin for output, with push-pull control;
@ -111,14 +111,17 @@ Methods
- ``Pin.AF_OD`` - configure the pin for alternate function, open-drain;
- ``Pin.ANALOG`` - configure the pin for analog.
- ``pull`` can be one of:
- *pull* can be one of:
- ``Pin.PULL_NONE`` - no pull up or down resistors;
- ``Pin.PULL_UP`` - enable the pull-up resistor;
- ``Pin.PULL_DOWN`` - enable the pull-down resistor.
- when mode is ``Pin.AF_PP`` or ``Pin.AF_OD``, then af can be the index or name
of one of the alternate functions associated with a pin.
- *value* if not None will set the port output value before enabling the pin.
- *alt* can be used when mode is ``Pin.AF_PP`` or ``Pin.AF_OD`` to set the
index or name of one of the alternate functions associated with a pin.
This arg was previously called *af* which can still be used if needed.
Returns: ``None``.

View File

@ -36,7 +36,7 @@ Constructors
the bus, if any). If extra arguments are given, the bus is initialised.
See ``init`` for parameters of initialisation.
The physical pins of the SPI busses are:
The physical pins of the SPI buses are:
- ``SPI(1)`` is on the X position: ``(NSS, SCK, MISO, MOSI) = (X5, X6, X7, X8) = (PA4, PA5, PA6, PA7)``
- ``SPI(2)`` is on the Y position: ``(NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)``

View File

@ -57,7 +57,7 @@ Constructors
the bus, if any). If extra arguments are given, the bus is initialised.
See ``init`` for parameters of initialisation.
The physical pins of the UART busses on Pyboard are:
The physical pins of the UART buses on Pyboard are:
- ``UART(4)`` is on ``XA``: ``(TX, RX) = (X1, X2) = (PA0, PA1)``
- ``UART(1)`` is on ``XB``: ``(TX, RX) = (X9, X10) = (PB6, PB7)``

View File

@ -126,7 +126,7 @@ Power related functions
- pclk2: frequency of the APB2 bus
If given any arguments then the function sets the frequency of the CPU,
and the busses if additional arguments are given. Frequencies are given in
and the buses if additional arguments are given. Frequencies are given in
Hz. Eg freq(120000000) sets sysclk (the CPU frequency) to 120MHz. Note that
not all values are supported and the largest supported frequency not greater
than the given value will be selected.

View File

@ -0,0 +1,36 @@
.. currentmodule:: rp2
.. _rp2.Flash:
class Flash -- access to built-in flash storage
===============================================
This class gives access to the SPI flash memory.
In most cases, to store persistent data on the device, you'll want to use a
higher-level abstraction, for example the filesystem via Python's standard file
API, but this interface is useful to :ref:`customise the filesystem
configuration <filesystem>` or implement a low-level storage system for your
application.
Constructors
------------
.. class:: Flash()
Gets the singleton object for accessing the SPI flash memory.
Methods
-------
.. method:: Flash.readblocks(block_num, buf)
Flash.readblocks(block_num, buf, offset)
.. method:: Flash.writeblocks(block_num, buf)
Flash.writeblocks(block_num, buf, offset)
.. method:: Flash.ioctl(cmd, arg)
These methods implement the simple and extended
:ref:`block protocol <block-device-interface>` defined by
:class:`uos.AbstractBlockDev`.

94
docs/library/rp2.PIO.rst Normal file
View File

@ -0,0 +1,94 @@
.. currentmodule:: rp2
.. _rp2.PIO:
class PIO -- advanced PIO usage
===============================
The :class:`PIO` class gives access to an instance of the RP2040's PIO
(programmable I/O) interface.
The preferred way to interact with PIO is using :class:`rp2.StateMachine`, the
PIO class is for advanced use.
For assembling PIO programs, see :func:`rp2.asm_pio`.
Constructors
------------
.. class:: PIO(id)
Gets the PIO instance numbered *id*. The RP2040 has two PIO instances,
numbered 0 and 1.
Raises a ``ValueError`` if any other argument is provided.
Methods
-------
.. method:: PIO.add_program(program)
Add the *program* to the instruction memory of this PIO instance.
The amount of memory available for programs on each PIO instance is
limited. If there isn't enough space left in the PIO's program memory
this method will raise ``OSError(ENOMEM)``.
.. method:: PIO.remove_program([program])
Remove *program* from the instruction memory of this PIO instance.
If no program is provided, it removes all programs.
It is not an error to remove a program which has already been removed.
.. method:: PIO.state_machine(id, [program, ...])
Gets the state machine numbered *id*. On the RP2040, each PIO instance has
four state machines, numbered 0 to 3.
Optionally initialize it with a *program*: see `StateMachine.init`.
>>> rp2.PIO(1).state_machine(3)
StateMachine(7)
.. method:: PIO.irq(handler=None, trigger=IRQ_SM0|IRQ_SM1|IRQ_SM2|IRQ_SM3, hard=False)
Returns the IRQ object for this PIO instance.
MicroPython only uses IRQ 0 on each PIO instance. IRQ 1 is not available.
Optionally configure it.
Constants
---------
.. data:: PIO.IN_LOW
PIO.IN_HIGH
PIO.OUT_LOW
PIO.OUT_HIGH
These constants are used for the *out_init*, *set_init*, and *sideset_init*
arguments to `asm_pio`.
.. data:: PIO.SHIFT_LEFT
PIO.SHIFT_RIGHT
These constants are used for the *in_shiftdir* and *out_shiftdir* arguments
to `asm_pio` or `StateMachine.init`.
.. data:: PIO.JOIN_NONE
PIO.JOIN_TX
PIO.JOIN_RX
These constants are used for the *fifo_join* argument to `asm_pio`.
.. data:: PIO.IRQ_SM0
PIO.IRQ_SM1
PIO.IRQ_SM2
PIO.IRQ_SM3
These constants are used for the *trigger* argument to `PIO.irq`.

View File

@ -0,0 +1,131 @@
.. currentmodule:: rp2
.. _rp2.StateMachine:
class StateMachine -- access to the RP2040's programmable I/O interface
=======================================================================
The :class:`StateMachine` class gives access to the RP2040's PIO (programmable
I/O) interface.
For assembling PIO programs, see :func:`rp2.asm_pio`.
Constructors
------------
.. class:: StateMachine(id, [program, ...])
Get the state machine numbered *id*. The RP2040 has two identical PIO
instances, each with 4 state machines: so there are 8 state machines in
total, numbered 0 to 7.
Optionally initialize it with the given program *program*: see
`StateMachine.init`.
Methods
-------
.. method:: StateMachine.init(program, freq=-1, *, in_base=None, out_base=None, set_base=None, jmp_pin=None, sideset_base=None, in_shiftdir=None, out_shiftdir=None, push_thresh=None, pull_thresh=None)
Configure the state machine instance to run the given *program*.
The program is added to the instruction memory of this PIO instance. If the
instruction memory already contains this program, then its offset is
re-used so as to save on instruction memory.
- *freq* is the frequency in Hz to run the state machine at. Defaults to
the system clock frequency.
The clock divider is computed as ``system clock frequency / freq``, so
there can be slight rounding errors.
The minimum possible clock divider is one 65536th of the system clock: so
at the default system clock frequency of 125MHz, the minimum value of
*freq* is ``1908``. To run state machines at slower frequencies, you'll
need to reduce the system clock speed with `machine.freq()`.
- *in_base* is the first pin to use for ``in()`` instructions.
- *out_base* is the first pin to use for ``out()`` instructions.
- *set_base* is the first pin to use for ``set()`` instructions.
- *jmp_pin* is the first pin to use for ``jmp(pin, ...)`` instructions.
- *sideset_base* is the first pin to use for side-setting.
- *in_shiftdir* is the direction the ISR will shift, either
`PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`.
- *out_shiftdir* is the direction the OSR will shift, either
`PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`.
- *push_thresh* is the threshold in bits before auto-push or conditional
re-pushing is triggered.
- *pull_thresh* is the threshold in bits before auto-push or conditional
re-pushing is triggered.
.. method:: StateMachine.active([value])
Gets or sets whether the state machine is currently running.
>>> sm.active()
True
>>> sm.active(0)
False
.. method:: StateMachine.restart()
Restarts the state machine and jumps to the beginning of the program.
This method clears the state machine's internal state using the RP2040's
``SM_RESTART`` register. This includes:
- input and output shift counters
- the contents of the input shift register
- the delay counter
- the waiting-on-IRQ state
- a stalled instruction run using `StateMachine.exec()`
.. method:: StateMachine.exec(instr)
Execute a single PIO instruction. Uses `asm_pio_encode` to encode the
instruction from the given string *instr*.
>>> sm.exec("set(0, 1)")
.. method:: StateMachine.get(buf=None, shift=0)
Pull a word from the state machine's RX FIFO.
If the FIFO is empty, it blocks until data arrives (i.e. the state machine
pushes a word).
The value is shifted right by *shift* bits before returning, i.e. the
return value is ``word >> shift``.
.. method:: StateMachine.put(value, shift=0)
Push a word onto the state machine's TX FIFO.
If the FIFO is full, it blocks until there is space (i.e. the state machine
pulls a word).
The value is first shifted left by *shift* bits, i.e. the state machine
receives ``value << shift``.
.. method:: StateMachine.rx_fifo()
Returns the number of words in the state machine's RX FIFO. A value of 0
indicates the FIFO is empty.
Useful for checking if data is waiting to be read, before calling
`StateMachine.get()`.
.. method:: StateMachine.tx_fifo()
Returns the number of words in the state machine's TX FIFO. A value of 0
indicates the FIFO is empty.
Useful for checking if there is space to push another word using
`StateMachine.put()`.
.. method:: StateMachine.irq(handler=None, trigger=0|1, hard=False)
Returns the IRQ object for the given StateMachine.
Optionally configure it.

83
docs/library/rp2.rst Normal file
View File

@ -0,0 +1,83 @@
.. currentmodule:: rp2
:mod:`rp2` --- functionality specific to the RP2040
===================================================
.. module:: rp2
:synopsis: functionality specific to the RP2
The ``rp2`` module contains functions and classes specific to the RP2040, as
used in the Raspberry Pi Pico.
See the `RP2040 Python datasheet
<https://datasheets.raspberrypi.org/pico/raspberry-pi-pico-python-sdk.pdf>`_
for more information, and `pico-micropython-examples
<https://github.com/raspberrypi/pico-micropython-examples/tree/master/pio>`_
for example code.
PIO related functions
---------------------
The ``rp2`` module includes functions for assembling PIO programs.
For running PIO programs, see :class:`rp2.StateMachine`.
.. function:: asm_pio(*, out_init=None, set_init=None, sideset_init=None, in_shiftdir=0, out_shiftdir=0, autopush=False, autopull=False, push_thresh=32, pull_thresh=32, fifo_join=PIO.JOIN_NONE)
Assemble a PIO program.
The following parameters control the initial state of the GPIO pins, as one
of `PIO.IN_LOW`, `PIO.IN_HIGH`, `PIO.OUT_LOW` or `PIO.OUT_HIGH`. If the
program uses more than one pin, provide a tuple, e.g.
``out_init=(PIO.OUT_LOW, PIO.OUT_LOW)``.
- *out_init* configures the pins used for ``out()`` instructions.
- *set_init* configures the pins used for ``set()`` instructions. There can
be at most 5.
- *sideset_init* configures the pins used side-setting. There can be at
most 5.
The following parameters are used by default, but can be overridden in
`StateMachine.init()`:
- *in_shiftdir* is the default direction the ISR will shift, either
`PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`.
- *out_shiftdir* is the default direction the OSR will shift, either
`PIO.SHIFT_LEFT` or `PIO.SHIFT_RIGHT`.
- *push_thresh* is the threshold in bits before auto-push or conditional
re-pushing is triggered.
- *pull_thresh* is the threshold in bits before auto-push or conditional
re-pushing is triggered.
The remaining parameters are:
- *autopush* configures whether auto-push is enabled.
- *autopull* configures whether auto-pull is enabled.
- *fifo_join* configures whether the 4-word TX and RX FIFOs should be
combined into a single 8-word FIFO for one direction only. The options
are `PIO.JOIN_NONE`, `PIO.JOIN_RX` and `PIO.JOIN_TX`.
.. function:: asm_pio_encode(instr, sideset_count)
Assemble a single PIO instruction. You usually want to use `asm_pio()`
instead.
>>> rp2.asm_pio_encode("set(0, 1)", 0)
57345
.. class:: PIOASMError
This exception is raised from `asm_pio()` or `asm_pio_encode()` if there is
an error assembling a PIO program.
Classes
-------
.. toctree::
:maxdepth: 1
rp2.Flash.rst
rp2.PIO.rst
rp2.StateMachine.rst

View File

@ -245,7 +245,7 @@ Module contents
.. data:: VOID
``VOID`` is an alias for ``UINT8``, and is provided to conviniently define
``VOID`` is an alias for ``UINT8``, and is provided to conveniently define
C's void pointers: ``(uctypes.PTR, uctypes.VOID)``.
.. data:: PTR

View File

@ -16,13 +16,13 @@ Constants
Error codes, based on ANSI C/POSIX standard. All error codes start with
"E". As mentioned above, inventory of the codes depends on
:term:`MicroPython port`. Errors are usually accessible as ``exc.args[0]``
:term:`MicroPython port`. Errors are usually accessible as ``exc.errno``
where ``exc`` is an instance of `OSError`. Usage example::
try:
uos.mkdir("my_dir")
except OSError as exc:
if exc.args[0] == uerrno.EEXIST:
if exc.errno == uerrno.EEXIST:
print("Directory already exists")
.. data:: errorcode

View File

@ -6,9 +6,11 @@
|see_cpython_module| :mod:`python:heapq`.
This module implements the heap queue algorithm.
This module implements the
`min heap queue algorithm <https://en.wikipedia.org/wiki/Heap_%28data_structure%29>`_.
A heap queue is simply a list that has its elements stored in a certain way.
A heap queue is essentially a list that has its elements stored in such a way
that the first item of the list is always the smallest.
Functions
---------
@ -19,8 +21,10 @@ Functions
.. function:: heappop(heap)
Pop the first item from the ``heap``, and return it. Raises IndexError if
heap is empty.
Pop the first item from the ``heap``, and return it. Raise ``IndexError`` if
``heap`` is empty.
The returned item will be the smallest item in the ``heap``.
.. function:: heapify(x)

View File

@ -18,7 +18,7 @@ Conceptual hierarchy
Conceptual hierarchy of stream base classes is simplified in MicroPython,
as described in this section.
(Abstract) base stream classes, which serve as a foundation for behavior
(Abstract) base stream classes, which serve as a foundation for behaviour
of all the concrete classes, adhere to few dichotomies (pair-wise
classifications) in CPython. In MicroPython, they are somewhat simplified
and made implicit to achieve higher efficiencies and save resources.
@ -41,15 +41,15 @@ more concise and efficient programs - something which is highly desirable
for MicroPython. So, while MicroPython doesn't support buffered streams,
it still provides for no-short-operations streams. Whether there will
be short operations or not depends on each particular class' needs, but
developers are strongly advised to favor no-short-operations behavior
developers are strongly advised to favour no-short-operations behaviour
for the reasons stated above. For example, MicroPython sockets are
guaranteed to avoid short read/writes. Actually, at this time, there is
no example of a short-operations stream class in the core, and one would
be a port-specific class, where such a need is governed by hardware
peculiarities.
The no-short-operations behavior gets tricky in case of non-blocking
streams, blocking vs non-blocking behavior being another CPython dichotomy,
The no-short-operations behaviour gets tricky in case of non-blocking
streams, blocking vs non-blocking behaviour being another CPython dichotomy,
fully supported by MicroPython. Non-blocking streams never wait for
data either to arrive or be written - they read/write whatever possible,
or signal lack of data (or ability to write data). Clearly, this conflicts

View File

@ -87,11 +87,11 @@ Methods
`callee-owned tuple`. This function provides an efficient, allocation-free
way to poll on streams.
If *flags* is 1, one-shot behavior for events is employed: streams for
If *flags* is 1, one-shot behaviour for events is employed: streams for
which events happened will have their event masks automatically reset
(equivalent to ``poll.modify(obj, 0)``), so new events for such a stream
won't be processed until new mask is set with `poll.modify()`. This
behavior is useful for asynchronous I/O schedulers.
behaviour is useful for asynchronous I/O schedulers.
.. admonition:: Difference to CPython
:class: attention

View File

@ -222,7 +222,7 @@ Methods
Unlike `send()`, this method will try to send all of data, by sending data
chunk by chunk consecutively.
The behavior of this method on non-blocking sockets is undefined. Due to this,
The behaviour of this method on non-blocking sockets is undefined. Due to this,
on MicroPython, it's recommended to use `write()` method instead, which
has the same "no short writes" policy for blocking sockets, and will return
number of bytes sent on non-blocking sockets.

View File

@ -14,6 +14,7 @@ Functions
---------
.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None, do_handshake=True)
Takes a `stream` *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
an SSL context. Returned object has the usual `stream` interface methods like

View File

@ -173,7 +173,7 @@ Functions
long sleep), then once you finally look again, it may seem to you that only 1 hour
has passed. To avoid this mistake, just look at the clock regularly. Your application
should do the same. "Too long sleep" metaphor also maps directly to application
behavior: don't let your application run any single task for too long. Run tasks
behaviour: don't let your application run any single task for too long. Run tasks
in steps, and do time-keeping inbetween.
`ticks_diff()` is designed to accommodate various usage patterns, among them:

View File

@ -93,7 +93,7 @@ on the pin for any changes, and the following will occur:
running Python script.
3. The microcontroller starts executing the special interrupt handler
associated with the switch's external trigger. This interrupt handler
get the function that you registered with ``sw.callback()`` and executes
gets the function that you registered with ``sw.callback()`` and executes
it.
4. Your callback function is executed until it finishes, returning control
to the switch interrupt handler.

18
docs/rp2/general.rst Normal file
View File

@ -0,0 +1,18 @@
.. _rp2_general:
General information about the RP2xxx port
=========================================
The rp2 port supports boards powered by the Raspberry Pi Foundation's RP2xxx
family of microcontrollers, most notably the Raspberry Pi Pico that employs
the RP2040.
Technical specifications and SoC datasheets
-------------------------------------------
Datasheets!
Short summary of tech specs!
Description of general structure of the port (it's built on top of the APIs
provided by the Raspberry Pi SDK).

BIN
docs/rp2/img/rpipico.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

288
docs/rp2/quickref.rst Normal file
View File

@ -0,0 +1,288 @@
.. _rp2_quickref:
Quick reference for the RP2
===========================
.. image:: img/rpipico.jpg
:alt: Raspberry Pi Pico
:width: 640px
The Raspberry Pi Pico Development Board (image attribution: Raspberry Pi Foundation).
Below is a quick reference for Raspberry Pi RP2xxx boards. If it is your first time
working with this board it may be useful to get an overview of the microcontroller:
.. toctree::
:maxdepth: 1
general.rst
tutorial/intro.rst
Installing MicroPython
----------------------
See the corresponding section of tutorial: :ref:`rp2_intro`. It also includes
a troubleshooting subsection.
General board control
---------------------
The MicroPython REPL is on the USB serial port.
Tab-completion is useful to find out what methods an object has.
Paste mode (ctrl-E) is useful to paste a large slab of Python code into
the REPL.
The :mod:`machine` module::
import machine
machine.freq() # get the current frequency of the CPU
machine.freq(240000000) # set the CPU frequency to 240 MHz
The :mod:`rp2` module::
import rp2
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
Timers
------
How do they work?
.. _rp2_Pins_and_GPIO:
Pins and GPIO
-------------
Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin
p0 = Pin(0, Pin.OUT) # create output pin on GPIO0
p0.on() # set pin to "on" (high) level
p0.off() # set pin to "off" (low) level
p0.value(1) # set pin to on/high
p2 = Pin(2, Pin.IN) # create input pin on GPIO2
print(p2.value()) # get value, 0 or 1
p4 = Pin(4, Pin.IN, Pin.PULL_UP) # enable internal pull-up resistor
p5 = Pin(5, Pin.OUT, value=1) # set pin high on creation
UART (serial bus)
-----------------
See :ref:`machine.UART <machine.UART>`. ::
from machine import UART
uart1 = UART(1, baudrate=9600, tx=33, rx=32)
uart1.write('hello') # write 5 bytes
uart1.read(5) # read up to 5 bytes
PWM (pulse width modulation)
----------------------------
How does PWM work on the RPi RP2xxx?
Use the ``machine.PWM`` class::
from machine import Pin, PWM
pwm0 = PWM(Pin(0)) # create PWM object from a pin
pwm0.freq() # get current frequency
pwm0.freq(1000) # set frequency
pwm0.duty_u16() # get current duty cycle, range 0-65535
pwm0.duty_u16(200) # set duty cycle, range 0-65535
pwm0.deinit() # turn off PWM on the pin
ADC (analog to digital conversion)
----------------------------------
How does the ADC module work?
Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
adc = ADC(Pin(32)) # create ADC object on ADC pin
adc.read_u16() # read value, 0-65535 across voltage range 0.0v - 3.3v
Software SPI bus
----------------
Software SPI (using bit-banging) works on all pins, and is accessed via the
:ref:`machine.SoftSPI <machine.SoftSPI>` class::
from machine import Pin, SoftSPI
# construct a SoftSPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))
spi.init(baudrate=200000) # set the baudrate
spi.read(10) # read 10 bytes on MISO
spi.read(10, 0xff) # read 10 bytes while outputting 0xff on MOSI
buf = bytearray(50) # create a buffer
spi.readinto(buf) # read into the given buffer (reads 50 bytes in this case)
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI
spi.write(b'12345') # write 5 bytes on MOSI
buf = bytearray(4) # create a buffer
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf
.. Warning::
Currently *all* of ``sck``, ``mosi`` and ``miso`` *must* be specified when
initialising Software SPI.
Hardware SPI bus
----------------
Hardware SPI is accessed via the :ref:`machine.SPI <machine.SPI>` class and
has the same methods as software SPI above::
from machine import Pin, SPI
spi = SPI(1, 10000000)
spi = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(12))
spi = SPI(2, baudrate=80000000, polarity=0, phase=0, bits=8, firstbit=0, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
Software I2C bus
----------------
Software I2C (using bit-banging) works on all output-capable pins, and is
accessed via the :ref:`machine.SoftI2C <machine.SoftI2C>` class::
from machine import Pin, SoftI2C
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000)
i2c.scan() # scan for devices
i2c.readfrom(0x3a, 4) # read 4 bytes from device with address 0x3a
i2c.writeto(0x3a, '12') # write '12' to device with address 0x3a
buf = bytearray(10) # create a buffer with 10 bytes
i2c.writeto(0x3a, buf) # write the given buffer to the slave
Hardware I2C bus
----------------
The driver is accessed via the :ref:`machine.I2C <machine.I2C>` class and
has the same methods as software I2C above::
from machine import Pin, I2C
i2c = I2C(0)
i2c = I2C(1, scl=Pin(5), sda=Pin(4), freq=400000)
Real time clock (RTC)
---------------------
See :ref:`machine.RTC <machine.RTC>` ::
from machine import RTC
rtc = RTC()
rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
rtc.datetime() # get date and time
WDT (Watchdog timer)
--------------------
Is there a watchdog timer?
See :ref:`machine.WDT <machine.WDT>`. ::
from machine import WDT
# enable the WDT with a timeout of 5s (1s is the minimum)
wdt = WDT(timeout=5000)
wdt.feed()
Deep-sleep mode
---------------
Is there deep-sleep support for the rp2?
The following code can be used to sleep, wake and check the reset cause::
import machine
# check if the device woke from a deep sleep
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
print('woke from a deep sleep')
# put the device to sleep for 10 seconds
machine.deepsleep(10000)
OneWire driver
--------------
The OneWire driver is implemented in software and works on all pins::
from machine import Pin
import onewire
ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12
ow.scan() # return a list of devices on the bus
ow.reset() # reset the bus
ow.readbyte() # read a byte
ow.writebyte(0x12) # write a byte on the bus
ow.write('123') # write bytes on the bus
ow.select_rom(b'12345678') # select a specific device by its ROM code
There is a specific driver for DS18S20 and DS18B20 devices::
import time, ds18x20
ds = ds18x20.DS18X20(ow)
roms = ds.scan()
ds.convert_temp()
time.sleep_ms(750)
for rom in roms:
print(ds.read_temp(rom))
Be sure to put a 4.7k pull-up resistor on the data line. Note that
the ``convert_temp()`` method must be called each time you want to
sample the temperature.
NeoPixel and APA106 driver
--------------------------
Use the ``neopixel`` and ``apa106`` modules::
from machine import Pin
from neopixel import NeoPixel
pin = Pin(0, Pin.OUT) # set GPIO0 to output to drive NeoPixels
np = NeoPixel(pin, 8) # create NeoPixel driver on GPIO0 for 8 pixels
np[0] = (255, 255, 255) # set the first pixel to white
np.write() # write data to all pixels
r, g, b = np[0] # get first pixel colour
The APA106 driver extends NeoPixel, but internally uses a different colour order::
from apa106 import APA106
ap = APA106(pin, 8)
r, g, b = ap[0]
APA102 (DotStar) uses a different driver as it has an additional clock pin.

View File

@ -0,0 +1,6 @@
.. _rp2_intro:
Getting started with MicroPython on the RP2xxx
==============================================
Let's get started!

View File

@ -58,6 +58,10 @@
<a class="biglink" href="{{ pathto("esp32/quickref") }}">Quick reference for the ESP32</a><br/>
<span class="linkdescr">pinout for ESP32-based boards, snippets of useful code, and a tutorial</span>
</p>
<p class="biglink">
<a class="biglink" href="{{ pathto("rp2/quickref") }}">Quick reference for the Raspberry Pi RP2xxx</a><br/>
<span class="linkdescr">pinout for rp2xxx-based boards, snippets of useful code, and a tutorial</span>
</p>
<p class="biglink">
<a class="biglink" href="{{ pathto("wipy/quickref") }}">Quick reference for the WiPy/CC3200</a><br/>
<span class="linkdescr">pinout for the WiPy/CC3200, snippets of useful code, and a tutorial</span>

View File

@ -112,7 +112,7 @@ void cyw43_deinit(cyw43_t *self) {
self->itf_state = 0;
// Disable async polling
SDMMC1->MASK &= ~SDMMC_MASK_SDIOITIE;
sdio_enable_irq(false);
cyw43_poll = NULL;
#ifdef pyb_pin_WL_RFSW_VDD
@ -164,7 +164,7 @@ STATIC int cyw43_ensure_up(cyw43_t *self) {
cyw43_sleep = CYW43_SLEEP_MAX;
cyw43_poll = cyw43_poll_func;
#if USE_SDIOIT
SDMMC1->MASK |= SDMMC_MASK_SDIOITIE;
sdio_enable_irq(true);
#else
extern void extint_set(const pin_obj_t *pin, uint32_t mode);
extint_set(pyb_pin_WL_HOST_WAKE, GPIO_MODE_IT_FALLING);
@ -209,7 +209,7 @@ STATIC void cyw43_poll_func(void) {
}
#if USE_SDIOIT
SDMMC1->MASK |= SDMMC_MASK_SDIOITIE;
sdio_enable_irq(true);
#endif
}
@ -227,10 +227,7 @@ int cyw43_cb_read_host_interrupt_pin(void *cb_data) {
void cyw43_cb_ensure_awake(void *cb_data) {
cyw43_sleep = CYW43_SLEEP_MAX;
#if !USE_SDIOIT
if (__HAL_RCC_SDMMC1_IS_CLK_DISABLED()) {
__HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral
sdio_enable_high_speed_4bit();
}
sdio_reenable();
#endif
}

View File

@ -55,7 +55,7 @@ STATIC void cywbt_wait_cts_low(void) {
}
mp_hal_delay_ms(1);
}
mp_hal_pin_config_alt_static(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, STATIC_AF_USART6_CTS);
mp_hal_pin_config_alt(pyb_pin_BT_CTS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_UART, mp_bluetooth_hci_uart_obj.uart_id);
}
STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
@ -149,10 +149,14 @@ STATIC int cywbt_download_firmware(const uint8_t *firmware) {
}
// RF switch must select high path during BT patch boot
#if MICROPY_HW_ENABLE_RF_SWITCH
mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_UP, 0);
#endif
mp_hal_delay_ms(10); // give some time for CTS to go high
cywbt_wait_cts_low();
#if MICROPY_HW_ENABLE_RF_SWITCH
mp_hal_pin_config(pyb_pin_WL_GPIO_1, MP_HAL_PIN_MODE_INPUT, MP_HAL_PIN_PULL_DOWN, 0); // Select chip antenna (could also select external)
#endif
mp_bluetooth_hci_uart_set_baudrate(115200);
cywbt_set_baudrate(3000000);
@ -170,9 +174,11 @@ int mp_bluetooth_hci_controller_init(void) {
mp_hal_pin_output(pyb_pin_BT_DEV_WAKE);
mp_hal_pin_low(pyb_pin_BT_DEV_WAKE);
#if MICROPY_HW_ENABLE_RF_SWITCH
// TODO don't select antenna if wifi is enabled
mp_hal_pin_config(pyb_pin_WL_GPIO_4, MP_HAL_PIN_MODE_OUTPUT, MP_HAL_PIN_PULL_NONE, 0); // RF-switch power
mp_hal_pin_high(pyb_pin_WL_GPIO_4); // Turn the RF-switch on
#endif
uint8_t buf[256];

View File

@ -37,12 +37,12 @@ class SSD1306(framebuf.FrameBuffer):
def init_display(self):
for cmd in (
SET_DISP | 0x00, # off
SET_DISP, # display off
# address setting
SET_MEM_ADDR,
0x00, # horizontal
# resolution and layout
SET_DISP_START_LINE | 0x00,
SET_DISP_START_LINE, # start at line 0
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
SET_MUX_RATIO,
self.height - 1,
@ -66,14 +66,14 @@ class SSD1306(framebuf.FrameBuffer):
# charge pump
SET_CHARGE_PUMP,
0x10 if self.external_vcc else 0x14,
SET_DISP | 0x01,
SET_DISP | 0x01, # display on
): # on
self.write_cmd(cmd)
self.fill(0)
self.show()
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
self.write_cmd(SET_DISP)
def poweron(self):
self.write_cmd(SET_DISP | 0x01)
@ -85,6 +85,10 @@ class SSD1306(framebuf.FrameBuffer):
def invert(self, invert):
self.write_cmd(SET_NORM_INV | (invert & 1))
def rotate(self, rotate):
self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3))
self.write_cmd(SET_SEG_REMAP | (rotate & 1))
def show(self):
x0 = 0
x1 = self.width - 1

View File

@ -176,6 +176,7 @@ class SDCard:
self.spi.readinto(self.tokenbuf, 0xFF)
if self.tokenbuf[0] == _TOKEN_DATA:
break
time.sleep_ms(1)
else:
self.cs(1)
raise OSError("timeout waiting for response")

View File

@ -34,38 +34,10 @@
#if MICROPY_PY_UCTYPES
/// \module uctypes - Access data structures in memory
///
/// The module allows to define layout of raw data structure (using terms
/// of C language), and then access memory buffers using this definition.
/// The module also provides convenience functions to access memory buffers
/// contained in Python objects or wrap memory buffers in Python objects.
/// \constant UINT8_1 - uint8_t value type
/// \class struct - C-like structure
///
/// Encapsulalation of in-memory data structure. This class doesn't define
/// any methods, only attribute access (for structure fields) and
/// indexing (for pointer and array fields).
///
/// Usage:
///
/// # Define layout of a structure with 2 fields
/// # 0 and 4 are byte offsets of fields from the beginning of struct
/// # they are logically ORed with field type
/// FOO_STRUCT = {"a": 0 | uctypes.UINT32, "b": 4 | uctypes.UINT8}
///
/// # Example memory buffer to access (contained in bytes object)
/// buf = b"\x64\0\0\0\0x14"
///
/// # Create structure object referring to address of
/// # the data in the buffer above
/// s = uctypes.struct(FOO_STRUCT, uctypes.addressof(buf))
///
/// # Access fields
/// print(s.a, s.b)
/// # Result:
/// # 100, 20
// The uctypes module allows defining the layout of a raw data structure (using
// terms of the C language), and then access memory buffers using this definition.
// The module also provides convenience functions to access memory buffers
// contained in Python objects or wrap memory buffers in Python objects.
#define LAYOUT_LITTLE_ENDIAN (0)
#define LAYOUT_BIG_ENDIAN (1)
@ -75,6 +47,7 @@
#define BITF_LEN_BITS 5
#define BITF_OFF_BITS 5
#define OFFSET_BITS 17
#define LEN_BITS (OFFSET_BITS + BITF_OFF_BITS)
#if VAL_TYPE_BITS + BITF_LEN_BITS + BITF_OFF_BITS + OFFSET_BITS != 31
#error Invalid encoding field length
#endif
@ -191,7 +164,7 @@ STATIC mp_uint_t uctypes_struct_agg_size(mp_obj_tuple_t *t, int layout_type, mp_
mp_uint_t item_s;
if (t->len == 2) {
// Elements of array are scalar
item_s = GET_SCALAR_SIZE(val_type);
item_s = uctypes_struct_scalar_size(val_type);
if (item_s > *max_field_size) {
*max_field_size = item_s;
}
@ -419,10 +392,8 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(deref);
mp_uint_t val_type = GET_TYPE(offset, VAL_TYPE_BITS);
offset &= VALUE_MASK(VAL_TYPE_BITS);
// printf("scalar type=%d offset=%x\n", val_type, offset);
if (val_type <= INT64 || val_type == FLOAT32 || val_type == FLOAT64) {
// printf("size=%d\n", GET_SCALAR_SIZE(val_type));
if (self->flags == LAYOUT_NATIVE) {
if (set_val == MP_OBJ_NULL) {
return get_aligned(val_type, self->addr + offset, 0);
@ -439,9 +410,9 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
}
}
} else if (val_type >= BFUINT8 && val_type <= BFINT32) {
uint bit_offset = (offset >> 17) & 31;
uint bit_len = (offset >> 22) & 31;
offset &= (1 << 17) - 1;
uint bit_offset = (offset >> OFFSET_BITS) & 31;
uint bit_len = (offset >> LEN_BITS) & 31;
offset &= (1 << OFFSET_BITS) - 1;
mp_uint_t val;
if (self->flags == LAYOUT_NATIVE) {
val = get_aligned_basic(val_type & 6, self->addr + offset);
@ -489,7 +460,6 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
mp_int_t offset = MP_OBJ_SMALL_INT_VALUE(sub->items[0]);
mp_uint_t agg_type = GET_TYPE(offset, AGG_TYPE_BITS);
offset &= VALUE_MASK(AGG_TYPE_BITS);
// printf("agg type=%d offset=%x\n", agg_type, offset);
switch (agg_type) {
case STRUCT: {
@ -514,7 +484,6 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
o->desc = MP_OBJ_FROM_PTR(sub);
o->addr = self->addr + offset;
o->flags = self->flags;
// printf("PTR/ARR base addr=%p\n", o->addr);
return MP_OBJ_FROM_PTR(o);
}
}
@ -572,7 +541,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_ob
return value; // just !MP_OBJ_NULL
}
} else {
byte *p = self->addr + GET_SCALAR_SIZE(val_type) * index;
byte *p = self->addr + uctypes_struct_scalar_size(val_type) * index;
if (value == MP_OBJ_SENTINEL) {
return get_unaligned(val_type, p, self->flags);
} else {
@ -647,9 +616,8 @@ STATIC mp_int_t uctypes_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo,
return 0;
}
/// \function addressof()
/// Return address of object's data (applies to object providing buffer
/// interface).
// addressof()
// Return address of object's data (applies to objects providing the buffer interface).
STATIC mp_obj_t uctypes_struct_addressof(mp_obj_t buf) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ);
@ -657,25 +625,20 @@ STATIC mp_obj_t uctypes_struct_addressof(mp_obj_t buf) {
}
MP_DEFINE_CONST_FUN_OBJ_1(uctypes_struct_addressof_obj, uctypes_struct_addressof);
/// \function bytearray_at()
/// Capture memory at given address of given size as bytearray. Memory is
/// captured by reference (and thus memory pointed by bytearray may change
/// or become invalid at later time). Use bytes_at() to capture by value.
// bytearray_at()
// Capture memory at given address of given size as bytearray.
STATIC mp_obj_t uctypes_struct_bytearray_at(mp_obj_t ptr, mp_obj_t size) {
return mp_obj_new_bytearray_by_ref(mp_obj_int_get_truncated(size), (void *)(uintptr_t)mp_obj_int_get_truncated(ptr));
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytearray_at_obj, uctypes_struct_bytearray_at);
/// \function bytes_at()
/// Capture memory at given address of given size as bytes. Memory is
/// captured by value, i.e. copied. Use bytearray_at() to capture by reference
/// ("zero copy").
// bytes_at()
// Capture memory at given address of given size as bytes.
STATIC mp_obj_t uctypes_struct_bytes_at(mp_obj_t ptr, mp_obj_t size) {
return mp_obj_new_bytes((void *)(uintptr_t)mp_obj_int_get_truncated(ptr), mp_obj_int_get_truncated(size));
}
MP_DEFINE_CONST_FUN_OBJ_2(uctypes_struct_bytes_at_obj, uctypes_struct_bytes_at);
STATIC const mp_obj_type_t uctypes_struct_type = {
{ &mp_type_type },
.name = MP_QSTR_struct,
@ -695,81 +658,63 @@ STATIC const mp_rom_map_elem_t mp_module_uctypes_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_bytes_at), MP_ROM_PTR(&uctypes_struct_bytes_at_obj) },
{ MP_ROM_QSTR(MP_QSTR_bytearray_at), MP_ROM_PTR(&uctypes_struct_bytearray_at_obj) },
/// \moduleref uctypes
/// \constant NATIVE - Native structure layout - native endianness,
/// platform-specific field alignment
{ MP_ROM_QSTR(MP_QSTR_NATIVE), MP_ROM_INT(LAYOUT_NATIVE) },
/// \constant LITTLE_ENDIAN - Little-endian structure layout, tightly packed
/// (no alignment constraints)
{ MP_ROM_QSTR(MP_QSTR_LITTLE_ENDIAN), MP_ROM_INT(LAYOUT_LITTLE_ENDIAN) },
/// \constant BIG_ENDIAN - Big-endian structure layout, tightly packed
/// (no alignment constraints)
{ MP_ROM_QSTR(MP_QSTR_BIG_ENDIAN), MP_ROM_INT(LAYOUT_BIG_ENDIAN) },
/// \constant VOID - void value type, may be used only as pointer target type.
{ MP_ROM_QSTR(MP_QSTR_VOID), MP_ROM_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) },
/// \constant UINT8 - uint8_t value type
{ MP_ROM_QSTR(MP_QSTR_UINT8), MP_ROM_INT(TYPE2SMALLINT(UINT8, 4)) },
/// \constant INT8 - int8_t value type
{ MP_ROM_QSTR(MP_QSTR_INT8), MP_ROM_INT(TYPE2SMALLINT(INT8, 4)) },
/// \constant UINT16 - uint16_t value type
{ MP_ROM_QSTR(MP_QSTR_UINT16), MP_ROM_INT(TYPE2SMALLINT(UINT16, 4)) },
/// \constant INT16 - int16_t value type
{ MP_ROM_QSTR(MP_QSTR_INT16), MP_ROM_INT(TYPE2SMALLINT(INT16, 4)) },
/// \constant UINT32 - uint32_t value type
{ MP_ROM_QSTR(MP_QSTR_UINT32), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
/// \constant INT32 - int32_t value type
{ MP_ROM_QSTR(MP_QSTR_INT32), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
/// \constant UINT64 - uint64_t value type
{ MP_ROM_QSTR(MP_QSTR_UINT64), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
/// \constant INT64 - int64_t value type
{ MP_ROM_QSTR(MP_QSTR_INT64), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_UINT8), MP_ROM_INT(TYPE2SMALLINT(UINT8, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_INT8), MP_ROM_INT(TYPE2SMALLINT(INT8, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_UINT16), MP_ROM_INT(TYPE2SMALLINT(UINT16, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_INT16), MP_ROM_INT(TYPE2SMALLINT(INT16, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_UINT32), MP_ROM_INT(TYPE2SMALLINT(UINT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_INT32), MP_ROM_INT(TYPE2SMALLINT(INT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_UINT64), MP_ROM_INT(TYPE2SMALLINT(UINT64, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_INT64), MP_ROM_INT(TYPE2SMALLINT(INT64, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BFUINT8), MP_ROM_INT(TYPE2SMALLINT(BFUINT8, 4)) },
{ MP_ROM_QSTR(MP_QSTR_BFINT8), MP_ROM_INT(TYPE2SMALLINT(BFINT8, 4)) },
{ MP_ROM_QSTR(MP_QSTR_BFUINT16), MP_ROM_INT(TYPE2SMALLINT(BFUINT16, 4)) },
{ MP_ROM_QSTR(MP_QSTR_BFINT16), MP_ROM_INT(TYPE2SMALLINT(BFINT16, 4)) },
{ MP_ROM_QSTR(MP_QSTR_BFUINT32), MP_ROM_INT(TYPE2SMALLINT(BFUINT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_BFINT32), MP_ROM_INT(TYPE2SMALLINT(BFINT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_BFUINT8), MP_ROM_INT(TYPE2SMALLINT(BFUINT8, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BFINT8), MP_ROM_INT(TYPE2SMALLINT(BFINT8, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BFUINT16), MP_ROM_INT(TYPE2SMALLINT(BFUINT16, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BFINT16), MP_ROM_INT(TYPE2SMALLINT(BFINT16, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BFUINT32), MP_ROM_INT(TYPE2SMALLINT(BFUINT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BFINT32), MP_ROM_INT(TYPE2SMALLINT(BFINT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_BF_POS), MP_ROM_INT(17) },
{ MP_ROM_QSTR(MP_QSTR_BF_LEN), MP_ROM_INT(22) },
{ MP_ROM_QSTR(MP_QSTR_BF_POS), MP_ROM_INT(OFFSET_BITS) },
{ MP_ROM_QSTR(MP_QSTR_BF_LEN), MP_ROM_INT(LEN_BITS) },
#if MICROPY_PY_BUILTINS_FLOAT
{ MP_ROM_QSTR(MP_QSTR_FLOAT32), MP_ROM_INT(TYPE2SMALLINT(FLOAT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_FLOAT64), MP_ROM_INT(TYPE2SMALLINT(FLOAT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_FLOAT32), MP_ROM_INT(TYPE2SMALLINT(FLOAT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_FLOAT64), MP_ROM_INT(TYPE2SMALLINT(FLOAT64, VAL_TYPE_BITS)) },
#endif
#if MICROPY_PY_UCTYPES_NATIVE_C_TYPES
// C native type aliases. These depend on GCC-compatible predefined
// preprocessor macros.
#if __SIZEOF_SHORT__ == 2
{ MP_ROM_QSTR(MP_QSTR_SHORT), MP_ROM_INT(TYPE2SMALLINT(INT16, 4)) },
{ MP_ROM_QSTR(MP_QSTR_USHORT), MP_ROM_INT(TYPE2SMALLINT(UINT16, 4)) },
{ MP_ROM_QSTR(MP_QSTR_SHORT), MP_ROM_INT(TYPE2SMALLINT(INT16, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_USHORT), MP_ROM_INT(TYPE2SMALLINT(UINT16, VAL_TYPE_BITS)) },
#endif
#if __SIZEOF_INT__ == 4
{ MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_UINT), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_INT), MP_ROM_INT(TYPE2SMALLINT(INT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_UINT), MP_ROM_INT(TYPE2SMALLINT(UINT32, VAL_TYPE_BITS)) },
#endif
#if __SIZEOF_LONG__ == 4
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT32, 4)) },
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT32, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT32, VAL_TYPE_BITS)) },
#elif __SIZEOF_LONG__ == 8
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_LONG), MP_ROM_INT(TYPE2SMALLINT(INT64, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_ULONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, VAL_TYPE_BITS)) },
#endif
#if __SIZEOF_LONG_LONG__ == 8
{ MP_ROM_QSTR(MP_QSTR_LONGLONG), MP_ROM_INT(TYPE2SMALLINT(INT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_ULONGLONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, 4)) },
{ MP_ROM_QSTR(MP_QSTR_LONGLONG), MP_ROM_INT(TYPE2SMALLINT(INT64, VAL_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_ULONGLONG), MP_ROM_INT(TYPE2SMALLINT(UINT64, VAL_TYPE_BITS)) },
#endif
#endif // MICROPY_PY_UCTYPES_NATIVE_C_TYPES
{ MP_ROM_QSTR(MP_QSTR_PTR), MP_ROM_INT(TYPE2SMALLINT(PTR, AGG_TYPE_BITS)) },
{ MP_ROM_QSTR(MP_QSTR_ARRAY), MP_ROM_INT(TYPE2SMALLINT(ARRAY, AGG_TYPE_BITS)) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_uctypes_globals, mp_module_uctypes_globals_table);
const mp_obj_module_t mp_module_uctypes = {

View File

@ -60,9 +60,16 @@
typedef struct _mp_obj_hash_t {
mp_obj_base_t base;
char state[0];
bool final; // if set, update and digest raise an exception
uintptr_t state[0]; // must be aligned to a machine word
} mp_obj_hash_t;
static void uhashlib_ensure_not_final(mp_obj_hash_t *self) {
if (self->final) {
mp_raise_ValueError(MP_ERROR_TEXT("hash is final"));
}
}
#if MICROPY_PY_UHASHLIB_SHA256
STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
@ -78,6 +85,7 @@ STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_arg
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context));
o->base.type = type;
o->final = false;
mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
if (n_args == 1) {
@ -88,6 +96,7 @@ STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_arg
STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_sha256_update_ret((mbedtls_sha256_context *)&self->state, bufinfo.buf, bufinfo.len);
@ -96,6 +105,8 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
self->final = true;
vstr_t vstr;
vstr_init_len(&vstr, 32);
mbedtls_sha256_finish_ret((mbedtls_sha256_context *)&self->state, (unsigned char *)vstr.buf);
@ -110,6 +121,7 @@ STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_arg
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX));
o->base.type = type;
o->final = false;
sha256_init((CRYAL_SHA256_CTX *)o->state);
if (n_args == 1) {
uhashlib_sha256_update(MP_OBJ_FROM_PTR(o), args[0]);
@ -119,6 +131,7 @@ STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_arg
STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
sha256_update((CRYAL_SHA256_CTX *)self->state, bufinfo.buf, bufinfo.len);
@ -127,6 +140,8 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t uhashlib_sha256_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
self->final = true;
vstr_t vstr;
vstr_init_len(&vstr, SHA256_BLOCK_SIZE);
sha256_final((CRYAL_SHA256_CTX *)self->state, (byte *)vstr.buf);
@ -160,6 +175,7 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(SHA1_CTX));
o->base.type = type;
o->final = false;
SHA1_Init((SHA1_CTX *)o->state);
if (n_args == 1) {
uhashlib_sha1_update(MP_OBJ_FROM_PTR(o), args[0]);
@ -169,6 +185,7 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
SHA1_Update((SHA1_CTX *)self->state, bufinfo.buf, bufinfo.len);
@ -177,6 +194,8 @@ STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
self->final = true;
vstr_t vstr;
vstr_init_len(&vstr, SHA1_SIZE);
SHA1_Final((byte *)vstr.buf, (SHA1_CTX *)self->state);
@ -196,6 +215,7 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context));
o->base.type = type;
o->final = false;
mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
if (n_args == 1) {
@ -206,6 +226,7 @@ STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args,
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_sha1_update_ret((mbedtls_sha1_context *)self->state, bufinfo.buf, bufinfo.len);
@ -214,6 +235,8 @@ STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
self->final = true;
vstr_t vstr;
vstr_init_len(&vstr, 20);
mbedtls_sha1_finish_ret((mbedtls_sha1_context *)self->state, (byte *)vstr.buf);
@ -247,6 +270,7 @@ STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(MD5_CTX));
o->base.type = type;
o->final = false;
MD5_Init((MD5_CTX *)o->state);
if (n_args == 1) {
uhashlib_md5_update(MP_OBJ_FROM_PTR(o), args[0]);
@ -256,6 +280,7 @@ STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args,
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
MD5_Update((MD5_CTX *)self->state, bufinfo.buf, bufinfo.len);
@ -264,6 +289,8 @@ STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
self->final = true;
vstr_t vstr;
vstr_init_len(&vstr, MD5_SIZE);
MD5_Final((byte *)vstr.buf, (MD5_CTX *)self->state);
@ -283,6 +310,7 @@ STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args,
mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_hash_t *o = m_new_obj_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context));
o->base.type = type;
o->final = false;
mbedtls_md5_init((mbedtls_md5_context *)o->state);
mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
if (n_args == 1) {
@ -293,6 +321,7 @@ STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args,
STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(arg, &bufinfo, MP_BUFFER_READ);
mbedtls_md5_update_ret((mbedtls_md5_context *)self->state, bufinfo.buf, bufinfo.len);
@ -301,6 +330,8 @@ STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg) {
STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self);
self->final = true;
vstr_t vstr;
vstr_init_len(&vstr, 16);
mbedtls_md5_finish_ret((mbedtls_md5_context *)self->state, (byte *)vstr.buf);

View File

@ -87,8 +87,11 @@ STATIC uint32_t yasmarang_randbelow(uint32_t n) {
STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) {
int n = mp_obj_get_int(num_in);
if (n > 32 || n == 0) {
mp_raise_ValueError(NULL);
if (n > 32 || n < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("bits must be 32 or less"));
}
if (n == 0) {
return MP_OBJ_NEW_SMALL_INT(0);
}
uint32_t mask = ~0;
// Beware of C undefined behavior when shifting by >= than bit size

View File

@ -40,10 +40,6 @@
// Flags for poll()
#define FLAG_ONESHOT (1)
/// \module select - Provides select function to wait for events on a stream
///
/// This module provides the select function.
typedef struct _poll_obj_t {
mp_obj_t obj;
mp_uint_t (*ioctl)(mp_obj_t obj, mp_uint_t request, uintptr_t arg, int *errcode);
@ -111,7 +107,7 @@ STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, size_t *rwx_num) {
return n_ready;
}
/// \function select(rlist, wlist, xlist[, timeout])
// select(rlist, wlist, xlist[, timeout])
STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
// get array data from tuple/list arguments
size_t rwx_len[3];
@ -178,8 +174,6 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
/// \class Poll - poll class
typedef struct _mp_obj_poll_t {
mp_obj_base_t base;
mp_map_t poll_map;
@ -190,7 +184,7 @@ typedef struct _mp_obj_poll_t {
mp_obj_t ret_tuple;
} mp_obj_poll_t;
/// \method register(obj[, eventmask])
// register(obj[, eventmask])
STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
mp_uint_t flags;
@ -204,7 +198,7 @@ STATIC mp_obj_t poll_register(size_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_register_obj, 2, 3, poll_register);
/// \method unregister(obj)
// unregister(obj)
STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP_REMOVE_IF_FOUND);
@ -213,7 +207,7 @@ STATIC mp_obj_t poll_unregister(mp_obj_t self_in, mp_obj_t obj_in) {
}
MP_DEFINE_CONST_FUN_OBJ_2(poll_unregister_obj, poll_unregister);
/// \method modify(obj, eventmask)
// modify(obj, eventmask)
STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmask_in) {
mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
mp_map_elem_t *elem = mp_map_lookup(&self->poll_map, mp_obj_id(obj_in), MP_MAP_LOOKUP);
@ -348,7 +342,7 @@ STATIC const mp_obj_type_t mp_type_poll = {
.locals_dict = (void *)&poll_locals_dict,
};
/// \function poll()
// poll()
STATIC mp_obj_t select_poll(void) {
mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t);
poll->base.type = &mp_type_poll;

View File

@ -82,7 +82,7 @@ async def open_connection(host, port):
try:
s.connect(ai[-1])
except OSError as er:
if er.args[0] != EINPROGRESS:
if er.errno != EINPROGRESS:
raise er
yield core._io_queue.queue_write(s)
return ss, ss
@ -112,7 +112,6 @@ class Server:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(ai[-1])
s.listen(backlog)
self.task = core.cur_task
# Accept incoming connections
while True:
try:
@ -135,7 +134,7 @@ class Server:
# TODO could use an accept-callback on socket read activity instead of creating a task
async def start_server(cb, host, port, backlog=5):
s = Server()
core.create_task(s._serve(cb, host, port, backlog))
s.task = core.create_task(s._serve(cb, host, port, backlog))
return s

View File

@ -133,7 +133,7 @@ int mp_uos_dupterm_rx_chr(void) {
nlr_pop();
if (buf[0] == mp_interrupt_char) {
// Signal keyboard interrupt to be raised as soon as the VM resumes
mp_keyboard_interrupt();
mp_sched_keyboard_interrupt();
return -2;
}
return buf[0];

View File

@ -256,7 +256,7 @@ STATIC mp_obj_t fat_vfs_mkdir(mp_obj_t vfs_in, mp_obj_t path_o) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_mkdir_obj, fat_vfs_mkdir);
/// Change current directory.
// Change current directory.
STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
const char *path;
@ -272,7 +272,7 @@ STATIC mp_obj_t fat_vfs_chdir(mp_obj_t vfs_in, mp_obj_t path_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_chdir_obj, fat_vfs_chdir);
/// Get the current directory.
// Get the current directory.
STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
char buf[MICROPY_ALLOC_PATH_MAX + 1];
@ -284,8 +284,7 @@ STATIC mp_obj_t fat_vfs_getcwd(mp_obj_t vfs_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_getcwd_obj, fat_vfs_getcwd);
/// \function stat(path)
/// Get the status of a file or directory.
// Get the status of a file or directory.
STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
const char *path = mp_obj_str_get_str(path_in);

View File

@ -588,8 +588,8 @@ friendly_repl_reset:
// If the GC is locked at this point there is no way out except a reset,
// so force the GC to be unlocked to help the user debug what went wrong.
if (MP_STATE_MEM(gc_lock_depth) != 0) {
MP_STATE_MEM(gc_lock_depth) = 0;
if (MP_STATE_THREAD(gc_lock_depth) != 0) {
MP_STATE_THREAD(gc_lock_depth) = 0;
}
vstr_reset(&line);

View File

@ -41,7 +41,6 @@ extern pyexec_mode_kind_t pyexec_mode_kind;
extern int pyexec_system_exit;
#define PYEXEC_FORCED_EXIT (0x100)
#define PYEXEC_SWITCH_MODE (0x200)
int pyexec_raw_repl(void);
int pyexec_friendly_repl(void);

132
lib/utils/semihosting.c Normal file
View File

@ -0,0 +1,132 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Ayke van Laethem
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "semihosting.h"
// Resources:
// http://embed.rs/articles/2016/semi-hosting-rust/
// https://wiki.dlang.org/Minimal_semihosted_ARM_Cortex-M_%22Hello_World%22
// https://github.com/arduino/OpenOCD/blob/master/src/target/arm_semihosting.c
#define SYS_OPEN 0x01
#define SYS_WRITEC 0x03
#define SYS_WRITE 0x05
#define SYS_READC 0x07
// Constants:
#define OPEN_MODE_READ (0) // mode "r"
#define OPEN_MODE_WRITE (4) // mode "w"
#ifndef __thumb__
#error Semihosting is only implemented for ARM microcontrollers.
#endif
static int mp_semihosting_stdout;
static uint32_t mp_semihosting_call(uint32_t num, const void *arg) {
// A semihosting call works as follows, similar to a SVCall:
// * the call is invoked by a special breakpoint: 0xAB
// * the command is placed in r0
// * a pointer to the arguments is placed in r1
// * the return value is placed in r0
// Note that because it uses the breakpoint instruction, applications
// will hang if they're not connected to a debugger. And they'll be
// stuck in a breakpoint if semihosting is not specifically enabled in
// the debugger.
// Also note that semihosting is extremely slow (sometimes >100ms per
// call).
register uint32_t num_reg __asm__ ("r0") = num;
register const void *args_reg __asm__ ("r1") = arg;
__asm__ __volatile__ (
"bkpt 0xAB\n" // invoke semihosting call
: "+r" (num_reg) // call number and result
: "r" (args_reg) // arguments
: "memory"); // make sure args aren't optimized away
return num_reg; // r0, which became the result
}
static int mp_semihosting_open_console(uint32_t mode) {
struct {
char *name;
uint32_t mode;
uint32_t name_len;
} args = {
.name = ":tt", // magic path to console
.mode = mode, // e.g. "r", "w" (see OPEN_MODE_* constants)
.name_len = 3, // strlen(":tt")
};
return mp_semihosting_call(SYS_OPEN, &args);
}
void mp_semihosting_init() {
mp_semihosting_stdout = mp_semihosting_open_console(OPEN_MODE_WRITE);
}
int mp_semihosting_rx_char() {
return mp_semihosting_call(SYS_READC, NULL);
}
static void mp_semihosting_tx_char(char c) {
mp_semihosting_call(SYS_WRITEC, &c);
}
uint32_t mp_semihosting_tx_strn(const char *str, size_t len) {
if (len == 0) {
return 0; // nothing to do
}
if (len == 1) {
mp_semihosting_tx_char(*str); // maybe faster?
return 0;
}
struct {
uint32_t fd;
const char *str;
uint32_t len;
} args = {
.fd = mp_semihosting_stdout,
.str = str,
.len = len,
};
return mp_semihosting_call(SYS_WRITE, &args);
}
uint32_t mp_semihosting_tx_strn_cooked(const char *str, size_t len) {
// Write chunks of data until (excluding) the first '\n' character,
// insert a '\r' character, and then continue with the next chunk
// (starting with '\n').
// Doing byte-by-byte writes would be easier to implement but is far
// too slow.
size_t start = 0;
for (size_t i = 0; i < len; i++) {
if (str[i] == '\n') {
mp_semihosting_tx_strn(str + start, i - start);
mp_semihosting_tx_char('\r');
start = i;
}
}
return mp_semihosting_tx_strn(str + start, len - start);
}

View File

@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
* Copyright (c) 2020 Philipp Ebensberger
* Copyright (c) 2018 Ayke van Laethem
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -23,11 +23,29 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef MICROPY_INCLUDED_LIB_UTILS_SEMIHOSTING_H
#define MICROPY_INCLUDED_LIB_UTILS_SEMIHOSTING_H
#include "pin.h"
/*
static pin_af_obj_t GPIO_11_af[] = {
PIN_AF(GPIOMUX_IO11, PIN_AF_MODE_ALT5, GPIO1, 0x10B0U),
};
To use semi-hosting for a replacement UART:
- Add lib/semihosting/semihosting.c to the Makefile sources.
- Call mp_semihosting_init() in main(), around the time UART is initialized.
- Replace mp_hal_stdin_rx_chr and similar in mphalport.c with the semihosting equivalent.
- Include lib/semihosting/semihosting.h in the relevant files.
pin_obj_t GPIO_11 = PIN(GPIO_11, GPIO1, 5, GPIO_11_af);
Then make sure the debugger is attached and enables semihosting. In OpenOCD this is
done with ARM semihosting enable followed by reset. The terminal will need further
configuration to work with MicroPython (bash: stty raw -echo).
*/
#include <stddef.h>
#include <stdint.h>
void mp_semihosting_init();
int mp_semihosting_rx_char();
uint32_t mp_semihosting_tx_strn(const char *str, size_t len);
uint32_t mp_semihosting_tx_strn_cooked(const char *str, size_t len);
#endif // MICROPY_INCLUDED_LIB_UTILS_SEMIHOSTING_H

View File

@ -5,7 +5,7 @@ include ../../py/mkenv.mk
include $(TOP)/py/py.mk
# Set makefile-level MicroPython feature configurations.
MICROPY_ROM_TEXT_COMPRESSION ?= 1
MICROPY_ROM_TEXT_COMPRESSION ?= 0
# Define toolchain and other tools.
CROSS_COMPILE ?= arm-none-eabi-

View File

@ -18,4 +18,4 @@ compiled and executed when the firmware starts. They produce output on the
system's stdout.
The size of the firmware (the machine code that is programmed to the
microcontroller's flash/ROM) is currently around 61200 bytes.
microcontroller's flash/ROM) is currently around 57900 bytes.

View File

@ -37,7 +37,7 @@
// Python internal features
#define MICROPY_ENABLE_EXTERNAL_IMPORT (0)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NONE)
#define MICROPY_CPYTHON_COMPAT (0)
#define MICROPY_MODULE_GETATTR (0)
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)

View File

@ -250,7 +250,7 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
int data = MAP_UARTCharGetNonBlocking(self->reg);
if (MP_STATE_PORT(os_term_dup_obj) && MP_STATE_PORT(os_term_dup_obj)->stream_o == self && data == mp_interrupt_char) {
// raise an exception when interrupts are finished
mp_keyboard_interrupt();
mp_sched_keyboard_interrupt();
} else { // there's always a read buffer available
uint16_t next_head = (self->read_buf_head + 1) % PYBUART_RX_BUFFER_LEN;
if (next_head != self->read_buf_tail) {

View File

@ -446,7 +446,7 @@ static void telnet_parse_input (uint8_t *str, int16_t *len) {
if (*_str <= 127) {
if (telnet_data.state == E_TELNET_STE_LOGGED_IN && *_str == mp_interrupt_char) {
// raise a keyboard exception
mp_keyboard_interrupt();
mp_sched_keyboard_interrupt();
(*len)--;
_str++;
}

View File

@ -1,6 +1,6 @@
# Top-level cmake file for building MicroPython on ESP32.
cmake_minimum_required(VERSION 3.18)
cmake_minimum_required(VERSION 3.12)
# Set the location of this port's directory.
set(MICROPY_PORT_DIR ${CMAKE_SOURCE_DIR})

View File

@ -26,6 +26,10 @@ endif
IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD) $(CMAKE_ARGS)
ifdef FROZEN_MANIFEST
IDFPY_FLAGS += -D MICROPY_FROZEN_MANIFEST=$(FROZEN_MANIFEST)
endif
all:
idf.py $(IDFPY_FLAGS) build
@$(PYTHON) makeimg.py \
@ -34,7 +38,7 @@ all:
$(BUILD)/micropython.bin \
$(BUILD)/firmware.bin
$(BUILD)/bootloader/bootloader.bin $(BUILD)/partition_table/partition -table.bin $(BUILD)/micropython.bin: FORCE
$(BUILD)/bootloader/bootloader.bin $(BUILD)/partition_table/partition-table.bin $(BUILD)/micropython.bin: FORCE
clean:
idf.py $(IDFPY_FLAGS) fullclean

View File

@ -2,5 +2,6 @@ set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.ble
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
endif()

View File

@ -4,4 +4,6 @@ set(SDKCONFIG_DEFAULTS
boards/GENERIC_D2WD/sdkconfig.board
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
endif()

View File

@ -4,4 +4,6 @@ set(SDKCONFIG_DEFAULTS
boards/GENERIC_OTA/sdkconfig.board
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
endif()

View File

@ -5,4 +5,6 @@ set(SDKCONFIG_DEFAULTS
boards/sdkconfig.usb
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
endif()

View File

@ -5,4 +5,6 @@ set(SDKCONFIG_DEFAULTS
boards/sdkconfig.240mhz
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
endif()

View File

@ -0,0 +1,75 @@
# M5Stack ATOM MicroPython Helper Library
# MIT license; Copyright (c) 2021 IAMLIUBO work for M5STACK
#
# Hardware details:
# ATOM Lite https://docs.m5stack.com/en/core/atom_lite
# ATOM Matrix https://docs.m5stack.com/en/core/atom_matrix
from micropython import const
from machine import Pin
import neopixel
# M5STACK ATOM Hardware Pin Assignments
"""
FRONT
|3V3|
|G21| IR G12 |G22|
|G25| BTN G39 |G19|
| 5V| WS2812 G27 |G23|
|GNG| MPU G21 G25 |G33|
G32 G26 5V GND
Grove Port
"""
# WS2812
WS2812_PIN = const(27)
# Button
BUTTON_PIN = const(39)
# IR
IR_PIN = const(12)
# I2C
I2C0_SCL_PIN = const(21)
I2C0_SDA_PIN = const(25)
# Grove port
GROVE_PORT_PIN = (const(26), const(32))
class ATOM:
def __init__(self, np_n):
self._np = neopixel.NeoPixel(pin=Pin(WS2812_PIN), n=np_n)
self._btn = Pin(BUTTON_PIN, Pin.IN, Pin.PULL_UP)
def get_button_status(self):
return self._btn.value()
def set_button_callback(self, cb):
self._btn.irq(trigger=Pin.IRQ_FALLING, handler=cb)
def set_pixel_color(self, num, r, g, b):
if num <= self._np.n:
self._np[num] = [r, g, b]
self._np.write()
def get_pixel_color(self, num):
if num <= self._np.n:
return self._np[num]
def set_pixels_color(self, r, g, b):
self._np.fill([r, g, b])
self._np.write()
class Lite(ATOM):
# WS2812 number: 1
def __init__(self):
super(Lite, self).__init__(np_n=1)
class Matrix(ATOM):
# WS2812 number: 25
def __init__(self):
super(Matrix, self).__init__(np_n=25)

View File

@ -0,0 +1,10 @@
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.ble
boards/sdkconfig.240mhz
boards/M5STACK_ATOM/sdkconfig.board
)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
endif()

View File

@ -0,0 +1,2 @@
#define MICROPY_HW_BOARD_NAME "M5Stack ATOM"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"

View File

@ -0,0 +1,5 @@
CONFIG_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_ESP32_REV_MIN_1=y
CONFIG_LWIP_LOCAL_HOSTNAME="M5StackATOM"

View File

@ -1,9 +0,0 @@
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.ble
boards/sdkconfig.240mhz
boards/sdkconfig.spiram
boards/TINYPICO/sdkconfig.board
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

View File

@ -1,2 +0,0 @@
#define MICROPY_HW_BOARD_NAME "TinyPICO"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"

View File

@ -0,0 +1,3 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("$(PORT_DIR)/boards/UM_TINYPICO/modules", "dotstar.py")
freeze("modules")

View File

@ -0,0 +1,101 @@
# FeatherS2 MicroPython Helper Library
# 2021 Seon Rozenblum - Unexpected Maker
#
# Project home:
# https://feathers2.io
#
# 2021-Mar-21 - v0.1 - Initial implementation
# Import required libraries
from micropython import const
from machine import Pin, SPI, ADC
import machine, time
# FeatherS2 Hardware Pin Assignments
# LDO
LDO2 = const(21)
# APA102 Dotstar pins
DOTSTAR_CLK = const(45)
DOTSTAR_DATA = const(40)
# SPI
SPI_MOSI = const(35)
SPI_MISO = const(37)
SPI_CLK = const(36)
# I2C
I2C_SDA = const(8)
I2C_SCL = const(9)
# DAC
DAC1 = const(17)
DAC2 = const(18)
# LED & Ambient Light Sensor
LED = const(13)
AMB_LIGHT = const(4)
# Helper functions
# LED & Ambient Light Sensor control
def set_led(state):
l = Pin(LED, Pin.OUT)
l.value(state)
def toggle_led(state):
l = Pin(LED, Pin.OUT)
l.value(not l.value())
# Create ADC and set attenuation and return the ambient light value from the onboard sensor
def get_amb_light():
adc = ADC(Pin(AMB_LIGHT))
adc.atten(ADC.ATTN_11DB)
return adc.read()
# LDO2 power control
# When we manually turn off the second LDO we also set the DotStar DATA and CLK pins to input to
# prevent parasitic power from lighting the LED even with the LDO off, causing current use.
# The DotStar is a beautiful LED, but parasitic power makes it a terrible choice for battery use :(
def set_ldo2_power(state):
"""Set the power for the on-board Dotstar to allow no current draw when not needed."""
# Set the power pin to the inverse of state
ldo2 = Pin(LDO2, Pin.OUT)
ldo2.value(state)
if state:
Pin(DOTSTAR_CLK, Pin.OUT)
Pin(DOTSTAR_DATA, Pin.OUT) # If power is on, set CLK to be output, otherwise input
else:
Pin(DOTSTAR_CLK, Pin.IN)
Pin(DOTSTAR_DATA, Pin.IN) # If power is on, set CLK to be output, otherwise input
# A small delay to let the IO change state
time.sleep(0.035)
# Dotstar rainbow colour wheel
def dotstar_color_wheel(wheel_pos):
"""Color wheel to allow for cycling through the rainbow of RGB colors."""
wheel_pos = wheel_pos % 255
if wheel_pos < 85:
return 255 - wheel_pos * 3, 0, wheel_pos * 3
elif wheel_pos < 170:
wheel_pos -= 85
return 0, wheel_pos * 3, 255 - wheel_pos * 3
else:
wheel_pos -= 170
return wheel_pos * 3, 255 - wheel_pos * 3, 0
# Go into deep sleep but shut down the APA first to save power
# Use this if you want lowest deep sleep current
def go_deepsleep(t):
"""Deep sleep helper that also powers down the on-board Dotstar."""
set_ldo2_power(False)
machine.deepsleep(t)

View File

@ -0,0 +1,9 @@
set(IDF_TARGET esp32s2)
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.spiram_sx
boards/sdkconfig.usb
boards/UM_FEATHERS2/sdkconfig.board
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)

View File

@ -0,0 +1,12 @@
#define MICROPY_HW_BOARD_NAME "FeatherS2"
#define MICROPY_HW_MCU_NAME "ESP32-S2"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
#define MICROPY_HW_I2C0_SCL (9)
#define MICROPY_HW_I2C0_SDA (8)
#define MICROPY_HW_SPI1_MOSI (35) // SDO
#define MICROPY_HW_SPI1_MISO (37) // SDI
#define MICROPY_HW_SPI1_SCK (36)

View File

@ -0,0 +1,16 @@
CONFIG_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_AFTER_NORESET=y
CONFIG_SPIRAM_MEMTEST=
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions-16MiB.csv"
#CONFIG_USB_AND_UART=y
# LWIP
CONFIG_LWIP_LOCAL_HOSTNAME="UMFeatherS2"
# end of LWIP

View File

@ -0,0 +1,2 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("modules")

View File

@ -80,7 +80,7 @@ def get_battery_charging():
# need to be able to cut power to it to minimise power consumption during deep sleep or with general battery powered use
# to minimise unneeded battery drain
def set_dotstar_power(state):
"""Set the power for the on-board Dostar to allow no current draw when not needed."""
"""Set the power for the on-board Dotstar to allow no current draw when not needed."""
# Set the power pin to the inverse of state
if state:
Pin(DOTSTAR_PWR, Pin.OUT, None) # Break the PULL_HOLD on the pin

View File

@ -0,0 +1,11 @@
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.ble
boards/sdkconfig.240mhz
boards/sdkconfig.spiram
boards/UM_TINYPICO/sdkconfig.board
)
if(NOT MICROPY_FROZEN_MANIFEST)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_BOARD_DIR}/manifest.py)
endif()

View File

@ -0,0 +1,9 @@
#define MICROPY_HW_BOARD_NAME "TinyPICO"
#define MICROPY_HW_MCU_NAME "ESP32-PICO-D4"
#define MICROPY_HW_I2C0_SCL (22)
#define MICROPY_HW_I2C0_SDA (21)
#define MICROPY_HW_SPI1_SCK (18)
#define MICROPY_HW_SPI1_MOSI (23)
#define MICROPY_HW_SPI1_MISO (19)

View File

@ -2,3 +2,4 @@ CONFIG_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_ESP32_REV_MIN_1=y
CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyPICO"

View File

@ -0,0 +1,2 @@
include("$(PORT_DIR)/boards/manifest.py")
freeze("modules")

View File

@ -0,0 +1,82 @@
# TinyS2 MicroPython Helper Library
# 2021 Seon Rozenblum - Unexpected Maker
#
# Project home:
# https://tinys2.io
#
# 2021-Apr-10 - v0.1 - Initial implementation
# Import required libraries
from micropython import const
from machine import Pin, SPI, ADC
import machine, time
# TinyS2 Hardware Pin Assignments
# Sense Pins
VBUS_SENSE = const(21)
VBAT_SENSE = const(3)
# RGB LED Pins
RGB_DATA = const(1)
RGB_PWR = const(2)
# SPI
SPI_MOSI = const(35)
SPI_MISO = const(36)
SPI_CLK = const(37)
# I2C
I2C_SDA = const(8)
I2C_SCL = const(9)
# DAC
DAC1 = const(17)
DAC2 = const(18)
# Helper functions
def set_pixel_power(state):
"""Enable or Disable power to the onboard NeoPixel to either show colour, or to reduce power for deep sleep."""
Pin(RGB_PWR, Pin.OUT).value(state)
def get_battery_voltage():
"""
Returns the current battery voltage. If no battery is connected, returns 4.2V which is the charge voltage
This is an approximation only, but useful to detect if the charge state of the battery is getting low.
"""
adc = ADC(Pin(VBAT_SENSE)) # Assign the ADC pin to read
measuredvbat = adc.read() # Read the value
measuredvbat /= 8192 # divide by 8192 as we are using the default ADC voltage range of 0-1V
measuredvbat *= 4.2 # Multiply by 4.2V, our reference voltage
return round(measuredvbat, 2)
def get_vbus_present():
"""Detect if VBUS (5V) power source is present"""
return Pin(VBUS_SENSE, Pin.IN).value() == 1
# NeoPixel rainbow colour wheel
def rgb_color_wheel(wheel_pos):
"""Color wheel to allow for cycling through the rainbow of RGB colors."""
wheel_pos = wheel_pos % 255
if wheel_pos < 85:
return 255 - wheel_pos * 3, 0, wheel_pos * 3
elif wheel_pos < 170:
wheel_pos -= 85
return 0, wheel_pos * 3, 255 - wheel_pos * 3
else:
wheel_pos -= 170
return wheel_pos * 3, 255 - wheel_pos * 3, 0
# Go into deep sleep but shut down the RGB LED first to save power
# Use this if you want lowest deep sleep current
def go_deepsleep(t):
"""Deep sleep helper that also powers down the on-board NeoPixel."""
set_pixel_power(False)
machine.deepsleep(t)

View File

@ -0,0 +1,8 @@
set(IDF_TARGET esp32s2)
set(SDKCONFIG_DEFAULTS
boards/sdkconfig.base
boards/sdkconfig.spiram_sx
boards/sdkconfig.usb
)
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)

View File

@ -0,0 +1,12 @@
#define MICROPY_HW_BOARD_NAME "TinyS2"
#define MICROPY_HW_MCU_NAME "ESP32-S2FN4R2"
#define MICROPY_PY_BLUETOOTH (0)
#define MICROPY_HW_ENABLE_SDCARD (0)
#define MICROPY_HW_I2C0_SCL (9)
#define MICROPY_HW_I2C0_SDA (8)
#define MICROPY_HW_SPI1_MOSI (35)
#define MICROPY_HW_SPI1_MISO (36)
#define MICROPY_HW_SPI1_SCK (37)

View File

@ -0,0 +1,6 @@
CONFIG_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_USB_AND_UART=y
# LWIP
CONFIG_LWIP_LOCAL_HOSTNAME="UMTinyS2"
# end of LWIP

View File

@ -1,6 +1,7 @@
include("manifest.py")
freeze("$(MPY_LIB_DIR)/upysh", "upysh.py")
freeze("$(MPY_LIB_DIR)/urequests", "urequests.py")
freeze("$(MPY_LIB_DIR)/umqtt.simple", "umqtt/simple.py")
freeze("$(MPY_LIB_DIR)/umqtt.robust", "umqtt/robust.py")
freeze("$(MPY_LIB_DIR)/python-ecosys/urequests", "urequests.py")
freeze("$(MPY_LIB_DIR)/micropython/upysh", "upysh.py")
freeze("$(MPY_LIB_DIR)/micropython/umqtt.simple", "umqtt/simple.py")
freeze("$(MPY_LIB_DIR)/micropython/umqtt.robust", "umqtt/robust.py")

View File

@ -0,0 +1,11 @@
# MicroPython on ESP32-S2 and ESP32-PAD1_subscript_3, ESP IDF configuration with SPIRAM support
CONFIG_ESP32S2_SPIRAM_SUPPORT=y
CONFIG_SPIRAM_TYPE_AUTO=y
CONFIG_DEFAULT_PSRAM_CLK_IO=30
CONFIG_DEFAULT_PSRAM_CS_IO=26
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
CONFIG_SPIRAM_USE_MEMMAP=y
CONFIG_SPIRAM_MEMTEST=y

View File

@ -96,7 +96,7 @@ STATIC mp_obj_t esp32_rmt_make_new(const mp_obj_type_t *type, size_t n_args, siz
self->carrier_freq = carrier_freq;
self->loop_en = false;
rmt_config_t config;
rmt_config_t config = {0};
config.rmt_mode = RMT_MODE_TX;
config.channel = (rmt_channel_t)self->channel_id;
config.gpio_num = self->pin;

View File

@ -11,9 +11,17 @@
void IRAM_ATTR esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numBytes, uint8_t timing) {
uint8_t *p, *end, pix, mask;
uint32_t t, time0, time1, period, c, startTime, pinMask;
uint32_t t, time0, time1, period, c, startTime, pinMask, gpio_reg_set, gpio_reg_clear;
if (pin < 32) {
pinMask = 1 << pin;
gpio_reg_set = GPIO_OUT_W1TS_REG;
gpio_reg_clear = GPIO_OUT_W1TC_REG;
} else {
pinMask = 1 << (pin - 32);
gpio_reg_set = GPIO_OUT1_W1TS_REG;
gpio_reg_clear = GPIO_OUT1_W1TC_REG;
}
p = pixels;
end = p + numBytes;
pix = *p++;
@ -42,12 +50,12 @@ void IRAM_ATTR esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32_t numByte
while (((c = mp_hal_ticks_cpu()) - startTime) < period) {
; // Wait for bit start
}
GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, pinMask); // Set high
GPIO_REG_WRITE(gpio_reg_set, pinMask); // Set high
startTime = c; // Save start time
while (((c = mp_hal_ticks_cpu()) - startTime) < t) {
; // Wait high duration
}
GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, pinMask); // Set low
GPIO_REG_WRITE(gpio_reg_clear, pinMask); // Set low
if (!(mask >>= 1)) { // Next bit/byte
if (p >= end) {
break;

Some files were not shown because too many files have changed in this diff Show More