initial v1.19.1 merge; not compiled yet

This commit is contained in:
Dan Halbert 2023-08-01 13:50:05 -04:00
commit 0d4bc8c163
423 changed files with 11363 additions and 9219 deletions

View File

@ -1,3 +1,15 @@
#all: Reformat remaining C code that doesn't have a space after a comma.
5b700b0af90591d6b1a2c087bb8de6b7f1bfdd2d
# ports: Reformat more C and Python source code.
5c32111fa0e31e451b0f1666bdf926be2fdfd82c
# all: Update Python formatting to latest Black version 22.1.0.
ab2923dfa1174dc177f0a90cb00a7e4ff87958d2
# all: Update Python formatting to latest Black version 21.12b0.
3770fab33449a5dadf8eb06edfae0767e75320a6
# tools/gen-cpydiff.py: Fix formatting of doc strings for new Black. # tools/gen-cpydiff.py: Fix formatting of doc strings for new Black.
0f78c36c5aa458a954eed39a46942209107a553e 0f78c36c5aa458a954eed39a46942209107a553e

View File

@ -1,10 +1,10 @@
:mod:`array` -- arrays of numeric data :mod:`array` -- arrays of numeric data
======================================= ======================================
.. module:: array .. module:: array
:synopsis: efficient arrays of numeric data :synopsis: efficient arrays of numeric data
|see_cpython_module| :mod:`cpython:array`. |see_cpython_module| :mod:`python:array`.
Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``, Supported format codes: ``b``, ``B``, ``h``, ``H``, ``i``, ``I``, ``l``,
``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the ``L``, ``q``, ``Q``, ``f``, ``d`` (the latter 2 depending on the

View File

@ -1,10 +1,10 @@
:mod:`binascii` -- binary/ASCII conversions :mod:`binascii` -- binary/ASCII conversions
============================================ ===========================================
.. module:: binascii .. module:: binascii
:synopsis: binary/ASCII conversions :synopsis: binary/ASCII conversions
|see_cpython_module| :mod:`cpython:binascii`. |see_cpython_module| :mod:`python:binascii`.
This module implements conversions between binary data and various This module implements conversions between binary data and various
encodings of it in ASCII form (in both directions). encodings of it in ASCII form (in both directions).
@ -31,11 +31,11 @@ Functions
Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_. Conforms to `RFC 2045 s.6.8 <https://tools.ietf.org/html/rfc2045#section-6.8>`_.
Returns a bytes object. Returns a bytes object.
.. function:: b2a_base64(data) .. function:: b2a_base64(data, *, newline=True)
Encode binary data in base64 format, as in `RFC 3548 Encode binary data in base64 format, as in `RFC 3548
<https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data <https://tools.ietf.org/html/rfc3548.html>`_. Returns the encoded data
followed by a newline character, as a bytes object. followed by a newline character if ``newline``is true, as a bytes object.
.. function:: crc32(data, value=0, /) .. function:: crc32(data, value=0, /)

View File

@ -7,7 +7,7 @@
:synopsis: simple BTree database :synopsis: simple BTree database
The ``btree`` module implements a simple key-value database using external The ``btree`` module implements a simple key-value database using external
storage (disk files, or in general case, a random-access ``stream``). Keys are storage (disk files, or in general case, a random-access `stream`). Keys are
stored sorted in the database, and besides efficient retrieval by a key stored sorted in the database, and besides efficient retrieval by a key
value, a database also supports efficient ordered range scans (retrieval value, a database also supports efficient ordered range scans (retrieval
of values with the keys in a given range). On the application interface of values with the keys in a given range). On the application interface
@ -80,7 +80,7 @@ Functions
.. function:: open(stream, *, flags=0, pagesize=0, cachesize=0, minkeypage=0) .. function:: open(stream, *, flags=0, pagesize=0, cachesize=0, minkeypage=0)
Open a database from a random-access ``stream`` (like an open file). All Open a database from a random-access `stream` (like an open file). All
other parameters are optional and keyword-only, and allow to tweak advanced other parameters are optional and keyword-only, and allow to tweak advanced
parameters of the database operation (most users will not need them): parameters of the database operation (most users will not need them):

View File

@ -33,7 +33,7 @@ Functions and types
.. class:: bytes() .. class:: bytes()
|see_cpython| `bytes`. |see_cpython| `python:bytes`.
.. function:: callable() .. function:: callable()
@ -68,7 +68,7 @@ Functions and types
.. class:: frozenset() .. class:: frozenset()
`frozenset()` is not enabled on non-Express CircuitPython boards. `frozenset()` is not enabled on the smallest CircuitPython boards for space reasons.
.. function:: getattr() .. function:: getattr()
@ -88,12 +88,12 @@ Functions and types
.. classmethod:: from_bytes(bytes, byteorder) .. classmethod:: from_bytes(bytes, byteorder)
In CircuitPython, ``byteorder`` parameter must be positional (this is In CircuitPython, the ``byteorder`` parameter must be positional (this is
compatible with CPython). compatible with CPython).
.. method:: to_bytes(size, byteorder) .. method:: to_bytes(size, byteorder)
In CircuitPython, ``byteorder`` parameter must be positional (this is In CircuitPython, the ``byteorder`` parameter must be positional (this is
compatible with CPython). compatible with CPython).
.. function:: isinstance() .. function:: isinstance()
@ -138,7 +138,7 @@ Functions and types
.. function:: reversed() .. function:: reversed()
`reversed()` is not enabled on non-Express CircuitPython boards. `reversed()` is not enabled on the smallest CircuitPython boards for space reasons.
.. function:: round() .. function:: round()
@ -224,10 +224,14 @@ Exceptions
.. exception:: SystemExit .. exception:: SystemExit
|see_cpython| `python:SystemExit`.
.. exception:: TimeoutError .. exception:: TimeoutError
.. exception:: TypeError .. exception:: TypeError
|see_cpython| `python:TypeError`.
.. exception:: UnicodeError .. exception:: UnicodeError
.. exception:: ValueError .. exception:: ValueError

View File

@ -1,12 +1,12 @@
:mod:`collections` -- collection and container types :mod:`collections` -- collection and container types
===================================================== ====================================================
.. include:: ../templates/unsupported_in_circuitpython.inc **Limitations:** Not implemented on the smallest CircuitPython boards for space reasons.
.. module:: collections .. module:: collections
:synopsis: collection and container types :synopsis: collection and container types
|see_cpython_module| :mod:`cpython:collections`. |see_cpython_module| :mod:`python:collections`.
This module implements advanced collection and container types to This module implements advanced collection and container types to
hold/accumulate various objects. hold/accumulate various objects.
@ -14,7 +14,7 @@ hold/accumulate various objects.
Classes Classes
------- -------
.. function:: deque(iterable, maxlen[, flags]) .. class:: deque(iterable, maxlen[, flags])
Deques (double-ended queues) are a list-like container that support O(1) Deques (double-ended queues) are a list-like container that support O(1)
appends and pops from either side of the deque. New deques are created appends and pops from either side of the deque. New deques are created
@ -59,7 +59,7 @@ Classes
print(t1.name) print(t1.name)
assert t2.name == t2[1] assert t2.name == t2[1]
.. function:: OrderedDict(...) .. class:: OrderedDict(...)
``dict`` type subclass which remembers and preserves the order of keys ``dict`` type subclass which remembers and preserves the order of keys
added. When ordered dict is iterated over, keys/items are returned in added. When ordered dict is iterated over, keys/items are returned in

View File

@ -4,10 +4,10 @@
.. module:: errno .. module:: errno
:synopsis: system error codes :synopsis: system error codes
|see_cpython_module| :mod:`cpython:errno`. |see_cpython_module| :mod:`python:errno`.
This module provides access to symbolic error codes for `OSError` exception. This module provides access to symbolic error codes for `OSError` exception.
A particular inventory of codes depends on :term:`MicroPython port`. The codes available may vary per CircuitPython build.
Constants Constants
--------- ---------
@ -15,14 +15,13 @@ Constants
.. data:: EEXIST, EAGAIN, etc. .. data:: EEXIST, EAGAIN, etc.
Error codes, based on ANSI C/POSIX standard. All error codes start with Error codes, based on ANSI C/POSIX standard. All error codes start with
"E". As mentioned above, inventory of the codes depends on "E". Errors are usually accessible as ``exc.errno``
:term:`MicroPython port`. Errors are usually accessible as ``exc.args[0]``
where ``exc`` is an instance of `OSError`. Usage example:: where ``exc`` is an instance of `OSError`. Usage example::
try: try:
os.mkdir("my_dir") os.mkdir("my_dir")
except OSError as exc: except OSError as exc:
if exc.args[0] == errno.EEXIST: if exc.errno == errno.EEXIST:
print("Directory already exists") print("Directory already exists")
.. data:: errorcode .. data:: errorcode

View File

@ -1,12 +1,10 @@
:mod:`gc` -- control the garbage collector :mod:`gc` -- control the garbage collector
========================================== ==========================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: gc .. module:: gc
:synopsis: control the garbage collector :synopsis: control the garbage collector
|see_cpython_module| :mod:`cpython:gc`. |see_cpython_module| :mod:`python:gc`.
Functions Functions
--------- ---------
@ -63,6 +61,6 @@ Functions
.. admonition:: Difference to CPython .. admonition:: Difference to CPython
:class: attention :class: attention
This function is a a MicroPython extension. CPython has a similar This function is a MicroPython extension. CPython has a similar
function - ``set_threshold()``, but due to different GC function - ``set_threshold()``, but due to different GC
implementations, its signature and semantics are different. implementations, its signature and semantics are different.

View File

@ -6,7 +6,7 @@
.. module:: heapq .. module:: heapq
:synopsis: heap queue algorithm :synopsis: heap queue algorithm
|see_cpython_module| :mod:`cpython:heapq`. |see_cpython_module| :mod:`python:heapq`.
This module implements the This module implements the
`min heap queue algorithm <https://en.wikipedia.org/wiki/Heap_%28data_structure%29>`_. `min heap queue algorithm <https://en.wikipedia.org/wiki/Heap_%28data_structure%29>`_.

View File

@ -15,7 +15,7 @@ CircuitPython's long-term goal is that code written in CircuitPython
using Python standard libraries will be runnable on CPython without changes. using Python standard libraries will be runnable on CPython without changes.
These libraries are not enabled on CircuitPython builds with These libraries are not enabled on CircuitPython builds with
limited flash memory, usually on non-Express builds: limited flash memory:
``binascii``, ``errno``, ``json``, ``re``. ``binascii``, ``errno``, ``json``, ``re``.
These libraries are not currently enabled in any CircuitPython build, but may be in the future: These libraries are not currently enabled in any CircuitPython build, but may be in the future:
@ -42,21 +42,6 @@ Omitted functions in the ``string`` library
------------------------------------------- -------------------------------------------
A few string operations are not enabled on small builds A few string operations are not enabled on small builds
(usually non-Express), due to limited flash memory: due to limited flash memory:
``string.center()``, ``string.partition()``, ``string.splitlines()``, ``string.center()``, ``string.partition()``, ``string.splitlines()``,
``string.reversed()``. ``string.reversed()``.
CircuitPython/MicroPython-specific libraries
--------------------------------------------
Functionality specific to the CircuitPython/MicroPython implementation is available in
the following libraries. These libraries may change significantly or be removed in future
versions of CircuitPython.
.. toctree::
:maxdepth: 1
btree.rst
framebuf.rst
micropython.rst

View File

@ -1,10 +1,10 @@
:mod:`io` -- input/output streams :mod:`io` -- input/output streams
================================== =================================
.. module:: io .. module:: io
:synopsis: input/output streams :synopsis: input/output streams
|see_cpython_module| :mod:`cpython:io`. |see_cpython_module| :mod:`python:io`.
This module contains additional types of ``stream`` (file-like) objects This module contains additional types of ``stream`` (file-like) objects
and helper functions. and helper functions.
@ -112,3 +112,20 @@ Classes
.. method:: getvalue() .. method:: getvalue()
Get the current contents of the underlying buffer which holds data. Get the current contents of the underlying buffer which holds data.
.. class:: StringIO(alloc_size)
:noindex:
.. class:: BytesIO(alloc_size)
:noindex:
Create an empty `StringIO`/`BytesIO` object, preallocated to hold up
to *alloc_size* number of bytes. That means that writing that amount
of bytes won't lead to reallocation of the buffer, and thus won't hit
out-of-memory situation or lead to memory fragmentation. These constructors
are a MicroPython extension and are recommended for usage only in special
cases and in system-level libraries, not for end-user applications.
.. admonition:: Difference to CPython
:class: attention
These constructors are a MicroPython extension.

View File

@ -1,10 +1,10 @@
:mod:`json` -- JSON encoding and decoding :mod:`json` -- JSON encoding and decoding
========================================== =========================================
.. module:: json .. module:: json
:synopsis: JSON encoding and decoding :synopsis: JSON encoding and decoding
|see_cpython_module| :mod:`cpython:json`. |see_cpython_module| :mod:`python:json`.
This modules allows to convert between Python objects and the JSON This modules allows to convert between Python objects and the JSON
data format. data format.
@ -12,14 +12,20 @@ data format.
Functions Functions
--------- ---------
.. function:: dump(obj, stream) .. function:: dump(obj, stream, separators=None)
Serialise ``obj`` to a JSON string, writing it to the given *stream*. Serialise ``obj`` to a JSON string, writing it to the given *stream*.
.. function:: dumps(obj) If specified, separators should be an ``(item_separator, key_separator)``
tuple. The default is ``(', ', ': ')``. To get the most compact JSON
representation, you should specify ``(',', ':')`` to eliminate whitespace.
.. function:: dumps(obj, separators=None)
Return ``obj`` represented as a JSON string. Return ``obj`` represented as a JSON string.
The arguments have the same meaning as in `dump`.
.. function:: load(stream) .. function:: load(stream)
Parse the given ``stream``, interpreting it as a JSON string and Parse the given ``stream``, interpreting it as a JSON string and

View File

@ -1,7 +1,5 @@
:mod:`micropython` -- access and control MicroPython internals :mod:`micropython` -- MicroPython extensions and internals
============================================================== ==========================================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: micropython .. module:: micropython
:synopsis: access and control MicroPython internals :synopsis: access and control MicroPython internals
@ -11,7 +9,7 @@ Functions
.. function:: const(expr) .. function:: const(expr)
Used to declare that the expression is a constant so that the compile can Used to declare that the expression is a constant so that the compiler can
optimise it. The use of this function should be as follows:: optimise it. The use of this function should be as follows::
from micropython import const from micropython import const
@ -28,111 +26,3 @@ Functions
provided as part of the :mod:`micropython` module mainly so that scripts can be provided as part of the :mod:`micropython` module mainly so that scripts can be
written which run under both CPython and MicroPython, by following the above written which run under both CPython and MicroPython, by following the above
pattern. pattern.
.. function:: opt_level([level])
If *level* is given then this function sets the optimisation level for subsequent
compilation of scripts, and returns ``None``. Otherwise it returns the current
optimisation level.
The optimisation level controls the following compilation features:
- Assertions: at level 0 assertion statements are enabled and compiled into the
bytecode; at levels 1 and higher assertions are not compiled.
- Built-in ``__debug__`` variable: at level 0 this variable expands to ``True``;
at levels 1 and higher it expands to ``False``.
- Source-code line numbers: at levels 0, 1 and 2 source-code line number are
stored along with the bytecode so that exceptions can report the line number
they occurred at; at levels 3 and higher line numbers are not stored.
The default optimisation level is usually level 0.
.. function:: mem_info([verbose])
Print information about currently used memory. If the *verbose* argument
is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the amount of stack and heap used. In verbose mode it prints out
the entire heap indicating which blocks are used and which are free.
.. function:: qstr_info([verbose])
Print information about currently interned strings. If the *verbose*
argument is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the number of interned strings and the amount of RAM they use. In
verbose mode it prints out the names of all RAM-interned strings.
.. function:: stack_use()
Return an integer representing the current amount of stack that is being
used. The absolute value of this is not particularly useful, rather it
should be used to compute differences in stack usage at different points.
.. function:: heap_lock()
.. function:: heap_unlock()
.. function:: heap_locked()
Lock or unlock the heap. When locked no memory allocation can occur and a
``MemoryError`` will be raised if any heap allocation is attempted.
`heap_locked()` returns a true value if the heap is currently locked.
These functions can be nested, ie `heap_lock()` can be called multiple times
in a row and the lock-depth will increase, and then `heap_unlock()` must be
called the same number of times to make the heap available again.
Both `heap_unlock()` and `heap_locked()` return the current lock depth
(after unlocking for the former) as a non-negative integer, with 0 meaning
the heap is not locked.
If the REPL becomes active with the heap locked then it will be forcefully
unlocked.
Note: `heap_locked()` is not enabled on most ports by default,
requires ``MICROPY_PY_MICROPYTHON_HEAP_LOCKED``.
.. function:: kbd_intr(chr)
Set the character that will raise a `KeyboardInterrupt` exception. By
default this is set to 3 during script execution, corresponding to Ctrl-C.
Passing -1 to this function will disable capture of Ctrl-C, and passing 3
will restore it.
This function can be used to prevent the capturing of Ctrl-C on the
incoming stream of characters that is usually used for the REPL, in case
that stream is used for other purposes.
.. function:: schedule(func, arg)
Schedule the function *func* to be executed "very soon". The function
is passed the value *arg* as its single argument. "Very soon" means that
the MicroPython runtime will do its best to execute the function at the
earliest possible time, given that it is also trying to be efficient, and
that the following conditions hold:
- A scheduled function will never preempt another scheduled function.
- Scheduled functions are always executed "between opcodes" which means
that all fundamental Python operations (such as appending to a list)
are guaranteed to be atomic.
- A given port may define "critical regions" within which scheduled
functions will never be executed. Functions may be scheduled within
a critical region but they will not be executed until that region
is exited. An example of a critical region is a preempting interrupt
handler (an IRQ).
A use for this function is to schedule a callback from a preempting IRQ.
Such an IRQ puts restrictions on the code that runs in the IRQ (for example
the heap may be locked) and scheduling a function to call later will lift
those restrictions.
Note: If `schedule()` is called from a preempting IRQ, when memory
allocation is not allowed and the callback to be passed to `schedule()` is
a bound method, passing this directly will fail. This is because creating a
reference to a bound method causes memory allocation. A solution is to
create a reference to the method in the class constructor and to pass that
reference to `schedule()`.
There is a finite queue to hold the scheduled functions and `schedule()`
will raise a `RuntimeError` if the queue is full.

View File

@ -1,10 +1,10 @@
:mod:`re` -- simple regular expressions :mod:`re` -- simple regular expressions
======================================== =======================================
.. module:: re .. module:: re
:synopsis: regular expressions :synopsis: regular expressions
|see_cpython_module| :mod:`cpython:re`. |see_cpython_module| :mod:`python:re`.
This module implements regular expression operations. Regular expression This module implements regular expression operations. Regular expression
syntax supported is a subset of CPython ``re`` module (and actually is syntax supported is a subset of CPython ``re`` module (and actually is

View File

@ -1,8 +1,6 @@
:mod:`select` -- wait for events on a set of streams :mod:`select` -- wait for events on a set of streams
==================================================== ====================================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: select .. module:: select
:synopsis: wait for events on a set of streams :synopsis: wait for events on a set of streams
@ -86,7 +84,7 @@ Methods
.. method:: poll.ipoll(timeout=-1, flags=0, /) .. method:: poll.ipoll(timeout=-1, flags=0, /)
Like :meth:`poll.poll`, but instead returns an iterator which yields a Like :meth:`poll.poll`, but instead returns an iterator which yields a
``callee-owned tuples``. This function provides efficient, allocation-free "callee-owned tuple". This function provides an efficient, allocation-free
way to poll on streams. way to poll on streams.
If *flags* is 1, one-shot behaviour for events is employed: streams for If *flags* is 1, one-shot behaviour for events is employed: streams for

View File

@ -1,12 +1,10 @@
:mod:`sys` -- system specific functions :mod:`sys` -- system specific functions
======================================== =======================================
.. include:: ../templates/unsupported_in_circuitpython.inc
.. module:: sys .. module:: sys
:synopsis: system specific functions :synopsis: system specific functions
|see_cpython_module| :mod:`cpython:sys`. |see_cpython_module| :mod:`python:sys`.
Functions Functions
--------- ---------
@ -35,6 +33,7 @@ Constants
* *name* - string "circuitpython" * *name* - string "circuitpython"
* *version* - tuple (major, minor, micro), e.g. (1, 7, 0) * *version* - tuple (major, minor, micro), e.g. (1, 7, 0)
* *_mpy* - supported mpy file-format version (optional attribute)
This object is the recommended way to distinguish CircuitPython from other This object is the recommended way to distinguish CircuitPython from other
Python implementations (note that it still may not exist in the very Python implementations (note that it still may not exist in the very
@ -97,6 +96,12 @@ Constants
If you need to check whether your program runs on CircuitPython (vs other If you need to check whether your program runs on CircuitPython (vs other
Python implementation), use `sys.implementation` instead. Python implementation), use `sys.implementation` instead.
.. data:: ps1
ps2
Mutable attributes holding strings, which are used for the REPL prompt. The defaults
give the standard Python prompt of ``>>>`` and ``...``.
.. data:: stderr .. data:: stderr
Standard error ``stream``. Standard error ``stream``.
@ -109,6 +114,14 @@ Constants
Standard output ``stream``. Standard output ``stream``.
.. data:: tracebacklimit
A mutable attribute holding an integer value which is the maximum number of traceback
entries to store in an exception. Set to 0 to disable adding tracebacks. Defaults
to 1000.
Note: this is not available on all ports.
.. data:: version .. data:: version
Python language version that this implementation conforms to, as a string. Python language version that this implementation conforms to, as a string.

View File

@ -159,7 +159,7 @@ Glossary
typically accessible on a host PC via USB. typically accessible on a host PC via USB.
stream stream
Also known as a "file-like object". An Python object which provides Also known as a "file-like object". A Python object which provides
sequential read-write access to the underlying data. A stream object sequential read-write access to the underlying data. A stream object
implements a corresponding interface, which consists of methods like implements a corresponding interface, which consists of methods like
``read()``, ``write()``, ``readinto()``, ``seek()``, ``flush()``, ``read()``, ``write()``, ``readinto()``, ``seek()``, ``flush()``,

199
docs/reference/mpyfiles.rst Normal file
View File

@ -0,0 +1,199 @@
.. _mpy_files:
MicroPython .mpy files
======================
MicroPython defines the concept of an .mpy file which is a binary container
file format that holds precompiled code, and which can be imported like a
normal .py module. The file ``foo.mpy`` can be imported via ``import foo``,
as long as ``foo.mpy`` can be found in the usual way by the import machinery.
Usually, each directory listed in ``sys.path`` is searched in order. When
searching a particular directory ``foo.py`` is looked for first and if that
is not found then ``foo.mpy`` is looked for, then the search continues in the
next directory if neither is found. As such, ``foo.py`` will take precedence
over ``foo.mpy``.
These .mpy files can contain bytecode which is usually generated from Python
source files (.py files) via the ``mpy-cross`` program. For some architectures
an .mpy file can also contain native machine code, which can be generated in
a variety of ways, most notably from C source code.
Versioning and compatibility of .mpy files
------------------------------------------
A given .mpy file may or may not be compatible with a given MicroPython system.
Compatibility is based on the following:
* Version of the .mpy file: the version of the file must match the version
supported by the system loading it.
* Sub-version of the .mpy file: if the .mpy file contains native machine code
then the sub-version of the file must match the version support by the
system loading it. Otherwise, if there is no native machine code in the .mpy
file, then the sub-version is ignored when loading.
* Small integer bits: the .mpy file will require a minimum number of bits in
a small integer and the system loading it must support at least this many
bits.
* Native architecture: if the .mpy file contains native machine code then
it will specify the architecture of that machine code and the system
loading it must support execution of that architecture's code.
If a MicroPython system supports importing .mpy files then the
``sys.implementation._mpy`` field will exist and return an integer which
encodes the version (lower 8 bits), features and native architecture.
Trying to import an .mpy file that fails one of the first four tests will
raise ``ValueError('incompatible .mpy file')``. Trying to import an .mpy
file that fails the native architecture test (if it contains native machine
code) will raise ``ValueError('incompatible .mpy arch')``.
If importing an .mpy file fails then try the following:
* Determine the .mpy version and flags supported by your MicroPython system
by executing::
import sys
sys_mpy = sys.implementation._mpy
arch = [None, 'x86', 'x64',
'armv6', 'armv6m', 'armv7m', 'armv7em', 'armv7emsp', 'armv7emdp',
'xtensa', 'xtensawin'][sys_mpy >> 10]
print('mpy version:', sys_mpy & 0xff)
print('mpy flags:', end='')
if arch:
print(' -march=' + arch, end='')
print()
* Check the validity of the .mpy file by inspecting the first two bytes of
the file. The first byte should be an uppercase 'M' and the second byte
will be the version number, which should match the system version from above.
If it doesn't match then rebuild the .mpy file.
* Check if the system .mpy version matches the version emitted by ``mpy-cross``
that was used to build the .mpy file, found by ``mpy-cross --version``.
If it doesn't match then recompile ``mpy-cross`` from the Git repository
checked out at the tag (or hash) reported by ``mpy-cross --version``.
* Make sure you are using the correct ``mpy-cross`` flags, found by the code
above, or by inspecting the ``MPY_CROSS_FLAGS`` Makefile variable for the
port that you are using.
The following table shows the correspondence between MicroPython release
and .mpy version.
=================== ============
MicroPython release .mpy version
=================== ============
v1.19 and up 6
v1.12 - v1.18 5
v1.11 4
v1.9.3 - v1.10 3
v1.9 - v1.9.2 2
v1.5.1 - v1.8.7 0
=================== ============
For completeness, the next table shows the Git commit of the main
MicroPython repository at which the .mpy version was changed.
=================== ========================================
.mpy version change Git commit
=================== ========================================
5 to 6 f2040bfc7ee033e48acef9f289790f3b4e6b74e5
4 to 5 5716c5cf65e9b2cb46c2906f40302401bdd27517
3 to 4 9a5f92ea72754c01cc03e5efcdfe94021120531e
2 to 3 ff93fd4f50321c6190e1659b19e64fef3045a484
1 to 2 dd11af209d226b7d18d5148b239662e30ed60bad
0 to 1 6a11048af1d01c78bdacddadd1b72dc7ba7c6478
initial version 0 d8c834c95d506db979ec871417de90b7951edc30
=================== ========================================
Binary encoding of .mpy files
-----------------------------
MicroPython .mpy files are a binary container format with code objects (bytecode
and native machine code) stored internally in a nested hierarchy. The code for
the outer module is stored first, and then its children follow. Each child may
have further children, for example in the case of a class having methods, or a
function defining a lambda or comprehension. To keep files small while still
providing a large range of possible values it uses the concept of a
variably-encoded-unsigned-integer (vuint) in many places. Similar to utf-8
encoding, this encoding stores 7 bits per byte with the 8th bit (MSB) set
if one or more bytes follow. The bits of the unsigned integer are stored
in the vuint in LSB form.
The top-level of an .mpy file consists of three parts:
* The header.
* The global qstr and constant tables.
* The raw-code for the outer scope of the module.
This outer scope is executed when the .mpy file is imported.
You can inspect the contents of a .mpy file by using ``mpy-tool.py``, for
example (run from the root of the main MicroPython repository)::
$ ./tools/mpy-tool.py -xd myfile.mpy
The header
~~~~~~~~~~
The .mpy header is:
====== ================================
size field
====== ================================
byte value 0x4d (ASCII 'M')
byte .mpy version number
byte feature flags
byte number of bits in a small int
====== ================================
The global qstr and constant tables
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An .mpy file contains a single qstr table, and a single constant object table.
These are global to the .mpy file, they are referenced by all nested raw-code
objects. The qstr table maps internal qstr number (internal to the .mpy file)
to the resolved qstr number of the runtime that the .mpy file is imported into.
This links the .mpy file with the rest of the system that it executes within.
The constant object table is populated with references to all constant objects
that the .mpy file needs.
====== ================================
size field
====== ================================
vuint number of qstrs
vuint number of constant objects
... qstr data
... encoded constant objects
====== ================================
Raw code elements
~~~~~~~~~~~~~~~~~
A raw-code element contains code, either bytecode or native machine code. Its
contents are:
====== ================================
size field
====== ================================
vuint type, size and whether there are sub-raw-code elements
... code (bytecode or machine code)
vuint number of sub-raw-code elements (only if non-zero)
... sub-raw-code elements
====== ================================
The first vuint in a raw-code element encodes the type of code stored in this
element (the two least-significant bits), whether this raw-code has any
children (the third least-significant bit), and the length of the code that
follows (the amount of RAM to allocate for it).
Following the vuint comes the code itself. Unless the code type is viper code
with relocations, this code is constant data and does not need to be modified.
If this raw-code has any children (as indicated by a bit in the first vuint),
following the code comes a vuint counting the number of sub-raw-code elements.
Finally any sub-raw-code elements are stored, recursively.

View File

@ -94,6 +94,10 @@ MDNS is used to resolve [`circuitpython.local`](http://circuitpython.local) to a
hostname of the form `cpy-XXXXXX.local`. The `XXXXXX` is based on network MAC address. The device hostname of the form `cpy-XXXXXX.local`. The `XXXXXX` is based on network MAC address. The device
also provides the MDNS service with service type `_circuitpython` and protocol `_tcp`. also provides the MDNS service with service type `_circuitpython` and protocol `_tcp`.
Since port 80 (or the port assigned to `CIRCUITPY_WEB_API_PORT`) is used for web workflow, the `mdns`
[module](https://docs.circuitpython.org/en/latest/shared-bindings/mdns/index.html#mdns.Server.advertise_service)
can't advertise an additional service on that port.
### HTTP ### HTTP
The web server is HTTP 1.1 and may use chunked responses so that it doesn't need to precompute The web server is HTTP 1.1 and may use chunked responses so that it doesn't need to precompute
content length. content length.

View File

@ -1 +0,0 @@
*.mpy

View File

@ -1,37 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module (different to built-in btree so it can coexist)
MOD = btree_$(ARCH)
# Source files (.c or .py)
SRC = btree_c.c btree_py.py
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
BTREE_DIR = $(MPY_DIR)/lib/berkeley-db-1.xx
BTREE_DEFS = -D__DBINTERFACE_PRIVATE=1 -Dmpool_error="(void)" -Dabort=abort_ "-Dvirt_fd_t=void*" $(BTREE_DEFS_EXTRA)
CFLAGS += -I$(BTREE_DIR)/PORT/include
CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
SRC += $(addprefix $(realpath $(BTREE_DIR))/,\
btree/bt_close.c \
btree/bt_conv.c \
btree/bt_delete.c \
btree/bt_get.c \
btree/bt_open.c \
btree/bt_overflow.c \
btree/bt_page.c \
btree/bt_put.c \
btree/bt_search.c \
btree/bt_seq.c \
btree/bt_split.c \
btree/bt_utils.c \
mpool/mpool.c \
)
include $(MPY_DIR)/py/dynruntime.mk
# btree needs gnu99 defined
CFLAGS += -std=gnu99

View File

@ -1,148 +0,0 @@
#define MICROPY_PY_BTREE (1)
#include "py/dynruntime.h"
#include <unistd.h>
#if !defined(__linux__)
void *memcpy(void *dst, const void *src, size_t n) {
return mp_fun_table.memmove_(dst, src, n);
}
void *memset(void *s, int c, size_t n) {
return mp_fun_table.memset_(s, c, n);
}
#endif
void *memmove(void *dest, const void *src, size_t n) {
return mp_fun_table.memmove_(dest, src, n);
}
void *malloc(size_t n) {
void *ptr = m_malloc(n, false);
return ptr;
}
void *realloc(void *ptr, size_t n) {
mp_printf(&mp_plat_print, "UNDEF %d\n", __LINE__);
return NULL;
}
void *calloc(size_t n, size_t m) {
void *ptr = m_malloc(n * m, false);
// memory already cleared by conservative GC
return ptr;
}
void free(void *ptr) {
m_free(ptr);
}
void abort_(void) {
nlr_raise(mp_obj_new_exception(mp_load_global(MP_QSTR_RuntimeError)));
}
int native_errno;
#if defined(__linux__)
int *__errno_location (void)
#else
int *__errno (void)
#endif
{
return &native_errno;
}
ssize_t mp_stream_posix_write(void *stream, const void *buf, size_t len) {
mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
mp_uint_t out_sz = stream_p->write(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
} else {
return out_sz;
}
}
ssize_t mp_stream_posix_read(void *stream, void *buf, size_t len) {
mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
mp_uint_t out_sz = stream_p->read(MP_OBJ_FROM_PTR(stream), buf, len, &native_errno);
if (out_sz == MP_STREAM_ERROR) {
return -1;
} else {
return out_sz;
}
}
off_t mp_stream_posix_lseek(void *stream, off_t offset, int whence) {
const mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
struct mp_stream_seek_t seek_s;
seek_s.offset = offset;
seek_s.whence = whence;
mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_SEEK, (mp_uint_t)(uintptr_t)&seek_s, &native_errno);
if (res == MP_STREAM_ERROR) {
return -1;
}
return seek_s.offset;
}
int mp_stream_posix_fsync(void *stream) {
mp_obj_base_t* o = stream;
const mp_stream_p_t *stream_p = o->type->ext[0].protocol;
mp_uint_t res = stream_p->ioctl(MP_OBJ_FROM_PTR(stream), MP_STREAM_FLUSH, 0, &native_errno);
if (res == MP_STREAM_ERROR) {
return -1;
}
return res;
}
mp_obj_full_type_t btree_type;
#include "extmod/modbtree.c"
mp_map_elem_t btree_locals_dict_table[8];
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
STATIC mp_obj_t btree_open(size_t n_args, const mp_obj_t *args) {
// Make sure we got a stream object
mp_get_stream_raise(args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
BTREEINFO openinfo = {0};
openinfo.flags = mp_obj_get_int(args[1]);
openinfo.cachesize = mp_obj_get_int(args[2]);
openinfo.psize = mp_obj_get_int(args[3]);
openinfo.minkeypage = mp_obj_get_int(args[4]);
DB *db = __bt_open(MP_OBJ_TO_PTR(args[0]), &btree_stream_fvtable, &openinfo, 0);
if (db == NULL) {
mp_raise_OSError(native_errno);
}
return MP_OBJ_FROM_PTR(btree_new(db, args[0]));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_open_obj, 5, 5, btree_open);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
btree_type.base.type = (void*)&mp_fun_table.type_type;
btree_type.flags = MP_TYPE_FLAG_EXTENDED;
btree_type.name = MP_QSTR_btree;
btree_type.print = btree_print;
btree_type.ext[0].getiter = btree_getiter;
btree_type.ext[0].iternext = btree_iternext;
btree_type.ext[0].binary_op = btree_binary_op;
btree_type.ext[0].subscr = btree_subscr;
btree_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_close), MP_OBJ_FROM_PTR(&btree_close_obj) };
btree_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_flush), MP_OBJ_FROM_PTR(&btree_flush_obj) };
btree_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_get), MP_OBJ_FROM_PTR(&btree_get_obj) };
btree_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_put), MP_OBJ_FROM_PTR(&btree_put_obj) };
btree_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_seq), MP_OBJ_FROM_PTR(&btree_seq_obj) };
btree_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_keys), MP_OBJ_FROM_PTR(&btree_keys_obj) };
btree_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_values), MP_OBJ_FROM_PTR(&btree_values_obj) };
btree_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_items), MP_OBJ_FROM_PTR(&btree_items_obj) };
btree_type.locals_dict = (void*)&btree_locals_dict;
mp_store_global(MP_QSTR__open, MP_OBJ_FROM_PTR(&btree_open_obj));
mp_store_global(MP_QSTR_INCL, MP_OBJ_NEW_SMALL_INT(FLAG_END_KEY_INCL));
mp_store_global(MP_QSTR_DESC, MP_OBJ_NEW_SMALL_INT(FLAG_DESC));
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,3 +0,0 @@
# Implemented in Python to support keyword arguments
def open(stream, *, flags=0, cachesize=0, pagesize=0, minkeypage=0):
return _open(stream, flags, cachesize, pagesize, minkeypage)

View File

@ -1,14 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module
MOD = features0
# Source files (.c or .py)
SRC = features0.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
# Include to get the rules for compiling and linking the module
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,40 +0,0 @@
/* This example demonstrates the following features in a native module:
- defining a simple function exposed to Python
- defining a local, helper C function
- getting and creating integer objects
*/
// Include the header file to get access to the MicroPython API
#include "py/dynruntime.h"
// Helper function to compute factorial
STATIC mp_int_t factorial_helper(mp_int_t x) {
if (x == 0) {
return 1;
}
return x * factorial_helper(x - 1);
}
// This is the function which will be called from Python, as factorial(x)
STATIC mp_obj_t factorial(mp_obj_t x_obj) {
// Extract the integer from the MicroPython input object
mp_int_t x = mp_obj_get_int(x_obj);
// Calculate the factorial
mp_int_t result = factorial_helper(x);
// Convert the result to a MicroPython integer object and return it
return mp_obj_new_int(result);
}
// Define a Python reference to the function above
STATIC MP_DEFINE_CONST_FUN_OBJ_1(factorial_obj, factorial);
// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// This must be first, it sets up the globals dict and other things
MP_DYNRUNTIME_INIT_ENTRY
// Make the function available in the module's namespace
mp_store_global(MP_QSTR_factorial, MP_OBJ_FROM_PTR(&factorial_obj));
// This must be last, it restores the globals dict
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,14 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module
MOD = features1
# Source files (.c or .py)
SRC = features1.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
# Include to get the rules for compiling and linking the module
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,106 +0,0 @@
/* This example demonstrates the following features in a native module:
- defining simple functions exposed to Python
- defining local, helper C functions
- defining constant integers and strings exposed to Python
- getting and creating integer objects
- creating Python lists
- raising exceptions
- allocating memory
- BSS and constant data (rodata)
- relocated pointers in rodata
*/
// Include the header file to get access to the MicroPython API
#include "py/dynruntime.h"
// BSS (zero) data
uint16_t data16[4];
// Constant data (rodata)
const uint8_t table8[] = { 0, 1, 1, 2, 3, 5, 8, 13 };
const uint16_t table16[] = { 0x1000, 0x2000 };
// Constant data pointing to BSS/constant data
uint16_t *const table_ptr16a[] = { &data16[0], &data16[1], &data16[2], &data16[3] };
const uint16_t *const table_ptr16b[] = { &table16[0], &table16[1] };
// A simple function that adds its 2 arguments (must be integers)
STATIC mp_obj_t add(mp_obj_t x_in, mp_obj_t y_in) {
mp_int_t x = mp_obj_get_int(x_in);
mp_int_t y = mp_obj_get_int(y_in);
return mp_obj_new_int(x + y);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
// A local helper function (not exposed to Python)
STATIC mp_int_t fibonacci_helper(mp_int_t x) {
if (x < MP_ARRAY_SIZE(table8)) {
return table8[x];
} else {
return fibonacci_helper(x - 1) + fibonacci_helper(x - 2);
}
}
// A function which computes Fibonacci numbers
STATIC mp_obj_t fibonacci(mp_obj_t x_in) {
mp_int_t x = mp_obj_get_int(x_in);
if (x < 0) {
mp_raise_ValueError(MP_ERROR_TEXT("can't compute negative Fibonacci number"));
}
return mp_obj_new_int(fibonacci_helper(x));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(fibonacci_obj, fibonacci);
// A function that accesses the BSS data
STATIC mp_obj_t access(size_t n_args, const mp_obj_t *args) {
if (n_args == 0) {
// Create a list holding all items from data16
mp_obj_list_t *lst = MP_OBJ_TO_PTR(mp_obj_new_list(MP_ARRAY_SIZE(data16), NULL));
for (int i = 0; i < MP_ARRAY_SIZE(data16); ++i) {
lst->items[i] = mp_obj_new_int(data16[i]);
}
return MP_OBJ_FROM_PTR(lst);
} else if (n_args == 1) {
// Get one item from data16
mp_int_t idx = mp_obj_get_int(args[0]) & 3;
return mp_obj_new_int(data16[idx]);
} else {
// Set one item in data16 (via table_ptr16a)
mp_int_t idx = mp_obj_get_int(args[0]) & 3;
*table_ptr16a[idx] = mp_obj_get_int(args[1]);
return mp_const_none;
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(access_obj, 0, 2, access);
// A function that allocates memory and creates a bytearray
STATIC mp_obj_t make_array(void) {
uint16_t *ptr = m_new(uint16_t, MP_ARRAY_SIZE(table_ptr16b));
for (int i = 0; i < MP_ARRAY_SIZE(table_ptr16b); ++i) {
ptr[i] = *table_ptr16b[i];
}
return mp_obj_new_bytearray_by_ref(sizeof(uint16_t) * MP_ARRAY_SIZE(table_ptr16b), ptr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(make_array_obj, make_array);
// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// This must be first, it sets up the globals dict and other things
MP_DYNRUNTIME_INIT_ENTRY
// Messages can be printed as usually
mp_printf(&mp_plat_print, "initialising module self=%p\n", self);
// Make the functions available in the module's namespace
mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj));
mp_store_global(MP_QSTR_fibonacci, MP_OBJ_FROM_PTR(&fibonacci_obj));
mp_store_global(MP_QSTR_access, MP_OBJ_FROM_PTR(&access_obj));
mp_store_global(MP_QSTR_make_array, MP_OBJ_FROM_PTR(&make_array_obj));
// Add some constants to the module's namespace
mp_store_global(MP_QSTR_VAL, MP_OBJ_NEW_SMALL_INT(42));
mp_store_global(MP_QSTR_MSG, MP_OBJ_NEW_QSTR(MP_QSTR_HELLO_MICROPYTHON));
// This must be last, it restores the globals dict
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,14 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module
MOD = features2
# Source files (.c or .py)
SRC = main.c prod.c test.py
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
# Include to get the rules for compiling and linking the module
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,83 +0,0 @@
/* This example demonstrates the following features in a native module:
- using floats
- defining additional code in Python (see test.py)
- have extra C code in a separate file (see prod.c)
*/
// Include the header file to get access to the MicroPython API
#include "py/dynruntime.h"
// Include the header for auxiliary C code for this module
#include "prod.h"
// Automatically detect if this module should include double-precision code.
// If double precision is supported by the target architecture then it can
// be used in native module regardless of what float setting the target
// MicroPython runtime uses (being none, float or double).
#if defined(__i386__) || defined(__x86_64__) || (defined(__ARM_FP) && (__ARM_FP & 8))
#define USE_DOUBLE 1
#else
#define USE_DOUBLE 0
#endif
// A function that uses the default float type configured for the current target
// This default can be overridden by specifying MICROPY_FLOAT_IMPL at the make level
STATIC mp_obj_t add(mp_obj_t x, mp_obj_t y) {
return mp_obj_new_float(mp_obj_get_float(x) + mp_obj_get_float(y));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_obj, add);
// A function that explicitly uses single precision floats
STATIC mp_obj_t add_f(mp_obj_t x, mp_obj_t y) {
return mp_obj_new_float_from_f(mp_obj_get_float_to_f(x) + mp_obj_get_float_to_f(y));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_f_obj, add_f);
#if USE_DOUBLE
// A function that explicitly uses double precision floats
STATIC mp_obj_t add_d(mp_obj_t x, mp_obj_t y) {
return mp_obj_new_float_from_d(mp_obj_get_float_to_d(x) + mp_obj_get_float_to_d(y));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(add_d_obj, add_d);
#endif
// A function that computes the product of floats in an array.
// This function uses the most general C argument interface, which is more difficult
// to use but has access to the globals dict of the module via self->globals.
STATIC mp_obj_t productf(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// Check number of arguments is valid
mp_arg_check_num(n_args, n_kw, 1, 1, false);
// Extract buffer pointer and verify typecode
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_RW);
if (bufinfo.typecode != 'f') {
mp_raise_ValueError(MP_ERROR_TEXT("expecting float array"));
}
// Compute product, store result back in first element of array
float *ptr = bufinfo.buf;
float prod = prod_array(bufinfo.len / sizeof(*ptr), ptr);
ptr[0] = prod;
return mp_const_none;
}
// This is the entry point and is called when the module is imported
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
// This must be first, it sets up the globals dict and other things
MP_DYNRUNTIME_INIT_ENTRY
// Make the functions available in the module's namespace
mp_store_global(MP_QSTR_add, MP_OBJ_FROM_PTR(&add_obj));
mp_store_global(MP_QSTR_add_f, MP_OBJ_FROM_PTR(&add_f_obj));
#if USE_DOUBLE
mp_store_global(MP_QSTR_add_d, MP_OBJ_FROM_PTR(&add_d_obj));
#endif
// The productf function uses the most general C argument interface
mp_store_global(MP_QSTR_productf, MP_DYNRUNTIME_MAKE_FUNCTION(productf));
// This must be last, it restores the globals dict
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,9 +0,0 @@
#include "prod.h"
float prod_array(int n, float *ar) {
float ans = 1;
for (int i = 0; i < n; ++i) {
ans *= ar[i];
}
return ans;
}

View File

@ -1 +0,0 @@
float prod_array(int n, float *ar);

View File

@ -1,29 +0,0 @@
# This Python code will be merged with the C code in main.c
import array
def isclose(a, b):
return abs(a - b) < 1e-3
def test():
tests = [
isclose(add(0.1, 0.2), 0.3),
isclose(add_f(0.1, 0.2), 0.3),
]
ar = array.array("f", [1, 2, 3.5])
productf(ar)
tests.append(isclose(ar[0], 7))
if "add_d" in globals():
tests.append(isclose(add_d(0.1, 0.2), 0.3))
print(tests)
if not all(tests):
raise SystemExit(1)
test()

View File

@ -1,13 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module (different to built-in framebuf so it can coexist)
MOD = framebuf_$(ARCH)
# Source files (.c or .py)
SRC = framebuf.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,50 +0,0 @@
#define MICROPY_PY_FRAMEBUF (1)
#include "py/dynruntime.h"
#if !defined(__linux__)
void *memset(void *s, int c, size_t n) {
return mp_fun_table.memset_(s, c, n);
}
#endif
mp_obj_full_type_t mp_type_framebuf;
#include "extmod/modframebuf.c"
mp_map_elem_t framebuf_locals_dict_table[10];
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
mp_type_framebuf.base.type = (void*)&mp_type_type;
mp_type_framebuf.flags = MP_TYPE_FLAG_EXTENDED;
mp_type_framebuf.name = MP_QSTR_FrameBuffer;
mp_type_framebuf.make_new = framebuf_make_new;
mp_type_framebuf.ext[0].buffer_p.get_buffer = framebuf_get_buffer;
framebuf_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill), MP_OBJ_FROM_PTR(&framebuf_fill_obj) };
framebuf_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_fill_rect), MP_OBJ_FROM_PTR(&framebuf_fill_rect_obj) };
framebuf_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_pixel), MP_OBJ_FROM_PTR(&framebuf_pixel_obj) };
framebuf_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_hline), MP_OBJ_FROM_PTR(&framebuf_hline_obj) };
framebuf_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_vline), MP_OBJ_FROM_PTR(&framebuf_vline_obj) };
framebuf_locals_dict_table[5] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_rect), MP_OBJ_FROM_PTR(&framebuf_rect_obj) };
framebuf_locals_dict_table[6] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_line), MP_OBJ_FROM_PTR(&framebuf_line_obj) };
framebuf_locals_dict_table[7] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_blit), MP_OBJ_FROM_PTR(&framebuf_blit_obj) };
framebuf_locals_dict_table[8] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_scroll), MP_OBJ_FROM_PTR(&framebuf_scroll_obj) };
framebuf_locals_dict_table[9] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_text), MP_OBJ_FROM_PTR(&framebuf_text_obj) };
mp_type_framebuf.locals_dict = (void*)&framebuf_locals_dict;
mp_store_global(MP_QSTR_FrameBuffer, MP_OBJ_FROM_PTR(&mp_type_framebuf));
mp_store_global(MP_QSTR_FrameBuffer1, MP_OBJ_FROM_PTR(&legacy_framebuffer1_obj));
mp_store_global(MP_QSTR_MVLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
mp_store_global(MP_QSTR_MONO_VLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB));
mp_store_global(MP_QSTR_RGB565, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565));
mp_store_global(MP_QSTR_GS2_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS2_HMSB));
mp_store_global(MP_QSTR_GS4_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB));
mp_store_global(MP_QSTR_GS8, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS8));
mp_store_global(MP_QSTR_MONO_HLSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB));
mp_store_global(MP_QSTR_MONO_HMSB, MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB));
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,13 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module (different to built-in uheapq so it can coexist)
MOD = uheapq_$(ARCH)
# Source files (.c or .py)
SRC = uheapq.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,16 +0,0 @@
#define MICROPY_PY_UHEAPQ (1)
#include "py/dynruntime.h"
#include "extmod/moduheapq.c"
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uheapq));
mp_store_global(MP_QSTR_heappush, MP_OBJ_FROM_PTR(&mod_uheapq_heappush_obj));
mp_store_global(MP_QSTR_heappop, MP_OBJ_FROM_PTR(&mod_uheapq_heappop_obj));
mp_store_global(MP_QSTR_heapify, MP_OBJ_FROM_PTR(&mod_uheapq_heapify_obj));
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,13 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module (different to built-in urandom so it can coexist)
MOD = urandom_$(ARCH)
# Source files (.c or .py)
SRC = urandom.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,33 +0,0 @@
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_URANDOM_EXTRA_FUNCS (1)
#include "py/dynruntime.h"
// Dynamic native modules don't support a data section so these must go in the BSS
uint32_t yasmarang_pad, yasmarang_n, yasmarang_d;
uint8_t yasmarang_dat;
#include "extmod/modurandom.c"
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
yasmarang_pad = 0xeda4baba;
yasmarang_n = 69;
yasmarang_d = 233;
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_urandom));
mp_store_global(MP_QSTR_getrandbits, MP_OBJ_FROM_PTR(&mod_urandom_getrandbits_obj));
mp_store_global(MP_QSTR_seed, MP_OBJ_FROM_PTR(&mod_urandom_seed_obj));
#if MICROPY_PY_URANDOM_EXTRA_FUNCS
mp_store_global(MP_QSTR_randrange, MP_OBJ_FROM_PTR(&mod_urandom_randrange_obj));
mp_store_global(MP_QSTR_randint, MP_OBJ_FROM_PTR(&mod_urandom_randint_obj));
mp_store_global(MP_QSTR_choice, MP_OBJ_FROM_PTR(&mod_urandom_choice_obj));
#if MICROPY_PY_BUILTINS_FLOAT
mp_store_global(MP_QSTR_random, MP_OBJ_FROM_PTR(&mod_urandom_random_obj));
mp_store_global(MP_QSTR_uniform, MP_OBJ_FROM_PTR(&mod_urandom_uniform_obj));
#endif
#endif
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,13 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module (different to built-in ure so it can coexist)
MOD = ure_$(ARCH)
# Source files (.c or .py)
SRC = ure.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,78 +0,0 @@
#define MICROPY_STACK_CHECK (1)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_URE_MATCH_GROUPS (1)
#define MICROPY_PY_URE_MATCH_SPAN_START_END (1)
#define MICROPY_PY_URE_SUB (0) // requires vstr interface
#include <alloca.h>
#include "py/dynruntime.h"
#define STACK_LIMIT (2048)
const char *stack_top;
void mp_stack_check(void) {
// Assumes descending stack on target
volatile char dummy;
if (stack_top - &dummy >= STACK_LIMIT) {
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("maximum recursion depth exceeded"));
}
}
#if !defined(__linux__)
void *memcpy(void *dst, const void *src, size_t n) {
return mp_fun_table.memmove_(dst, src, n);
}
void *memset(void *s, int c, size_t n) {
return mp_fun_table.memset_(s, c, n);
}
#endif
void *memmove(void *dest, const void *src, size_t n) {
return mp_fun_table.memmove_(dest, src, n);
}
mp_obj_type_t match_type;
mp_obj_type_t re_type;
#include "extmod/modure.c"
mp_map_elem_t match_locals_dict_table[5];
STATIC MP_DEFINE_CONST_DICT(match_locals_dict, match_locals_dict_table);
mp_map_elem_t re_locals_dict_table[3];
STATIC MP_DEFINE_CONST_DICT(re_locals_dict, re_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
char dummy;
stack_top = &dummy;
// Because MP_QSTR_start/end/split are static, xtensa and xtensawin will make a small data section
// to copy in this key/value pair if they are specified as a struct, so assign them separately.
match_type.base.type = (void*)&mp_fun_table.type_type;
match_type.name = MP_QSTR_match;
match_type.print = match_print;
match_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_group), MP_OBJ_FROM_PTR(&match_group_obj) };
match_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_groups), MP_OBJ_FROM_PTR(&match_groups_obj) };
match_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_span), MP_OBJ_FROM_PTR(&match_span_obj) };
match_locals_dict_table[3] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_start), MP_OBJ_FROM_PTR(&match_start_obj) };
match_locals_dict_table[4] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_OBJ_FROM_PTR(&match_end_obj) };
match_type.locals_dict = (void*)&match_locals_dict;
re_type.base.type = (void*)&mp_fun_table.type_type;
re_type.name = MP_QSTR_ure;
re_type.print = re_print;
re_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_match), MP_OBJ_FROM_PTR(&re_match_obj) };
re_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_search), MP_OBJ_FROM_PTR(&re_search_obj) };
re_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_split), MP_OBJ_FROM_PTR(&re_split_obj) };
re_type.locals_dict = (void*)&re_locals_dict;
mp_store_global(MP_QSTR_compile, MP_OBJ_FROM_PTR(&mod_re_compile_obj));
mp_store_global(MP_QSTR_match, MP_OBJ_FROM_PTR(&re_match_obj));
mp_store_global(MP_QSTR_search, MP_OBJ_FROM_PTR(&re_search_obj));
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,13 +0,0 @@
# Location of top-level MicroPython directory
MPY_DIR = ../../..
# Name of module (different to built-in uzlib so it can coexist)
MOD = uzlib_$(ARCH)
# Source files (.c or .py)
SRC = uzlib.c
# Architecture to build for (x86, x64, armv7m, xtensa, xtensawin)
ARCH = x64
include $(MPY_DIR)/py/dynruntime.mk

View File

@ -1,40 +0,0 @@
#define MICROPY_PY_UZLIB (1)
#include "py/dynruntime.h"
#if !defined(__linux__)
void *memset(void *s, int c, size_t n) {
return mp_fun_table.memset_(s, c, n);
}
#endif
mp_obj_full_type_t decompio_type;
mp_stream_p_t decompio_stream_p;
#include "extmod/moduzlib.c"
mp_map_elem_t decompio_locals_dict_table[3];
STATIC MP_DEFINE_CONST_DICT(decompio_locals_dict, decompio_locals_dict_table);
mp_obj_t mpy_init(mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, mp_obj_t *args) {
MP_DYNRUNTIME_INIT_ENTRY
decompio_stream_p.name = MP_QSTR_protocol_stream;
decompio_stream_p.read = decompio_read;
decompio_type.base.type = mp_fun_table.type_type;
decompio_type.flags = MP_TYPE_FLAG_EXTENDED;
decompio_type.name = MP_QSTR_DecompIO;
decompio_type.make_new = decompio_make_new;
decompio_type.ext[0].protocol = &decompio_stream_p;
decompio_locals_dict_table[0] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_read), MP_OBJ_FROM_PTR(&mp_stream_read_obj) };
decompio_locals_dict_table[1] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), MP_OBJ_FROM_PTR(&mp_stream_readinto_obj) };
decompio_locals_dict_table[2] = (mp_map_elem_t){ MP_OBJ_NEW_QSTR(MP_QSTR_readline), MP_OBJ_FROM_PTR(&mp_stream_unbuffered_readline_obj) };
decompio_type.locals_dict = (void*)&decompio_locals_dict;
mp_store_global(MP_QSTR___name__, MP_OBJ_NEW_QSTR(MP_QSTR_uzlib));
mp_store_global(MP_QSTR_decompress, MP_OBJ_FROM_PTR(&mod_uzlib_decompress_obj));
mp_store_global(MP_QSTR_DecompIO, MP_OBJ_FROM_PTR(&decompio_type));
MP_DYNRUNTIME_INIT_EXIT
}

View File

@ -1,37 +0,0 @@
// Include MicroPython API.
#include "py/runtime.h"
// This is the function which will be called from Python as cexample.add_ints(a, b).
STATIC mp_obj_t example_add_ints(mp_obj_t a_obj, mp_obj_t b_obj) {
// Extract the ints from the micropython input objects.
int a = mp_obj_get_int(a_obj);
int b = mp_obj_get_int(b_obj);
// Calculate the addition and convert to MicroPython object.
return mp_obj_new_int(a + b);
}
// Define a Python reference to the function above.
STATIC MP_DEFINE_CONST_FUN_OBJ_2(example_add_ints_obj, example_add_ints);
// Define all properties of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
// optimized to word-sized integers by the build system (interned strings).
STATIC const mp_rom_map_elem_t example_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cexample) },
{ MP_ROM_QSTR(MP_QSTR_add_ints), MP_ROM_PTR(&example_add_ints_obj) },
};
STATIC MP_DEFINE_CONST_DICT(example_module_globals, example_module_globals_table);
// Define module object.
const mp_obj_module_t example_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&example_module_globals,
};
// Register the module to make it available in Python.
// Note: the "1" in the third argument means this module is always enabled.
// This "1" can be optionally replaced with a macro like MODULE_CEXAMPLE_ENABLED
// which can then be used to conditionally enable this module.
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1);

View File

@ -1,15 +0,0 @@
# Create an INTERFACE library for our C module.
add_library(usermod_cexample INTERFACE)
# Add our source files to the lib
target_sources(usermod_cexample INTERFACE
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
)
# Add the current directory as an include directory.
target_include_directories(usermod_cexample INTERFACE
${CMAKE_CURRENT_LIST_DIR}
)
# Link our INTERFACE library to the usermod target.
target_link_libraries(usermod INTERFACE usermod_cexample)

View File

@ -1,9 +0,0 @@
EXAMPLE_MOD_DIR := $(USERMOD_DIR)
# Add all C files to SRC_USERMOD.
SRC_USERMOD += $(EXAMPLE_MOD_DIR)/examplemodule.c
# We can add our module folder to include paths if needed
# This is not actually needed in this example.
CFLAGS_USERMOD += -I$(EXAMPLE_MOD_DIR)
CEXAMPLE_MOD_DIR := $(USERMOD_DIR)

View File

@ -1,17 +0,0 @@
extern "C" {
#include <examplemodule.h>
// Here we implement the function using C++ code, but since it's
// declaration has to be compatible with C everything goes in extern "C" scope.
mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj) {
// Prove we have (at least) C++11 features.
const auto a = mp_obj_get_int(a_obj);
const auto b = mp_obj_get_int(b_obj);
const auto sum = [&]() {
return mp_obj_new_int(a + b);
} ();
// Prove we're being scanned for QSTRs.
mp_obj_t tup[] = {sum, MP_ROM_QSTR(MP_QSTR_hellocpp)};
return mp_obj_new_tuple(2, tup);
}
}

View File

@ -1,28 +0,0 @@
#include <examplemodule.h>
// Define a Python reference to the function we'll make available.
// See example.cpp for the definition.
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cppfunc_obj, cppfunc);
// Define all properties of the module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
// optimized to word-sized integers by the build system (interned strings).
STATIC const mp_rom_map_elem_t cppexample_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_cppexample) },
{ MP_ROM_QSTR(MP_QSTR_cppfunc), MP_ROM_PTR(&cppfunc_obj) },
};
STATIC MP_DEFINE_CONST_DICT(cppexample_module_globals, cppexample_module_globals_table);
// Define module object.
const mp_obj_module_t cppexample_user_cmodule = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&cppexample_module_globals,
};
// Register the module to make it available in Python.
// Note: the "1" in the third argument means this module is always enabled.
// This "1" can be optionally replaced with a macro like MODULE_CPPEXAMPLE_ENABLED
// which can then be used to conditionally enable this module.
MP_REGISTER_MODULE(MP_QSTR_cppexample, cppexample_user_cmodule, 1);

View File

@ -1,5 +0,0 @@
// Include MicroPython API.
#include "py/runtime.h"
// Declare the function we'll make available in Python as cppexample.cppfunc().
extern mp_obj_t cppfunc(mp_obj_t a_obj, mp_obj_t b_obj);

View File

@ -1,16 +0,0 @@
# Create an INTERFACE library for our CPP module.
add_library(usermod_cppexample INTERFACE)
# Add our source files to the library.
target_sources(usermod_cppexample INTERFACE
${CMAKE_CURRENT_LIST_DIR}/example.cpp
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
)
# Add the current directory as an include directory.
target_include_directories(usermod_cppexample INTERFACE
${CMAKE_CURRENT_LIST_DIR}
)
# Link our INTERFACE library to the usermod target.
target_link_libraries(usermod INTERFACE usermod_cppexample)

View File

@ -1,12 +0,0 @@
CPPEXAMPLE_MOD_DIR := $(USERMOD_DIR)
# Add our source files to the respective variables.
SRC_USERMOD += $(CPPEXAMPLE_MOD_DIR)/examplemodule.c
SRC_USERMOD_CXX += $(CPPEXAMPLE_MOD_DIR)/example.cpp
# Add our module directory to the include path.
CFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR)
CXXFLAGS_USERMOD += -I$(CPPEXAMPLE_MOD_DIR)
# We use C++ features so have to link against the standard library.
LDFLAGS_USERMOD += -lstdc++

View File

@ -1,10 +0,0 @@
# This top-level micropython.cmake is responsible for listing
# the individual modules we want to include.
# Paths are absolute, and ${CMAKE_CURRENT_LIST_DIR} can be
# used to prefix subdirectories.
# Add the C example.
include(${CMAKE_CURRENT_LIST_DIR}/cexample/micropython.cmake)
# Add the CPP example.
include(${CMAKE_CURRENT_LIST_DIR}/cppexample/micropython.cmake)

View File

@ -26,7 +26,11 @@
#ifndef AXTLS_OS_PORT_H #ifndef AXTLS_OS_PORT_H
#define AXTLS_OS_PORT_H #define AXTLS_OS_PORT_H
#ifndef __ets__
#include <arpa/inet.h>
#endif
#include <errno.h> #include <errno.h>
#include <sys/time.h>
#include "py/stream.h" #include "py/stream.h"
#include "lib/crypto-algorithms/sha256.h" #include "lib/crypto-algorithms/sha256.h"

View File

@ -1,98 +0,0 @@
# CMake fragment for MicroPython extmod component
set(MICROPY_EXTMOD_DIR "${MICROPY_DIR}/extmod")
set(MICROPY_OOFATFS_DIR "${MICROPY_DIR}/lib/oofatfs")
set(MICROPY_SOURCE_EXTMOD
${MICROPY_DIR}/shared/libc/abort_.c
${MICROPY_DIR}/shared/libc/printf.c
${MICROPY_EXTMOD_DIR}/machine_bitstream.c
${MICROPY_EXTMOD_DIR}/machine_i2c.c
${MICROPY_EXTMOD_DIR}/machine_mem.c
${MICROPY_EXTMOD_DIR}/machine_pulse.c
${MICROPY_EXTMOD_DIR}/machine_pwm.c
${MICROPY_EXTMOD_DIR}/machine_signal.c
${MICROPY_EXTMOD_DIR}/machine_spi.c
${MICROPY_EXTMOD_DIR}/modbluetooth.c
${MICROPY_EXTMOD_DIR}/modbtree.c
${MICROPY_EXTMOD_DIR}/modframebuf.c
${MICROPY_EXTMOD_DIR}/modnetwork.c
${MICROPY_EXTMOD_DIR}/modonewire.c
${MICROPY_EXTMOD_DIR}/moduasyncio.c
${MICROPY_EXTMOD_DIR}/modubinascii.c
${MICROPY_EXTMOD_DIR}/moducryptolib.c
${MICROPY_EXTMOD_DIR}/moductypes.c
${MICROPY_EXTMOD_DIR}/moduhashlib.c
${MICROPY_EXTMOD_DIR}/moduheapq.c
${MICROPY_EXTMOD_DIR}/modujson.c
${MICROPY_EXTMOD_DIR}/moduplatform.c
${MICROPY_EXTMOD_DIR}/modurandom.c
${MICROPY_EXTMOD_DIR}/modure.c
${MICROPY_EXTMOD_DIR}/moduselect.c
${MICROPY_EXTMOD_DIR}/modusocket.c
${MICROPY_EXTMOD_DIR}/modussl_axtls.c
${MICROPY_EXTMOD_DIR}/modussl_mbedtls.c
${MICROPY_EXTMOD_DIR}/modutimeq.c
${MICROPY_EXTMOD_DIR}/moduwebsocket.c
${MICROPY_EXTMOD_DIR}/moduzlib.c
${MICROPY_EXTMOD_DIR}/modwebrepl.c
${MICROPY_EXTMOD_DIR}/uos_dupterm.c
${MICROPY_EXTMOD_DIR}/utime_mphal.c
${MICROPY_EXTMOD_DIR}/vfs.c
${MICROPY_EXTMOD_DIR}/vfs_blockdev.c
${MICROPY_EXTMOD_DIR}/vfs_fat.c
${MICROPY_EXTMOD_DIR}/vfs_fat_diskio.c
${MICROPY_EXTMOD_DIR}/vfs_fat_file.c
${MICROPY_EXTMOD_DIR}/vfs_lfs.c
${MICROPY_EXTMOD_DIR}/vfs_posix.c
${MICROPY_EXTMOD_DIR}/vfs_posix_file.c
${MICROPY_EXTMOD_DIR}/vfs_reader.c
${MICROPY_EXTMOD_DIR}/virtpin.c
${MICROPY_EXTMOD_DIR}/nimble/modbluetooth_nimble.c
)
# Library for btree module and associated code
set(MICROPY_LIB_BERKELEY_DIR "${MICROPY_DIR}/lib/berkeley-db-1.xx")
if(EXISTS "${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c")
add_library(micropy_extmod_btree OBJECT
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_close.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_conv.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_debug.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_delete.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_get.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_open.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_overflow.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_page.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_put.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_search.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_seq.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_split.c
${MICROPY_LIB_BERKELEY_DIR}/btree/bt_utils.c
${MICROPY_LIB_BERKELEY_DIR}/mpool/mpool.c
)
target_include_directories(micropy_extmod_btree PRIVATE
${MICROPY_LIB_BERKELEY_DIR}/PORT/include
)
target_compile_definitions(micropy_extmod_btree PRIVATE
__DBINTERFACE_PRIVATE=1
mpool_error=printf
abort=abort_
"virt_fd_t=void*"
)
# The include directories and compile definitions below are needed to build
# modbtree.c and should be added to the main MicroPython target.
list(APPEND MICROPY_INC_CORE
"${MICROPY_LIB_BERKELEY_DIR}/PORT/include"
)
list(APPEND MICROPY_DEF_CORE
__DBINTERFACE_PRIVATE=1
"virt_fd_t=void*"
)
endif()

View File

@ -28,8 +28,6 @@ SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
lfs1.c \ lfs1.c \
lfs1_util.c \ lfs1_util.c \
) )
else
CFLAGS_MOD += -DMICROPY_VFS_LFS1=0
endif endif
ifeq ($(MICROPY_VFS_LFS2),1) ifeq ($(MICROPY_VFS_LFS2),1)
@ -39,8 +37,6 @@ SRC_MOD += $(addprefix $(LITTLEFS_DIR)/,\
lfs2.c \ lfs2.c \
lfs2_util.c \ lfs2_util.c \
) )
else
CFLAGS_MOD += -DMICROPY_VFS_LFS2=0
$(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-missing-field-initializers $(BUILD)/$(LITTLEFS_DIR)/lfs2.o: CFLAGS += -Wno-missing-field-initializers
endif endif
@ -232,3 +228,4 @@ CFLAGS_MOD += -DMICROPY_PY_BTREE=1
$(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS) $(BUILD)/$(BTREE_DIR)/%.o: CFLAGS += -Wno-old-style-definition -Wno-sign-compare -Wno-unused-parameter $(BTREE_DEFS)
$(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS) $(BUILD)/extmod/modbtree.o: CFLAGS += $(BTREE_DEFS)
endif endif

View File

@ -1,8 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* 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.
*/
#ifndef MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H #ifndef MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H
#define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H #define MICROPY_INCLUDED_STM32_FONT_PETME128_8X8_H

View File

@ -1,367 +0,0 @@
// Copyright (c) 2016 Paul Sokolovsky
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
//
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <string.h>
#include <errno.h> // for declaration of global errno variable
#include <fcntl.h>
#include "py/runtime.h"
#include "py/stream.h"
#if MICROPY_PY_BTREE
#include <db.h>
#include <../../btree/btree.h>
typedef struct _mp_obj_btree_t {
mp_obj_base_t base;
mp_obj_t stream; // retain a reference to prevent GC from reclaiming it
DB *db;
mp_obj_t start_key;
mp_obj_t end_key;
#define FLAG_END_KEY_INCL 1
#define FLAG_DESC 2
#define FLAG_ITER_TYPE_MASK 0xc0
#define FLAG_ITER_KEYS 0x40
#define FLAG_ITER_VALUES 0x80
#define FLAG_ITER_ITEMS 0xc0
byte flags;
byte next_flags;
} mp_obj_btree_t;
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_obj_type_t btree_type;
#endif
#define CHECK_ERROR(res) \
if (res == RET_ERROR) { \
mp_raise_OSError(errno); \
}
void __dbpanic(DB *db) {
mp_printf(&mp_plat_print, "__dbpanic(%p)\n", db);
}
STATIC mp_obj_btree_t *btree_new(DB *db, mp_obj_t stream) {
mp_obj_btree_t *o = m_new_obj(mp_obj_btree_t);
o->base.type = (mp_obj_type_t *)&btree_type;
o->stream = stream;
o->db = db;
o->start_key = mp_const_none;
o->end_key = mp_const_none;
o->next_flags = 0;
return o;
}
STATIC void btree_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "<btree %p>", self->db);
}
STATIC mp_obj_t btree_flush(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(__bt_sync(self->db, 0));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(btree_flush_obj, btree_flush);
STATIC mp_obj_t btree_close(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(__bt_close(self->db));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(btree_close_obj, btree_close);
STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
DBT key, val;
key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
val.data = (void *)mp_obj_str_get_data(args[2], &val.size);
return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
DBT key, val;
key.data = (void *)mp_obj_str_get_data(args[1], &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
if (n_args > 2) {
return args[2];
} else {
return mp_const_none;
}
}
CHECK_ERROR(res);
return mp_obj_new_bytes(val.data, val.size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_get_obj, 2, 3, btree_get);
STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
DBT key, val;
if (n_args > 2) {
key.data = (void *)mp_obj_str_get_data(args[2], &key.size);
}
int res = __bt_seq(self->db, &key, &val, flags);
CHECK_ERROR(res);
if (res == RET_SPECIAL) {
return mp_const_none;
}
mp_obj_t pair_o = mp_obj_new_tuple(2, NULL);
mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(pair_o);
pair->items[0] = mp_obj_new_bytes(key.data, key.size);
pair->items[1] = mp_obj_new_bytes(val.data, val.size);
return pair_o;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_seq_obj, 2, 4, btree_seq);
STATIC mp_obj_t btree_init_iter(size_t n_args, const mp_obj_t *args, byte type) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
self->next_flags = type;
self->start_key = mp_const_none;
self->end_key = mp_const_none;
if (n_args > 1) {
self->start_key = args[1];
if (n_args > 2) {
self->end_key = args[2];
if (n_args > 3) {
self->next_flags = type | MP_OBJ_SMALL_INT_VALUE(args[3]);
}
}
}
return args[0];
}
STATIC mp_obj_t btree_keys(size_t n_args, const mp_obj_t *args) {
return btree_init_iter(n_args, args, FLAG_ITER_KEYS);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_keys_obj, 1, 4, btree_keys);
STATIC mp_obj_t btree_values(size_t n_args, const mp_obj_t *args) {
return btree_init_iter(n_args, args, FLAG_ITER_VALUES);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_values_obj, 1, 4, btree_values);
STATIC mp_obj_t btree_items(size_t n_args, const mp_obj_t *args) {
return btree_init_iter(n_args, args, FLAG_ITER_ITEMS);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_items_obj, 1, 4, btree_items);
STATIC mp_obj_t btree_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
(void)iter_buf;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
if (self->next_flags != 0) {
// If we're called immediately after keys(), values(), or items(),
// use their setup for iteration.
self->flags = self->next_flags;
self->next_flags = 0;
} else {
// Otherwise, iterate over all keys.
self->flags = FLAG_ITER_KEYS;
self->start_key = mp_const_none;
self->end_key = mp_const_none;
}
return self_in;
}
STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
DBT key, val;
int res;
bool desc = self->flags & FLAG_DESC;
if (self->start_key != MP_OBJ_NULL) {
int flags = R_FIRST;
if (self->start_key != mp_const_none) {
key.data = (void *)mp_obj_str_get_data(self->start_key, &key.size);
flags = R_CURSOR;
} else if (desc) {
flags = R_LAST;
}
res = __bt_seq(self->db, &key, &val, flags);
self->start_key = MP_OBJ_NULL;
} else {
res = __bt_seq(self->db, &key, &val, desc ? R_PREV : R_NEXT);
}
if (res == RET_SPECIAL) {
return MP_OBJ_STOP_ITERATION;
}
CHECK_ERROR(res);
if (self->end_key != mp_const_none) {
DBT end_key;
end_key.data = (void *)mp_obj_str_get_data(self->end_key, &end_key.size);
BTREE *t = self->db->internal;
int cmp = t->bt_cmp(&key, &end_key);
if (desc) {
cmp = -cmp;
}
if (self->flags & FLAG_END_KEY_INCL) {
cmp--;
}
if (cmp >= 0) {
self->end_key = MP_OBJ_NULL;
return MP_OBJ_STOP_ITERATION;
}
}
switch (self->flags & FLAG_ITER_TYPE_MASK) {
case FLAG_ITER_KEYS:
return mp_obj_new_bytes(key.data, key.size);
case FLAG_ITER_VALUES:
return mp_obj_new_bytes(val.data, val.size);
default: {
mp_obj_t pair_o = mp_obj_new_tuple(2, NULL);
mp_obj_tuple_t *pair = MP_OBJ_TO_PTR(pair_o);
pair->items[0] = mp_obj_new_bytes(key.data, key.size);
pair->items[1] = mp_obj_new_bytes(val.data, val.size);
return pair_o;
}
}
}
STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_btree_t *self = mp_obj_cast_to_native_base(self_in, &btree_type);
if (value == MP_OBJ_NULL) {
// delete
DBT key;
key.data = (void *)mp_obj_str_get_data(index, &key.size);
int res = __bt_delete(self->db, &key, 0);
if (res == RET_SPECIAL) {
mp_raise_type(&mp_type_KeyError);
}
CHECK_ERROR(res);
return mp_const_none;
} else if (value == MP_OBJ_SENTINEL) {
// load
DBT key, val;
key.data = (void *)mp_obj_str_get_data(index, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
mp_raise_type(&mp_type_KeyError);
}
CHECK_ERROR(res);
return mp_obj_new_bytes(val.data, val.size);
} else {
// store
DBT key, val;
key.data = (void *)mp_obj_str_get_data(index, &key.size);
val.data = (void *)mp_obj_str_get_data(value, &val.size);
int res = __bt_put(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_const_none;
}
}
STATIC mp_obj_t btree_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
case MP_BINARY_OP_CONTAINS: {
DBT key, val;
key.data = (void *)mp_obj_str_get_data(rhs_in, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_obj_new_bool(res != RET_SPECIAL);
}
default:
// op not supported
return MP_OBJ_NULL;
}
}
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t btree_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&btree_close_obj) },
{ MP_ROM_QSTR(MP_QSTR_flush), MP_ROM_PTR(&btree_flush_obj) },
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&btree_get_obj) },
{ MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&btree_put_obj) },
{ MP_ROM_QSTR(MP_QSTR_seq), MP_ROM_PTR(&btree_seq_obj) },
{ MP_ROM_QSTR(MP_QSTR_keys), MP_ROM_PTR(&btree_keys_obj) },
{ MP_ROM_QSTR(MP_QSTR_values), MP_ROM_PTR(&btree_values_obj) },
{ MP_ROM_QSTR(MP_QSTR_items), MP_ROM_PTR(&btree_items_obj) },
};
STATIC MP_DEFINE_CONST_DICT(btree_locals_dict, btree_locals_dict_table);
STATIC const mp_obj_type_t btree_type = {
{ &mp_type_type },
// Save on qstr's, reuse same as for module
.flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_btree,
.print = btree_print,
.locals_dict = (void *)&btree_locals_dict,
MP_TYPE_EXTENDED_FIELDS(
.getiter = btree_getiter,
.iternext = btree_iternext,
.binary_op = btree_binary_op,
.subscr = btree_subscr,
),
};
#endif
STATIC const FILEVTABLE btree_stream_fvtable = {
mp_stream_posix_read,
mp_stream_posix_write,
mp_stream_posix_lseek,
mp_stream_posix_fsync
};
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC mp_obj_t mod_btree_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_flags, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_cachesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_pagesize, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_minkeypage, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
};
// Make sure we got a stream object
mp_get_stream_raise(pos_args[0], MP_STREAM_OP_READ | MP_STREAM_OP_WRITE | MP_STREAM_OP_IOCTL);
struct {
mp_arg_val_t flags;
mp_arg_val_t cachesize;
mp_arg_val_t pagesize;
mp_arg_val_t minkeypage;
} args;
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t *)&args);
BTREEINFO openinfo = {0};
openinfo.flags = args.flags.u_int;
openinfo.cachesize = args.cachesize.u_int;
openinfo.psize = args.pagesize.u_int;
openinfo.minkeypage = args.minkeypage.u_int;
DB *db = __bt_open(MP_OBJ_TO_PTR(pos_args[0]), &btree_stream_fvtable, &openinfo, /*dflags*/ 0);
if (db == NULL) {
mp_raise_OSError(errno);
}
return MP_OBJ_FROM_PTR(btree_new(db, pos_args[0]));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_btree_open_obj, 1, mod_btree_open);
STATIC const mp_rom_map_elem_t mp_module_btree_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_btree) },
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mod_btree_open_obj) },
{ MP_ROM_QSTR(MP_QSTR_INCL), MP_ROM_INT(FLAG_END_KEY_INCL) },
{ MP_ROM_QSTR(MP_QSTR_DESC), MP_ROM_INT(FLAG_DESC) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_btree_globals, mp_module_btree_globals_table);
const mp_obj_module_t mp_module_btree = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_btree_globals,
};
#endif
#endif // MICROPY_PY_BTREE

View File

@ -1,667 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
//
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <string.h>
#include "py/runtime.h"
#include "py/objtype.h"
#include "py/proto.h"
#if MICROPY_PY_FRAMEBUF
#include "font_petme128_8x8.h"
typedef struct _mp_obj_framebuf_t {
mp_obj_base_t base;
mp_obj_t buf_obj; // need to store this to prevent GC from reclaiming buf
void *buf;
uint16_t width, height, stride;
uint8_t format;
} mp_obj_framebuf_t;
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_obj_type_t mp_type_framebuf;
#endif
typedef void (*setpixel_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int, uint32_t);
typedef uint32_t (*getpixel_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int);
typedef void (*fill_rect_t)(const mp_obj_framebuf_t *, unsigned int, unsigned int, unsigned int, unsigned int, uint32_t);
typedef struct _mp_framebuf_p_t {
setpixel_t setpixel;
getpixel_t getpixel;
fill_rect_t fill_rect;
} mp_framebuf_p_t;
// constants for formats
#define FRAMEBUF_MVLSB (0)
#define FRAMEBUF_RGB565 (1)
#define FRAMEBUF_GS2_HMSB (5)
#define FRAMEBUF_GS4_HMSB (2)
#define FRAMEBUF_GS8 (6)
#define FRAMEBUF_MHLSB (3)
#define FRAMEBUF_MHMSB (4)
// Functions for MHLSB and MHMSB
STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
size_t index = (x + y * fb->stride) >> 3;
unsigned int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
}
STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
size_t index = (x + y * fb->stride) >> 3;
unsigned int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
return (((uint8_t *)fb->buf)[index] >> (offset)) & 0x01;
}
STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
unsigned int reverse = fb->format == FRAMEBUF_MHMSB;
unsigned int advance = fb->stride >> 3;
while (w--) {
uint8_t *b = &((uint8_t *)fb->buf)[(x >> 3) + y * advance];
unsigned int offset = reverse ? x & 7 : 7 - (x & 7);
for (unsigned int hh = h; hh; --hh) {
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
b += advance;
}
++x;
}
}
// Functions for MVLSB format
STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
size_t index = (y >> 3) * fb->stride + x;
uint8_t offset = y & 0x07;
((uint8_t *)fb->buf)[index] = (((uint8_t *)fb->buf)[index] & ~(0x01 << offset)) | ((col != 0) << offset);
}
STATIC uint32_t mvlsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
return (((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x] >> (y & 0x07)) & 0x01;
}
STATIC void mvlsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
while (h--) {
uint8_t *b = &((uint8_t *)fb->buf)[(y >> 3) * fb->stride + x];
uint8_t offset = y & 0x07;
for (unsigned int ww = w; ww; --ww) {
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
++b;
}
++y;
}
}
// Functions for RGB565 format
STATIC void rgb565_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
((uint16_t *)fb->buf)[x + y * fb->stride] = col;
}
STATIC uint32_t rgb565_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
return ((uint16_t *)fb->buf)[x + y * fb->stride];
}
STATIC void rgb565_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
uint16_t *b = &((uint16_t *)fb->buf)[x + y * fb->stride];
while (h--) {
for (unsigned int ww = w; ww; --ww) {
*b++ = col;
}
b += fb->stride - w;
}
}
// Functions for GS2_HMSB format
STATIC void gs2_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
uint8_t shift = (x & 0x3) << 1;
uint8_t mask = 0x3 << shift;
uint8_t color = (col & 0x3) << shift;
*pixel = color | (*pixel & (~mask));
}
STATIC uint32_t gs2_hmsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
uint8_t pixel = ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 2];
uint8_t shift = (x & 0x3) << 1;
return (pixel >> shift) & 0x3;
}
STATIC void gs2_hmsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
for (unsigned int xx = x; xx < x + w; xx++) {
for (unsigned int yy = y; yy < y + h; yy++) {
gs2_hmsb_setpixel(fb, xx, yy, col);
}
}
}
// Functions for GS4_HMSB format
STATIC void gs4_hmsb_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
if (x % 2) {
*pixel = ((uint8_t)col & 0x0f) | (*pixel & 0xf0);
} else {
*pixel = ((uint8_t)col << 4) | (*pixel & 0x0f);
}
}
STATIC uint32_t gs4_hmsb_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
if (x % 2) {
return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] & 0x0f;
}
return ((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1] >> 4;
}
STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
col &= 0x0f;
uint8_t *pixel_pair = &((uint8_t *)fb->buf)[(x + y * fb->stride) >> 1];
uint8_t col_shifted_left = col << 4;
uint8_t col_pixel_pair = col_shifted_left | col;
unsigned int pixel_count_till_next_line = (fb->stride - w) >> 1;
bool odd_x = (x % 2 == 1);
while (h--) {
unsigned int ww = w;
if (odd_x && ww > 0) {
*pixel_pair = (*pixel_pair & 0xf0) | col;
pixel_pair++;
ww--;
}
memset(pixel_pair, col_pixel_pair, ww >> 1);
pixel_pair += ww >> 1;
if (ww % 2) {
*pixel_pair = col_shifted_left | (*pixel_pair & 0x0f);
if (!odd_x) {
pixel_pair++;
}
}
pixel_pair += pixel_count_till_next_line;
}
}
// Functions for GS8 format
STATIC void gs8_setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
*pixel = col & 0xff;
}
STATIC uint32_t gs8_getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
return ((uint8_t *)fb->buf)[(x + y * fb->stride)];
}
STATIC void gs8_fill_rect(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, unsigned int w, unsigned int h, uint32_t col) {
uint8_t *pixel = &((uint8_t *)fb->buf)[(x + y * fb->stride)];
while (h--) {
memset(pixel, col, w);
pixel += fb->stride;
}
}
STATIC const mp_framebuf_p_t formats[] = {
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
[FRAMEBUF_GS2_HMSB] = {gs2_hmsb_setpixel, gs2_hmsb_getpixel, gs2_hmsb_fill_rect},
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
[FRAMEBUF_GS8] = {gs8_setpixel, gs8_getpixel, gs8_fill_rect},
[FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
[FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
};
static inline void setpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y, uint32_t col) {
formats[fb->format].setpixel(fb, x, y, col);
}
static inline uint32_t getpixel(const mp_obj_framebuf_t *fb, unsigned int x, unsigned int y) {
return formats[fb->format].getpixel(fb, x, y);
}
STATIC void fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
if (h < 1 || w < 1 || x + w <= 0 || y + h <= 0 || y >= fb->height || x >= fb->width) {
// No operation needed.
return;
}
// clip to the framebuffer
int xend = MIN(fb->width, x + w);
int yend = MIN(fb->height, y + h);
x = MAX(x, 0);
y = MAX(y, 0);
formats[fb->format].fill_rect(fb, x, y, xend - x, yend - y, col);
}
STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 4, 5, false);
mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
o->base.type = type;
o->buf_obj = args[0];
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
o->width = mp_obj_get_int(args[1]);
o->height = mp_obj_get_int(args[2]);
o->format = mp_obj_get_int(args[3]);
if (n_args >= 5) {
o->stride = mp_obj_get_int(args[4]);
} else {
o->stride = o->width;
}
switch (o->format) {
case FRAMEBUF_MVLSB:
case FRAMEBUF_RGB565:
break;
case FRAMEBUF_MHLSB:
case FRAMEBUF_MHMSB:
o->stride = (o->stride + 7) & ~7;
break;
case FRAMEBUF_GS2_HMSB:
o->stride = (o->stride + 3) & ~3;
break;
case FRAMEBUF_GS4_HMSB:
o->stride = (o->stride + 1) & ~1;
break;
case FRAMEBUF_GS8:
break;
default:
mp_raise_ValueError(MP_ERROR_TEXT("invalid format"));
}
return MP_OBJ_FROM_PTR(o);
}
#if !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME)
STATIC const mp_obj_type_t mp_type_framebuf;
#endif
// Helper to ensure we have the native super class instead of a subclass.
static mp_obj_framebuf_t *native_framebuf(mp_obj_t framebuf_obj) {
mp_obj_t native_framebuf = mp_obj_cast_to_native_base(framebuf_obj, &mp_type_framebuf);
mp_obj_assert_native_inited(native_framebuf);
if (native_framebuf == MP_OBJ_NULL) {
mp_raise_TypeError(NULL);
}
return MP_OBJ_TO_PTR(native_framebuf);
}
STATIC mp_int_t framebuf_get_buffer(mp_obj_t self_in, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
(void)flags;
mp_obj_framebuf_t *self = native_framebuf(self_in);
bufinfo->buf = self->buf;
bufinfo->len = self->stride * self->height * (self->format == FRAMEBUF_RGB565 ? 2 : 1);
bufinfo->typecode = 'B'; // view framebuf as bytes
return 0;
}
STATIC mp_obj_t framebuf_fill(mp_obj_t self_in, mp_obj_t col_in) {
mp_obj_framebuf_t *self = native_framebuf(self_in);
mp_int_t col = mp_obj_get_int(col_in);
formats[self->format].fill_rect(self, 0, 0, self->width, self->height, col);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(framebuf_fill_obj, framebuf_fill);
STATIC mp_obj_t framebuf_fill_rect(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_int_t x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]);
mp_int_t width = mp_obj_get_int(args[3]);
mp_int_t height = mp_obj_get_int(args[4]);
mp_int_t col = mp_obj_get_int(args[5]);
fill_rect(self, x, y, width, height, col);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_fill_rect_obj, 6, 6, framebuf_fill_rect);
STATIC mp_obj_t framebuf_pixel(size_t n_args, const mp_obj_t *args) {
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_int_t x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]);
if (0 <= x && x < self->width && 0 <= y && y < self->height) {
if (n_args == 3) {
// get
return MP_OBJ_NEW_SMALL_INT(getpixel(self, x, y));
} else {
// set
setpixel(self, x, y, mp_obj_get_int(args[3]));
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_pixel_obj, 3, 4, framebuf_pixel);
STATIC mp_obj_t framebuf_hline(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_int_t x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]);
mp_int_t w = mp_obj_get_int(args[3]);
mp_int_t col = mp_obj_get_int(args[4]);
fill_rect(self, x, y, w, 1, col);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_hline_obj, 5, 5, framebuf_hline);
STATIC mp_obj_t framebuf_vline(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_int_t x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]);
mp_int_t h = mp_obj_get_int(args[3]);
mp_int_t col = mp_obj_get_int(args[4]);
fill_rect(self, x, y, 1, h, col);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_vline_obj, 5, 5, framebuf_vline);
STATIC mp_obj_t framebuf_rect(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_int_t x = mp_obj_get_int(args[1]);
mp_int_t y = mp_obj_get_int(args[2]);
mp_int_t w = mp_obj_get_int(args[3]);
mp_int_t h = mp_obj_get_int(args[4]);
mp_int_t col = mp_obj_get_int(args[5]);
fill_rect(self, x, y, w, 1, col);
fill_rect(self, x, y + h - 1, w, 1, col);
fill_rect(self, x, y, 1, h, col);
fill_rect(self, x + w - 1, y, 1, h, col);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_rect_obj, 6, 6, framebuf_rect);
STATIC mp_obj_t framebuf_line(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_int_t x1 = mp_obj_get_int(args[1]);
mp_int_t y1 = mp_obj_get_int(args[2]);
mp_int_t x2 = mp_obj_get_int(args[3]);
mp_int_t y2 = mp_obj_get_int(args[4]);
mp_int_t col = mp_obj_get_int(args[5]);
mp_int_t dx = x2 - x1;
mp_int_t sx;
if (dx > 0) {
sx = 1;
} else {
dx = -dx;
sx = -1;
}
mp_int_t dy = y2 - y1;
mp_int_t sy;
if (dy > 0) {
sy = 1;
} else {
dy = -dy;
sy = -1;
}
bool steep;
if (dy > dx) {
mp_int_t temp;
temp = x1;
x1 = y1;
y1 = temp;
temp = dx;
dx = dy;
dy = temp;
temp = sx;
sx = sy;
sy = temp;
steep = true;
} else {
steep = false;
}
mp_int_t e = 2 * dy - dx;
for (mp_int_t i = 0; i < dx; ++i) {
if (steep) {
if (0 <= y1 && y1 < self->width && 0 <= x1 && x1 < self->height) {
setpixel(self, y1, x1, col);
}
} else {
if (0 <= x1 && x1 < self->width && 0 <= y1 && y1 < self->height) {
setpixel(self, x1, y1, col);
}
}
while (e >= 0) {
y1 += sy;
e -= 2 * dx;
}
x1 += sx;
e += 2 * dy;
}
if (0 <= x2 && x2 < self->width && 0 <= y2 && y2 < self->height) {
setpixel(self, x2, y2, col);
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_line_obj, 6, 6, framebuf_line);
STATIC mp_obj_t framebuf_blit(size_t n_args, const mp_obj_t *args) {
mp_obj_framebuf_t *self = native_framebuf(args[0]);
mp_obj_framebuf_t *source = native_framebuf(args[1]);
mp_int_t x = mp_obj_get_int(args[2]);
mp_int_t y = mp_obj_get_int(args[3]);
mp_int_t key = -1;
if (n_args > 4) {
key = mp_obj_get_int(args[4]);
}
mp_obj_framebuf_t *palette = NULL;
if (n_args > 5 && args[5] != mp_const_none) {
palette = MP_OBJ_TO_PTR(mp_obj_cast_to_native_base(args[5], MP_OBJ_FROM_PTR(&mp_type_framebuf)));
}
if (
(x >= self->width) ||
(y >= self->height) ||
(-x >= source->width) ||
(-y >= source->height)
) {
// Out of bounds, no-op.
return mp_const_none;
}
// Clip.
int x0 = MAX(0, x);
int y0 = MAX(0, y);
int x1 = MAX(0, -x);
int y1 = MAX(0, -y);
int x0end = MIN(self->width, x + source->width);
int y0end = MIN(self->height, y + source->height);
for (; y0 < y0end; ++y0) {
int cx1 = x1;
for (int cx0 = x0; cx0 < x0end; ++cx0) {
uint32_t col = getpixel(source, cx1, y1);
if (palette) {
col = getpixel(palette, col, 0);
}
if (col != (uint32_t)key) {
setpixel(self, cx0, y0, col);
}
++cx1;
}
++y1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_blit_obj, 4, 6, framebuf_blit);
STATIC mp_obj_t framebuf_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t ystep_in) {
mp_obj_framebuf_t *self = native_framebuf(self_in);
mp_int_t xstep = mp_obj_get_int(xstep_in);
mp_int_t ystep = mp_obj_get_int(ystep_in);
int sx, y, xend, yend, dx, dy;
if (xstep < 0) {
sx = 0;
xend = self->width + xstep;
dx = 1;
} else {
sx = self->width - 1;
xend = xstep - 1;
dx = -1;
}
if (ystep < 0) {
y = 0;
yend = self->height + ystep;
dy = 1;
} else {
y = self->height - 1;
yend = ystep - 1;
dy = -1;
}
for (; y != yend; y += dy) {
for (int x = sx; x != xend; x += dx) {
setpixel(self, x, y, getpixel(self, x - xstep, y - ystep));
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf_scroll_obj, framebuf_scroll);
STATIC mp_obj_t framebuf_text(size_t n_args, const mp_obj_t *args) {
// extract arguments
mp_obj_framebuf_t *self = native_framebuf(args[0]);
const char *str = mp_obj_str_get_str(args[1]);
mp_int_t x0 = mp_obj_get_int(args[2]);
mp_int_t y0 = mp_obj_get_int(args[3]);
mp_int_t col = 1;
if (n_args >= 5) {
col = mp_obj_get_int(args[4]);
}
// loop over chars
for (; *str; ++str) {
// get char and make sure its in range of font
int chr = *(uint8_t *)str;
if (chr < 32 || chr > 127) {
chr = 127;
}
// get char data
const uint8_t *chr_data = &font_petme128_8x8[(chr - 32) * 8];
// loop over char data
for (int j = 0; j < 8; j++, x0++) {
if (0 <= x0 && x0 < self->width) { // clip x
uint vline_data = chr_data[j]; // each byte is a column of 8 pixels, LSB at top
for (int y = y0; vline_data; vline_data >>= 1, y++) { // scan over vertical column
if (vline_data & 1) { // only draw if pixel set
if (0 <= y && y < self->height) { // clip y
setpixel(self, x0, y, col);
}
}
}
}
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(framebuf_text_obj, 4, 5, framebuf_text);
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t framebuf_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&framebuf_fill_obj) },
{ MP_ROM_QSTR(MP_QSTR_fill_rect), MP_ROM_PTR(&framebuf_fill_rect_obj) },
{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&framebuf_pixel_obj) },
{ MP_ROM_QSTR(MP_QSTR_hline), MP_ROM_PTR(&framebuf_hline_obj) },
{ MP_ROM_QSTR(MP_QSTR_vline), MP_ROM_PTR(&framebuf_vline_obj) },
{ MP_ROM_QSTR(MP_QSTR_rect), MP_ROM_PTR(&framebuf_rect_obj) },
{ MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&framebuf_line_obj) },
{ MP_ROM_QSTR(MP_QSTR_blit), MP_ROM_PTR(&framebuf_blit_obj) },
{ MP_ROM_QSTR(MP_QSTR_scroll), MP_ROM_PTR(&framebuf_scroll_obj) },
{ MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&framebuf_text_obj) },
};
STATIC MP_DEFINE_CONST_DICT(framebuf_locals_dict, framebuf_locals_dict_table);
STATIC const mp_obj_type_t mp_type_framebuf = {
{ &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_FrameBuffer,
.make_new = framebuf_make_new,
.locals_dict = (mp_obj_dict_t *)&framebuf_locals_dict,
MP_TYPE_EXTENDED_FIELDS(
.buffer_p = { .get_buffer = framebuf_get_buffer },
),
};
#endif
// this factory function is provided for backwards compatibility with old FrameBuffer1 class
STATIC mp_obj_t legacy_framebuffer1(size_t n_args, const mp_obj_t *args) {
mp_obj_framebuf_t *o = m_new_obj(mp_obj_framebuf_t);
o->base.type = (mp_obj_type_t *)&mp_type_framebuf;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_WRITE);
o->buf = bufinfo.buf;
o->width = mp_obj_get_int(args[1]);
o->height = mp_obj_get_int(args[2]);
o->format = FRAMEBUF_MVLSB;
if (n_args >= 4) {
o->stride = mp_obj_get_int(args[3]);
} else {
o->stride = o->width;
}
return MP_OBJ_FROM_PTR(o);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(legacy_framebuffer1_obj, 3, 4, legacy_framebuffer1);
#if !MICROPY_ENABLE_DYNRUNTIME
STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_framebuf) },
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) },
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_ROM_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_ROM_INT(FRAMEBUF_RGB565) },
{ MP_ROM_QSTR(MP_QSTR_GS2_HMSB), MP_ROM_INT(FRAMEBUF_GS2_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_ROM_INT(FRAMEBUF_GS4_HMSB) },
{ MP_ROM_QSTR(MP_QSTR_GS8), MP_ROM_INT(FRAMEBUF_GS8) },
{ MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_ROM_INT(FRAMEBUF_MHLSB) },
{ MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_ROM_INT(FRAMEBUF_MHMSB) },
};
STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table);
const mp_obj_module_t mp_module_framebuf = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&framebuf_module_globals,
};
#endif
#endif // MICROPY_PY_FRAMEBUF

View File

@ -1,145 +0,0 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors)
// SPDX-FileCopyrightText: Copyright (c) 2015-2017 Damien P. George
//
// SPDX-License-Identifier: MIT
#include <stdio.h>
#include <stdint.h>
#include "py/obj.h"
#include "py/mphal.h"
#if MICROPY_PY_ONEWIRE
/******************************************************************************/
// Low-level 1-Wire routines
#define TIMING_RESET1 (480)
#define TIMING_RESET2 (70)
#define TIMING_RESET3 (410)
#define TIMING_READ1 (5)
#define TIMING_READ2 (5)
#define TIMING_READ3 (40)
#define TIMING_WRITE1 (10)
#define TIMING_WRITE2 (50)
#define TIMING_WRITE3 (10)
STATIC int onewire_bus_reset(mp_hal_pin_obj_t pin) {
mp_hal_pin_od_low(pin);
mp_hal_delay_us(TIMING_RESET1);
uint32_t i = mp_hal_quiet_timing_enter();
mp_hal_pin_od_high(pin);
mp_hal_delay_us_fast(TIMING_RESET2);
int status = !mp_hal_pin_read(pin);
mp_hal_quiet_timing_exit(i);
mp_hal_delay_us(TIMING_RESET3);
return status;
}
STATIC int onewire_bus_readbit(mp_hal_pin_obj_t pin) {
mp_hal_pin_od_high(pin);
uint32_t i = mp_hal_quiet_timing_enter();
mp_hal_pin_od_low(pin);
mp_hal_delay_us_fast(TIMING_READ1);
mp_hal_pin_od_high(pin);
mp_hal_delay_us_fast(TIMING_READ2);
int value = mp_hal_pin_read(pin);
mp_hal_quiet_timing_exit(i);
mp_hal_delay_us_fast(TIMING_READ3);
return value;
}
STATIC void onewire_bus_writebit(mp_hal_pin_obj_t pin, int value) {
uint32_t i = mp_hal_quiet_timing_enter();
mp_hal_pin_od_low(pin);
mp_hal_delay_us_fast(TIMING_WRITE1);
if (value) {
mp_hal_pin_od_high(pin);
}
mp_hal_delay_us_fast(TIMING_WRITE2);
mp_hal_pin_od_high(pin);
mp_hal_delay_us_fast(TIMING_WRITE3);
mp_hal_quiet_timing_exit(i);
}
/******************************************************************************/
// MicroPython bindings
STATIC mp_obj_t onewire_reset(mp_obj_t pin_in) {
return mp_obj_new_bool(onewire_bus_reset(mp_hal_get_pin_obj(pin_in)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_reset_obj, onewire_reset);
STATIC mp_obj_t onewire_readbit(mp_obj_t pin_in) {
return MP_OBJ_NEW_SMALL_INT(onewire_bus_readbit(mp_hal_get_pin_obj(pin_in)));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbit_obj, onewire_readbit);
STATIC mp_obj_t onewire_readbyte(mp_obj_t pin_in) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
uint8_t value = 0;
for (int i = 0; i < 8; ++i) {
value |= onewire_bus_readbit(pin) << i;
}
return MP_OBJ_NEW_SMALL_INT(value);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_readbyte_obj, onewire_readbyte);
STATIC mp_obj_t onewire_writebit(mp_obj_t pin_in, mp_obj_t value_in) {
onewire_bus_writebit(mp_hal_get_pin_obj(pin_in), mp_obj_get_int(value_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebit_obj, onewire_writebit);
STATIC mp_obj_t onewire_writebyte(mp_obj_t pin_in, mp_obj_t value_in) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_in);
int value = mp_obj_get_int(value_in);
for (int i = 0; i < 8; ++i) {
onewire_bus_writebit(pin, value & 1);
value >>= 1;
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(onewire_writebyte_obj, onewire_writebyte);
STATIC mp_obj_t onewire_crc8(mp_obj_t data) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ);
uint8_t crc = 0;
for (size_t i = 0; i < bufinfo.len; ++i) {
uint8_t byte = ((uint8_t *)bufinfo.buf)[i];
for (int b = 0; b < 8; ++b) {
uint8_t fb_bit = (crc ^ byte) & 0x01;
if (fb_bit == 0x01) {
crc = crc ^ 0x18;
}
crc = (crc >> 1) & 0x7f;
if (fb_bit == 0x01) {
crc = crc | 0x80;
}
byte = byte >> 1;
}
}
return MP_OBJ_NEW_SMALL_INT(crc);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(onewire_crc8_obj, onewire_crc8);
STATIC const mp_rom_map_elem_t onewire_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_onewire) },
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&onewire_reset_obj) },
{ MP_ROM_QSTR(MP_QSTR_readbit), MP_ROM_PTR(&onewire_readbit_obj) },
{ MP_ROM_QSTR(MP_QSTR_readbyte), MP_ROM_PTR(&onewire_readbyte_obj) },
{ MP_ROM_QSTR(MP_QSTR_writebit), MP_ROM_PTR(&onewire_writebit_obj) },
{ MP_ROM_QSTR(MP_QSTR_writebyte), MP_ROM_PTR(&onewire_writebyte_obj) },
{ MP_ROM_QSTR(MP_QSTR_crc8), MP_ROM_PTR(&onewire_crc8_obj) },
};
STATIC MP_DEFINE_CONST_DICT(onewire_module_globals, onewire_module_globals_table);
const mp_obj_module_t mp_module_onewire = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&onewire_module_globals,
};
#endif // MICROPY_PY_ONEWIRE

View File

@ -70,6 +70,7 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf);
/******************************************************************************/ /******************************************************************************/
// Ticks for task ordering in pairing heap // Ticks for task ordering in pairing heap
// CIRCUITPY-style ticks
#define _TICKS_PERIOD (1lu << 29) #define _TICKS_PERIOD (1lu << 29)
#define _TICKS_MAX (_TICKS_PERIOD - 1) #define _TICKS_MAX (_TICKS_PERIOD - 1)
#define _TICKS_HALFPERIOD (_TICKS_PERIOD >> 1) #define _TICKS_HALFPERIOD (_TICKS_PERIOD >> 1)
@ -105,8 +106,7 @@ STATIC int task_lt(mp_pairheap_t *n1, mp_pairheap_t *n2) {
STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t task_queue_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
(void)args; (void)args;
mp_arg_check_num(n_args, n_kw, 0, 0, false); mp_arg_check_num(n_args, n_kw, 0, 0, false);
mp_obj_task_queue_t *self = m_new_obj(mp_obj_task_queue_t); mp_obj_task_queue_t *self = mp_obj_malloc(mp_obj_task_queue_t, type);
self->base.type = type;
self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt); self->heap = (mp_obj_task_t *)mp_pairheap_new(task_lt);
return MP_OBJ_FROM_PTR(self); return MP_OBJ_FROM_PTR(self);
} }
@ -121,7 +121,7 @@ STATIC mp_obj_t task_queue_peek(mp_obj_t self_in) {
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek); STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_peek_obj, task_queue_peek);
STATIC mp_obj_t task_queue_push_sorted(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t task_queue_push(size_t n_args, const mp_obj_t *args) {
mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]); mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(args[0]);
mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]); mp_obj_task_t *task = MP_OBJ_TO_PTR(args[1]);
task->data = mp_const_none; task->data = mp_const_none;
@ -134,9 +134,9 @@ STATIC mp_obj_t task_queue_push_sorted(size_t n_args, const mp_obj_t *args) {
self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task)); self->heap = (mp_obj_task_t *)mp_pairheap_push(task_lt, TASK_PAIRHEAP(self->heap), TASK_PAIRHEAP(task));
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_sorted_obj, 2, 3, task_queue_push_sorted); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(task_queue_push_obj, 2, 3, task_queue_push);
STATIC mp_obj_t task_queue_pop_head(mp_obj_t self_in) { STATIC mp_obj_t task_queue_pop(mp_obj_t self_in) {
mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap); mp_obj_task_t *head = (mp_obj_task_t *)mp_pairheap_peek(task_lt, &self->heap->pairheap);
if (head == NULL) { if (head == NULL) {
@ -145,7 +145,7 @@ STATIC mp_obj_t task_queue_pop_head(mp_obj_t self_in) {
self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap); self->heap = (mp_obj_task_t *)mp_pairheap_pop(task_lt, &self->heap->pairheap);
return MP_OBJ_FROM_PTR(head); return MP_OBJ_FROM_PTR(head);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_head_obj, task_queue_pop_head); STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_queue_pop_obj, task_queue_pop);
STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) { STATIC mp_obj_t task_queue_remove(mp_obj_t self_in, mp_obj_t task_in) {
mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_task_queue_t *self = MP_OBJ_TO_PTR(self_in);
@ -157,9 +157,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(task_queue_remove_obj, task_queue_remove);
STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = { STATIC const mp_rom_map_elem_t task_queue_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) }, { MP_ROM_QSTR(MP_QSTR_peek), MP_ROM_PTR(&task_queue_peek_obj) },
{ MP_ROM_QSTR(MP_QSTR_push_sorted), MP_ROM_PTR(&task_queue_push_sorted_obj) }, { MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&task_queue_push_obj) },
{ MP_ROM_QSTR(MP_QSTR_push_head), MP_ROM_PTR(&task_queue_push_sorted_obj) }, { MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&task_queue_pop_obj) },
{ MP_ROM_QSTR(MP_QSTR_pop_head), MP_ROM_PTR(&task_queue_pop_head_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) }, { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&task_queue_remove_obj) },
}; };
STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table); STATIC MP_DEFINE_CONST_DICT(task_queue_locals_dict, task_queue_locals_dict_table);
@ -223,18 +222,18 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
// Not on the main running queue, remove the task from the queue it's on. // Not on the main running queue, remove the task from the queue it's on.
dest[2] = MP_OBJ_FROM_PTR(self); dest[2] = MP_OBJ_FROM_PTR(self);
mp_call_method_n_kw(1, 0, dest); mp_call_method_n_kw(1, 0, dest);
// _task_queue.push_head(self) // _task_queue.push(self)
dest[0] = _task_queue; dest[0] = _task_queue;
dest[1] = MP_OBJ_FROM_PTR(self); dest[1] = MP_OBJ_FROM_PTR(self);
task_queue_push_sorted(2, dest); task_queue_push(2, dest);
} else if (ticks_diff(self->ph_key, ticks()) > 0) { } else if (ticks_diff(self->ph_key, ticks()) > 0) {
// On the main running queue but scheduled in the future, so bring it forward to now. // On the main running queue but scheduled in the future, so bring it forward to now.
// _task_queue.remove(self) // _task_queue.remove(self)
task_queue_remove(_task_queue, MP_OBJ_FROM_PTR(self)); task_queue_remove(_task_queue, MP_OBJ_FROM_PTR(self));
// _task_queue.push_head(self) // _task_queue.push(self)
dest[0] = _task_queue; dest[0] = _task_queue;
dest[1] = MP_OBJ_FROM_PTR(self); dest[1] = MP_OBJ_FROM_PTR(self);
task_queue_push_sorted(2, dest); task_queue_push(2, dest);
} }
self->data = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError)); self->data = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_CancelledError));
@ -243,6 +242,7 @@ STATIC mp_obj_t task_cancel(mp_obj_t self_in) {
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel); STATIC MP_DEFINE_CONST_FUN_OBJ_1(task_cancel_obj, task_cancel);
// CIRCUITPY provides __await__().
STATIC mp_obj_t task_await(mp_obj_t self_in) { STATIC mp_obj_t task_await(mp_obj_t self_in) {
return task_getiter(self_in, NULL); return task_getiter(self_in, NULL);
} }
@ -266,6 +266,7 @@ STATIC void task_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
dest[1] = self_in; dest[1] = self_in;
} else if (attr == MP_QSTR_ph_key) { } else if (attr == MP_QSTR_ph_key) {
dest[0] = self->ph_key; dest[0] = self->ph_key;
// CIRCUITPY provides __await__().
} else if (attr == MP_QSTR___await__) { } else if (attr == MP_QSTR___await__) {
dest[0] = MP_OBJ_FROM_PTR(&task_await_obj); dest[0] = MP_OBJ_FROM_PTR(&task_await_obj);
dest[1] = self_in; dest[1] = self_in;
@ -291,6 +292,9 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
} else if (self->state == TASK_STATE_RUNNING_NOT_WAITED_ON) { } else if (self->state == TASK_STATE_RUNNING_NOT_WAITED_ON) {
// Allocate the waiting queue. // Allocate the waiting queue.
self->state = task_queue_make_new(&task_queue_type, 0, 0, NULL); self->state = task_queue_make_new(&task_queue_type, 0, 0, NULL);
} else if (mp_obj_get_type(self->state) != &task_queue_type) {
// Task has state used for another purpose, so can't also wait on it.
mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("can't wait"));
} }
return self_in; return self_in;
} }
@ -298,6 +302,7 @@ STATIC mp_obj_t task_getiter(mp_obj_t self_in, mp_obj_iter_buf_t *iter_buf) {
STATIC mp_obj_t task_iternext(mp_obj_t self_in) { STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_task_t *self = MP_OBJ_TO_PTR(self_in);
if (TASK_IS_DONE(self)) { if (TASK_IS_DONE(self)) {
// CIRCUITPY
if (self->data == mp_const_none) { if (self->data == mp_const_none) {
// Task finished but has already been sent to the loop's exception handler. // Task finished but has already been sent to the loop's exception handler.
mp_raise_StopIteration(MP_OBJ_NULL); mp_raise_StopIteration(MP_OBJ_NULL);
@ -309,7 +314,7 @@ STATIC mp_obj_t task_iternext(mp_obj_t self_in) {
// Put calling task on waiting queue. // Put calling task on waiting queue.
mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task)); mp_obj_t cur_task = mp_obj_dict_get(uasyncio_context, MP_OBJ_NEW_QSTR(MP_QSTR_cur_task));
mp_obj_t args[2] = { self->state, cur_task }; mp_obj_t args[2] = { self->state, cur_task };
task_queue_push_sorted(2, args); task_queue_push(2, args);
// Set calling task's data to this task that it waits on, to double-link it. // Set calling task's data to this task that it waits on, to double-link it.
((mp_obj_task_t *)MP_OBJ_TO_PTR(cur_task))->data = self_in; ((mp_obj_task_t *)MP_OBJ_TO_PTR(cur_task))->data = self_in;
} }
@ -347,6 +352,6 @@ const mp_obj_module_t mp_module_uasyncio = {
.globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals, .globals = (mp_obj_dict_t *)&mp_module_uasyncio_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR__asyncio, mp_module_uasyncio, MICROPY_PY_UASYNCIO); MP_REGISTER_MODULE(MP_QSTR__uasyncio, mp_module_uasyncio);
#endif // MICROPY_PY_UASYNCIO #endif // MICROPY_PY_UASYNCIO

View File

@ -1,8 +1,28 @@
// Copyright (c) 2014 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// SPDX-FileCopyrightText: 2022 Beat Ludin for Adafruit Industries *
// * The MIT License (MIT)
// SPDX-License-Identifier: MIT *
* Copyright (c) 2014 Paul Sokolovsky
*
* 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 <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
@ -20,6 +40,7 @@ static void check_not_unicode(const mp_obj_t arg) {
} }
#endif #endif
} }
#if MICROPY_PY_UBINASCII
STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t mod_binascii_hexlify(size_t n_args, const mp_obj_t *args) {
// First argument is the data to convert. // First argument is the data to convert.
@ -154,13 +175,20 @@ STATIC mp_obj_t mod_binascii_a2b_base64(mp_obj_t data) {
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64); STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_a2b_base64_obj, mod_binascii_a2b_base64);
STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) { STATIC mp_obj_t mod_binascii_b2a_base64(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
check_not_unicode(data); enum { ARG_newline };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_newline, MP_ARG_BOOL, {.u_bool = true} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
uint8_t newline = args[ARG_newline].u_bool;
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
mp_get_buffer_raise(data, &bufinfo, MP_BUFFER_READ); mp_get_buffer_raise(pos_args[0], &bufinfo, MP_BUFFER_READ);
vstr_t vstr; vstr_t vstr;
vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + 1); vstr_init_len(&vstr, ((bufinfo.len != 0) ? (((bufinfo.len - 1) / 3) + 1) * 4 : 0) + newline);
// First pass, we convert input buffer to numeric base 64 values // First pass, we convert input buffer to numeric base 64 values
byte *in = bufinfo.buf, *out = (byte *)vstr.buf; byte *in = bufinfo.buf, *out = (byte *)vstr.buf;
@ -186,7 +214,7 @@ STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
// Second pass, we convert number base 64 values to actual base64 ascii encoding // Second pass, we convert number base 64 values to actual base64 ascii encoding
out = (byte *)vstr.buf; out = (byte *)vstr.buf;
for (mp_uint_t j = vstr.len - 1; j--;) { for (mp_uint_t j = vstr.len - newline; j--;) {
if (*out < 26) { if (*out < 26) {
*out += 'A'; *out += 'A';
} else if (*out < 52) { } else if (*out < 52) {
@ -202,10 +230,15 @@ STATIC mp_obj_t mod_binascii_b2a_base64(mp_obj_t data) {
} }
out++; out++;
} }
if (newline) {
*out = '\n'; *out = '\n';
}
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_binascii_b2a_base64_obj, mod_binascii_b2a_base64); STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_binascii_b2a_base64_obj, 1, mod_binascii_b2a_base64);
// CIRCUITPY uses a self-contained implementation of CRC32,
// instead of depending on uzlib, like MicroPython.
/* /*
* CRC32 checksum * CRC32 checksum
@ -296,4 +329,6 @@ const mp_obj_module_t mp_module_ubinascii = {
.globals = (mp_obj_dict_t *)&mp_module_binascii_globals, .globals = (mp_obj_dict_t *)&mp_module_binascii_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_binascii, mp_module_ubinascii, MICROPY_PY_UBINASCII); MP_REGISTER_MODULE(MP_QSTR_ubinascii, mp_module_ubinascii);
#endif // MICROPY_PY_UBINASCII

View File

@ -1,7 +1,28 @@
// Copyright (c) 2014-2018 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2014-2018 Paul Sokolovsky
*
* 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 <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -76,8 +97,7 @@ STATIC NORETURN void syntax_error(void) {
STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t uctypes_struct_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 2, 3, false); mp_arg_check_num(n_args, n_kw, 2, 3, false);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, type);
o->base.type = type;
o->addr = (void *)(uintptr_t)mp_obj_int_get_truncated(args[0]); o->addr = (void *)(uintptr_t)mp_obj_int_get_truncated(args[0]);
o->desc = args[1]; o->desc = args[1];
o->flags = LAYOUT_NATIVE; o->flags = LAYOUT_NATIVE;
@ -444,8 +464,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
switch (agg_type) { switch (agg_type) {
case STRUCT: { case STRUCT: {
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
o->base.type = &uctypes_struct_type;
o->desc = sub->items[1]; o->desc = sub->items[1];
o->addr = self->addr + offset; o->addr = self->addr + offset;
o->flags = self->flags; o->flags = self->flags;
@ -460,8 +479,7 @@ STATIC mp_obj_t uctypes_struct_attr_op(mp_obj_t self_in, qstr attr, mp_obj_t set
MP_FALLTHROUGH MP_FALLTHROUGH
} }
case PTR: { case PTR: {
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
o->base.type = &uctypes_struct_type;
o->desc = MP_OBJ_FROM_PTR(sub); o->desc = MP_OBJ_FROM_PTR(sub);
o->addr = self->addr + offset; o->addr = self->addr + offset;
o->flags = self->flags; o->flags = self->flags;
@ -533,8 +551,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
} else if (value == MP_OBJ_SENTINEL) { } else if (value == MP_OBJ_SENTINEL) {
mp_uint_t dummy = 0; mp_uint_t dummy = 0;
mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy); mp_uint_t size = uctypes_struct_size(t->items[2], self->flags, &dummy);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
o->base.type = &uctypes_struct_type;
o->desc = t->items[2]; o->desc = t->items[2];
o->addr = self->addr + size * index; o->addr = self->addr + size * index;
o->flags = self->flags; o->flags = self->flags;
@ -551,8 +568,7 @@ STATIC mp_obj_t uctypes_struct_subscr(mp_obj_t base_in, mp_obj_t index_in, mp_ob
} else { } else {
mp_uint_t dummy = 0; mp_uint_t dummy = 0;
mp_uint_t size = uctypes_struct_size(t->items[1], self->flags, &dummy); mp_uint_t size = uctypes_struct_size(t->items[1], self->flags, &dummy);
mp_obj_uctypes_struct_t *o = m_new_obj(mp_obj_uctypes_struct_t); mp_obj_uctypes_struct_t *o = mp_obj_malloc(mp_obj_uctypes_struct_t, &uctypes_struct_type);
o->base.type = &uctypes_struct_type;
o->desc = t->items[1]; o->desc = t->items[1];
o->addr = p + size * index; o->addr = p + size * index;
o->flags = self->flags; o->flags = self->flags;
@ -706,4 +722,6 @@ const mp_obj_module_t mp_module_uctypes = {
.globals = (mp_obj_dict_t *)&mp_module_uctypes_globals, .globals = (mp_obj_dict_t *)&mp_module_uctypes_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_uctypes, mp_module_uctypes);
#endif #endif

View File

@ -1,7 +1,28 @@
// Copyright (c) 2014 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
*
* 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 <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -39,7 +60,6 @@
#endif #endif
typedef struct _mp_obj_hash_t { typedef struct _mp_obj_hash_t {
mp_obj_base_t base; mp_obj_base_t base;
bool final; // if set, update and digest raise an exception bool final; // if set, update and digest raise an exception
@ -65,8 +85,7 @@ STATIC mp_obj_t uhashlib_sha256_update(mp_obj_t self_in, mp_obj_t arg);
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); 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)); mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha256_context), type);
o->base.type = type;
o->final = false; o->final = false;
mbedtls_sha256_init((mbedtls_sha256_context *)&o->state); mbedtls_sha256_init((mbedtls_sha256_context *)&o->state);
mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0); mbedtls_sha256_starts_ret((mbedtls_sha256_context *)&o->state, 0);
@ -110,8 +129,7 @@ static void check_not_unicode(const mp_obj_t arg) {
STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t uhashlib_sha256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); 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)); mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(CRYAL_SHA256_CTX), type);
o->base.type = type;
o->final = false; o->final = false;
sha256_init((CRYAL_SHA256_CTX *)o->state); sha256_init((CRYAL_SHA256_CTX *)o->state);
if (n_args == 1) { if (n_args == 1) {
@ -159,16 +177,13 @@ STATIC const mp_obj_type_t uhashlib_sha256_type = {
}; };
#endif #endif
#endif
#if MICROPY_PY_UHASHLIB_SHA1 #if MICROPY_PY_UHASHLIB_SHA1
STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg); STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg);
#if MICROPY_SSL_AXTLS #if MICROPY_SSL_AXTLS
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, kw_args, 0, 1, false); 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)); mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(SHA1_CTX), type);
o->base.type = type;
o->final = false; o->final = false;
SHA1_Init((SHA1_CTX *)o->state); SHA1_Init((SHA1_CTX *)o->state);
if (n_args == 1) { if (n_args == 1) {
@ -178,7 +193,6 @@ 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) { STATIC mp_obj_t uhashlib_sha1_update(mp_obj_t self_in, mp_obj_t arg) {
check_not_unicode(arg);
mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_hash_t *self = MP_OBJ_TO_PTR(self_in);
uhashlib_ensure_not_final(self); uhashlib_ensure_not_final(self);
mp_buffer_info_t bufinfo; mp_buffer_info_t bufinfo;
@ -208,8 +222,7 @@ STATIC mp_obj_t uhashlib_sha1_digest(mp_obj_t self_in) {
STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t uhashlib_sha1_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); 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)); mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_sha1_context), type);
o->base.type = type;
o->final = false; o->final = false;
mbedtls_sha1_init((mbedtls_sha1_context *)o->state); mbedtls_sha1_init((mbedtls_sha1_context *)o->state);
mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state); mbedtls_sha1_starts_ret((mbedtls_sha1_context *)o->state);
@ -263,8 +276,7 @@ STATIC mp_obj_t uhashlib_md5_update(mp_obj_t self_in, mp_obj_t arg);
#if MICROPY_SSL_AXTLS #if MICROPY_SSL_AXTLS
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); 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)); mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(MD5_CTX), type);
o->base.type = type;
o->final = false; o->final = false;
MD5_Init((MD5_CTX *)o->state); MD5_Init((MD5_CTX *)o->state);
if (n_args == 1) { if (n_args == 1) {
@ -303,8 +315,7 @@ STATIC mp_obj_t uhashlib_md5_digest(mp_obj_t self_in) {
STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t uhashlib_md5_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); 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)); mp_obj_hash_t *o = mp_obj_malloc_var(mp_obj_hash_t, char, sizeof(mbedtls_md5_context), type);
o->base.type = type;
o->final = false; o->final = false;
mbedtls_md5_init((mbedtls_md5_context *)o->state); mbedtls_md5_init((mbedtls_md5_context *)o->state);
mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state); mbedtls_md5_starts_ret((mbedtls_md5_context *)o->state);
@ -372,4 +383,6 @@ const mp_obj_module_t mp_module_uhashlib = {
.globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals, .globals = (mp_obj_dict_t *)&mp_module_uhashlib_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_uhashlib, mp_module_uhashlib, MICROPY_PY_UHASHLIB);
#endif // MICROPY_PY_UHASHLIB #endif // MICROPY_PY_UHASHLIB

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
*
* 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 "py/objlist.h" #include "py/objlist.h"
#include "py/runtime.h" #include "py/runtime.h"
@ -98,6 +119,8 @@ const mp_obj_module_t mp_module_uheapq = {
.base = { &mp_type_module }, .base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_uheapq_globals, .globals = (mp_obj_dict_t *)&mp_module_uheapq_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_uheapq, mp_module_uheapq);
#endif #endif
#endif // MICROPY_PY_UHEAPQ #endif // MICROPY_PY_UHEAPQ

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2014-2019 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2014-2019 Damien P. George
*
* 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 <stdio.h> #include <stdio.h>
@ -112,6 +133,7 @@ typedef struct _ujson_stream_t {
mp_obj_t stream_obj; mp_obj_t stream_obj;
mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode);
int errcode; int errcode;
// CIRCUITPY
mp_obj_t python_readinto[2 + 1]; mp_obj_t python_readinto[2 + 1];
mp_obj_array_t bytearray_obj; mp_obj_array_t bytearray_obj;
size_t start; size_t start;
@ -136,6 +158,8 @@ STATIC byte ujson_stream_next(ujson_stream_t *s) {
return s->cur; return s->cur;
} }
// CIRCUITPY
// We read from an object's `readinto` method in chunks larger than the json // We read from an object's `readinto` method in chunks larger than the json
// parser needs to reduce the number of function calls done. // parser needs to reduce the number of function calls done.
@ -375,6 +399,8 @@ STATIC mp_obj_t _mod_ujson_load(mp_obj_t stream_obj, bool return_first_json) {
} }
} }
success: success:
// CIRCUITPY
// It is legal for a stream to have contents after JSON. // It is legal for a stream to have contents after JSON.
// E.g., A UART is not closed after receiving an object; in load() we will // E.g., A UART is not closed after receiving an object; in load() we will
// return the first complete JSON object, while in loads() we will retain // return the first complete JSON object, while in loads() we will retain
@ -432,6 +458,6 @@ const mp_obj_module_t mp_module_ujson = {
.globals = (mp_obj_dict_t *)&mp_module_ujson_globals, .globals = (mp_obj_dict_t *)&mp_module_ujson_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_json, mp_module_ujson, MICROPY_PY_UJSON); MP_REGISTER_MODULE(MP_QSTR_ujson, mp_module_ujson);
#endif // MICROPY_PY_UJSON #endif // MICROPY_PY_UJSON

181
extmod/moduos.c Normal file
View File

@ -0,0 +1,181 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016-2022 Damien P. George
*
* 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 "py/objstr.h"
#include "py/runtime.h"
#if MICROPY_PY_UOS
#include "extmod/misc.h"
#include "extmod/vfs.h"
#if MICROPY_VFS_FAT
#include "extmod/vfs_fat.h"
#endif
#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2
#include "extmod/vfs_lfs.h"
#endif
#if MICROPY_VFS_POSIX
#include "extmod/vfs_posix.h"
#endif
#if MICROPY_PY_UOS_UNAME
#include "genhdr/mpversion.h"
#endif
#ifdef MICROPY_PY_UOS_INCLUDEFILE
#include MICROPY_PY_UOS_INCLUDEFILE
#endif
#ifdef MICROPY_BUILD_TYPE
#define MICROPY_BUILD_TYPE_PAREN " (" MICROPY_BUILD_TYPE ")"
#else
#define MICROPY_BUILD_TYPE_PAREN
#endif
#if MICROPY_PY_UOS_UNAME
#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
#define CONST_RELEASE
#else
#define CONST_RELEASE const
#endif
STATIC const qstr mp_uos_uname_info_fields[] = {
MP_QSTR_sysname,
MP_QSTR_nodename,
MP_QSTR_release,
MP_QSTR_version,
MP_QSTR_machine
};
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_sysname_obj, MICROPY_PY_SYS_PLATFORM);
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_nodename_obj, MICROPY_PY_SYS_PLATFORM);
STATIC CONST_RELEASE MP_DEFINE_STR_OBJ(mp_uos_uname_info_release_obj, MICROPY_VERSION_STRING);
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_version_obj, MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE MICROPY_BUILD_TYPE_PAREN);
STATIC const MP_DEFINE_STR_OBJ(mp_uos_uname_info_machine_obj, MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME);
STATIC MP_DEFINE_ATTRTUPLE(
mp_uos_uname_info_obj,
mp_uos_uname_info_fields,
5,
MP_ROM_PTR(&mp_uos_uname_info_sysname_obj),
MP_ROM_PTR(&mp_uos_uname_info_nodename_obj),
MP_ROM_PTR(&mp_uos_uname_info_release_obj),
MP_ROM_PTR(&mp_uos_uname_info_version_obj),
MP_ROM_PTR(&mp_uos_uname_info_machine_obj)
);
STATIC mp_obj_t mp_uos_uname(void) {
#if MICROPY_PY_UOS_UNAME_RELEASE_DYNAMIC
const char *release = mp_uos_uname_release();
mp_uos_uname_info_release_obj.len = strlen(release);
mp_uos_uname_info_release_obj.data = (const byte *)release;
#endif
return MP_OBJ_FROM_PTR(&mp_uos_uname_info_obj);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_uos_uname_obj, mp_uos_uname);
#endif
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
#if MICROPY_PY_UOS_GETENV_PUTENV_UNSETENV
{ MP_ROM_QSTR(MP_QSTR_getenv), MP_ROM_PTR(&mp_uos_getenv_obj) },
{ MP_ROM_QSTR(MP_QSTR_putenv), MP_ROM_PTR(&mp_uos_putenv_obj) },
{ MP_ROM_QSTR(MP_QSTR_unsetenv), MP_ROM_PTR(&mp_uos_unsetenv_obj) },
#endif
#if MICROPY_PY_UOS_SEP
{ MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
#endif
#if MICROPY_PY_UOS_SYNC
{ MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mp_uos_sync_obj) },
#endif
#if MICROPY_PY_UOS_SYSTEM
{ MP_ROM_QSTR(MP_QSTR_system), MP_ROM_PTR(&mp_uos_system_obj) },
#endif
#if MICROPY_PY_UOS_UNAME
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&mp_uos_uname_obj) },
#endif
#if MICROPY_PY_UOS_URANDOM
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&mp_uos_urandom_obj) },
#endif
#if MICROPY_VFS
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&mp_vfs_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
#endif
// The following are MicroPython extensions.
#if MICROPY_PY_OS_DUPTERM
{ MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
#endif
#if MICROPY_PY_UOS_DUPTERM_NOTIFY
{ MP_ROM_QSTR(MP_QSTR_dupterm_notify), MP_ROM_PTR(&mp_uos_dupterm_notify_obj) },
#endif
#if MICROPY_PY_UOS_ERRNO
{ MP_ROM_QSTR(MP_QSTR_errno), MP_ROM_PTR(&mp_uos_errno_obj) },
#endif
#if MICROPY_VFS
{ MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
#if MICROPY_VFS_FAT
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
#endif
#if MICROPY_VFS_LFS1
{ MP_ROM_QSTR(MP_QSTR_VfsLfs1), MP_ROM_PTR(&mp_type_vfs_lfs1) },
#endif
#if MICROPY_VFS_LFS2
{ MP_ROM_QSTR(MP_QSTR_VfsLfs2), MP_ROM_PTR(&mp_type_vfs_lfs2) },
#endif
#if MICROPY_VFS_POSIX
{ MP_ROM_QSTR(MP_QSTR_VfsPosix), MP_ROM_PTR(&mp_type_vfs_posix) },
#endif
#endif
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
const mp_obj_module_t mp_module_uos = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&os_module_globals,
};
MP_REGISTER_MODULE(MP_QSTR_uos, mp_module_uos);
#endif // MICROPY_PY_UOS

View File

@ -29,87 +29,19 @@
#include "py/objtuple.h" #include "py/objtuple.h"
#include "py/objstr.h" #include "py/objstr.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "extmod/moduplatform.h"
#include "genhdr/mpversion.h" #include "genhdr/mpversion.h"
#if MICROPY_PY_UPLATFORM #if MICROPY_PY_UPLATFORM
// platform - Access to underlying platform's identifying data // platform - Access to underlying platform's identifying data
// TODO: Add more architectures, compilers and libraries. STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, MICROPY_PLATFORM_SYSTEM "-" \
// See: https://sourceforge.net/p/predef/wiki/Home/ MICROPY_VERSION_STRING "-" MICROPY_PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" \
MICROPY_PLATFORM_LIBC_LIB "" MICROPY_PLATFORM_LIBC_VER);
#if defined(__ARM_ARCH) STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, MICROPY_PLATFORM_COMPILER);
#define PLATFORM_ARCH "arm" STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, MICROPY_PLATFORM_LIBC_LIB);
#elif defined(__x86_64__) || defined(_WIN64) STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, MICROPY_PLATFORM_LIBC_VER);
#define PLATFORM_ARCH "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
#define PLATFORM_ARCH "x86"
#elif defined(__xtensa__) || defined(_M_IX86)
#define PLATFORM_ARCH "xtensa"
#else
#define PLATFORM_ARCH ""
#endif
#if defined(__GNUC__)
#define PLATFORM_COMPILER \
"GCC " \
MP_STRINGIFY(__GNUC__) "." \
MP_STRINGIFY(__GNUC_MINOR__) "." \
MP_STRINGIFY(__GNUC_PATCHLEVEL__)
#elif defined(__ARMCC_VERSION)
#define PLATFORM_COMPILER \
"ARMCC " \
MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
MP_STRINGIFY((__ARMCC_VERSION % 10000))
#elif defined(_MSC_VER)
#if defined(_WIN64)
#define COMPILER_BITS "64 bit"
#elif defined(_M_IX86)
#define COMPILER_BITS "32 bit"
#else
#define COMPILER_BITS ""
#endif
#define PLATFORM_COMPILER \
"MSC v." MP_STRINGIFY(_MSC_VER) " " COMPILER_BITS
#else
#define PLATFORM_COMPILER ""
#endif
#if defined(__GLIBC__)
#define PLATFORM_LIBC_LIB "glibc"
#define PLATFORM_LIBC_VER \
MP_STRINGIFY(__GLIBC__) "." \
MP_STRINGIFY(__GLIBC_MINOR__)
#elif defined(__NEWLIB__)
#define PLATFORM_LIBC_LIB "newlib"
#define PLATFORM_LIBC_VER _NEWLIB_VERSION
#else
#define PLATFORM_LIBC_LIB ""
#define PLATFORM_LIBC_VER ""
#endif
#if defined(__linux)
#define PLATFORM_SYSTEM "Linux"
#elif defined(__unix__)
#define PLATFORM_SYSTEM "Unix"
#elif defined(__CYGWIN__)
#define PLATFORM_SYSTEM "Cygwin"
#elif defined(_WIN32)
#define PLATFORM_SYSTEM "Windows"
#else
#define PLATFORM_SYSTEM "MicroPython"
#endif
#ifndef MICROPY_PLATFORM_VERSION
#define MICROPY_PLATFORM_VERSION ""
#endif
STATIC const MP_DEFINE_STR_OBJ(info_platform_obj, PLATFORM_SYSTEM "-" MICROPY_VERSION_STRING "-" \
PLATFORM_ARCH "-" MICROPY_PLATFORM_VERSION "-with-" PLATFORM_LIBC_LIB "" PLATFORM_LIBC_VER);
STATIC const MP_DEFINE_STR_OBJ(info_python_compiler_obj, PLATFORM_COMPILER);
STATIC const MP_DEFINE_STR_OBJ(info_libc_lib_obj, PLATFORM_LIBC_LIB);
STATIC const MP_DEFINE_STR_OBJ(info_libc_ver_obj, PLATFORM_LIBC_VER);
STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = { STATIC const mp_rom_obj_tuple_t info_libc_tuple_obj = {
{&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)} {&mp_type_tuple}, 2, {MP_ROM_PTR(&info_libc_lib_obj), MP_ROM_PTR(&info_libc_ver_obj)}
}; };
@ -143,4 +75,6 @@ const mp_obj_module_t mp_module_uplatform = {
.globals = (mp_obj_dict_t *)&modplatform_globals, .globals = (mp_obj_dict_t *)&modplatform_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_uplatform, mp_module_uplatform);
#endif // MICROPY_PY_UPLATFORM #endif // MICROPY_PY_UPLATFORM

105
extmod/moduplatform.h Normal file
View File

@ -0,0 +1,105 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2021 Ibrahim Abdelkader <iabdalkader@openmv.io>
*
* 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.
*/
#ifndef MICROPY_INCLUDED_MODUPLATFORM_H
#define MICROPY_INCLUDED_MODUPLATFORM_H
#include "py/misc.h" // For MP_STRINGIFY.
#include "py/mpconfig.h"
// Preprocessor directives indentifying the platform.
// The (u)platform module itself is guarded by MICROPY_PY_UPLATFORM, see the
// .c file, but these are made available because they're generally usable.
// TODO: Add more architectures, compilers and libraries.
// See: https://sourceforge.net/p/predef/wiki/Home/
#if defined(__ARM_ARCH)
#define MICROPY_PLATFORM_ARCH "arm"
#elif defined(__x86_64__) || defined(_WIN64)
#define MICROPY_PLATFORM_ARCH "x86_64"
#elif defined(__i386__) || defined(_M_IX86)
#define MICROPY_PLATFORM_ARCH "x86"
#elif defined(__xtensa__) || defined(_M_IX86)
#define MICROPY_PLATFORM_ARCH "xtensa"
#else
#define MICROPY_PLATFORM_ARCH ""
#endif
#if defined(__GNUC__)
#define MICROPY_PLATFORM_COMPILER \
"GCC " \
MP_STRINGIFY(__GNUC__) "." \
MP_STRINGIFY(__GNUC_MINOR__) "." \
MP_STRINGIFY(__GNUC_PATCHLEVEL__)
#elif defined(__ARMCC_VERSION)
#define MICROPY_PLATFORM_COMPILER \
"ARMCC " \
MP_STRINGIFY((__ARMCC_VERSION / 1000000)) "." \
MP_STRINGIFY((__ARMCC_VERSION / 10000 % 100)) "." \
MP_STRINGIFY((__ARMCC_VERSION % 10000))
#elif defined(_MSC_VER)
#if defined(_WIN64)
#define MICROPY_PLATFORM_COMPILER_BITS "64 bit"
#elif defined(_M_IX86)
#define MICROPY_PLATFORM_COMPILER_BITS "32 bit"
#else
#define MICROPY_PLATFORM_COMPILER_BITS ""
#endif
#define MICROPY_PLATFORM_COMPILER \
"MSC v." MP_STRINGIFY(_MSC_VER) " " MICROPY_PLATFORM_COMPILER_BITS
#else
#define MICROPY_PLATFORM_COMPILER ""
#endif
#if defined(__GLIBC__)
#define MICROPY_PLATFORM_LIBC_LIB "glibc"
#define MICROPY_PLATFORM_LIBC_VER \
MP_STRINGIFY(__GLIBC__) "." \
MP_STRINGIFY(__GLIBC_MINOR__)
#elif defined(__NEWLIB__)
#define MICROPY_PLATFORM_LIBC_LIB "newlib"
#define MICROPY_PLATFORM_LIBC_VER _NEWLIB_VERSION
#else
#define MICROPY_PLATFORM_LIBC_LIB ""
#define MICROPY_PLATFORM_LIBC_VER ""
#endif
#if defined(__linux)
#define MICROPY_PLATFORM_SYSTEM "Linux"
#elif defined(__unix__)
#define MICROPY_PLATFORM_SYSTEM "Unix"
#elif defined(__CYGWIN__)
#define MICROPY_PLATFORM_SYSTEM "Cygwin"
#elif defined(_WIN32)
#define MICROPY_PLATFORM_SYSTEM "Windows"
#else
#define MICROPY_PLATFORM_SYSTEM "MicroPython"
#endif
#ifndef MICROPY_PLATFORM_VERSION
#define MICROPY_PLATFORM_VERSION ""
#endif
#endif // MICROPY_INCLUDED_MODUPLATFORM_H

View File

@ -1,7 +1,28 @@
// Copyright (c) 2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* 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 <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
@ -195,7 +216,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_uniform_obj, mod_urandom_uniform);
#endif // MICROPY_PY_URANDOM_EXTRA_FUNCS #endif // MICROPY_PY_URANDOM_EXTRA_FUNCS
#if SEED_ON_IMPORT #if SEED_ON_IMPORT
STATIC mp_obj_t mod_urandom___init__() { STATIC mp_obj_t mod_urandom___init__(void) {
// This module may be imported by more than one name so need to ensure // This module may be imported by more than one name so need to ensure
// that it's only ever seeded once. // that it's only ever seeded once.
static bool seeded = false; static bool seeded = false;
@ -233,6 +254,8 @@ const mp_obj_module_t mp_module_urandom = {
.base = { &mp_type_module }, .base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_urandom_globals, .globals = (mp_obj_dict_t *)&mp_module_urandom_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_urandom, mp_module_urandom);
#endif #endif
#endif // MICROPY_PY_URANDOM #endif // MICROPY_PY_URANDOM

View File

@ -1,7 +1,28 @@
// Copyright (c) 2014 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2014 Paul Sokolovsky
*
* 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 <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
@ -18,6 +39,7 @@
#include "lib/re1.5/re1.5.h" #include "lib/re1.5/re1.5.h"
//CIRCUITPY
#if MICROPY_PY_URE_DEBUG #if MICROPY_PY_URE_DEBUG
#define FLAG_DEBUG 0x1000 #define FLAG_DEBUG 0x1000
#endif #endif
@ -168,7 +190,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
} }
Subject subj; Subject subj;
size_t len; size_t len;
subj.begin = mp_obj_str_get_data(args[1], &len); subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
subj.end = subj.begin + len; subj.end = subj.begin + len;
#if MICROPY_PY_URE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME) #if MICROPY_PY_URE_MATCH_SPAN_START_END && !(defined(MICROPY_ENABLE_DYNRUNTIME) && MICROPY_ENABLE_DYNRUNTIME)
@ -231,7 +253,7 @@ STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
Subject subj; Subject subj;
size_t len; size_t len;
const mp_obj_type_t *str_type = mp_obj_get_type(args[1]); const mp_obj_type_t *str_type = mp_obj_get_type(args[1]);
subj.begin = mp_obj_str_get_data(args[1], &len); subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len);
subj.end = subj.begin + len; subj.end = subj.begin + len;
int caps_num = (self->re.sub + 1) * 2; int caps_num = (self->re.sub + 1) * 2;
@ -291,7 +313,7 @@ STATIC mp_obj_t re_sub_helper(size_t n_args, const mp_obj_t *args) {
size_t where_len; size_t where_len;
const char *where_str = mp_obj_str_get_data(where, &where_len); const char *where_str = mp_obj_str_get_data(where, &where_len);
Subject subj; Subject subj;
subj.begin = where_str; subj.begin_line = subj.begin = where_str;
subj.end = subj.begin + where_len; subj.end = subj.begin + where_len;
int caps_num = (self->re.sub + 1) * 2; int caps_num = (self->re.sub + 1) * 2;
@ -421,8 +443,7 @@ STATIC mp_obj_t mod_re_compile(size_t n_args, const mp_obj_t *args) {
if (size == -1) { if (size == -1) {
goto error; goto error;
} }
mp_obj_re_t *o = m_new_obj_var(mp_obj_re_t, char, size); mp_obj_re_t *o = mp_obj_malloc_var(mp_obj_re_t, char, size, &re_type);
o->base.type = &re_type;
#if MICROPY_PY_URE_DEBUG #if MICROPY_PY_URE_DEBUG
int flags = 0; int flags = 0;
if (n_args > 1) { if (n_args > 1) {
@ -470,7 +491,7 @@ const mp_obj_module_t mp_module_ure = {
.globals = (mp_obj_dict_t *)&mp_module_re_globals, .globals = (mp_obj_dict_t *)&mp_module_re_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_re, mp_module_ure, MICROPY_PY_URE); MP_REGISTER_MODULE(MP_QSTR_ure, mp_module_ure);
#endif #endif
// Source files #include'd here to make sure they're compiled in // Source files #include'd here to make sure they're compiled in

View File

@ -1,8 +1,29 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// SPDX-FileCopyrightText: Copyright (c) 2015-2017 Paul Sokolovsky *
// * The MIT License (MIT)
// SPDX-License-Identifier: MIT *
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2015-2017 Paul Sokolovsky
*
* 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 "py/mpconfig.h" #include "py/mpconfig.h"
#if MICROPY_PY_USELECT #if MICROPY_PY_USELECT
@ -151,6 +172,7 @@ STATIC mp_obj_t select_select(size_t n_args, const mp_obj_t *args) {
mp_map_deinit(&poll_map); mp_map_deinit(&poll_map);
return mp_obj_new_tuple(3, list_array); return mp_obj_new_tuple(3, list_array);
} }
// CIRCUITPY
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
} }
} }
@ -230,6 +252,7 @@ STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) { if (n_ready > 0 || (timeout != (mp_uint_t)-1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
break; break;
} }
// CIRCUITPY
RUN_BACKGROUND_TASKS; RUN_BACKGROUND_TASKS;
if (mp_hal_is_interrupted()) { if (mp_hal_is_interrupted()) {
return 0; return 0;
@ -324,6 +347,8 @@ STATIC const mp_obj_type_t mp_type_poll = {
{ &mp_type_type }, { &mp_type_type },
.flags = MP_TYPE_FLAG_EXTENDED, .flags = MP_TYPE_FLAG_EXTENDED,
.name = MP_QSTR_poll, .name = MP_QSTR_poll,
.getiter = mp_identity_getiter,
.iternext = poll_iternext,
.locals_dict = (void *)&poll_locals_dict, .locals_dict = (void *)&poll_locals_dict,
MP_TYPE_EXTENDED_FIELDS( MP_TYPE_EXTENDED_FIELDS(
.getiter = mp_identity_getiter, .getiter = mp_identity_getiter,
@ -333,8 +358,7 @@ STATIC const mp_obj_type_t mp_type_poll = {
// poll() // poll()
STATIC mp_obj_t select_poll(void) { STATIC mp_obj_t select_poll(void) {
mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t); mp_obj_poll_t *poll = mp_obj_malloc(mp_obj_poll_t, &mp_type_poll);
poll->base.type = &mp_type_poll;
mp_map_init(&poll->poll_map, 0); mp_map_init(&poll->poll_map, 0);
poll->iter_cnt = 0; poll->iter_cnt = 0;
poll->ret_tuple = MP_OBJ_NULL; poll->ret_tuple = MP_OBJ_NULL;
@ -361,6 +385,6 @@ const mp_obj_module_t mp_module_uselect = {
.globals = (mp_obj_dict_t *)&mp_module_select_globals, .globals = (mp_obj_dict_t *)&mp_module_select_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_select, mp_module_uselect, MICROPY_PY_USELECT); MP_REGISTER_MODULE(MP_QSTR_uselect, mp_module_uselect);
#endif // MICROPY_PY_USELECT #endif // MICROPY_PY_USELECT

View File

@ -1,8 +1,29 @@
// Copyright (c) 2016-2017 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George *
// * The MIT License (MIT)
// SPDX-License-Identifier: MIT *
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2016-2017 Paul Sokolovsky
*
* 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 <string.h> #include <string.h>
@ -58,8 +79,7 @@ STATIC bool time_less_than(struct qentry *item, struct qentry *parent) {
STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t utimeq_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_arg_check_num(n_args, n_kw, 1, 1, false);
mp_uint_t alloc = mp_obj_get_int(args[0]); mp_uint_t alloc = mp_obj_get_int(args[0]);
mp_obj_utimeq_t *o = m_new_obj_var(mp_obj_utimeq_t, struct qentry, alloc); mp_obj_utimeq_t *o = mp_obj_malloc_var(mp_obj_utimeq_t, struct qentry, alloc, type);
o->base.type = type;
memset(o->items, 0, sizeof(*o->items) * alloc); memset(o->items, 0, sizeof(*o->items) * alloc);
o->alloc = alloc; o->alloc = alloc;
o->len = 0; o->len = 0;
@ -214,4 +234,6 @@ const mp_obj_module_t mp_module_utimeq = {
.globals = (mp_obj_dict_t *)&mp_module_utimeq_globals, .globals = (mp_obj_dict_t *)&mp_module_utimeq_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_utimeq, mp_module_utimeq);
#endif // MICROPY_PY_UTIMEQ #endif // MICROPY_PY_UTIMEQ

View File

@ -1,7 +1,28 @@
// Copyright (c) 2014-2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2014-2016 Paul Sokolovsky
*
* 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 <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -51,15 +72,14 @@ STATIC int read_src_stream(TINF_DATA *data) {
STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_arg_check_num(n_args, n_kw, 1, 2, false);
mp_get_stream_raise(args[0], MP_STREAM_OP_READ); mp_get_stream_raise(args[0], MP_STREAM_OP_READ);
mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t); mp_obj_decompio_t *o = mp_obj_malloc(mp_obj_decompio_t, type);
o->base.type = type;
memset(&o->decomp, 0, sizeof(o->decomp)); memset(&o->decomp, 0, sizeof(o->decomp));
o->decomp.readSource = read_src_stream; o->decomp.readSource = read_src_stream;
o->src_stream = args[0]; o->src_stream = args[0];
o->eof = false; o->eof = false;
mp_int_t dict_opt = 0; mp_int_t dict_opt = 0;
int dict_sz; uint dict_sz;
if (n_args > 1) { if (n_args > 1) {
dict_opt = mp_obj_get_int(args[1]); dict_opt = mp_obj_get_int(args[1]);
} }
@ -76,7 +96,10 @@ STATIC mp_obj_t decompio_make_new(const mp_obj_type_t *type, size_t n_args, size
header_error: header_error:
mp_raise_ValueError(MP_ERROR_TEXT("compression header")); mp_raise_ValueError(MP_ERROR_TEXT("compression header"));
} }
dict_sz = 1 << dict_opt; // RFC 1950 section 2.2:
// CINFO is the base-2 logarithm of the LZ77 window size,
// minus eight (CINFO=7 indicates a 32K window size)
dict_sz = 1 << (dict_opt + 8);
} else { } else {
dict_sz = 1 << -dict_opt; dict_sz = 1 << -dict_opt;
} }
@ -92,12 +115,13 @@ STATIC mp_uint_t decompio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
} }
o->decomp.dest = buf; o->decomp.dest = buf;
o->decomp.dest_limit = (unsigned char *)buf + size; o->decomp.dest_limit = (byte *)buf + size;
int st = uzlib_uncompress_chksum(&o->decomp); int st = uzlib_uncompress_chksum(&o->decomp);
if (st == TINF_DONE) { if (st == TINF_DONE) {
o->eof = true; o->eof = true;
} }
if (st < 0) { if (st < 0) {
DEBUG_printf("uncompress error=" INT_FMT "\n", st);
*errcode = MP_EINVAL; *errcode = MP_EINVAL;
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
} }
@ -146,9 +170,10 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
decomp->dest = dest_buf; decomp->dest = dest_buf;
decomp->dest_limit = dest_buf + dest_buf_size; decomp->dest_limit = dest_buf + dest_buf_size;
DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", decomp->destSize); DEBUG_printf("uzlib: Initial out buffer: " UINT_FMT " bytes\n", dest_buf_size);
decomp->source = bufinfo.buf; decomp->source = bufinfo.buf;
decomp->source_limit = (unsigned char *)bufinfo.buf + bufinfo.len; decomp->source_limit = (byte *)bufinfo.buf + bufinfo.len;
int st; int st;
bool is_zlib = true; bool is_zlib = true;
@ -175,7 +200,7 @@ STATIC mp_obj_t mod_uzlib_decompress(size_t n_args, const mp_obj_t *args) {
dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256); dest_buf = m_renew(byte, dest_buf, dest_buf_size, dest_buf_size + 256);
dest_buf_size += 256; dest_buf_size += 256;
decomp->dest = dest_buf + offset; decomp->dest = dest_buf + offset;
decomp->dest_limit = dest_buf + offset + 256; decomp->dest_limit = decomp->dest + 256;
} }
mp_uint_t final_sz = decomp->dest - dest_buf; mp_uint_t final_sz = decomp->dest - dest_buf;
@ -203,6 +228,9 @@ const mp_obj_module_t mp_module_uzlib = {
.base = { &mp_type_module }, .base = { &mp_type_module },
.globals = (mp_obj_dict_t *)&mp_module_uzlib_globals, .globals = (mp_obj_dict_t *)&mp_module_uzlib_globals,
}; };
MP_REGISTER_MODULE(MP_QSTR_uzlib, mp_module_uzlib);
#endif #endif
// Source files #include'd here to make sure they're compiled in // Source files #include'd here to make sure they're compiled in

View File

@ -1,30 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019 Damien P. George
from .core import *
__version__ = (3, 0, 0)
_attrs = {
"wait_for": "funcs",
"wait_for_ms": "funcs",
"gather": "funcs",
"Event": "event",
"ThreadSafeFlag": "event",
"Lock": "lock",
"open_connection": "stream",
"start_server": "stream",
"StreamReader": "stream",
"StreamWriter": "stream",
}
# Lazy loader, effectively does:
# global attr
# from .mod import attr
def __getattr__(attr):
mod = _attrs.get(attr, None)
if mod is None:
raise AttributeError(attr)
value = getattr(__import__(mod, None, None, True, 1), attr)
globals()[attr] = value
return value

View File

@ -1,295 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019 Damien P. George
from time import ticks_ms as ticks, ticks_diff, ticks_add
import sys, select
# Import TaskQueue and Task, preferring built-in C code over Python code
try:
from _uasyncio import TaskQueue, Task
except:
from .task import TaskQueue, Task
################################################################################
# Exceptions
class CancelledError(BaseException):
pass
class TimeoutError(Exception):
pass
# Used when calling Loop.call_exception_handler
_exc_context = {"message": "Task exception wasn't retrieved", "exception": None, "future": None}
################################################################################
# Sleep functions
# "Yield" once, then raise StopIteration
class SingletonGenerator:
def __init__(self):
self.state = None
self.exc = StopIteration()
def __await__(self):
return self
def __next__(self):
if self.state is not None:
_task_queue.push_sorted(cur_task, self.state)
self.state = None
return None
else:
self.exc.__traceback__ = None
raise self.exc
# Pause task execution for the given time (integer in milliseconds, uPy extension)
# Use a SingletonGenerator to do it without allocating on the heap
def sleep_ms(t, sgen=SingletonGenerator()):
assert sgen.state is None
sgen.state = ticks_add(ticks(), max(0, t))
return sgen
# Pause task execution for the given time (in seconds)
def sleep(t):
return sleep_ms(int(t * 1000))
################################################################################
# Queue and poller for stream IO
class IOQueue:
def __init__(self):
self.poller = select.poll()
self.map = {} # maps id(stream) to [task_waiting_read, task_waiting_write, stream]
def _enqueue(self, s, idx):
if id(s) not in self.map:
entry = [None, None, s]
entry[idx] = cur_task
self.map[id(s)] = entry
self.poller.register(s, select.POLLIN if idx == 0 else select.POLLOUT)
else:
sm = self.map[id(s)]
assert sm[idx] is None
assert sm[1 - idx] is not None
sm[idx] = cur_task
self.poller.modify(s, select.POLLIN | select.POLLOUT)
# Link task to this IOQueue so it can be removed if needed
cur_task.data = self
def _dequeue(self, s):
del self.map[id(s)]
self.poller.unregister(s)
def queue_read(self, s):
self._enqueue(s, 0)
def queue_write(self, s):
self._enqueue(s, 1)
def remove(self, task):
while True:
del_s = None
for k in self.map: # Iterate without allocating on the heap
q0, q1, s = self.map[k]
if q0 is task or q1 is task:
del_s = s
break
if del_s is not None:
self._dequeue(s)
else:
break
def wait_io_event(self, dt):
for s, ev in self.poller.ipoll(dt):
sm = self.map[id(s)]
# print('poll', s, sm, ev)
if ev & ~select.POLLOUT and sm[0] is not None:
# POLLIN or error
_task_queue.push_head(sm[0])
sm[0] = None
if ev & ~select.POLLIN and sm[1] is not None:
# POLLOUT or error
_task_queue.push_head(sm[1])
sm[1] = None
if sm[0] is None and sm[1] is None:
self._dequeue(s)
elif sm[0] is None:
self.poller.modify(s, select.POLLOUT)
else:
self.poller.modify(s, select.POLLIN)
################################################################################
# Main run loop
# Ensure the awaitable is a task
def _promote_to_task(aw):
return aw if isinstance(aw, Task) else create_task(aw)
# Create and schedule a new task from a coroutine
def create_task(coro):
if not hasattr(coro, "send"):
raise TypeError("coroutine expected")
t = Task(coro, globals())
_task_queue.push_head(t)
return t
# Keep scheduling tasks until there are none left to schedule
def run_until_complete(main_task=None):
global cur_task
excs_all = (CancelledError, Exception) # To prevent heap allocation in loop
excs_stop = (CancelledError, StopIteration) # To prevent heap allocation in loop
while True:
# Wait until the head of _task_queue is ready to run
dt = 1
while dt > 0:
dt = -1
t = _task_queue.peek()
if t:
# A task waiting on _task_queue; "ph_key" is time to schedule task at
dt = max(0, ticks_diff(t.ph_key, ticks()))
elif not _io_queue.map:
# No tasks can be woken so finished running
return
# print('(poll {})'.format(dt), len(_io_queue.map))
_io_queue.wait_io_event(dt)
# Get next task to run and continue it
t = _task_queue.pop_head()
cur_task = t
try:
# Continue running the coroutine, it's responsible for rescheduling itself
exc = t.data
if not exc:
t.coro.send(None)
else:
# If the task is finished and on the run queue and gets here, then it
# had an exception and was not await'ed on. Throwing into it now will
# raise StopIteration and the code below will catch this and run the
# call_exception_handler function.
t.data = None
t.coro.throw(exc)
except excs_all as er:
# Check the task is not on any event queue
assert t.data is None
# This task is done, check if it's the main task and then loop should stop
if t is main_task:
if isinstance(er, StopIteration):
return er.value
raise er
if t.state:
# Task was running but is now finished.
waiting = False
if t.state is True:
# "None" indicates that the task is complete and not await'ed on (yet).
t.state = None
else:
# Schedule any other tasks waiting on the completion of this task.
while t.state.peek():
_task_queue.push_head(t.state.pop_head())
waiting = True
# "False" indicates that the task is complete and has been await'ed on.
t.state = False
if not waiting and not isinstance(er, excs_stop):
# An exception ended this detached task, so queue it for later
# execution to handle the uncaught exception if no other task retrieves
# the exception in the meantime (this is handled by Task.throw).
_task_queue.push_head(t)
# Save return value of coro to pass up to caller.
t.data = er
elif t.state is None:
# Task is already finished and nothing await'ed on the task,
# so call the exception handler.
_exc_context["exception"] = exc
_exc_context["future"] = t
Loop.call_exception_handler(_exc_context)
# Create a new task from a coroutine and run it until it finishes
def run(coro):
return run_until_complete(create_task(coro))
################################################################################
# Event loop wrapper
async def _stopper():
pass
_stop_task = None
class Loop:
_exc_handler = None
def create_task(coro):
return create_task(coro)
def run_forever():
global _stop_task
_stop_task = Task(_stopper(), globals())
run_until_complete(_stop_task)
# TODO should keep running until .stop() is called, even if there're no tasks left
def run_until_complete(aw):
return run_until_complete(_promote_to_task(aw))
def stop():
global _stop_task
if _stop_task is not None:
_task_queue.push_head(_stop_task)
# If stop() is called again, do nothing
_stop_task = None
def close():
pass
def set_exception_handler(handler):
Loop._exc_handler = handler
def get_exception_handler():
return Loop._exc_handler
def default_exception_handler(loop, context):
print(context["message"])
print("future:", context["future"], "coro=", context["future"].coro)
sys.print_exception(context["exception"])
def call_exception_handler(context):
(Loop._exc_handler or Loop.default_exception_handler)(Loop, context)
# The runq_len and waitq_len arguments are for legacy uasyncio compatibility
def get_event_loop(runq_len=0, waitq_len=0):
return Loop
def current_task():
return cur_task
def new_event_loop():
global _task_queue, _io_queue
# TaskQueue of Task instances
_task_queue = TaskQueue()
# Task queue and poller for stream IO
_io_queue = IOQueue()
return Loop
# Initialise default event loop
new_event_loop()

View File

@ -1,33 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
# Event class for primitive events that can be waited on, set, and cleared
class Event:
def __init__(self):
self.state = False # False=unset; True=set
self.waiting = core.TaskQueue() # Queue of Tasks waiting on completion of this event
def is_set(self):
return self.state
def set(self):
# Event becomes set, schedule any tasks waiting on it
# Note: This must not be called from anything except the thread running
# the asyncio loop (i.e. neither hard or soft IRQ, or a different thread).
while self.waiting.peek():
core._task_queue.push_head(self.waiting.pop_head())
self.state = True
def clear(self):
self.state = False
async def wait(self):
if not self.state:
# Event not set, put the calling task on the event's waiting queue
self.waiting.push_head(core.cur_task)
# Set calling task's data to the event's queue so it can be removed if needed
core.cur_task.data = self.waiting
yield
return True

View File

@ -1,74 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
async def wait_for(aw, timeout, sleep=core.sleep):
aw = core._promote_to_task(aw)
if timeout is None:
return await aw
def runner(waiter, aw):
nonlocal status, result
try:
result = await aw
s = True
except BaseException as er:
s = er
if status is None:
# The waiter is still waiting, set status for it and cancel it.
status = s
waiter.cancel()
# Run aw in a separate runner task that manages its exceptions.
status = None
result = None
runner_task = core.create_task(runner(core.cur_task, aw))
try:
# Wait for the timeout to elapse.
await sleep(timeout)
except core.CancelledError as er:
if status is True:
# aw completed successfully and cancelled the sleep, so return aw's result.
return result
elif status is None:
# This wait_for was cancelled externally, so cancel aw and re-raise.
status = True
runner_task.cancel()
raise er
else:
# aw raised an exception, propagate it out to the caller.
raise status
# The sleep finished before aw, so cancel aw and raise TimeoutError.
status = True
runner_task.cancel()
await runner_task
raise core.TimeoutError
def wait_for_ms(aw, timeout):
return wait_for(aw, timeout, core.sleep_ms)
async def gather(*aws, return_exceptions=False):
ts = [core._promote_to_task(aw) for aw in aws]
for i in range(len(ts)):
try:
# TODO handle cancel of gather itself
# if ts[i].coro:
# iter(ts[i]).waiting.push_head(cur_task)
# try:
# yield
# except CancelledError as er:
# # cancel all waiting tasks
# raise er
ts[i] = await ts[i]
except (core.CancelledError, Exception) as er:
if return_exceptions:
ts[i] = er
else:
raise er
return ts

View File

@ -1,53 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
# Lock class for primitive mutex capability
class Lock:
def __init__(self):
# The state can take the following values:
# - 0: unlocked
# - 1: locked
# - <Task>: unlocked but this task has been scheduled to acquire the lock next
self.state = 0
# Queue of Tasks waiting to acquire this Lock
self.waiting = core.TaskQueue()
def locked(self):
return self.state == 1
def release(self):
if self.state != 1:
raise RuntimeError("Lock not acquired")
if self.waiting.peek():
# Task(s) waiting on lock, schedule next Task
self.state = self.waiting.pop_head()
core._task_queue.push_head(self.state)
else:
# No Task waiting so unlock
self.state = 0
async def acquire(self):
if self.state != 0:
# Lock unavailable, put the calling Task on the waiting queue
self.waiting.push_head(core.cur_task)
# Set calling task's data to the lock's queue so it can be removed if needed
core.cur_task.data = self.waiting
try:
yield
except core.CancelledError as er:
if self.state == core.cur_task:
# Cancelled while pending on resume, schedule next waiting Task
self.state = 1
self.release()
raise er
# Lock available, set it as locked
self.state = 1
return True
async def __aenter__(self):
return await self.acquire()
async def __aexit__(self, exc_type, exc, tb):
return self.release()

View File

@ -1,13 +0,0 @@
# This list of frozen files doesn't include task.py because that's provided by the C module.
freeze(
"..",
(
"uasyncio/__init__.py",
"uasyncio/core.py",
"uasyncio/event.py",
"uasyncio/funcs.py",
"uasyncio/lock.py",
"uasyncio/stream.py",
),
opt=3,
)

View File

@ -1,164 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
from . import core
class Stream:
def __init__(self, s, e={}):
self.s = s
self.e = e
self.out_buf = b""
def get_extra_info(self, v):
return self.e[v]
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc, tb):
await self.close()
def close(self):
pass
async def wait_closed(self):
# TODO yield?
self.s.close()
async def read(self, n):
yield core._io_queue.queue_read(self.s)
return self.s.read(n)
async def readinto(self, buf):
yield core._io_queue.queue_read(self.s)
return self.s.readinto(buf)
async def readexactly(self, n):
r = b""
while n:
yield core._io_queue.queue_read(self.s)
r2 = self.s.read(n)
if r2 is not None:
if not len(r2):
raise EOFError
r += r2
n -= len(r2)
return r
async def readline(self):
l = b""
while True:
yield core._io_queue.queue_read(self.s)
l2 = self.s.readline() # may do multiple reads but won't block
l += l2
if not l2 or l[-1] == 10: # \n (check l in case l2 is str)
return l
def write(self, buf):
self.out_buf += buf
async def drain(self):
mv = memoryview(self.out_buf)
off = 0
while off < len(mv):
yield core._io_queue.queue_write(self.s)
ret = self.s.write(mv[off:])
if ret is not None:
off += ret
self.out_buf = b""
# Stream can be used for both reading and writing to save code size
StreamReader = Stream
StreamWriter = Stream
# Create a TCP stream connection to a remote host
async def open_connection(host, port):
from uerrno import EINPROGRESS
import usocket as socket
ai = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)[0] # TODO this is blocking!
s = socket.socket(ai[0], ai[1], ai[2])
s.setblocking(False)
ss = Stream(s)
try:
s.connect(ai[-1])
except OSError as er:
if er.errno != EINPROGRESS:
raise er
yield core._io_queue.queue_write(s)
return ss, ss
# Class representing a TCP stream server, can be closed and used in "async with"
class Server:
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc, tb):
self.close()
await self.wait_closed()
def close(self):
self.task.cancel()
async def wait_closed(self):
await self.task
async def _serve(self, s, cb):
# Accept incoming connections
while True:
try:
yield core._io_queue.queue_read(s)
except core.CancelledError:
# Shutdown server
s.close()
return
try:
s2, addr = s.accept()
except:
# Ignore a failed accept
continue
s2.setblocking(False)
s2s = Stream(s2, {"peername": addr})
core.create_task(cb(s2s, s2s))
# Helper function to start a TCP stream server, running as a new task
# TODO could use an accept-callback on socket read activity instead of creating a task
async def start_server(cb, host, port, backlog=5):
import usocket as socket
# Create and bind server socket.
host = socket.getaddrinfo(host, port)[0] # TODO this is blocking!
s = socket.socket()
s.setblocking(False)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(host[-1])
s.listen(backlog)
# Create and return server object and task.
srv = Server()
srv.task = core.create_task(srv._serve(s, cb))
return srv
################################################################################
# Legacy uasyncio compatibility
async def stream_awrite(self, buf, off=0, sz=-1):
if off != 0 or sz != -1:
buf = memoryview(buf)
if sz == -1:
sz = len(buf)
buf = buf[off : off + sz]
self.write(buf)
await self.drain()
Stream.aclose = Stream.wait_closed
Stream.awrite = stream_awrite
Stream.awritestr = stream_awrite # TODO explicitly convert to bytes?

View File

@ -1,179 +0,0 @@
# MicroPython uasyncio module
# MIT license; Copyright (c) 2019-2020 Damien P. George
# This file contains the core TaskQueue based on a pairing heap, and the core Task class.
# They can optionally be replaced by C implementations.
from . import core
# pairing-heap meld of 2 heaps; O(1)
def ph_meld(h1, h2):
if h1 is None:
return h2
if h2 is None:
return h1
lt = core.ticks_diff(h1.ph_key, h2.ph_key) < 0
if lt:
if h1.ph_child is None:
h1.ph_child = h2
else:
h1.ph_child_last.ph_next = h2
h1.ph_child_last = h2
h2.ph_next = None
h2.ph_rightmost_parent = h1
return h1
else:
h1.ph_next = h2.ph_child
h2.ph_child = h1
if h1.ph_next is None:
h2.ph_child_last = h1
h1.ph_rightmost_parent = h2
return h2
# pairing-heap pairing operation; amortised O(log N)
def ph_pairing(child):
heap = None
while child is not None:
n1 = child
child = child.ph_next
n1.ph_next = None
if child is not None:
n2 = child
child = child.ph_next
n2.ph_next = None
n1 = ph_meld(n1, n2)
heap = ph_meld(heap, n1)
return heap
# pairing-heap delete of a node; stable, amortised O(log N)
def ph_delete(heap, node):
if node is heap:
child = heap.ph_child
node.ph_child = None
return ph_pairing(child)
# Find parent of node
parent = node
while parent.ph_next is not None:
parent = parent.ph_next
parent = parent.ph_rightmost_parent
# Replace node with pairing of its children
if node is parent.ph_child and node.ph_child is None:
parent.ph_child = node.ph_next
node.ph_next = None
return heap
elif node is parent.ph_child:
child = node.ph_child
next = node.ph_next
node.ph_child = None
node.ph_next = None
node = ph_pairing(child)
parent.ph_child = node
else:
n = parent.ph_child
while node is not n.ph_next:
n = n.ph_next
child = node.ph_child
next = node.ph_next
node.ph_child = None
node.ph_next = None
node = ph_pairing(child)
if node is None:
node = n
else:
n.ph_next = node
node.ph_next = next
if next is None:
node.ph_rightmost_parent = parent
parent.ph_child_last = node
return heap
# TaskQueue class based on the above pairing-heap functions.
class TaskQueue:
def __init__(self):
self.heap = None
def peek(self):
return self.heap
def push_sorted(self, v, key):
v.data = None
v.ph_key = key
v.ph_child = None
v.ph_next = None
self.heap = ph_meld(v, self.heap)
def push_head(self, v):
self.push_sorted(v, core.ticks())
def pop_head(self):
v = self.heap
self.heap = ph_pairing(self.heap.ph_child)
return v
def remove(self, v):
self.heap = ph_delete(self.heap, v)
# Task class representing a coroutine, can be waited on and cancelled.
class Task:
def __init__(self, coro, globals=None):
self.coro = coro # Coroutine of this Task
self.data = None # General data for queue it is waiting on
self.state = True # None, False, True or a TaskQueue instance
self.ph_key = 0 # Pairing heap
self.ph_child = None # Paring heap
self.ph_child_last = None # Paring heap
self.ph_next = None # Paring heap
self.ph_rightmost_parent = None # Paring heap
def __await__(self):
if not self.state:
# Task finished, signal that is has been await'ed on.
self.state = False
elif self.state is True:
# Allocated head of linked list of Tasks waiting on completion of this task.
self.state = TaskQueue()
return self
def __next__(self):
if not self.state:
if self.data is None:
# Task finished but has already been sent to the loop's exception handler.
raise StopIteration
else:
# Task finished, raise return value to caller so it can continue.
raise self.data
else:
# Put calling task on waiting queue.
self.state.push_head(core.cur_task)
# Set calling task's data to this task that it waits on, to double-link it.
core.cur_task.data = self
def done(self):
return not self.state
def cancel(self):
# Check if task is already finished.
if not self.state:
return False
# Can't cancel self (not supported yet).
if self is core.cur_task:
raise RuntimeError("can't cancel self")
# If Task waits on another task then forward the cancel to the one it's waiting on.
while isinstance(self.data, Task):
self = self.data
# Reschedule Task as a cancelled task.
if hasattr(self.data, "remove"):
# Not on the main running queue, remove the task from the queue it's on.
self.data.remove(self)
core._task_queue.push_head(self)
elif core.ticks_diff(self.ph_key, core.ticks()) > 0:
# On the main running queue but scheduled in the future, so bring it forward to now.
core._task_queue.remove(self)
core._task_queue.push_head(self)
self.data = core.CancelledError
return True

View File

@ -1,8 +1,29 @@
// Copyright (c) 2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// SPDX-FileCopyrightText: Copyright (c) 2013-2016 Damien P. George *
// * The MIT License (MIT)
// SPDX-License-Identifier: MIT *
* Copyright (c) 2013-2016 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* 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 "py/mpconfig.h" #include "py/mpconfig.h"
#if MICROPY_PY_UTIME_MP_HAL #if MICROPY_PY_UTIME_MP_HAL

View File

@ -1,9 +1,29 @@
// Copyright (c) 2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// SPDX-FileCopyrightText: Copyright (c) 2013-2016 Damien P. George *
// * The MIT License (MIT)
// SPDX-License-Identifier: MIT *
* Copyright (c) 2013-2016 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* 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.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H #ifndef MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H
#define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H #define MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2017 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2017 Damien P. George
*
* 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 <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@ -386,8 +407,7 @@ mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args) {
if (vfs == MP_VFS_ROOT) { if (vfs == MP_VFS_ROOT) {
// list the root directory // list the root directory
mp_vfs_ilistdir_it_t *iter = m_new_obj(mp_vfs_ilistdir_it_t); mp_vfs_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_ilistdir_it_t, &mp_type_polymorph_iter);
iter->base.type = &mp_type_polymorph_iter;
iter->iternext = mp_vfs_ilistdir_it_iternext; iter->iternext = mp_vfs_ilistdir_it_iternext;
iter->cur.vfs = MP_STATE_VM(vfs_mount_table); iter->cur.vfs = MP_STATE_VM(vfs_mount_table);
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;

View File

@ -1,12 +1,32 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2017 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2017 Damien P. George
*
* 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.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_VFS_H #ifndef MICROPY_INCLUDED_EXTMOD_VFS_H
#define MICROPY_INCLUDED_EXTMOD_VFS_H #define MICROPY_INCLUDED_EXTMOD_VFS_H
#include "py/lexer.h" #include "py/builtin.h"
#include "py/obj.h" #include "py/obj.h"
#include "py/proto.h" #include "py/proto.h"

View File

@ -1,8 +1,29 @@
// Copyright (c) 2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George *
// * The MIT License (MIT)
// SPDX-License-Identifier: MIT *
* Copyright (c) 2014 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* 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 "py/mpconfig.h" #include "py/mpconfig.h"
#if MICROPY_VFS_FAT #if MICROPY_VFS_FAT
@ -54,8 +75,7 @@ STATIC mp_obj_t fat_vfs_make_new(const mp_obj_type_t *type, size_t n_args, size_
mp_arg_check_num(n_args, n_kw, 1, 1, false); mp_arg_check_num(n_args, n_kw, 1, 1, false);
// create new object // create new object
fs_user_mount_t *vfs = m_new_obj(fs_user_mount_t); fs_user_mount_t *vfs = mp_obj_malloc(fs_user_mount_t, type);
vfs->base.type = type;
vfs->fatfs.drv = vfs; vfs->fatfs.drv = vfs;
// Initialise underlying block device // Initialise underlying block device
@ -171,8 +191,7 @@ STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
} }
// Create a new iterator object to list the dir // Create a new iterator object to list the dir
mp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t); mp_vfs_fat_ilistdir_it_t *iter = mp_obj_malloc(mp_vfs_fat_ilistdir_it_t, &mp_type_polymorph_iter);
iter->base.type = &mp_type_polymorph_iter;
iter->iternext = mp_vfs_fat_ilistdir_it_iternext; iter->iternext = mp_vfs_fat_ilistdir_it_iternext;
iter->is_str = is_str_type; iter->is_str = is_str_type;
FRESULT res = f_opendir(&self->fatfs, &iter->dir, path); FRESULT res = f_opendir(&self->fatfs, &iter->dir, path);

View File

@ -1,8 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* 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.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_VFS_FAT_H #ifndef MICROPY_INCLUDED_EXTMOD_VFS_FAT_H
#define MICROPY_INCLUDED_EXTMOD_VFS_FAT_H #define MICROPY_INCLUDED_EXTMOD_VFS_FAT_H

View File

@ -1,7 +1,31 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * Original template for this file comes from:
* Low level disk I/O module skeleton for FatFs, (C)ChaN, 2013
*
* The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* 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 "py/mpconfig.h" #include "py/mpconfig.h"
#if MICROPY_VFS && MICROPY_VFS_FAT #if MICROPY_VFS && MICROPY_VFS_FAT

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2013, 2014 Damien P. George
*
* 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 "py/mpconfig.h" #include "py/mpconfig.h"
#if MICROPY_VFS && MICROPY_VFS_FAT #if MICROPY_VFS && MICROPY_VFS_FAT
@ -136,6 +157,7 @@ STATIC const mp_arg_t file_open_args[] = {
}; };
#define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args) #define FILE_OPEN_NUM_ARGS MP_ARRAY_SIZE(file_open_args)
// CIRCUITPY is more careful about validating the open mode.
STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) { STATIC mp_obj_t file_open(fs_user_mount_t *vfs, const mp_obj_type_t *type, mp_arg_val_t *args) {
int mode = 0; int mode = 0;
const char *mode_s = mp_obj_str_get_str(args[1].u_obj); const char *mode_s = mp_obj_str_get_str(args[1].u_obj);

View File

@ -203,8 +203,7 @@ STATIC mp_obj_t MP_VFS_LFSx(ilistdir_func)(size_t n_args, const mp_obj_t *args)
path = vstr_null_terminated_str(&self->cur_dir); path = vstr_null_terminated_str(&self->cur_dir);
} }
MP_VFS_LFSx(ilistdir_it_t) * iter = m_new_obj(MP_VFS_LFSx(ilistdir_it_t)); MP_VFS_LFSx(ilistdir_it_t) * iter = mp_obj_malloc(MP_VFS_LFSx(ilistdir_it_t), &mp_type_polymorph_iter);
iter->base.type = &mp_type_polymorph_iter;
iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext); iter->iternext = MP_VFS_LFSx(ilistdir_it_iternext);
iter->is_str = is_str_type; iter->is_str = is_str_type;
iter->vfs = self; iter->vfs = self;

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2017-2018 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2017-2018 Damien P. George
*
* 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 "py/runtime.h" #include "py/runtime.h"
#include "py/mperrno.h" #include "py/mperrno.h"
@ -16,6 +37,9 @@
#include <string.h> #include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <dirent.h> #include <dirent.h>
#ifdef _MSC_VER
#include <direct.h> // For mkdir etc.
#endif
typedef struct _mp_obj_vfs_posix_t { typedef struct _mp_obj_vfs_posix_t {
mp_obj_base_t base; mp_obj_base_t base;
@ -74,8 +98,7 @@ STATIC mp_import_stat_t mp_vfs_posix_import_stat(void *self_in, const char *path
STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { STATIC mp_obj_t vfs_posix_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false); mp_arg_check_num(n_args, n_kw, 0, 1, false);
mp_obj_vfs_posix_t *vfs = m_new_obj(mp_obj_vfs_posix_t); mp_obj_vfs_posix_t *vfs = mp_obj_malloc(mp_obj_vfs_posix_t, type);
vfs->base.type = type;
vstr_init(&vfs->root, 0); vstr_init(&vfs->root, 0);
if (n_args == 1) { if (n_args == 1) {
vstr_add_str(&vfs->root, mp_obj_str_get_str(args[0])); vstr_add_str(&vfs->root, mp_obj_str_get_str(args[0]));
@ -205,8 +228,7 @@ STATIC mp_obj_t vfs_posix_ilistdir_it_iternext(mp_obj_t self_in) {
STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) { STATIC mp_obj_t vfs_posix_ilistdir(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
vfs_posix_ilistdir_it_t *iter = m_new_obj(vfs_posix_ilistdir_it_t); vfs_posix_ilistdir_it_t *iter = mp_obj_malloc(vfs_posix_ilistdir_it_t, &mp_type_polymorph_iter);
iter->base.type = &mp_type_polymorph_iter;
iter->iternext = vfs_posix_ilistdir_it_iternext; iter->iternext = vfs_posix_ilistdir_it_iternext;
iter->is_str = mp_obj_get_type(path_in) == &mp_type_str; iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
const char *path = vfs_posix_get_path_str(self, path_in); const char *path = vfs_posix_get_path_str(self, path_in);
@ -233,7 +255,11 @@ STATIC mp_obj_t vfs_posix_mkdir(mp_obj_t self_in, mp_obj_t path_in) {
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
const char *path = vfs_posix_get_path_str(self, path_in); const char *path = vfs_posix_get_path_str(self, path_in);
MP_THREAD_GIL_EXIT(); MP_THREAD_GIL_EXIT();
#ifdef _WIN32
int ret = mkdir(path);
#else
int ret = mkdir(path, 0777); int ret = mkdir(path, 0777);
#endif
MP_THREAD_GIL_ENTER(); MP_THREAD_GIL_ENTER();
if (ret != 0) { if (ret != 0) {
mp_raise_OSError(errno); mp_raise_OSError(errno);
@ -287,6 +313,8 @@ STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) {
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat); STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_stat_obj, vfs_posix_stat);
#if MICROPY_PY_UOS_STATVFS
#ifdef __ANDROID__ #ifdef __ANDROID__
#define USE_STATFS 1 #define USE_STATFS 1
#endif #endif
@ -328,6 +356,8 @@ STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) {
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_statvfs_obj, vfs_posix_statvfs); STATIC MP_DEFINE_CONST_FUN_OBJ_2(vfs_posix_statvfs_obj, vfs_posix_statvfs);
#endif
STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = { STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_posix_mount_obj) }, { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&vfs_posix_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_posix_umount_obj) }, { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&vfs_posix_umount_obj) },
@ -341,7 +371,9 @@ STATIC const mp_rom_map_elem_t vfs_posix_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_posix_rename_obj) }, { MP_ROM_QSTR(MP_QSTR_rename), MP_ROM_PTR(&vfs_posix_rename_obj) },
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_posix_rmdir_obj) }, { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&vfs_posix_rmdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_posix_stat_obj) }, { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&vfs_posix_stat_obj) },
#if MICROPY_PY_UOS_STATVFS
{ MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) }, { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&vfs_posix_statvfs_obj) },
#endif
}; };
STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table); STATIC MP_DEFINE_CONST_DICT(vfs_posix_locals_dict, vfs_posix_locals_dict_table);

View File

@ -1,8 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2018 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2018 Damien P. George
*
* 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.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H #ifndef MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H
#define MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H #define MICROPY_INCLUDED_EXTMOD_VFS_POSIX_H

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2013-2018 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2013-2018 Damien P. George
*
* 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 "py/mphal.h" #include "py/mphal.h"
#include "py/mpthread.h" #include "py/mpthread.h"

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) /*
// SPDX-FileCopyrightText: Copyright (c) 2013-2017 Damien P. George * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2013-2017 Damien P. George
*
* 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 <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>

View File

@ -1,7 +1,28 @@
// SPDX-FileCopyrightText: Copyright (c) 2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* 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 "extmod/virtpin.h" #include "extmod/virtpin.h"
#include "py/proto.h" #include "py/proto.h"

View File

@ -1,8 +1,28 @@
// Copyright (c) 2016 Paul Sokolovsky /*
// SPDX-FileCopyrightText: 2014 MicroPython & CircuitPython contributors (https://github.com/adafruit/circuitpython/graphs/contributors) * This file is part of the MicroPython project, http://micropython.org/
// *
// SPDX-License-Identifier: MIT * The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* 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.
*/
#ifndef MICROPY_INCLUDED_EXTMOD_VIRTPIN_H #ifndef MICROPY_INCLUDED_EXTMOD_VIRTPIN_H
#define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H #define MICROPY_INCLUDED_EXTMOD_VIRTPIN_H

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
/* /*
* The little filesystem * The little filesystem
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -22,7 +23,7 @@ extern "C"
// Software library version // Software library version
// Major (top-nibble), incremented on backwards incompatible changes // Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions // Minor (bottom-nibble), incremented on feature additions
#define LFS2_VERSION 0x00020003 #define LFS2_VERSION 0x00020005
#define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16)) #define LFS2_VERSION_MAJOR (0xffff & (LFS2_VERSION >> 16))
#define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0)) #define LFS2_VERSION_MINOR (0xffff & (LFS2_VERSION >> 0))
@ -159,49 +160,49 @@ struct lfs2_config {
// information to the block device operations // information to the block device operations
void *context; void *context;
// Read a region in a block. Negative error codes are propogated // Read a region in a block. Negative error codes are propagated
// to the user. // to the user.
int (*read)(const struct lfs2_config *c, lfs2_block_t block, int (*read)(const struct lfs2_config *c, lfs2_block_t block,
lfs2_off_t off, void *buffer, lfs2_size_t size); lfs2_off_t off, void *buffer, lfs2_size_t size);
// Program a region in a block. The block must have previously // Program a region in a block. The block must have previously
// been erased. Negative error codes are propogated to the user. // been erased. Negative error codes are propagated to the user.
// May return LFS2_ERR_CORRUPT if the block should be considered bad. // May return LFS2_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs2_config *c, lfs2_block_t block, int (*prog)(const struct lfs2_config *c, lfs2_block_t block,
lfs2_off_t off, const void *buffer, lfs2_size_t size); lfs2_off_t off, const void *buffer, lfs2_size_t size);
// Erase a block. A block must be erased before being programmed. // Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes // The state of an erased block is undefined. Negative error codes
// are propogated to the user. // are propagated to the user.
// May return LFS2_ERR_CORRUPT if the block should be considered bad. // May return LFS2_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs2_config *c, lfs2_block_t block); int (*erase)(const struct lfs2_config *c, lfs2_block_t block);
// Sync the state of the underlying block device. Negative error codes // Sync the state of the underlying block device. Negative error codes
// are propogated to the user. // are propagated to the user.
int (*sync)(const struct lfs2_config *c); int (*sync)(const struct lfs2_config *c);
#ifdef LFS2_THREADSAFE #ifdef LFS2_THREADSAFE
// Lock the underlying block device. Negative error codes // Lock the underlying block device. Negative error codes
// are propogated to the user. // are propagated to the user.
int (*lock)(const struct lfs2_config *c); int (*lock)(const struct lfs2_config *c);
// Unlock the underlying block device. Negative error codes // Unlock the underlying block device. Negative error codes
// are propogated to the user. // are propagated to the user.
int (*unlock)(const struct lfs2_config *c); int (*unlock)(const struct lfs2_config *c);
#endif #endif
// Minimum size of a block read. All read operations will be a // Minimum size of a block read in bytes. All read operations will be a
// multiple of this value. // multiple of this value.
lfs2_size_t read_size; lfs2_size_t read_size;
// Minimum size of a block program. All program operations will be a // Minimum size of a block program in bytes. All program operations will be
// multiple of this value. // a multiple of this value.
lfs2_size_t prog_size; lfs2_size_t prog_size;
// Size of an erasable block. This does not impact ram consumption and // Size of an erasable block in bytes. This does not impact ram consumption
// may be larger than the physical erase size. However, non-inlined files // and may be larger than the physical erase size. However, non-inlined
// take up at minimum one block. Must be a multiple of the read // files take up at minimum one block. Must be a multiple of the read and
// and program sizes. // program sizes.
lfs2_size_t block_size; lfs2_size_t block_size;
// Number of erasable blocks on the device. // Number of erasable blocks on the device.
@ -215,11 +216,11 @@ struct lfs2_config {
// Set to -1 to disable block-level wear-leveling. // Set to -1 to disable block-level wear-leveling.
int32_t block_cycles; int32_t block_cycles;
// Size of block caches. Each cache buffers a portion of a block in RAM. // Size of block caches in bytes. Each cache buffers a portion of a block in
// The littlefs needs a read cache, a program cache, and one additional // RAM. The littlefs needs a read cache, a program cache, and one additional
// cache per file. Larger caches can improve performance by storing more // cache per file. Larger caches can improve performance by storing more
// data and reducing the number of disk accesses. Must be a multiple of // data and reducing the number of disk accesses. Must be a multiple of the
// the read and program sizes, and a factor of the block size. // read and program sizes, and a factor of the block size.
lfs2_size_t cache_size; lfs2_size_t cache_size;
// Size of the lookahead buffer in bytes. A larger lookahead buffer // Size of the lookahead buffer in bytes. A larger lookahead buffer
@ -256,6 +257,12 @@ struct lfs2_config {
// larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to // larger attributes size but must be <= LFS2_ATTR_MAX. Defaults to
// LFS2_ATTR_MAX when zero. // LFS2_ATTR_MAX when zero.
lfs2_size_t attr_max; lfs2_size_t attr_max;
// Optional upper limit on total space given to metadata pairs in bytes. On
// devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)
// can help bound the metadata compaction time. Must be <= block_size.
// Defaults to block_size when zero.
lfs2_size_t metadata_max;
}; };
// File info structure // File info structure
@ -479,7 +486,7 @@ int lfs2_stat(lfs2_t *lfs2, const char *path, struct lfs2_info *info);
// Returns the size of the attribute, or a negative error code on failure. // Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective // Note, the returned size is the size of the attribute on disk, irrespective
// of the size of the buffer. This can be used to dynamically allocate a buffer // of the size of the buffer. This can be used to dynamically allocate a buffer
// or check for existance. // or check for existence.
lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path, lfs2_ssize_t lfs2_getattr(lfs2_t *lfs2, const char *path,
uint8_t type, void *buffer, lfs2_size_t size); uint8_t type, void *buffer, lfs2_size_t size);
@ -507,6 +514,7 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type);
/// File operations /// /// File operations ///
#ifndef LFS2_NO_MALLOC
// Open a file // Open a file
// //
// The mode that the file is opened in is determined by the flags, which // The mode that the file is opened in is determined by the flags, which
@ -516,6 +524,10 @@ int lfs2_removeattr(lfs2_t *lfs2, const char *path, uint8_t type);
int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file, int lfs2_file_open(lfs2_t *lfs2, lfs2_file_t *file,
const char *path, int flags); const char *path, int flags);
// if LFS2_NO_MALLOC is defined, lfs2_file_open() will fail with LFS2_ERR_NOMEM
// thus use lfs2_file_opencfg() with config.buffer set.
#endif
// Open a file with extra configuration // Open a file with extra configuration
// //
// The mode that the file is opened in is determined by the flags, which // The mode that the file is opened in is determined by the flags, which

View File

@ -1,6 +1,7 @@
/* /*
* lfs2 util functions * lfs2 util functions
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */

View File

@ -1,6 +1,7 @@
/* /*
* lfs2 utility functions * lfs2 utility functions
* *
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved. * Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -49,6 +50,7 @@ extern "C"
// code footprint // code footprint
// Logging functions // Logging functions
#ifndef LFS2_TRACE
#ifdef LFS2_YES_TRACE #ifdef LFS2_YES_TRACE
#define LFS2_TRACE_(fmt, ...) \ #define LFS2_TRACE_(fmt, ...) \
printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
@ -56,7 +58,9 @@ extern "C"
#else #else
#define LFS2_TRACE(...) #define LFS2_TRACE(...)
#endif #endif
#endif
#ifndef LFS2_DEBUG
#ifndef LFS2_NO_DEBUG #ifndef LFS2_NO_DEBUG
#define LFS2_DEBUG_(fmt, ...) \ #define LFS2_DEBUG_(fmt, ...) \
printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
@ -64,7 +68,9 @@ extern "C"
#else #else
#define LFS2_DEBUG(...) #define LFS2_DEBUG(...)
#endif #endif
#endif
#ifndef LFS2_WARN
#ifndef LFS2_NO_WARN #ifndef LFS2_NO_WARN
#define LFS2_WARN_(fmt, ...) \ #define LFS2_WARN_(fmt, ...) \
printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
@ -72,7 +78,9 @@ extern "C"
#else #else
#define LFS2_WARN(...) #define LFS2_WARN(...)
#endif #endif
#endif
#ifndef LFS2_ERROR
#ifndef LFS2_NO_ERROR #ifndef LFS2_NO_ERROR
#define LFS2_ERROR_(fmt, ...) \ #define LFS2_ERROR_(fmt, ...) \
printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__) printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
@ -80,13 +88,16 @@ extern "C"
#else #else
#define LFS2_ERROR(...) #define LFS2_ERROR(...)
#endif #endif
#endif
// Runtime assertions // Runtime assertions
#ifndef LFS2_ASSERT
#ifndef LFS2_NO_ASSERT #ifndef LFS2_NO_ASSERT
#define LFS2_ASSERT(test) assert(test) #define LFS2_ASSERT(test) assert(test)
#else #else
#define LFS2_ASSERT(test) #define LFS2_ASSERT(test)
#endif #endif
#endif
// Builtin functions, these may be replaced by more efficient // Builtin functions, these may be replaced by more efficient

View File

@ -6,7 +6,7 @@
* *
* The MIT License (MIT) * The MIT License (MIT)
* *
* SPDX-FileCopyrightText: Copyright (c) 2013-2019 Damien P. George * Copyright (c) 2013-2019 Damien P. George
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal

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