Merge tag 'v1.15' into dev-8.0
The esp32 port moves to CMake and has S2 support, new features for rp2 This release of MicroPython adds general support in the core for using CMake as a build system. The rp2 port is consolidated to use the new CMake files, and the esp32 and zephyr ports have switched to build as pure CMake projects. These three ports have SDKs which are built around CMake and this change should make them easier to maintain and use. As part of this work, CMake based ports now have support for user C modules. Authors of user C modules should now provide both .mk and .cmake configuration files (following the documentation and examples). A bug was fixed in the multiple precision integer library, an arithmetic overflow in the long division routine. Prior to this fix certain integer divisions would take excessive time and produce incorrect results. See commit 0a59938574502b19b3d685133084399c090d3c11 for details. There was also a fix for regular expressions, to check and report byte overflow errors when compiling expressions. See commit 172fb5230a3943eeb6fbbb4de1dc56b16e2a7637. In the uasyncio library, a new MicroPython extension has been added, ThreadSafeFlag, which can be set from outside the asyncio event loop, such as other threads, IRQs or scheduler context. It allows preemptive code like IRQs to signal asyncio tasks, which are by nature cooperative (non-preemptive). asyncio.current_task() has also been added, with the same semantics as CPython. As mentioned above, the esp32 port has switched to a full CMake-based project, and traditional make capability has been removed (although a simple helper Makefile remains to keep top-level build/deploy commands consistent with other ports). Because of the move to CMake, network.LAN support has been removed, to be added back in the future (use a prior release if LAN is needed). Basic support for Non-Volatile-Storage is added to the esp32 module. And there is also preliminary support for ESP32S2 SoCs and USB, with a GENERIC_S2 board defined. On the mimxrt and samd ports, USB CDC TX handling has been fixed so that it now works reliably. The rp2 port has had many more core Python features enabled, along with the enabling of ubinascii.crc32(), the uos.VfsFat and machine.Signal classes, and the uerrno module. uos.urandom() has been added and machine.freq() can now change the CPU clock frequency. The machine.UART class now has support for timeout/timeout_char, inverted TX/RX lines, and buffered TX/RX with configurable sized buffers. For PIO, StateMachine has added restart(), rx_fifo() and tx_fifo() helper functions, and support for FIFO joining. There is now support for user C modules (via CMake) and for building different board configurations (the default remains the PICO board). USB reliability has been improved. For the stm32 port, there is now more configuration options for boards, such as USBD VID/PID and fine-grained selection of modules. The UART class now supports LPUART on L0, L4, H7 and WB MCUs. WB MCUs have a fix for a race condition accessing the BLE ACL free buffer list, and a workaround for a low-level BLE bug. The zephyr port has been updated to use zephyr v2.5.0, and now builds MicroPython as a CMake target. What follows is a detailed list of changes, generated from the git commit history, and organised into sections. Main components =============== all: - rename BYTES_PER_WORD to MP_BYTES_PER_OBJ_WORD - add .git-blame-ignore-revs for fixing up git blame output py core: - gc: don't include mpconfig.h and misc.h in gc.h - remove BITS_PER_WORD definition - rename BITS_PER_BYTE to MP_BITS_PER_BYTE - rename WORD_MSBIT_HIGH to MP_OBJ_WORD_MSBIT_HIGH - gc: change include of stdint.h to stddef.h - mpz: fix overflow of borrow in mpn_div - add core cmake rule files - expand lists in core cmake custom commands - mkrules.cmake: rename QSTR_DEFS variables to QSTRDEFS - mkrules.cmake: add MICROPY_QSTRDEFS_PORT to qstr build process - nlr: implement NLR for AArch64 - nlrx64: fix typo in comment - vm: for tracing use mp_printf, and print state when thread enabled - rename remaining object types to be of the form mp_type_xxx - py.cmake: move qstr helper code to micropy_gather_target_properties - py.cmake: introduce MICROPY_INC_CORE as a list with core includes - profile: resolve name collision with STATIC unset - runtime: make sys.modules preallocate to a configurable size extmod: - vfs_posix_file: allow closing an already closed file - btstack: add HCI trace debugging option in btstack_hci_uart - btstack: add stub functions for passkey, l2cap bindings - btstack: enable SYNC_EVENTS, PAIRING_BONDING by default - uasyncio: add asyncio.current_task() - add core cmake rule files - nimble: ensure handle is set on read error - moduselect: fix unsigned/signed comparison for timeout!=-1 - uasyncio: add ThreadSafeFlag - nimble/hal/hal_uart: fix HCI_TRACE format specifiers - modbluetooth: allow NimBLE to use Zephyr static address - modussl: fix ussl read/recv/send/write errors when non-blocking - btstack: use MICROPY_HW_BLE_UART_BAUDRATE for first UART init - modbluetooth: separate enabling of "client" from "central" - extmod.cmake: add modonewire.c to MICROPY_SOURCE_EXTMOD list - modbluetooth: free temp arrays in gatts register services - re1.5: check and report byte overflow errors in _compilecode - extmod.cmake: add support to build btree module with CMake lib: - tinyusb: update to version 0.8.0 - mbedtls: switch to currently latest commit of LTS branch v2.16 - utils/gchelper_generic: implement AArch64 support - pico-sdk: update to latest version 1.1.0 drivers: no changes specific to this component/port mpy-cross: no changes specific to this component/port Support components ================== docs: - library/uasyncio.rst: add docs for ThreadSafeFlag - develop/cmodules.rst: document C-modules and micropython.cmake - develop: improve user C modules to properly describe how to build examples: - usercmodule: add micropython.cmake to the C and CPP examples - usercmodules: simplify user C module enabling - embedding: fix example so it compiles again tests: - extmod/vfs_posix.py: add more tests for VfsPosix class - extmod: add test for ThreadSafeFlag - multi_bluetooth: add basic performance tests - rename run-tests to run-tests.py for consistency - run-tests.py: reformat with Black - multi_bluetooth: skip tests when BLE features are unsupported - extmod/vfs_fat_fileio2.py: close test file at end of test - run-tests.py: provide more info if script run via pyboard crashes - feature_check: check for lack of pass result rather than failure - net_inet: add 'Strict-Transport-Security' to exp file tools: - add filesystem action examples to pyboard.py help - ci.sh: change esp32 CI to work with idf.py and IDF v4.0.2 - makemanifest.py: allow passing option args to include() - ci.sh: update zephyr docker image to v0.11.13 - verifygitlog.py: show required format regexp in error message - pydfu.py: support DFU files with elements of zero size - ci.sh: add CI for CMake USER_C_MODULE support - ci.sh: build user C modules for esp32 - metrics.py: fix esp32 output filename due to move to CMake - ci.sh: build esp32 using IDF v4.0.2 and v4.3 The ports ========= all ports: - remove def of MP_PLAT_PRINT_STRN if it's the same as the default - update to build with new tinyusb bare-arm port: - clean up the code, make it run on an F405, and add a README cc3200 port: no changes specific to this component/port esp8266 port: - modules: fix fs_corrupted() to use start_sec not START_SEC esp32 port: - add support to build using IDF with cmake - esp32_rmt: don't do unnecessary check for unsigned less than zero - add explicit initialisers to silence compiler warnings - remove traditional "make" capability - boards: remove old IDF v3 sdkconfig values - boards: enable BLE on all boards - README: update based on new IDF v4 cmake build process - add support to build with ESP-IDF v4.1.1 - add support to build with ESP-IDF v4.2 - remove obsolete IDF v3 code wrapped in MICROPY_ESP_IDF_4 - modsocket: remove unix socket error code translation - set MICROPY_USE_INTERNAL_ERRNO=0 to use toolchain's errno.h - boards: enable size optimisation for builds - add support to build with ESP-IDF v4.3 pre-release - add basic support for Non-Volatile-Storage in esp32 module - make machine.soft_reset() work in main.py and reset_cause() - define MICROPY_QSTRDEFS_PORT to include special qstrs - Makefile: specify port and baud on erase_flash command - machine_hw_spi: use default pins when making SPI if none given - restore USER_C_MODULE support with new CMake build system - fix multiple definition errors with mp_hal_stdout_tx functions - enable btree module - modsocket: correctly handle poll/read of unconnected TCP socket - add initial support for ESP32S2 SoCs - add support for USB with CDC ACM - boards: add GENERIC_S2 board definition - machine_pin: use rtc_gpio_deinit instead of gpio_reset_pin javascript port: no changes specific to this component/port mimxrt port: - fix USB CDC handling so it works reliably - boards: add MIMXRT1050_EVK board, based on MIMXRT1060_EVK - enable CPYTHON_COMPAT, PY_ASYNC_AWAIT, PY_ATTRTUPLE options minimal port: no changes specific to this component/port nrf port: - drivers/usb: add USBD_IRQHandler which calls tud_int_handler pic16bit port: no changes specific to this component/port powerpc port: no changes specific to this component/port qemu-arm port: no changes specific to this component/port rp2 port: - machine_adc: only initialise the ADC periph if not already enabled - micropy_rules.cmake: fix makemoduledefs vpath to work with abs path - use local tinyusb instead of the one in pico-sdk - enable MICROPY_PY_UBINASCII_CRC32 to get ubinascii.crc32() - enable VfsFat class for FAT filesystem support - machine_uart: add timeout/timeout_char to read and write - machine_uart: add support for inverted TX and RX lines - rp2_pio: allow more than 8 consecutive pins for PIO out/set/sideset - rp2_pio: fix sm.get(buf) to not wait after getting last item - modmachine: allow changing CPU clock frequency - modmachine: re-init UART for REPL on frequency change - rp2_flash: prevent MICROPY_HW_FLASH_STORAGE_BASE being set negative - enable uerrno module - enabled more core Python features - modmachine: enable machine.Signal class - use core-provided cmake fragments instead of custom ones - mpthreadport.h: cast core_state to _mp_state_thread_t - add support for USER_C_MODULES to CMake build system - don't advertise remote wakeup for USB serial - CMakeLists.txt: enable USB enumeration fix - import uarray instead of array in rp2 module - rp2_pio: validate state machine frequency in constructor - moduos: implement uos.urandom() - rp2_pio: add StateMachine restart,rx_fifo,tx_fifo helper functions - machine_uart: add buffered transfer of data with rxbuf/txbuf kwargs - add support for building different board configurations - rp2_pio: add fifo_join support for PIO samd port: - mphalport: fix USB CDC tx handling to work reliably stm32 port: - uart: add uart_set_baudrate function - mpbthciport: only init the uart once, then use uart_set_baudrate - mboot: add unpack-dfu command to mboot_pack_dfu.py tool - usb: allow a board to configure USBD_VID and all PIDs - make pyb, uos, utime, machine and onewire modules configurable - boards: disable onewire module on boards with small flash - mpbthciport: fix initial baudrate to use provided value - mpbthciport: use mp_printf instead of printf for error message - mpbtstackport: allow chipset and secondary baudrate to be set - mboot: after sig verify, only write firmware-head if latter valid - uart: add support for LPUART1 on L0, L4, H7 and WB MCUs - boards/NUCLEO_WB55: enable LPUART1 on PA2/PA3 - enable MICROPY_PY_UBINASCII_CRC32 to get ubinascii.crc32() - rfcore: allow BLE settings to be changed by a board - storage: prevent attempts to read/write invalid block addresses - make-stmconst.py: allow "[]" chars when parsing source comments - main: fix passing state.reset_mode to init_flash_fs - powerctrl: save and restore EWUP state when configuring standby - spi: fix baudrate calculation for H7 series - boardctrl: add MICROPY_BOARD_STARTUP hook - Makefile: fix C++ linker flags when toolchain has spaces in path - Makefile: allow QSTR_DEFS,QSTR_GLOBAL_DEPENDENCIES to be extended - include .ARM section in firmware for C++ exception handling - powerctrl: allow a board to configure AHB and APB clock dividers - powerctrl: support using PLLI2C on STM32F413 as USB clock source - boards/pllvalues.py: relax PLLQ constraints on STM32F413 MCUs - mpconfigport.h: add support for a board to specify root pointers - boardctrl: give boards control over execution of boot.py,main.py - boards/NUCLEO_L476RG: add 5 remaining UARTs - rfcore: fix race condition with C2 accessing free buffer list - rfcore: intercept addr-resolution HCI cmd to work around BLE bug - boards: split UARTx_RTS_DE into UARTx_RTS/UARTx_DE in pin defs - uart: use LL_USART_GetBaudRate to compute baudrate - sdram: make MICROPY_HW_FMC_BA1,MICROPY_HW_FMC_A11 optional pins teensy port: no changes specific to this component/port unix port: - mpbtstackport_common: implement mp_bluetooth_hci_active - moduselect: don't allow both posix and non-posix configurations - improve command line argument processing - main: make static variable that's potentially clobbered by longjmp windows port: no changes specific to this component/port zephyr port: - update to zephyr v2.5.0 - disable frozen source modules - remove unused build files - build MicroPython as a cmake target - boards: add support for the nucleo_h743zi board - modusocket: fix parameter in calls to net_context_get_XXX()
This commit is contained in:
commit
070da978e2
@ -74,7 +74,7 @@ copyright = '2014-2021, Damien P. George, Paul Sokolovsky, and contributors'
|
||||
#
|
||||
# We don't follow "The short X.Y version" vs "The full version, including alpha/beta/rc tags"
|
||||
# breakdown, so use the same version identifier for both to avoid confusion.
|
||||
version = release = '1.14'
|
||||
version = release = '1.15'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
||||
@ -18,7 +18,11 @@ If however you're targeting obscure or proprietary systems it may make
|
||||
more sense to keep this external to the main MicroPython repository.
|
||||
|
||||
This chapter describes how to compile such external modules into the
|
||||
MicroPython executable or firmware image.
|
||||
MicroPython executable or firmware image. Both Make and CMake build
|
||||
tools are supported, and when writing an external module it's a good idea to
|
||||
add the build files for both of these tools so the module can be used on all
|
||||
ports. But when compiling a particular port you will only need to use one
|
||||
method of building, either Make or CMake.
|
||||
|
||||
An alternative approach is to use :ref:`natmod` which allows writing custom C
|
||||
code that is placed in a .mpy file, which can be imported dynamically in to
|
||||
@ -53,6 +57,30 @@ A MicroPython user C module is a directory with the following files:
|
||||
for header files), these should be added to ``CFLAGS_USERMOD`` for C code
|
||||
and to ``CXXFLAGS_USERMOD`` for C++ code.
|
||||
|
||||
* ``micropython.cmake`` contains the CMake configuration for this module.
|
||||
|
||||
In ``micropython.cmake``, you may use ``${CMAKE_CURRENT_LIST_DIR}`` as the path to
|
||||
the current module.
|
||||
|
||||
Your ``micropython.cmake`` should define an ``INTERFACE`` library and associate
|
||||
your source files, compile definitions and include directories with it.
|
||||
The library should then be linked to the ``usermod`` target.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(usermod_cexample INTERFACE)
|
||||
|
||||
target_sources(usermod_cexample INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/examplemodule.c
|
||||
)
|
||||
|
||||
target_include_directories(usermod_cexample INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
target_link_libraries(usermod INTERFACE usermod_cexample)
|
||||
|
||||
|
||||
See below for full usage example.
|
||||
|
||||
|
||||
@ -70,9 +98,11 @@ and has a source file and a Makefile fragment with content as descibed above::
|
||||
└──usercmodule/
|
||||
└──cexample/
|
||||
├── examplemodule.c
|
||||
└── micropython.mk
|
||||
├── micropython.mk
|
||||
└── micropython.cmake
|
||||
|
||||
Refer to the comments in these 2 files for additional explanation.
|
||||
|
||||
Refer to the comments in these files for additional explanation.
|
||||
Next to the ``cexample`` module there's also ``cppexample`` which
|
||||
works in the same way but shows one way of mixing C and C++ code
|
||||
in MicroPython.
|
||||
@ -85,78 +115,140 @@ To build such a module, compile MicroPython (see `getting started
|
||||
<https://github.com/micropython/micropython/wiki/Getting-Started>`_),
|
||||
applying 2 modifications:
|
||||
|
||||
- an extra ``make`` flag named ``USER_C_MODULES`` set to the directory
|
||||
containing all modules you want included (not to the module itself).
|
||||
For building the example modules which come with MicroPython,
|
||||
set ``USER_C_MODULES`` to the ``examples/usercmodule`` directory.
|
||||
For your own projects it's more convenient to keep custom code out of
|
||||
the main source tree so a typical project directory structure will look
|
||||
like this::
|
||||
1. Set the build-time flag ``USER_C_MODULES`` to point to the modules
|
||||
you want to include. For ports that use Make this variable should be a
|
||||
directory which is searched automatically for modules. For ports that
|
||||
use CMake this variable should be a file which includes the modules to
|
||||
build. See below for details.
|
||||
|
||||
my_project/
|
||||
├── modules/
|
||||
│ └──example1/
|
||||
│ ├──example1.c
|
||||
│ └──micropython.mk
|
||||
│ └──example2/
|
||||
│ ├──example2.c
|
||||
│ └──micropython.mk
|
||||
└── micropython/
|
||||
├──ports/
|
||||
... ├──stm32/
|
||||
...
|
||||
2. Enable the modules by setting the corresponding C preprocessor macro to
|
||||
1. This is only needed if the modules you are building are not
|
||||
automatically enabled.
|
||||
|
||||
For building the example modules which come with MicroPython,
|
||||
set ``USER_C_MODULES`` to the ``examples/usercmodule`` directory for Make,
|
||||
or to ``examples/usercmodule/micropython.cmake`` for CMake.
|
||||
|
||||
with ``USER_C_MODULES`` set to the ``my_project/modules`` directory.
|
||||
|
||||
- all modules found in this directory will be compiled, but only those
|
||||
which are explicitly enabled will be availabe for importing. Enabling a
|
||||
module is done by setting the preprocessor define from its module
|
||||
registration to 1. For example if the source code defines the module with
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED);
|
||||
|
||||
|
||||
then ``MODULE_CEXAMPLE_ENABLED`` has to be set to 1 to make the module available.
|
||||
This can be done by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1`` to
|
||||
the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h``
|
||||
to add
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define MODULE_CEXAMPLE_ENABLED (1)
|
||||
|
||||
|
||||
Note that the exact method depends on the port as they have different
|
||||
structures. If not done correctly it will compile but importing will
|
||||
fail to find the module.
|
||||
|
||||
To sum up, here's how the ``cexample`` module from the ``examples/usercmodule``
|
||||
directory can be built for the unix port:
|
||||
For example, here's how the to build the unix port with the example modules:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd micropython/ports/unix
|
||||
make USER_C_MODULES=../../examples/usercmodule CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1 all
|
||||
make USER_C_MODULES=../../examples/usercmodule
|
||||
|
||||
The build output will show the modules found::
|
||||
You may need to run ``make clean`` once at the start when including new
|
||||
user modules in the build. The build output will show the modules found::
|
||||
|
||||
...
|
||||
Including User C Module from ../../examples/usercmodule/cexample
|
||||
Including User C Module from ../../examples/usercmodule/cppexample
|
||||
...
|
||||
|
||||
For a CMake-based port such as rp2, this will look a little different (note
|
||||
that CMake is actually invoked by ``make``):
|
||||
|
||||
Or for your own project with a directory structure as shown above,
|
||||
including both modules and building the stm32 port for example:
|
||||
.. code-block:: bash
|
||||
|
||||
cd micropython/ports/rp2
|
||||
make USER_C_MODULES=../../examples/usercmodule/micropython.cmake
|
||||
|
||||
Again, you may need to run ``make clean`` first for CMake to pick up the
|
||||
user modules. The CMake build output lists the modules by name::
|
||||
|
||||
...
|
||||
Including User C Module(s) from ../../examples/usercmodule/micropython.cmake
|
||||
Found User C Module(s): usermod_cexample, usermod_cppexample
|
||||
...
|
||||
|
||||
The contents of the top-level ``micropython.cmake`` can be used to control which
|
||||
modules are enabled.
|
||||
|
||||
For your own projects it's more convenient to keep custom code out of the main
|
||||
MicroPython source tree, so a typical project directory structure will look
|
||||
like this::
|
||||
|
||||
my_project/
|
||||
├── modules/
|
||||
│ ├── example1/
|
||||
│ │ ├── example1.c
|
||||
│ │ ├── micropython.mk
|
||||
│ │ └── micropython.cmake
|
||||
│ ├── example2/
|
||||
│ │ ├── example2.c
|
||||
│ │ ├── micropython.mk
|
||||
│ │ └── micropython.cmake
|
||||
│ └── micropython.cmake
|
||||
└── micropython/
|
||||
├──ports/
|
||||
... ├──stm32/
|
||||
...
|
||||
|
||||
When building with Make set ``USER_C_MODULES`` to the ``my_project/modules``
|
||||
directory. For example, building the stm32 port:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd my_project/micropython/ports/stm32
|
||||
make USER_C_MODULES=../../../modules \
|
||||
CFLAGS_EXTRA="-DMODULE_EXAMPLE1_ENABLED=1 -DMODULE_EXAMPLE2_ENABLED=1" all
|
||||
make USER_C_MODULES=../../../modules
|
||||
|
||||
When building with CMake the top level ``micropython.cmake`` -- found directly
|
||||
in the ``my_project/modules`` directory -- should ``include`` all of the modules
|
||||
you want to have available:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/example1/micropython.cmake)
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/example2/micropython.cmake)
|
||||
|
||||
Then build with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
cd my_project/micropython/ports/esp32
|
||||
make USER_C_MODULES=../../../../modules/micropython.cmake
|
||||
|
||||
Note that the esp32 port needs the extra ``..`` for relative paths due to the
|
||||
location of its main ``CMakeLists.txt`` file. You can also specify absolute
|
||||
paths to ``USER_C_MODULES``.
|
||||
|
||||
All modules specified by the ``USER_C_MODULES`` variable (either found in this
|
||||
directory when using Make, or added via ``include`` when using CMake) will be
|
||||
compiled, but only those which are enabled will be available for importing.
|
||||
User modules are usually enabled by default (this is decided by the developer
|
||||
of the module), in which case there is nothing more to do than set ``USER_C_MODULES``
|
||||
as described above.
|
||||
|
||||
If a module is not enabled by default then the corresponding C preprocessor macro
|
||||
must be enabled. This macro name can be found by searching for the ``MP_REGISTER_MODULE``
|
||||
line in the module's source code (it usually appears at the end of the main source file).
|
||||
The third argument to ``MP_REGISTER_MODULE`` is the macro name, and this must be set
|
||||
to 1 using ``CFLAGS_EXTRA`` to make the module available. If the third argument is just
|
||||
the number 1 then the module is enabled by default.
|
||||
|
||||
For example, the ``examples/usercmodule/cexample`` module is enabled by default so
|
||||
has the following line in its source code:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, 1);
|
||||
|
||||
Alternatively, to make this module disabled by default but selectable through
|
||||
a preprocessor configuration option, it would be:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED);
|
||||
|
||||
In this case the module is enabled by adding ``CFLAGS_EXTRA=-DMODULE_CEXAMPLE_ENABLED=1``
|
||||
to the ``make`` command, or editing ``mpconfigport.h`` or ``mpconfigboard.h`` to add
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
#define MODULE_CEXAMPLE_ENABLED (1)
|
||||
|
||||
Note that the exact method depends on the port as they have different
|
||||
structures. If not done correctly it will compile but importing will
|
||||
fail to find the module.
|
||||
|
||||
|
||||
Module usage in MicroPython
|
||||
|
||||
@ -21,6 +21,9 @@ CWARN = -Wall -Werror
|
||||
CWARN += -Wpointer-arith -Wuninitialized
|
||||
CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
# Some systems (eg MacOS) need -fno-common so that mp_state_ctx is placed in the BSS.
|
||||
CFLAGS += -fno-common
|
||||
|
||||
# Debugging/Optimization
|
||||
ifdef DEBUG
|
||||
CFLAGS += -g
|
||||
@ -133,7 +136,6 @@ SRC_C = $(addprefix ports/unix/,\
|
||||
gccollect.c \
|
||||
unix_mphal.c \
|
||||
input.c \
|
||||
file.c \
|
||||
modmachine.c \
|
||||
modos.c \
|
||||
moduselect.c \
|
||||
@ -146,6 +148,7 @@ SRC_C = $(addprefix ports/unix/,\
|
||||
LIB_SRC_C = $(addprefix lib/,\
|
||||
$(LIB_SRC_C_EXTRA) \
|
||||
utils/printf.c \
|
||||
utils/gchelper_generic.c \
|
||||
timeutils/timeutils.c \
|
||||
)
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ PIO_RX_PIN = Pin(3, Pin.IN, Pin.PULL_UP)
|
||||
autopush=True,
|
||||
push_thresh=8,
|
||||
in_shiftdir=rp2.PIO.SHIFT_RIGHT,
|
||||
fifo_join=PIO.JOIN_RX,
|
||||
)
|
||||
def uart_rx_mini():
|
||||
# fmt: off
|
||||
|
||||
@ -31,4 +31,7 @@ const mp_obj_module_t example_user_cmodule = {
|
||||
};
|
||||
|
||||
// Register the module to make it available in Python.
|
||||
MP_REGISTER_MODULE(MP_QSTR_cexample, example_user_cmodule, MODULE_CEXAMPLE_ENABLED);
|
||||
// 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);
|
||||
|
||||
15
examples/usercmodule/cexample/micropython.cmake
Normal file
15
examples/usercmodule/cexample/micropython.cmake
Normal file
@ -0,0 +1,15 @@
|
||||
# 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)
|
||||
@ -22,4 +22,7 @@ const mp_obj_module_t cppexample_user_cmodule = {
|
||||
};
|
||||
|
||||
// Register the module to make it available in Python.
|
||||
MP_REGISTER_MODULE(MP_QSTR_cppexample, cppexample_user_cmodule, MODULE_CPPEXAMPLE_ENABLED);
|
||||
// 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);
|
||||
|
||||
16
examples/usercmodule/cppexample/micropython.cmake
Normal file
16
examples/usercmodule/cppexample/micropython.cmake
Normal file
@ -0,0 +1,16 @@
|
||||
# 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)
|
||||
11
examples/usercmodule/micropython.cmake
Normal file
11
examples/usercmodule/micropython.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
# 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)
|
||||
|
||||
@ -4,6 +4,8 @@ set(MICROPY_EXTMOD_DIR "${MICROPY_DIR}/extmod")
|
||||
set(MICROPY_OOFATFS_DIR "${MICROPY_DIR}/lib/oofatfs")
|
||||
|
||||
set(MICROPY_SOURCE_EXTMOD
|
||||
${MICROPY_DIR}/lib/embed/abort_.c
|
||||
${MICROPY_DIR}/lib/utils/printf.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_i2c.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_mem.c
|
||||
${MICROPY_EXTMOD_DIR}/machine_pulse.c
|
||||
@ -43,3 +45,49 @@ set(MICROPY_SOURCE_EXTMOD
|
||||
${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()
|
||||
|
||||
@ -8,11 +8,20 @@
|
||||
((code ? memmove(code + at + num, code + at, pc - at) : 0), pc += num)
|
||||
#define REL(at, to) (to - at - 2)
|
||||
#define EMIT(at, byte) (code ? (code[at] = byte) : (at))
|
||||
#define EMIT_CHECKED(at, byte) (_emit_checked(at, code, byte, &err))
|
||||
#define PC (prog->bytelen)
|
||||
|
||||
static void _emit_checked(int at, char *code, int val, bool *err) {
|
||||
*err |= val != (int8_t)val;
|
||||
if (code) {
|
||||
code[at] = val;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
{
|
||||
char *code = sizecode ? NULL : prog->insts;
|
||||
bool err = false;
|
||||
int start = PC;
|
||||
int term = PC;
|
||||
int alt_label = 0;
|
||||
@ -64,7 +73,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
}
|
||||
EMIT(PC++, *re);
|
||||
}
|
||||
EMIT(term + 1, cnt);
|
||||
EMIT_CHECKED(term + 1, cnt);
|
||||
break;
|
||||
}
|
||||
case '(': {
|
||||
@ -75,7 +84,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
if (capture) {
|
||||
sub = ++prog->sub;
|
||||
EMIT(PC++, Save);
|
||||
EMIT(PC++, 2 * sub);
|
||||
EMIT_CHECKED(PC++, 2 * sub);
|
||||
prog->len++;
|
||||
} else {
|
||||
re += 2;
|
||||
@ -86,7 +95,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
|
||||
if (capture) {
|
||||
EMIT(PC++, Save);
|
||||
EMIT(PC++, 2 * sub + 1);
|
||||
EMIT_CHECKED(PC++, 2 * sub + 1);
|
||||
prog->len++;
|
||||
}
|
||||
|
||||
@ -101,7 +110,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
} else {
|
||||
EMIT(term, Split);
|
||||
}
|
||||
EMIT(term + 1, REL(term, PC));
|
||||
EMIT_CHECKED(term + 1, REL(term, PC));
|
||||
prog->len++;
|
||||
term = PC;
|
||||
break;
|
||||
@ -109,7 +118,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
if (PC == term) return NULL; // nothing to repeat
|
||||
INSERT_CODE(term, 2, PC);
|
||||
EMIT(PC, Jmp);
|
||||
EMIT(PC + 1, REL(PC, term));
|
||||
EMIT_CHECKED(PC + 1, REL(PC, term));
|
||||
PC += 2;
|
||||
if (re[1] == '?') {
|
||||
EMIT(term, RSplit);
|
||||
@ -117,7 +126,7 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
} else {
|
||||
EMIT(term, Split);
|
||||
}
|
||||
EMIT(term + 1, REL(term, PC));
|
||||
EMIT_CHECKED(term + 1, REL(term, PC));
|
||||
prog->len += 2;
|
||||
term = PC;
|
||||
break;
|
||||
@ -129,20 +138,20 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
} else {
|
||||
EMIT(PC, RSplit);
|
||||
}
|
||||
EMIT(PC + 1, REL(PC, term));
|
||||
EMIT_CHECKED(PC + 1, REL(PC, term));
|
||||
PC += 2;
|
||||
prog->len++;
|
||||
term = PC;
|
||||
break;
|
||||
case '|':
|
||||
if (alt_label) {
|
||||
EMIT(alt_label, REL(alt_label, PC) + 1);
|
||||
EMIT_CHECKED(alt_label, REL(alt_label, PC) + 1);
|
||||
}
|
||||
INSERT_CODE(start, 2, PC);
|
||||
EMIT(PC++, Jmp);
|
||||
alt_label = PC++;
|
||||
EMIT(start, Split);
|
||||
EMIT(start + 1, REL(start, PC));
|
||||
EMIT_CHECKED(start + 1, REL(start, PC));
|
||||
prog->len += 2;
|
||||
term = PC;
|
||||
break;
|
||||
@ -160,9 +169,9 @@ static const char *_compilecode(const char *re, ByteProg *prog, int sizecode)
|
||||
}
|
||||
|
||||
if (alt_label) {
|
||||
EMIT(alt_label, REL(alt_label, PC) + 1);
|
||||
EMIT_CHECKED(alt_label, REL(alt_label, PC) + 1);
|
||||
}
|
||||
return re;
|
||||
return err ? NULL : re;
|
||||
}
|
||||
|
||||
int re1_5_sizecode(const char *re)
|
||||
|
||||
@ -18,7 +18,13 @@ GIT_SUBMODULES = lib/berkeley-db-1.xx
|
||||
|
||||
.PHONY: all clean deploy erase submodules FORCE
|
||||
|
||||
IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD)
|
||||
CMAKE_ARGS =
|
||||
|
||||
ifdef USER_C_MODULES
|
||||
CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES}
|
||||
endif
|
||||
|
||||
IDFPY_FLAGS += -D MICROPY_BOARD=$(BOARD) -B $(BUILD) $(CMAKE_ARGS)
|
||||
|
||||
all:
|
||||
idf.py $(IDFPY_FLAGS) build
|
||||
|
||||
8
ports/esp32/boards/GENERIC_S2/mpconfigboard.cmake
Normal file
8
ports/esp32/boards/GENERIC_S2/mpconfigboard.cmake
Normal file
@ -0,0 +1,8 @@
|
||||
set(IDF_TARGET esp32s2)
|
||||
|
||||
set(SDKCONFIG_DEFAULTS
|
||||
boards/sdkconfig.base
|
||||
boards/sdkconfig.usb
|
||||
)
|
||||
|
||||
set(MICROPY_FROZEN_MANIFEST ${MICROPY_PORT_DIR}/boards/manifest.py)
|
||||
5
ports/esp32/boards/GENERIC_S2/mpconfigboard.h
Normal file
5
ports/esp32/boards/GENERIC_S2/mpconfigboard.h
Normal file
@ -0,0 +1,5 @@
|
||||
#define MICROPY_HW_BOARD_NAME "ESP32S2 module"
|
||||
#define MICROPY_HW_MCU_NAME "ESP32S2"
|
||||
|
||||
#define MICROPY_PY_BLUETOOTH (0)
|
||||
#define MICROPY_HW_ENABLE_SDCARD (0)
|
||||
@ -1,7 +1,6 @@
|
||||
# MicroPython on ESP32, ESP IDF configuration
|
||||
# The following options override the defaults
|
||||
|
||||
CONFIG_IDF_TARGET="esp32"
|
||||
CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000
|
||||
|
||||
# Compiler options: use -Os to reduce size, but keep full assertions
|
||||
|
||||
4
ports/esp32/boards/sdkconfig.usb
Normal file
4
ports/esp32/boards/sdkconfig.usb
Normal file
@ -0,0 +1,4 @@
|
||||
CONFIG_USB_ENABLED=y
|
||||
CONFIG_USB_CDC_ENABLED=y
|
||||
CONFIG_USB_CDC_RX_BUFSIZE=256
|
||||
CONFIG_USB_CDC_TX_BUFSIZE=256
|
||||
@ -26,6 +26,8 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#include "esp32/ulp.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
@ -95,3 +97,5 @@ const mp_obj_type_t esp32_ulp_type = {
|
||||
.make_new = esp32_ulp_make_new,
|
||||
.locals_dict = (mp_obj_t)&esp32_ulp_locals_dict,
|
||||
};
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
@ -60,7 +60,11 @@ STATIC mp_obj_t madc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
|
||||
|
||||
static int initialized = 0;
|
||||
if (!initialized) {
|
||||
adc1_config_width(ADC_WIDTH_12Bit);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
adc1_config_width(ADC_WIDTH_BIT_13);
|
||||
#else
|
||||
adc1_config_width(ADC_WIDTH_BIT_12);
|
||||
#endif
|
||||
adc_bit_width = 12;
|
||||
initialized = 1;
|
||||
}
|
||||
@ -128,6 +132,7 @@ STATIC mp_obj_t madc_width(mp_obj_t cls_in, mp_obj_t width_in) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("parameter error"));
|
||||
}
|
||||
switch (width) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case ADC_WIDTH_9Bit:
|
||||
adc_bit_width = 9;
|
||||
break;
|
||||
@ -140,6 +145,11 @@ STATIC mp_obj_t madc_width(mp_obj_t cls_in, mp_obj_t width_in) {
|
||||
case ADC_WIDTH_12Bit:
|
||||
adc_bit_width = 12;
|
||||
break;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
case ADC_WIDTH_BIT_13:
|
||||
adc_bit_width = 13;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -160,10 +170,14 @@ STATIC const mp_rom_map_elem_t madc_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_ATTN_6DB), MP_ROM_INT(ADC_ATTEN_6db) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_ATTN_11DB), MP_ROM_INT(ADC_ATTEN_11db) },
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH_9BIT), MP_ROM_INT(ADC_WIDTH_9Bit) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH_10BIT), MP_ROM_INT(ADC_WIDTH_10Bit) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH_11BIT), MP_ROM_INT(ADC_WIDTH_11Bit) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH_12BIT), MP_ROM_INT(ADC_WIDTH_12Bit) },
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH_13BIT), MP_ROM_INT(ADC_WIDTH_BIT_13) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(madc_locals_dict, madc_locals_dict_table);
|
||||
|
||||
@ -43,8 +43,13 @@ typedef struct _mdac_obj_t {
|
||||
} mdac_obj_t;
|
||||
|
||||
STATIC const mdac_obj_t mdac_obj[] = {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{{&machine_dac_type}, GPIO_NUM_25, DAC_CHANNEL_1},
|
||||
{{&machine_dac_type}, GPIO_NUM_26, DAC_CHANNEL_2},
|
||||
#else
|
||||
{{&machine_dac_type}, GPIO_NUM_17, DAC_CHANNEL_1},
|
||||
{{&machine_dac_type}, GPIO_NUM_18, DAC_CHANNEL_2},
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mdac_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
|
||||
|
||||
@ -184,8 +184,12 @@ STATIC void machine_hw_spi_init_internal(
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (self->host != HSPI_HOST && self->host != VSPI_HOST) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("SPI ID must be either HSPI(1) or VSPI(2)"));
|
||||
if (self->host != HSPI_HOST
|
||||
#ifdef VSPI_HOST
|
||||
&& self->host != VSPI_HOST
|
||||
#endif
|
||||
) {
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("SPI(%d) doesn't exist"), self->host);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
@ -220,8 +224,10 @@ STATIC void machine_hw_spi_init_internal(
|
||||
int dma_chan = 0;
|
||||
if (self->host == HSPI_HOST) {
|
||||
dma_chan = 1;
|
||||
#ifdef VSPI_HOST
|
||||
} else if (self->host == VSPI_HOST) {
|
||||
dma_chan = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
ret = spi_bus_initialize(self->host, &buscfg, dma_chan);
|
||||
|
||||
@ -34,8 +34,13 @@
|
||||
|
||||
#define I2C_0_DEFAULT_SCL (GPIO_NUM_18)
|
||||
#define I2C_0_DEFAULT_SDA (GPIO_NUM_19)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define I2C_1_DEFAULT_SCL (GPIO_NUM_25)
|
||||
#define I2C_1_DEFAULT_SDA (GPIO_NUM_26)
|
||||
#else
|
||||
#define I2C_1_DEFAULT_SCL (GPIO_NUM_9)
|
||||
#define I2C_1_DEFAULT_SDA (GPIO_NUM_8)
|
||||
#endif
|
||||
|
||||
#define I2C_DEFAULT_TIMEOUT_US (10000) // 10ms
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rtc_io.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
@ -77,10 +78,17 @@ STATIC const machine_pin_obj_t machine_pin_obj[] = {
|
||||
{{&machine_pin_type}, GPIO_NUM_19},
|
||||
{{NULL}, -1},
|
||||
{{&machine_pin_type}, GPIO_NUM_21},
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{{&machine_pin_type}, GPIO_NUM_22},
|
||||
{{&machine_pin_type}, GPIO_NUM_23},
|
||||
{{NULL}, -1},
|
||||
{{&machine_pin_type}, GPIO_NUM_25},
|
||||
#else
|
||||
{{NULL}, -1},
|
||||
{{NULL}, -1},
|
||||
{{NULL}, -1},
|
||||
{{NULL}, -1},
|
||||
#endif
|
||||
{{&machine_pin_type}, GPIO_NUM_26},
|
||||
{{&machine_pin_type}, GPIO_NUM_27},
|
||||
{{NULL}, -1},
|
||||
@ -150,9 +158,11 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// reset the pin first if this is a mode-setting init (grab it back from ADC)
|
||||
// reset the pin to digital if this is a mode-setting init (grab it back from ADC)
|
||||
if (args[ARG_mode].u_obj != mp_const_none) {
|
||||
gpio_reset_pin(self->id);
|
||||
if (rtc_gpio_is_valid_gpio(self->id)) {
|
||||
rtc_gpio_deinit(self->id);
|
||||
}
|
||||
}
|
||||
|
||||
// configure the pin for gpio
|
||||
@ -411,10 +421,17 @@ STATIC const machine_pin_irq_obj_t machine_pin_irq_object[] = {
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_19},
|
||||
{{NULL}, -1},
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_21},
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_22},
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_23},
|
||||
{{NULL}, -1},
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_25},
|
||||
#else
|
||||
{{NULL}, -1},
|
||||
{{NULL}, -1},
|
||||
{{NULL}, -1},
|
||||
{{NULL}, -1},
|
||||
#endif
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_26},
|
||||
{{&machine_pin_irq_type}, GPIO_NUM_27},
|
||||
{{NULL}, -1},
|
||||
|
||||
@ -50,7 +50,11 @@ STATIC int chan_gpio[LEDC_CHANNEL_MAX];
|
||||
// 5khz
|
||||
#define PWFREQ (5000)
|
||||
// High speed mode
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define PWMODE (LEDC_HIGH_SPEED_MODE)
|
||||
#else
|
||||
#define PWMODE (LEDC_LOW_SPEED_MODE)
|
||||
#endif
|
||||
// 10-bit resolution (compatible with esp8266 PWM)
|
||||
#define PWRES (LEDC_TIMER_10_BIT)
|
||||
// Timer 1
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
#include "py/mperrno.h"
|
||||
#include "extmod/vfs_fat.h"
|
||||
|
||||
#if MICROPY_HW_ENABLE_SDCARD
|
||||
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/sdspi_host.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
@ -50,10 +52,6 @@
|
||||
// Hosts are de-inited in __del__. Slots do not need de-initing.
|
||||
//
|
||||
|
||||
// Currently the ESP32 Library doesn't support MMC cards, so
|
||||
// we don't enable on MICROPY_HW_ENABLE_MMCARD.
|
||||
#if MICROPY_HW_ENABLE_SDCARD
|
||||
|
||||
// Forward declaration
|
||||
const mp_obj_type_t machine_sdcard_type;
|
||||
|
||||
|
||||
@ -30,12 +30,17 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "driver/timer.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "modmachine.h"
|
||||
#include "mphalport.h"
|
||||
|
||||
#include "driver/timer.h"
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 1)
|
||||
#include "hal/timer_ll.h"
|
||||
#define HAVE_TIMER_LL (1)
|
||||
#endif
|
||||
|
||||
#define TIMER_INTR_SEL TIMER_INTR_LEVEL
|
||||
#define TIMER_DIVIDER 8
|
||||
|
||||
@ -127,6 +132,18 @@ STATIC void machine_timer_isr(void *self_in) {
|
||||
machine_timer_obj_t *self = self_in;
|
||||
timg_dev_t *device = self->group ? &(TIMERG1) : &(TIMERG0);
|
||||
|
||||
#if HAVE_TIMER_LL
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
device->hw_timer[self->index].update = 1;
|
||||
#else
|
||||
device->hw_timer[self->index].update.update = 1;
|
||||
#endif
|
||||
timer_ll_clear_intr_status(device, self->index);
|
||||
timer_ll_set_alarm_enable(device, self->index, self->repeat);
|
||||
|
||||
#else
|
||||
|
||||
device->hw_timer[self->index].update = 1;
|
||||
if (self->index) {
|
||||
device->int_clr_timers.t1 = 1;
|
||||
@ -135,6 +152,8 @@ STATIC void machine_timer_isr(void *self_in) {
|
||||
}
|
||||
device->hw_timer[self->index].config.alarm_en = self->repeat;
|
||||
|
||||
#endif
|
||||
|
||||
mp_sched_schedule(self->callback, self);
|
||||
mp_hal_wake_main_task_from_isr();
|
||||
}
|
||||
|
||||
@ -24,18 +24,15 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/touch_pad.h"
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/touch_pad.h"
|
||||
|
||||
typedef struct _mtp_obj_t {
|
||||
mp_obj_base_t base;
|
||||
gpio_num_t gpio_id;
|
||||
@ -120,3 +117,5 @@ const mp_obj_type_t machine_touchpad_type = {
|
||||
.make_new = mtp_make_new,
|
||||
.locals_dict = (mp_obj_t)&mtp_locals_dict,
|
||||
};
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
@ -307,10 +307,12 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
self->rx = 9;
|
||||
self->tx = 10;
|
||||
break;
|
||||
#if SOC_UART_NUM > 2
|
||||
case UART_NUM_2:
|
||||
self->rx = 16;
|
||||
self->tx = 17;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Remove any existing configuration
|
||||
|
||||
@ -37,7 +37,12 @@
|
||||
#include "esp_task.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/spiram.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/spiram.h"
|
||||
#endif
|
||||
|
||||
#include "py/stackctrl.h"
|
||||
#include "py/nlr.h"
|
||||
@ -50,6 +55,7 @@
|
||||
#include "lib/mp-readline/readline.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "uart.h"
|
||||
#include "usb.h"
|
||||
#include "modmachine.h"
|
||||
#include "modnetwork.h"
|
||||
#include "mpthreadport.h"
|
||||
@ -72,7 +78,11 @@ void mp_task(void *pvParameter) {
|
||||
#if MICROPY_PY_THREAD
|
||||
mp_thread_init(pxTaskGetStackStart(NULL), MP_TASK_STACK_SIZE / sizeof(uintptr_t));
|
||||
#endif
|
||||
#if CONFIG_USB_ENABLED
|
||||
usb_init();
|
||||
#else
|
||||
uart_init();
|
||||
#endif
|
||||
machine_init();
|
||||
|
||||
// TODO: CONFIG_SPIRAM_SUPPORT is for 3.3 compatibility, remove after move to 4.0.
|
||||
|
||||
@ -3,7 +3,11 @@ get_filename_component(MICROPY_DIR ${PROJECT_DIR}/../.. ABSOLUTE)
|
||||
|
||||
# Include core source components.
|
||||
include(${MICROPY_DIR}/py/py.cmake)
|
||||
include(${MICROPY_DIR}/extmod/extmod.cmake)
|
||||
|
||||
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||
include(${MICROPY_DIR}/py/usermod.cmake)
|
||||
include(${MICROPY_DIR}/extmod/extmod.cmake)
|
||||
endif()
|
||||
|
||||
set(MICROPY_QSTRDEFS_PORT
|
||||
${PROJECT_DIR}/qstrdefsport.h
|
||||
@ -21,7 +25,6 @@ set(MICROPY_SOURCE_LIB
|
||||
${MICROPY_DIR}/lib/oofatfs/ffunicode.c
|
||||
${MICROPY_DIR}/lib/timeutils/timeutils.c
|
||||
${MICROPY_DIR}/lib/utils/interrupt_char.c
|
||||
${MICROPY_DIR}/lib/utils/stdout_helpers.c
|
||||
${MICROPY_DIR}/lib/utils/sys_stdio_mphal.c
|
||||
${MICROPY_DIR}/lib/utils/pyexec.c
|
||||
)
|
||||
@ -34,6 +37,7 @@ set(MICROPY_SOURCE_DRIVERS
|
||||
set(MICROPY_SOURCE_PORT
|
||||
${PROJECT_DIR}/main.c
|
||||
${PROJECT_DIR}/uart.c
|
||||
${PROJECT_DIR}/usb.c
|
||||
${PROJECT_DIR}/gccollect.c
|
||||
${PROJECT_DIR}/mphalport.c
|
||||
${PROJECT_DIR}/fatfs_port.c
|
||||
@ -74,6 +78,7 @@ include(${MICROPY_DIR}/lib/lv_bindings/mkrules.cmake)
|
||||
set(MICROPY_SOURCE_QSTR
|
||||
${MICROPY_SOURCE_PY}
|
||||
${MICROPY_SOURCE_EXTMOD}
|
||||
${MICROPY_SOURCE_USERMOD}
|
||||
${MICROPY_SOURCE_LIB}
|
||||
${MICROPY_SOURCE_PORT}
|
||||
${LV_SRC}
|
||||
@ -84,7 +89,6 @@ set(IDF_COMPONENTS
|
||||
bootloader_support
|
||||
bt
|
||||
driver
|
||||
esp32
|
||||
esp_common
|
||||
esp_eth
|
||||
esp_event
|
||||
@ -126,6 +130,13 @@ if(IDF_VERSION_MINOR GREATER_EQUAL 3)
|
||||
list(APPEND IDF_COMPONENTS hal)
|
||||
endif()
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND IDF_COMPONENTS esp32)
|
||||
elseif(IDF_TARGET STREQUAL "esp32s2")
|
||||
list(APPEND IDF_COMPONENTS esp32s2)
|
||||
list(APPEND IDF_COMPONENTS tinyusb)
|
||||
endif()
|
||||
|
||||
# Register the main IDF component.
|
||||
idf_component_register(
|
||||
SRCS
|
||||
@ -136,7 +147,8 @@ idf_component_register(
|
||||
${MICROPY_SOURCE_PORT}
|
||||
${LV_SRC}
|
||||
INCLUDE_DIRS
|
||||
${MICROPY_DIR}
|
||||
${MICROPY_INC_CORE}
|
||||
${MICROPY_INC_USERMOD}
|
||||
${MICROPY_PORT_DIR}
|
||||
${MICROPY_BOARD_DIR}
|
||||
${CMAKE_BINARY_DIR}
|
||||
@ -153,6 +165,7 @@ set(MICROPY_CROSS_FLAGS -march=xtensawin)
|
||||
|
||||
# Set compile options for this port.
|
||||
target_compile_definitions(${MICROPY_TARGET} PUBLIC
|
||||
${MICROPY_DEF_CORE}
|
||||
MICROPY_ESP_IDF_4=1
|
||||
MICROPY_VFS_FAT=1
|
||||
MICROPY_VFS_LFS2=1
|
||||
@ -169,24 +182,14 @@ target_compile_options(${MICROPY_TARGET} PUBLIC
|
||||
-Wno-missing-field-initializers
|
||||
)
|
||||
|
||||
# Add additional extmod and usermod components.
|
||||
target_link_libraries(${MICROPY_TARGET} micropy_extmod_btree)
|
||||
target_link_libraries(${MICROPY_TARGET} usermod)
|
||||
|
||||
|
||||
# Collect all of the include directories and compile definitions for the IDF components.
|
||||
foreach(comp ${IDF_COMPONENTS})
|
||||
get_target_property(type __idf_${comp} TYPE)
|
||||
set(_inc OFF)
|
||||
set(_def OFF)
|
||||
if(${type} STREQUAL STATIC_LIBRARY)
|
||||
get_target_property(_inc __idf_${comp} INCLUDE_DIRECTORIES)
|
||||
get_target_property(_def __idf_${comp} COMPILE_DEFINITIONS)
|
||||
elseif(${type} STREQUAL INTERFACE_LIBRARY)
|
||||
get_target_property(_inc __idf_${comp} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_target_property(_def __idf_${comp} INTERFACE_COMPILE_DEFINITIONS)
|
||||
endif()
|
||||
if(_inc)
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${_inc})
|
||||
endif()
|
||||
if(_def)
|
||||
list(APPEND MICROPY_CPP_DEF_EXTRA ${_def})
|
||||
endif()
|
||||
micropy_gather_target_properties(__idf_${comp})
|
||||
endforeach()
|
||||
|
||||
if(IDF_VERSION_MINOR GREATER_EQUAL 2)
|
||||
@ -194,6 +197,10 @@ if(IDF_VERSION_MINOR GREATER_EQUAL 2)
|
||||
# so add them explicitly.
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/soc/soc/${IDF_TARGET}/include)
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/soc/soc/include)
|
||||
if(IDF_VERSION_MINOR GREATER_EQUAL 3)
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/tinyusb/additions/include)
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${IDF_PATH}/components/tinyusb/tinyusb/src)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Include the main MicroPython cmake rules.
|
||||
|
||||
@ -132,6 +132,8 @@ STATIC mp_obj_t esp32_wake_on_ext1(size_t n_args, const mp_obj_t *pos_args, mp_m
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp32_wake_on_ext1_obj, 0, esp32_wake_on_ext1);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
STATIC mp_obj_t esp32_raw_temperature(void) {
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_TSENS_CTRL_REG, SENS_TSENS_CLK_DIV, 10, SENS_TSENS_CLK_DIV_S);
|
||||
@ -154,6 +156,8 @@ STATIC mp_obj_t esp32_hall_sensor(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_hall_sensor_obj, esp32_hall_sensor);
|
||||
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t esp32_idf_heap_info(const mp_obj_t cap_in) {
|
||||
mp_int_t cap = mp_obj_get_int(cap_in);
|
||||
multi_heap_info_t info;
|
||||
@ -182,14 +186,18 @@ STATIC const mp_rom_map_elem_t esp32_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_wake_on_touch), MP_ROM_PTR(&esp32_wake_on_touch_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_wake_on_ext0), MP_ROM_PTR(&esp32_wake_on_ext0_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_wake_on_ext1), MP_ROM_PTR(&esp32_wake_on_ext1_obj) },
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{ MP_ROM_QSTR(MP_QSTR_raw_temperature), MP_ROM_PTR(&esp32_raw_temperature_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_hall_sensor), MP_ROM_PTR(&esp32_hall_sensor_obj) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_idf_heap_info), MP_ROM_PTR(&esp32_idf_heap_info_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_NVS), MP_ROM_PTR(&esp32_nvs_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RMT), MP_ROM_PTR(&esp32_rmt_type) },
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&esp32_ulp_type) },
|
||||
#endif
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_WAKEUP_ALL_LOW), MP_ROM_FALSE },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WAKEUP_ANY_HIGH), MP_ROM_TRUE },
|
||||
|
||||
@ -32,12 +32,18 @@
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/clk.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_pm.h"
|
||||
#include "driver/touch_pad.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "esp32s2/clk.h"
|
||||
#endif
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
@ -71,7 +77,11 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) {
|
||||
if (freq != 20 && freq != 40 && freq != 80 && freq != 160 && freq != 240) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("frequency must be 20MHz, 40MHz, 80Mhz, 160MHz or 240MHz"));
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
esp_pm_config_esp32_t pm;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
esp_pm_config_esp32s2_t pm;
|
||||
#endif
|
||||
pm.max_freq_mhz = freq;
|
||||
pm.min_freq_mhz = freq;
|
||||
pm.light_sleep_enable = false;
|
||||
@ -260,7 +270,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
{ MP_ROM_QSTR(MP_QSTR_TouchPad), MP_ROM_PTR(&machine_touchpad_type) },
|
||||
#endif
|
||||
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) },
|
||||
|
||||
@ -59,13 +59,19 @@
|
||||
#define MDNS_QUERY_TIMEOUT_MS (5000)
|
||||
#define MDNS_LOCAL_SUFFIX ".local"
|
||||
|
||||
enum {
|
||||
SOCKET_STATE_NEW,
|
||||
SOCKET_STATE_CONNECTED,
|
||||
SOCKET_STATE_PEER_CLOSED,
|
||||
};
|
||||
|
||||
typedef struct _socket_obj_t {
|
||||
mp_obj_base_t base;
|
||||
int fd;
|
||||
uint8_t domain;
|
||||
uint8_t type;
|
||||
uint8_t proto;
|
||||
bool peer_closed;
|
||||
uint8_t state;
|
||||
unsigned int retries;
|
||||
#if MICROPY_PY_USOCKET_EVENTS
|
||||
mp_obj_t events_callback;
|
||||
@ -254,7 +260,6 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
|
||||
sock->domain = AF_INET;
|
||||
sock->type = SOCK_STREAM;
|
||||
sock->proto = 0;
|
||||
sock->peer_closed = false;
|
||||
if (n_args > 0) {
|
||||
sock->domain = mp_obj_get_int(args[0]);
|
||||
if (n_args > 1) {
|
||||
@ -265,6 +270,8 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type_in, size_t n_args, siz
|
||||
}
|
||||
}
|
||||
|
||||
sock->state = sock->type == SOCK_STREAM ? SOCKET_STATE_NEW : SOCKET_STATE_CONNECTED;
|
||||
|
||||
sock->fd = lwip_socket(sock->domain, sock->type, sock->proto);
|
||||
if (sock->fd < 0) {
|
||||
mp_raise_OSError(errno);
|
||||
@ -278,6 +285,7 @@ STATIC mp_obj_t socket_bind(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
struct addrinfo *res;
|
||||
_socket_getaddrinfo(arg1, &res);
|
||||
self->state = SOCKET_STATE_CONNECTED;
|
||||
int r = lwip_bind(self->fd, res->ai_addr, res->ai_addrlen);
|
||||
lwip_freeaddrinfo(res);
|
||||
if (r < 0) {
|
||||
@ -290,6 +298,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
|
||||
STATIC mp_obj_t socket_listen(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
|
||||
int backlog = mp_obj_get_int(arg1);
|
||||
self->state = SOCKET_STATE_CONNECTED;
|
||||
int r = lwip_listen(self->fd, backlog);
|
||||
if (r < 0) {
|
||||
mp_raise_OSError(errno);
|
||||
@ -332,7 +341,7 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) {
|
||||
sock->domain = self->domain;
|
||||
sock->type = self->type;
|
||||
sock->proto = self->proto;
|
||||
sock->peer_closed = false;
|
||||
sock->state = SOCKET_STATE_CONNECTED;
|
||||
_socket_settimeout(sock, UINT64_MAX);
|
||||
|
||||
// make the return value
|
||||
@ -351,6 +360,7 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
|
||||
struct addrinfo *res;
|
||||
_socket_getaddrinfo(arg1, &res);
|
||||
MP_THREAD_GIL_EXIT();
|
||||
self->state = SOCKET_STATE_CONNECTED;
|
||||
int r = lwip_connect(self->fd, res->ai_addr, res->ai_addrlen);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
lwip_freeaddrinfo(res);
|
||||
@ -471,11 +481,17 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size,
|
||||
struct sockaddr *from, socklen_t *from_len, int *errcode) {
|
||||
socket_obj_t *sock = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
// A new socket cannot be read from.
|
||||
if (sock->state == SOCKET_STATE_NEW) {
|
||||
*errcode = MP_ENOTCONN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
// If the peer closed the connection then the lwIP socket API will only return "0" once
|
||||
// from lwip_recvfrom and then block on subsequent calls. To emulate POSIX behaviour,
|
||||
// which continues to return "0" for each call on a closed socket, we set a flag when
|
||||
// the peer closed the socket.
|
||||
if (sock->peer_closed) {
|
||||
if (sock->state == SOCKET_STATE_PEER_CLOSED) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -500,7 +516,7 @@ STATIC mp_uint_t _socket_read_data(mp_obj_t self_in, void *buf, size_t size,
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
if (r == 0) {
|
||||
sock->peer_closed = true;
|
||||
sock->state = SOCKET_STATE_PEER_CLOSED;
|
||||
}
|
||||
if (r >= 0) {
|
||||
return r;
|
||||
@ -702,6 +718,12 @@ STATIC mp_uint_t socket_stream_ioctl(mp_obj_t self_in, mp_uint_t request, uintpt
|
||||
if (FD_ISSET(socket->fd, &efds)) {
|
||||
ret |= MP_STREAM_POLL_HUP;
|
||||
}
|
||||
|
||||
// New (unconnected) sockets are writable and have HUP set.
|
||||
if (socket->state == SOCKET_STATE_NEW) {
|
||||
ret |= (arg & MP_STREAM_POLL_WR) | MP_STREAM_POLL_HUP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else if (request == MP_STREAM_CLOSE) {
|
||||
if (socket->fd >= 0) {
|
||||
|
||||
@ -153,7 +153,9 @@
|
||||
#define MICROPY_PY_MACHINE_SPI (1)
|
||||
#define MICROPY_PY_MACHINE_SPI_MSB (0)
|
||||
#define MICROPY_PY_MACHINE_SPI_LSB (1)
|
||||
#ifndef MICROPY_HW_ENABLE_SDCARD
|
||||
#define MICROPY_HW_ENABLE_SDCARD (1)
|
||||
#endif
|
||||
#define MICROPY_HW_SOFTSPI_MIN_DELAY (0)
|
||||
#define MICROPY_HW_SOFTSPI_MAX_BAUDRATE (ets_get_cpu_frequency() * 1000000 / 200) // roughly
|
||||
#define MICROPY_PY_USSL (1)
|
||||
@ -162,6 +164,7 @@
|
||||
#define MICROPY_PY_UWEBSOCKET (1)
|
||||
#define MICROPY_PY_WEBREPL (1)
|
||||
#define MICROPY_PY_FRAMEBUF (1)
|
||||
#define MICROPY_PY_BTREE (1)
|
||||
#define MICROPY_PY_USOCKET_EVENTS (MICROPY_PY_WEBREPL)
|
||||
#define MICROPY_PY_BLUETOOTH_RANDOM_ADDR (1)
|
||||
#define MICROPY_PY_BLUETOOTH_DEFAULT_GAP_NAME ("ESP32")
|
||||
|
||||
@ -43,10 +43,11 @@
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "mphalport.h"
|
||||
#include "usb.h"
|
||||
|
||||
TaskHandle_t mp_main_task_handle;
|
||||
|
||||
STATIC uint8_t stdin_ringbuf_array[256];
|
||||
STATIC uint8_t stdin_ringbuf_array[260];
|
||||
ringbuf_t stdin_ringbuf = {stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0};
|
||||
|
||||
// Check the ESP-IDF error code and raise an OSError if it's not ESP_OK.
|
||||
@ -110,9 +111,13 @@ void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
|
||||
if (release_gil) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
}
|
||||
#if CONFIG_USB_ENABLED
|
||||
usb_tx_strn(str, len);
|
||||
#else
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
uart_tx_one_char(str[i]);
|
||||
}
|
||||
#endif
|
||||
if (release_gil) {
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
|
||||
@ -49,7 +49,11 @@ STATIC void IRAM_ATTR uart_irq_handler(void *arg) {
|
||||
uart->int_clr.frm_err = 1;
|
||||
uart->int_clr.rxfifo_tout = 1;
|
||||
while (uart->status.rxfifo_cnt) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t c = uart->fifo.rw_byte;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
uint8_t c = READ_PERI_REG(UART_FIFO_AHB_REG(0)); // UART0
|
||||
#endif
|
||||
if (c == mp_interrupt_char) {
|
||||
mp_keyboard_interrupt();
|
||||
} else {
|
||||
|
||||
92
ports/esp32/usb.c
Normal file
92
ports/esp32/usb.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 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/mphal.h"
|
||||
#include "usb.h"
|
||||
|
||||
#if CONFIG_USB_ENABLED
|
||||
|
||||
#include "tinyusb.h"
|
||||
#include "tusb_cdc_acm.h"
|
||||
|
||||
#define CDC_ITF TINYUSB_CDC_ACM_0
|
||||
|
||||
static uint8_t usb_rx_buf[CONFIG_USB_CDC_RX_BUFSIZE];
|
||||
|
||||
static void usb_callback_rx(int itf, cdcacm_event_t *event) {
|
||||
// TODO: what happens if more chars come in during this function, are they lost?
|
||||
for (;;) {
|
||||
size_t len = 0;
|
||||
esp_err_t ret = tinyusb_cdcacm_read(itf, usb_rx_buf, sizeof(usb_rx_buf), &len);
|
||||
if (ret != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
if (usb_rx_buf[i] == mp_interrupt_char) {
|
||||
mp_keyboard_interrupt();
|
||||
} else {
|
||||
ringbuf_put(&stdin_ringbuf, usb_rx_buf[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void usb_init(void) {
|
||||
// Initialise the USB with defaults.
|
||||
tinyusb_config_t tusb_cfg = {0};
|
||||
ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
|
||||
|
||||
// Initialise the USB serial interface.
|
||||
tinyusb_config_cdcacm_t amc_cfg = {
|
||||
.usb_dev = TINYUSB_USBDEV_0,
|
||||
.cdc_port = CDC_ITF,
|
||||
.rx_unread_buf_sz = 256,
|
||||
.callback_rx = &usb_callback_rx,
|
||||
.callback_rx_wanted_char = NULL,
|
||||
.callback_line_state_changed = NULL,
|
||||
.callback_line_coding_changed = NULL
|
||||
};
|
||||
ESP_ERROR_CHECK(tusb_cdc_acm_init(&amc_cfg));
|
||||
}
|
||||
|
||||
void usb_tx_strn(const char *str, size_t len) {
|
||||
while (len) {
|
||||
size_t l = len;
|
||||
if (l > CONFIG_USB_CDC_TX_BUFSIZE) {
|
||||
l = CONFIG_USB_CDC_TX_BUFSIZE;
|
||||
}
|
||||
tinyusb_cdcacm_write_queue(CDC_ITF, (uint8_t *)str, l);
|
||||
tinyusb_cdcacm_write_flush(CDC_ITF, pdMS_TO_TICKS(1000));
|
||||
str += l;
|
||||
len -= l;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CONFIG_USB_ENABLED
|
||||
32
ports/esp32/usb.h
Normal file
32
ports/esp32/usb.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the MicroPython project, http://micropython.org/
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2021 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_ESP32_USB_H
|
||||
#define MICROPY_INCLUDED_ESP32_USB_H
|
||||
|
||||
void usb_init(void);
|
||||
void usb_tx_strn(const char *str, size_t len);
|
||||
|
||||
#endif // MICROPY_INCLUDED_ESP32_USB_H
|
||||
@ -46,11 +46,9 @@
|
||||
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||
#define MICROPY_ENABLE_SOURCE_LINE (1)
|
||||
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
|
||||
#define MICROPY_CPYTHON_COMPAT (0)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||
|
||||
// Control over Python builtins
|
||||
#define MICROPY_PY_ASYNC_AWAIT (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_COUNT (0)
|
||||
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
|
||||
#define MICROPY_PY_BUILTINS_SET (1)
|
||||
@ -63,7 +61,6 @@
|
||||
#define MICROPY_PY___FILE__ (0)
|
||||
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
|
||||
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
|
||||
#define MICROPY_PY_ATTRTUPLE (0)
|
||||
#define MICROPY_PY_COLLECTIONS (0)
|
||||
#define MICROPY_PY_SYS_MAXSIZE (1)
|
||||
|
||||
|
||||
@ -17,6 +17,30 @@ endif()
|
||||
# Use the local tinyusb instead of the one in pico-sdk
|
||||
set(PICO_TINYUSB_PATH ${MICROPY_DIR}/lib/tinyusb)
|
||||
|
||||
# Set the location of this port's directory.
|
||||
set(MICROPY_PORT_DIR ${CMAKE_SOURCE_DIR})
|
||||
|
||||
# Set the board if it's not already set.
|
||||
if(NOT MICROPY_BOARD)
|
||||
set(MICROPY_BOARD PICO)
|
||||
endif()
|
||||
|
||||
# Set the PICO_BOARD if it's not already set.
|
||||
if(NOT PICO_BOARD)
|
||||
string(TOLOWER ${MICROPY_BOARD} PICO_BOARD)
|
||||
endif()
|
||||
|
||||
# Set the board directory and check that it exists.
|
||||
if(NOT MICROPY_BOARD_DIR)
|
||||
set(MICROPY_BOARD_DIR ${MICROPY_PORT_DIR}/boards/${MICROPY_BOARD})
|
||||
endif()
|
||||
if(NOT EXISTS ${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
|
||||
message(FATAL_ERROR "Invalid MICROPY_BOARD specified: ${MICROPY_BOARD}")
|
||||
endif()
|
||||
|
||||
# Include board config
|
||||
include(${MICROPY_BOARD_DIR}/mpconfigboard.cmake)
|
||||
|
||||
# Include component cmake fragments
|
||||
include(${MICROPY_DIR}/py/py.cmake)
|
||||
include(${MICROPY_DIR}/extmod/extmod.cmake)
|
||||
@ -27,6 +51,8 @@ project(${MICROPY_TARGET})
|
||||
|
||||
pico_sdk_init()
|
||||
|
||||
include(${MICROPY_DIR}/py/usermod.cmake)
|
||||
|
||||
add_executable(${MICROPY_TARGET})
|
||||
|
||||
set(MICROPY_QSTRDEFS_PORT
|
||||
@ -80,6 +106,7 @@ set(MICROPY_SOURCE_PORT
|
||||
set(MICROPY_SOURCE_QSTR
|
||||
${MICROPY_SOURCE_PY}
|
||||
${MICROPY_SOURCE_EXTMOD}
|
||||
${MICROPY_SOURCE_USERMOD}
|
||||
${MICROPY_DIR}/lib/utils/mpirq.c
|
||||
${MICROPY_DIR}/lib/utils/sys_stdio_mphal.c
|
||||
${PROJECT_SOURCE_DIR}/machine_adc.c
|
||||
@ -142,9 +169,13 @@ target_sources(${MICROPY_TARGET} PRIVATE
|
||||
${MICROPY_SOURCE_PORT}
|
||||
)
|
||||
|
||||
target_link_libraries(${MICROPY_TARGET} usermod)
|
||||
|
||||
target_include_directories(${MICROPY_TARGET} PRIVATE
|
||||
${MICROPY_INC_CORE}
|
||||
${MICROPY_INC_USERMOD}
|
||||
${MICROPY_BOARD_DIR}
|
||||
"${PROJECT_SOURCE_DIR}"
|
||||
"${MICROPY_DIR}"
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
)
|
||||
|
||||
@ -164,6 +195,7 @@ target_compile_definitions(${MICROPY_TARGET} PRIVATE
|
||||
PICO_NO_PROGRAM_VERSION_STRING=1 # do it ourselves in main.c
|
||||
MICROPY_BUILD_TYPE="${CMAKE_C_COMPILER_ID} ${CMAKE_C_COMPILER_VERSION} ${CMAKE_BUILD_TYPE}"
|
||||
PICO_NO_BI_STDIO_UART=1 # we call it UART REPL
|
||||
PICO_RP2040_USB_DEVICE_ENUMERATION_FIX=1
|
||||
)
|
||||
|
||||
target_link_libraries(${MICROPY_TARGET}
|
||||
@ -186,29 +218,9 @@ add_custom_command(TARGET ${MICROPY_TARGET}
|
||||
)
|
||||
|
||||
# Collect all the include directories and compile definitions for the pico-sdk components.
|
||||
macro(_process_target targ)
|
||||
if(TARGET ${targ})
|
||||
get_target_property(type ${targ} TYPE)
|
||||
set(_inc OFF)
|
||||
set(_def OFF)
|
||||
if(${type} STREQUAL STATIC_LIBRARY)
|
||||
get_target_property(_inc ${targ} INCLUDE_DIRECTORIES)
|
||||
get_target_property(_def ${targ} COMPILE_DEFINITIONS)
|
||||
elseif(${type} STREQUAL INTERFACE_LIBRARY)
|
||||
get_target_property(_inc ${targ} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_target_property(_def ${targ} INTERFACE_COMPILE_DEFINITIONS)
|
||||
endif()
|
||||
if(_inc)
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${_inc})
|
||||
endif()
|
||||
if(_def)
|
||||
list(APPEND MICROPY_CPP_DEF_EXTRA ${_def})
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
foreach(comp ${PICO_SDK_COMPONENTS})
|
||||
_process_target(${comp})
|
||||
_process_target(${comp}_headers)
|
||||
micropy_gather_target_properties(${comp})
|
||||
micropy_gather_target_properties(${comp}_headers)
|
||||
endforeach()
|
||||
|
||||
# Include the main MicroPython cmake rules.
|
||||
|
||||
@ -2,12 +2,20 @@
|
||||
#
|
||||
# This is a simple wrapper around cmake
|
||||
|
||||
BUILD = build
|
||||
BOARD ?= PICO
|
||||
|
||||
BUILD ?= build-$(BOARD)
|
||||
|
||||
$(VERBOSE)MAKESILENT = -s
|
||||
|
||||
CMAKE_ARGS = -DMICROPY_BOARD=$(BOARD)
|
||||
|
||||
ifdef USER_C_MODULES
|
||||
CMAKE_ARGS += -DUSER_C_MODULES=${USER_C_MODULES}
|
||||
endif
|
||||
|
||||
all:
|
||||
[ -d $(BUILD) ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0
|
||||
[ -d $(BUILD) ] || cmake -S . -B $(BUILD) -DPICO_BUILD_DOCS=0 ${CMAKE_ARGS}
|
||||
$(MAKE) $(MAKESILENT) -C $(BUILD)
|
||||
|
||||
clean:
|
||||
|
||||
@ -0,0 +1 @@
|
||||
# cmake file for Adafruit Feather RP2040
|
||||
3
ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h
Normal file
3
ports/rp2/boards/ADAFRUIT_FEATHER_RP2040/mpconfigboard.h
Normal file
@ -0,0 +1,3 @@
|
||||
// Board and hardware specific configuration
|
||||
#define MICROPY_HW_BOARD_NAME "Adafruit Feather RP2040"
|
||||
#define MICROPY_HW_FLASH_STORAGE_BYTES (3072 * 1024)
|
||||
1
ports/rp2/boards/PICO/mpconfigboard.cmake
Normal file
1
ports/rp2/boards/PICO/mpconfigboard.cmake
Normal file
@ -0,0 +1 @@
|
||||
# cmake file for Raspberry Pi Pico
|
||||
3
ports/rp2/boards/PICO/mpconfigboard.h
Normal file
3
ports/rp2/boards/PICO/mpconfigboard.h
Normal file
@ -0,0 +1,3 @@
|
||||
// Board and hardware specific configuration
|
||||
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
|
||||
#define MICROPY_HW_FLASH_STORAGE_BYTES (1408 * 1024)
|
||||
@ -28,9 +28,12 @@
|
||||
#include "py/stream.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/ringbuf.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/uart.h"
|
||||
#include "hardware/regs/uart.h"
|
||||
|
||||
#define DEFAULT_UART_BAUDRATE (115200)
|
||||
#define DEFAULT_UART_BITS (8)
|
||||
@ -39,6 +42,9 @@
|
||||
#define DEFAULT_UART0_RX (1)
|
||||
#define DEFAULT_UART1_TX (4)
|
||||
#define DEFAULT_UART1_RX (5)
|
||||
#define DEFAULT_BUFFER_SIZE (256)
|
||||
#define MIN_BUFFER_SIZE (32)
|
||||
#define MAX_BUFFER_SIZE (32766)
|
||||
|
||||
#define IS_VALID_PERIPH(uart, pin) (((((pin) + 4) & 8) >> 3) == (uart))
|
||||
#define IS_VALID_TX(uart, pin) (((pin) & 3) == 0 && IS_VALID_PERIPH(uart, pin))
|
||||
@ -61,28 +67,81 @@ typedef struct _machine_uart_obj_t {
|
||||
uint16_t timeout; // timeout waiting for first char (in ms)
|
||||
uint16_t timeout_char; // timeout waiting between chars (in ms)
|
||||
uint8_t invert;
|
||||
ringbuf_t read_buffer;
|
||||
bool read_lock;
|
||||
ringbuf_t write_buffer;
|
||||
bool write_lock;
|
||||
} machine_uart_obj_t;
|
||||
|
||||
STATIC machine_uart_obj_t machine_uart_obj[] = {
|
||||
{{&machine_uart_type}, uart0, 0, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP, DEFAULT_UART0_TX, DEFAULT_UART0_RX, 0, 0, 0},
|
||||
{{&machine_uart_type}, uart1, 1, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP, DEFAULT_UART1_TX, DEFAULT_UART1_RX, 0, 0, 0},
|
||||
{{&machine_uart_type}, uart0, 0, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP,
|
||||
DEFAULT_UART0_TX, DEFAULT_UART0_RX, 0, 0, 0, {NULL, 1, 0, 0}, 0, {NULL, 1, 0, 0}, 0},
|
||||
{{&machine_uart_type}, uart1, 1, 0, DEFAULT_UART_BITS, UART_PARITY_NONE, DEFAULT_UART_STOP,
|
||||
DEFAULT_UART1_TX, DEFAULT_UART1_RX, 0, 0, 0, {NULL, 1, 0, 0}, 0, {NULL, 1, 0, 0}, 0,},
|
||||
};
|
||||
|
||||
STATIC const char *_parity_name[] = {"None", "0", "1"};
|
||||
STATIC const char *_invert_name[] = {"None", "INV_TX", "INV_RX", "INV_TX|INV_RX"};
|
||||
|
||||
/******************************************************************************/
|
||||
// IRQ and buffer handling
|
||||
|
||||
// take all bytes from the fifo and store them, if possible, in the buffer
|
||||
STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self) {
|
||||
while (uart_is_readable(self->uart)) {
|
||||
// try to write the data, ignore the fail
|
||||
ringbuf_put(&(self->read_buffer), uart_get_hw(self->uart)->dr);
|
||||
}
|
||||
}
|
||||
|
||||
// take bytes from the buffer and put them into the UART FIFO
|
||||
STATIC void uart_fill_tx_fifo(machine_uart_obj_t *self) {
|
||||
while (uart_is_writable(self->uart) && ringbuf_avail(&self->write_buffer) > 0) {
|
||||
// get a byte from the buffer and put it into the uart
|
||||
uart_get_hw(self->uart)->dr = ringbuf_get(&(self->write_buffer));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC inline void uart_service_interrupt(machine_uart_obj_t *self) {
|
||||
if (uart_get_hw(self->uart)->mis & UART_UARTMIS_RXMIS_BITS) { // rx interrupt?
|
||||
// clear all interrupt bits but tx
|
||||
uart_get_hw(self->uart)->icr = UART_UARTICR_BITS & (~UART_UARTICR_TXIC_BITS);
|
||||
if (!self->read_lock) {
|
||||
uart_drain_rx_fifo(self);
|
||||
}
|
||||
}
|
||||
if (uart_get_hw(self->uart)->mis & UART_UARTMIS_TXMIS_BITS) { // tx interrupt?
|
||||
// clear all interrupt bits but rx
|
||||
uart_get_hw(self->uart)->icr = UART_UARTICR_BITS & (~UART_UARTICR_RXIC_BITS);
|
||||
if (!self->write_lock) {
|
||||
uart_fill_tx_fifo(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void uart0_irq_handler(void) {
|
||||
uart_service_interrupt(&machine_uart_obj[0]);
|
||||
}
|
||||
|
||||
STATIC void uart1_irq_handler(void) {
|
||||
uart_service_interrupt(&machine_uart_obj[1]);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
// MicroPython bindings for UART
|
||||
|
||||
STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, timeout=%u, timeout_char=%u, invert=%s)",
|
||||
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, tx=%d, rx=%d, "
|
||||
"txbuf=%d, rxbuf=%d, timeout=%u, timeout_char=%u, invert=%s)",
|
||||
self->uart_id, self->baudrate, self->bits, _parity_name[self->parity],
|
||||
self->stop, self->tx, self->rx, self->timeout, self->timeout_char, _invert_name[self->invert]);
|
||||
self->stop, self->tx, self->rx, self->write_buffer.size - 1, self->read_buffer.size - 1,
|
||||
self->timeout, self->timeout_char, _invert_name[self->invert]);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
enum { ARG_id, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx, ARG_timeout, ARG_timeout_char, ARG_invert };
|
||||
enum { ARG_id, ARG_baudrate, ARG_bits, ARG_parity, ARG_stop, ARG_tx, ARG_rx,
|
||||
ARG_timeout, ARG_timeout_char, ARG_invert, ARG_txbuf, ARG_rxbuf};
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} },
|
||||
@ -94,6 +153,8 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_timeout_char, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_invert, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_txbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
{ MP_QSTR_rxbuf, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
@ -169,6 +230,30 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
self->invert = args[ARG_invert].u_int;
|
||||
}
|
||||
|
||||
self->read_lock = false;
|
||||
|
||||
// Set the RX buffer size if configured.
|
||||
size_t rxbuf_len = DEFAULT_BUFFER_SIZE;
|
||||
if (args[ARG_rxbuf].u_int > 0) {
|
||||
rxbuf_len = args[ARG_rxbuf].u_int;
|
||||
if (rxbuf_len < MIN_BUFFER_SIZE) {
|
||||
rxbuf_len = MIN_BUFFER_SIZE;
|
||||
} else if (rxbuf_len > MAX_BUFFER_SIZE) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("rxbuf too large"));
|
||||
}
|
||||
}
|
||||
|
||||
// Set the TX buffer size if configured.
|
||||
size_t txbuf_len = DEFAULT_BUFFER_SIZE;
|
||||
if (args[ARG_txbuf].u_int > 0) {
|
||||
txbuf_len = args[ARG_txbuf].u_int;
|
||||
if (txbuf_len < MIN_BUFFER_SIZE) {
|
||||
txbuf_len = MIN_BUFFER_SIZE;
|
||||
} else if (txbuf_len > MAX_BUFFER_SIZE) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("txbuf too large"));
|
||||
}
|
||||
}
|
||||
|
||||
// Initialise the UART peripheral if any arguments given, or it was not initialised previously.
|
||||
if (n_args > 1 || n_kw > 0 || self->baudrate == 0) {
|
||||
if (self->baudrate == 0) {
|
||||
@ -192,6 +277,25 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
if (self->invert & UART_INVERT_TX) {
|
||||
gpio_set_outover(self->tx, GPIO_OVERRIDE_INVERT);
|
||||
}
|
||||
|
||||
// Allocate the RX/TX buffers.
|
||||
ringbuf_alloc(&(self->read_buffer), rxbuf_len + 1);
|
||||
MP_STATE_PORT(rp2_uart_rx_buffer[uart_id]) = self->read_buffer.buf;
|
||||
|
||||
ringbuf_alloc(&(self->write_buffer), txbuf_len + 1);
|
||||
MP_STATE_PORT(rp2_uart_tx_buffer[uart_id]) = self->write_buffer.buf;
|
||||
|
||||
// Set the irq handler.
|
||||
if (self->uart_id == 0) {
|
||||
irq_set_exclusive_handler(UART0_IRQ, uart0_irq_handler);
|
||||
irq_set_enabled(UART0_IRQ, true);
|
||||
} else {
|
||||
irq_set_exclusive_handler(UART1_IRQ, uart1_irq_handler);
|
||||
irq_set_enabled(UART1_IRQ, true);
|
||||
}
|
||||
|
||||
// Enable the uart irq; this macro sets the rx irq level to 4.
|
||||
uart_set_irq_enables(self->uart, true, true);
|
||||
}
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
@ -199,7 +303,11 @@ STATIC mp_obj_t machine_uart_make_new(const mp_obj_type_t *type, size_t n_args,
|
||||
|
||||
STATIC mp_obj_t machine_uart_any(mp_obj_t self_in) {
|
||||
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(uart_is_readable(self->uart));
|
||||
// get all bytes from the fifo first
|
||||
self->read_lock = true;
|
||||
uart_drain_rx_fifo(self);
|
||||
self->read_lock = false;
|
||||
return MP_OBJ_NEW_SMALL_INT(ringbuf_avail(&self->read_buffer));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_uart_any_obj, machine_uart_any);
|
||||
|
||||
@ -236,7 +344,7 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// Wait for the first/next character
|
||||
while (!uart_is_readable(self->uart)) {
|
||||
while (ringbuf_avail(&self->read_buffer) == 0) {
|
||||
if (time_us_64() > t) { // timed out
|
||||
if (i <= 0) {
|
||||
*errcode = MP_EAGAIN;
|
||||
@ -246,8 +354,12 @@ STATIC mp_uint_t machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t siz
|
||||
}
|
||||
}
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
// Force a few incoming bytes to the buffer
|
||||
self->read_lock = true;
|
||||
uart_drain_rx_fifo(self);
|
||||
self->read_lock = false;
|
||||
}
|
||||
*dest++ = uart_get_hw(self->uart)->dr;
|
||||
*dest++ = ringbuf_get(&(self->read_buffer));
|
||||
t = time_us_64() + timeout_char_us;
|
||||
}
|
||||
return size;
|
||||
@ -258,10 +370,23 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
|
||||
uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000;
|
||||
uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000;
|
||||
const uint8_t *src = buf_in;
|
||||
size_t i = 0;
|
||||
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
// wait for the first/next character
|
||||
while (!uart_is_writable(self->uart)) {
|
||||
// Put as many bytes as possible into the transmit buffer.
|
||||
while (i < size && ringbuf_free(&(self->write_buffer)) > 0) {
|
||||
ringbuf_put(&(self->write_buffer), *src++);
|
||||
++i;
|
||||
}
|
||||
|
||||
// Kickstart the UART transmit.
|
||||
self->write_lock = true;
|
||||
uart_fill_tx_fifo(self);
|
||||
self->write_lock = false;
|
||||
|
||||
// Send the next characters while busy waiting.
|
||||
while (i < size) {
|
||||
// Wait for the first/next character to be sent.
|
||||
while (ringbuf_free(&(self->write_buffer)) == 0) {
|
||||
if (time_us_64() > t) { // timed out
|
||||
if (i <= 0) {
|
||||
*errcode = MP_EAGAIN;
|
||||
@ -272,9 +397,15 @@ STATIC mp_uint_t machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uin
|
||||
}
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
}
|
||||
uart_get_hw(self->uart)->dr = *src++;
|
||||
ringbuf_put(&(self->write_buffer), *src++);
|
||||
++i;
|
||||
t = time_us_64() + timeout_char_us;
|
||||
self->write_lock = true;
|
||||
uart_fill_tx_fifo(self);
|
||||
self->write_lock = false;
|
||||
}
|
||||
|
||||
// Just in case the fifo was drained during refill of the ringbuf.
|
||||
return size;
|
||||
}
|
||||
|
||||
@ -284,10 +415,10 @@ STATIC mp_uint_t machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint
|
||||
if (request == MP_STREAM_POLL) {
|
||||
uintptr_t flags = arg;
|
||||
ret = 0;
|
||||
if ((flags & MP_STREAM_POLL_RD) && uart_is_readable(self->uart)) {
|
||||
if ((flags & MP_STREAM_POLL_RD) && ringbuf_avail(&self->read_buffer) > 0) {
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if ((flags & MP_STREAM_POLL_WR) && uart_is_writable(self->uart)) {
|
||||
if ((flags & MP_STREAM_POLL_WR) && ringbuf_free(&self->write_buffer) > 0) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/stackctrl.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
#include "lib/utils/gchelper.h"
|
||||
@ -168,10 +169,21 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c
|
||||
}
|
||||
#endif
|
||||
|
||||
#define POLY (0xD5)
|
||||
|
||||
uint8_t rosc_random_u8(size_t cycles) {
|
||||
static uint8_t r;
|
||||
for (size_t i = 0; i < cycles; ++i) {
|
||||
r = ((r << 1) | rosc_hw->randombit) ^ (r & 0x80 ? POLY : 0);
|
||||
mp_hal_delay_us_fast(1);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
uint32_t rosc_random_u32(void) {
|
||||
uint32_t value = 0;
|
||||
for (size_t i = 0; i < 32; ++i) {
|
||||
value = value << 1 | rosc_hw->randombit;
|
||||
for (size_t i = 0; i < 4; ++i) {
|
||||
value = value << 8 | rosc_random_u8(32);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -31,14 +31,18 @@ class PIOASMEmit:
|
||||
autopush=False,
|
||||
autopull=False,
|
||||
push_thresh=32,
|
||||
pull_thresh=32
|
||||
pull_thresh=32,
|
||||
fifo_join=0
|
||||
):
|
||||
from array import array
|
||||
# uarray is a built-in module so importing it here won't require
|
||||
# scanning the filesystem.
|
||||
from uarray import array
|
||||
|
||||
self.labels = {}
|
||||
execctrl = 0
|
||||
shiftctrl = (
|
||||
(pull_thresh & 0x1F) << 25
|
||||
fifo_join << 30
|
||||
| (pull_thresh & 0x1F) << 25
|
||||
| (push_thresh & 0x1F) << 20
|
||||
| out_shiftdir << 19
|
||||
| in_shiftdir << 18
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
#include "extmod/vfs_lfs.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
|
||||
uint8_t rosc_random_u8(size_t cycles);
|
||||
|
||||
STATIC const qstr os_uname_info_fields[] = {
|
||||
MP_QSTR_sysname, MP_QSTR_nodename,
|
||||
MP_QSTR_release, MP_QSTR_version, MP_QSTR_machine
|
||||
@ -57,10 +59,22 @@ STATIC mp_obj_t os_uname(void) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(os_uname_obj, os_uname);
|
||||
|
||||
STATIC mp_obj_t os_urandom(mp_obj_t num) {
|
||||
mp_int_t n = mp_obj_get_int(num);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
vstr.buf[i] = rosc_random_u8(8);
|
||||
}
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
|
||||
|
||||
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
|
||||
|
||||
#if MICROPY_VFS
|
||||
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
|
||||
|
||||
@ -31,8 +31,9 @@
|
||||
#include "hardware/sync.h"
|
||||
#include "pico/binary_info.h"
|
||||
|
||||
#include "mpconfigboard.h"
|
||||
|
||||
// Board and hardware specific configuration
|
||||
#define MICROPY_HW_BOARD_NAME "Raspberry Pi Pico"
|
||||
#define MICROPY_HW_MCU_NAME "RP2040"
|
||||
#define MICROPY_HW_ENABLE_UART_REPL (0) // useful if there is no USB
|
||||
#define MICROPY_HW_ENABLE_USBDEV (1)
|
||||
@ -174,6 +175,8 @@ extern const struct _mp_obj_module_t mp_module_utime;
|
||||
void *machine_pin_irq_obj[30]; \
|
||||
void *rp2_pio_irq_obj[2]; \
|
||||
void *rp2_state_machine_irq_obj[8]; \
|
||||
void *rp2_uart_rx_buffer[2]; \
|
||||
void *rp2_uart_tx_buffer[2]; \
|
||||
|
||||
#define MP_STATE_PORT MP_STATE_VM
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ static inline void mp_thread_set_state(struct _mp_state_thread_t *state) {
|
||||
}
|
||||
|
||||
static inline struct _mp_state_thread_t *mp_thread_get_state(void) {
|
||||
return core_state[get_core_num()];
|
||||
return (struct _mp_state_thread_t *)core_state[get_core_num()];
|
||||
}
|
||||
|
||||
static inline void mp_thread_mutex_init(mp_thread_mutex_t *m) {
|
||||
|
||||
@ -66,6 +66,7 @@ typedef struct _rp2_state_machine_irq_obj_t {
|
||||
} rp2_state_machine_irq_obj_t;
|
||||
|
||||
STATIC const rp2_state_machine_obj_t rp2_state_machine_obj[8];
|
||||
STATIC uint8_t rp2_state_machine_initial_pc[8];
|
||||
|
||||
STATIC mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
|
||||
@ -359,6 +360,10 @@ STATIC const mp_rom_map_elem_t rp2_pio_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_SHIFT_LEFT), MP_ROM_INT(0) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_SHIFT_RIGHT), MP_ROM_INT(1) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_JOIN_NONE), MP_ROM_INT(0) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_JOIN_TX), MP_ROM_INT(1) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_JOIN_RX), MP_ROM_INT(2) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_SM0), MP_ROM_INT(0x100) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_SM1), MP_ROM_INT(0x200) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_IRQ_SM2), MP_ROM_INT(0x400) },
|
||||
@ -459,16 +464,28 @@ STATIC mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
|
||||
if (offset < 0) {
|
||||
rp2_pio_add_program(&rp2_pio_obj[PIO_NUM(self->pio)], args[ARG_prog].u_obj);
|
||||
offset = mp_obj_get_int(prog[PROG_OFFSET_PIO0 + PIO_NUM(self->pio)]);
|
||||
rp2_state_machine_initial_pc[self->id] = offset;
|
||||
}
|
||||
|
||||
// Compute the clock divider.
|
||||
float div;
|
||||
uint16_t clkdiv_int;
|
||||
uint8_t clkdiv_frac;
|
||||
if (args[ARG_freq].u_int < 0) {
|
||||
div = 1;
|
||||
// Default: run at CPU frequency.
|
||||
clkdiv_int = 1;
|
||||
clkdiv_frac = 0;
|
||||
} else if (args[ARG_freq].u_int == 0) {
|
||||
div = 0;
|
||||
// Special case of 0: set clkdiv to 0.
|
||||
clkdiv_int = 0;
|
||||
clkdiv_frac = 0;
|
||||
} else {
|
||||
div = (float)clock_get_hz(clk_sys) / (float)args[ARG_freq].u_int;
|
||||
// Frequency given in Hz, compute clkdiv from it.
|
||||
uint64_t div = (uint64_t)clock_get_hz(clk_sys) * 256ULL / (uint64_t)args[ARG_freq].u_int;
|
||||
if (!(div >= 1 * 256 && div <= 65536 * 256)) {
|
||||
mp_raise_ValueError(MP_ERROR_TEXT("freq out of range"));
|
||||
}
|
||||
clkdiv_int = div / 256;
|
||||
clkdiv_frac = div & 0xff;
|
||||
}
|
||||
|
||||
// Disable and reset the state machine.
|
||||
@ -476,7 +493,7 @@ STATIC mp_obj_t rp2_state_machine_init_helper(const rp2_state_machine_obj_t *sel
|
||||
|
||||
// Build the state machine config.
|
||||
pio_sm_config config = pio_get_default_sm_config();
|
||||
sm_config_set_clkdiv(&config, div);
|
||||
sm_config_set_clkdiv_int_frac(&config, clkdiv_int, clkdiv_frac);
|
||||
config.execctrl = mp_obj_get_int_truncated(prog[PROG_EXECCTRL]);
|
||||
config.shiftctrl = mp_obj_get_int_truncated(prog[PROG_SHIFTCTRL]);
|
||||
|
||||
@ -581,6 +598,15 @@ STATIC mp_obj_t rp2_state_machine_active(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_state_machine_active_obj, 1, 2, rp2_state_machine_active);
|
||||
|
||||
// StateMachine.restart()
|
||||
STATIC mp_obj_t rp2_state_machine_restart(mp_obj_t self_in) {
|
||||
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
pio_sm_restart(self->pio, self->sm);
|
||||
pio_sm_exec(self->pio, self->sm, pio_encode_jmp(rp2_state_machine_initial_pc[self->id]));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2_state_machine_restart_obj, rp2_state_machine_restart);
|
||||
|
||||
// StateMachine.exec(instr)
|
||||
STATIC mp_obj_t rp2_state_machine_exec(mp_obj_t self_in, mp_obj_t instr_in) {
|
||||
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
@ -689,6 +715,20 @@ STATIC mp_obj_t rp2_state_machine_put(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_state_machine_put_obj, 2, 3, rp2_state_machine_put);
|
||||
|
||||
// StateMachine.rx_fifo()
|
||||
STATIC mp_obj_t rp2_state_machine_rx_fifo(mp_obj_t self_in) {
|
||||
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(pio_sm_get_rx_fifo_level(self->pio, self->sm));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2_state_machine_rx_fifo_obj, rp2_state_machine_rx_fifo);
|
||||
|
||||
// StateMachine.tx_fifo()
|
||||
STATIC mp_obj_t rp2_state_machine_tx_fifo(mp_obj_t self_in) {
|
||||
rp2_state_machine_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
return MP_OBJ_NEW_SMALL_INT(pio_sm_get_tx_fifo_level(self->pio, self->sm));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2_state_machine_tx_fifo_obj, rp2_state_machine_tx_fifo);
|
||||
|
||||
// StateMachine.irq(handler=None, trigger=0|1, hard=False)
|
||||
STATIC mp_obj_t rp2_state_machine_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_handler, ARG_trigger, ARG_hard };
|
||||
@ -748,9 +788,12 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(rp2_state_machine_irq_obj, 1, rp2_state_machin
|
||||
STATIC const mp_rom_map_elem_t rp2_state_machine_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&rp2_state_machine_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&rp2_state_machine_active_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_restart), MP_ROM_PTR(&rp2_state_machine_restart_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_exec), MP_ROM_PTR(&rp2_state_machine_exec_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&rp2_state_machine_get_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_put), MP_ROM_PTR(&rp2_state_machine_put_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_rx_fifo), MP_ROM_PTR(&rp2_state_machine_rx_fifo_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_tx_fifo), MP_ROM_PTR(&rp2_state_machine_tx_fifo_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&rp2_state_machine_irq_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(rp2_state_machine_locals_dict, rp2_state_machine_locals_dict_table);
|
||||
|
||||
@ -68,7 +68,7 @@ static const tusb_desc_device_t usbd_desc_device = {
|
||||
|
||||
static const uint8_t usbd_desc_cfg[USBD_DESC_LEN] = {
|
||||
TUD_CONFIG_DESCRIPTOR(1, USBD_ITF_MAX, USBD_STR_0, USBD_DESC_LEN,
|
||||
TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, USBD_MAX_POWER_MA),
|
||||
0, USBD_MAX_POWER_MA),
|
||||
|
||||
TUD_CDC_DESCRIPTOR(USBD_ITF_CDC, USBD_STR_CDC, USBD_CDC_EP_CMD,
|
||||
USBD_CDC_CMD_MAX_SIZE, USBD_CDC_EP_OUT, USBD_CDC_EP_IN, USBD_CDC_IN_OUT_MAX_SIZE),
|
||||
|
||||
@ -658,7 +658,7 @@ TEXT0_ADDR ?= 0x08000000
|
||||
ifeq ($(TEXT1_ADDR),)
|
||||
# No TEXT1_ADDR given so put all firmware at TEXT0_ADDR location
|
||||
|
||||
TEXT0_SECTIONS ?= .isr_vector .text .data
|
||||
TEXT0_SECTIONS ?= .isr_vector .text .data .ARM
|
||||
|
||||
deploy-stlink: $(BUILD)/firmware.bin
|
||||
$(call RUN_STLINK,$^,$(TEXT0_ADDR))
|
||||
@ -676,7 +676,7 @@ else
|
||||
# TEXT0_ADDR and TEXT1_ADDR are specified so split firmware between these locations
|
||||
|
||||
TEXT0_SECTIONS ?= .isr_vector
|
||||
TEXT1_SECTIONS ?= .text .data
|
||||
TEXT1_SECTIONS ?= .text .data .ARM
|
||||
|
||||
deploy-stlink: $(BUILD)/firmware0.bin $(BUILD)/firmware1.bin
|
||||
$(call RUN_STLINK,$(word 1,$^),$(TEXT0_ADDR))
|
||||
@ -765,7 +765,7 @@ CMSIS_MCU_HDR = $(CMSIS_DIR)/$(CMSIS_MCU_LOWER).h
|
||||
modmachine.c: $(GEN_PLLFREQTABLE_HDR)
|
||||
$(GEN_PLLFREQTABLE_HDR): $(PLLVALUES) | $(HEADER_BUILD)
|
||||
$(ECHO) "GEN $@"
|
||||
$(Q)$(PYTHON) $(PLLVALUES) -c -m $(MCU_SERIES) file:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h > $@
|
||||
$(Q)$(PYTHON) $(PLLVALUES) -c -m $(CMSIS_MCU_LOWER) file:$(BOARD_DIR)/stm32$(MCU_SERIES)xx_hal_conf.h > $@
|
||||
|
||||
$(BUILD)/modstm.o: $(GEN_STMCONST_HDR)
|
||||
# Use a pattern rule here so that make will only call make-stmconst.py once to
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "boardctrl.h"
|
||||
@ -140,13 +141,21 @@ void boardctrl_top_soft_reset_loop(boardctrl_state_t *state) {
|
||||
led_state(4, 0);
|
||||
}
|
||||
|
||||
void boardctrl_before_boot_py(boardctrl_state_t *state) {
|
||||
state->run_boot_py = state->reset_mode == 1 || state->reset_mode == 3;
|
||||
}
|
||||
int boardctrl_run_boot_py(boardctrl_state_t *state) {
|
||||
bool run_boot_py = state->reset_mode == 1 || state->reset_mode == 3;
|
||||
|
||||
void boardctrl_after_boot_py(boardctrl_state_t *state) {
|
||||
if (state->run_boot_py && !state->last_ret) {
|
||||
flash_error(4);
|
||||
if (run_boot_py) {
|
||||
// Run boot.py, if it exists.
|
||||
const char *boot_py = "boot.py";
|
||||
int ret = pyexec_file_if_exists(boot_py);
|
||||
|
||||
// Take action based on the execution result.
|
||||
if (ret & PYEXEC_FORCED_EXIT) {
|
||||
return BOARDCTRL_GOTO_SOFT_RESET_EXIT;
|
||||
}
|
||||
if (!ret) {
|
||||
flash_error(4);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn boot-up LEDs off
|
||||
@ -160,17 +169,34 @@ void boardctrl_after_boot_py(boardctrl_state_t *state) {
|
||||
led_state(2, 0);
|
||||
led_state(3, 0);
|
||||
led_state(4, 0);
|
||||
|
||||
return BOARDCTRL_CONTINUE;
|
||||
}
|
||||
|
||||
void boardctrl_before_main_py(boardctrl_state_t *state) {
|
||||
state->run_main_py = (state->reset_mode == 1 || state->reset_mode == 3)
|
||||
int boardctrl_run_main_py(boardctrl_state_t *state) {
|
||||
bool run_main_py = (state->reset_mode == 1 || state->reset_mode == 3)
|
||||
&& pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL;
|
||||
}
|
||||
|
||||
void boardctrl_after_main_py(boardctrl_state_t *state) {
|
||||
if (state->run_main_py && !state->last_ret) {
|
||||
flash_error(3);
|
||||
if (run_main_py) {
|
||||
// Run main.py (or what it was configured to be), if it exists.
|
||||
const char *main_py;
|
||||
if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) {
|
||||
main_py = "main.py";
|
||||
} else {
|
||||
main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main));
|
||||
}
|
||||
int ret = pyexec_file_if_exists(main_py);
|
||||
|
||||
// Take action based on the execution result.
|
||||
if (ret & PYEXEC_FORCED_EXIT) {
|
||||
return BOARDCTRL_GOTO_SOFT_RESET_EXIT;
|
||||
}
|
||||
if (!ret) {
|
||||
flash_error(3);
|
||||
}
|
||||
}
|
||||
|
||||
return BOARDCTRL_CONTINUE;
|
||||
}
|
||||
|
||||
void boardctrl_start_soft_reset(boardctrl_state_t *state) {
|
||||
|
||||
@ -44,20 +44,12 @@
|
||||
#define MICROPY_BOARD_TOP_SOFT_RESET_LOOP boardctrl_top_soft_reset_loop
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_BOARD_BEFORE_BOOT_PY
|
||||
#define MICROPY_BOARD_BEFORE_BOOT_PY boardctrl_before_boot_py
|
||||
#ifndef MICROPY_BOARD_RUN_BOOT_PY
|
||||
#define MICROPY_BOARD_RUN_BOOT_PY boardctrl_run_boot_py
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_BOARD_AFTER_BOOT_PY
|
||||
#define MICROPY_BOARD_AFTER_BOOT_PY boardctrl_after_boot_py
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_BOARD_BEFORE_MAIN_PY
|
||||
#define MICROPY_BOARD_BEFORE_MAIN_PY boardctrl_before_main_py
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_BOARD_AFTER_MAIN_PY
|
||||
#define MICROPY_BOARD_AFTER_MAIN_PY boardctrl_after_main_py
|
||||
#ifndef MICROPY_BOARD_RUN_MAIN_PY
|
||||
#define MICROPY_BOARD_RUN_MAIN_PY boardctrl_run_main_py
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_BOARD_START_SOFT_RESET
|
||||
@ -68,20 +60,20 @@
|
||||
#define MICROPY_BOARD_END_SOFT_RESET boardctrl_end_soft_reset
|
||||
#endif
|
||||
|
||||
enum {
|
||||
BOARDCTRL_CONTINUE,
|
||||
BOARDCTRL_GOTO_SOFT_RESET_EXIT,
|
||||
};
|
||||
|
||||
typedef struct _boardctrl_state_t {
|
||||
uint8_t reset_mode;
|
||||
bool run_boot_py;
|
||||
bool run_main_py;
|
||||
bool log_soft_reset;
|
||||
int last_ret;
|
||||
} boardctrl_state_t;
|
||||
|
||||
void boardctrl_before_soft_reset_loop(boardctrl_state_t *state);
|
||||
void boardctrl_top_soft_reset_loop(boardctrl_state_t *state);
|
||||
void boardctrl_before_boot_py(boardctrl_state_t *state);
|
||||
void boardctrl_after_boot_py(boardctrl_state_t *state);
|
||||
void boardctrl_before_main_py(boardctrl_state_t *state);
|
||||
void boardctrl_after_main_py(boardctrl_state_t *state);
|
||||
int boardctrl_run_boot_py(boardctrl_state_t *state);
|
||||
int boardctrl_run_main_py(boardctrl_state_t *state);
|
||||
void boardctrl_start_soft_reset(boardctrl_state_t *state);
|
||||
void boardctrl_end_soft_reset(boardctrl_state_t *state);
|
||||
|
||||
|
||||
@ -9,45 +9,64 @@
|
||||
#define MICROPY_HW_ENABLE_DAC (1)
|
||||
|
||||
// MSI is used and is 4MHz
|
||||
#define MICROPY_HW_CLK_PLLM (1)
|
||||
#define MICROPY_HW_CLK_PLLN (40)
|
||||
#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7)
|
||||
#define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2)
|
||||
#define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2)
|
||||
#define MICROPY_HW_CLK_PLLM (1)
|
||||
#define MICROPY_HW_CLK_PLLN (40)
|
||||
#define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV7)
|
||||
#define MICROPY_HW_CLK_PLLQ (RCC_PLLQ_DIV2)
|
||||
#define MICROPY_HW_CLK_PLLR (RCC_PLLR_DIV2)
|
||||
|
||||
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
|
||||
|
||||
// The board has an external 32kHz crystal
|
||||
#define MICROPY_HW_RTC_USE_LSE (1)
|
||||
|
||||
// UART config
|
||||
#define MICROPY_HW_UART2_TX (pin_A2)
|
||||
#define MICROPY_HW_UART2_RX (pin_A3)
|
||||
|
||||
// USART1 config
|
||||
#define MICROPY_HW_UART1_TX (pin_A9)
|
||||
#define MICROPY_HW_UART1_RX (pin_A10)
|
||||
// USART2 config. Connected to ST-Link
|
||||
#define MICROPY_HW_UART2_TX (pin_A2)
|
||||
#define MICROPY_HW_UART2_RX (pin_A3)
|
||||
#define MICROPY_HW_UART2_RTS (pin_A1)
|
||||
#define MICROPY_HW_UART2_CTS (pin_A0)
|
||||
// USART3 config
|
||||
#define MICROPY_HW_UART3_TX (pin_C4)
|
||||
#define MICROPY_HW_UART3_RX (pin_C5)
|
||||
#define MICROPY_HW_UART3_RTS (pin_B14)
|
||||
#define MICROPY_HW_UART3_CTS (pin_B13)
|
||||
// UART4 config
|
||||
#define MICROPY_HW_UART4_TX (pin_A0)
|
||||
#define MICROPY_HW_UART4_RX (pin_A1)
|
||||
// UART5 config
|
||||
#define MICROPY_HW_UART5_TX (pin_C12)
|
||||
#define MICROPY_HW_UART5_RX (pin_D2)
|
||||
// LPUART config
|
||||
#define MICROPY_HW_LPUART1_TX (pin_C1)
|
||||
#define MICROPY_HW_LPUART1_RX (pin_C0)
|
||||
// USART2 is connected to the virtual com port on the ST-Link
|
||||
#define MICROPY_HW_UART_REPL PYB_UART_2
|
||||
#define MICROPY_HW_UART_REPL_BAUD 115200
|
||||
|
||||
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
|
||||
|
||||
// I2C busses
|
||||
#define MICROPY_HW_I2C1_SCL (pin_B8)
|
||||
#define MICROPY_HW_I2C1_SDA (pin_B9)
|
||||
#define MICROPY_HW_I2C2_SCL (pin_B10)
|
||||
#define MICROPY_HW_I2C2_SDA (pin_B11)
|
||||
#define MICROPY_HW_I2C3_SCL (pin_C0)
|
||||
#define MICROPY_HW_I2C3_SDA (pin_C1)
|
||||
#define MICROPY_HW_I2C1_SCL (pin_B8)
|
||||
#define MICROPY_HW_I2C1_SDA (pin_B9)
|
||||
#define MICROPY_HW_I2C2_SCL (pin_B10)
|
||||
#define MICROPY_HW_I2C2_SDA (pin_B11)
|
||||
#define MICROPY_HW_I2C3_SCL (pin_C0)
|
||||
#define MICROPY_HW_I2C3_SDA (pin_C1)
|
||||
|
||||
// SPI busses
|
||||
#define MICROPY_HW_SPI1_NSS (pin_A4)
|
||||
#define MICROPY_HW_SPI1_SCK (pin_B3)
|
||||
#define MICROPY_HW_SPI1_MISO (pin_B4)
|
||||
#define MICROPY_HW_SPI1_MOSI (pin_B5)
|
||||
#define MICROPY_HW_SPI2_NSS (pin_B12)
|
||||
#define MICROPY_HW_SPI2_SCK (pin_B13)
|
||||
#define MICROPY_HW_SPI2_MISO (pin_B14)
|
||||
#define MICROPY_HW_SPI2_MOSI (pin_B15)
|
||||
#define MICROPY_HW_SPI1_NSS (pin_A4)
|
||||
#define MICROPY_HW_SPI1_SCK (pin_B3)
|
||||
#define MICROPY_HW_SPI1_MISO (pin_B4)
|
||||
#define MICROPY_HW_SPI1_MOSI (pin_B5)
|
||||
#define MICROPY_HW_SPI2_NSS (pin_B12)
|
||||
#define MICROPY_HW_SPI2_SCK (pin_B13)
|
||||
#define MICROPY_HW_SPI2_MISO (pin_B14)
|
||||
#define MICROPY_HW_SPI2_MOSI (pin_B15)
|
||||
|
||||
// CAN bus
|
||||
#define MICROPY_HW_CAN1_TX (pin_A12)
|
||||
#define MICROPY_HW_CAN1_RX (pin_A11)
|
||||
#define MICROPY_HW_CAN1_TX (pin_A12)
|
||||
#define MICROPY_HW_CAN1_RX (pin_A11)
|
||||
|
||||
// USRSW is pulled low. Pressing the button makes the input go high.
|
||||
#define MICROPY_HW_USRSW_PIN (pin_C13)
|
||||
@ -61,4 +80,4 @@
|
||||
#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
|
||||
|
||||
// USB config
|
||||
#define MICROPY_HW_USB_FS (1)
|
||||
#define MICROPY_HW_USB_FS (1)
|
||||
|
||||
@ -6,7 +6,7 @@ AF_FILE = boards/stm32f722_af.csv
|
||||
LD_FILES = boards/PYBD_SF2/f722_qspi.ld
|
||||
TEXT0_ADDR = 0x08008000
|
||||
TEXT1_ADDR = 0x90000000
|
||||
TEXT0_SECTIONS = .isr_vector .text .data
|
||||
TEXT0_SECTIONS = .isr_vector .text .data .ARM
|
||||
TEXT1_SECTIONS = .text_ext
|
||||
|
||||
# MicroPython settings
|
||||
|
||||
@ -6,7 +6,7 @@ AF_FILE = boards/stm32f722_af.csv
|
||||
LD_FILES = boards/PYBD_SF2/f722_qspi.ld
|
||||
TEXT0_ADDR = 0x08008000
|
||||
TEXT1_ADDR = 0x90000000
|
||||
TEXT0_SECTIONS = .isr_vector .text .data
|
||||
TEXT0_SECTIONS = .isr_vector .text .data .ARM
|
||||
TEXT1_SECTIONS = .text_ext
|
||||
|
||||
# MicroPython settings
|
||||
|
||||
@ -22,7 +22,7 @@ ifeq ($(USE_QSPI_XIP),1)
|
||||
LD_FILES = boards/STM32F769DISC/f769_qspi.ld
|
||||
TEXT0_ADDR = 0x08020000
|
||||
TEXT1_ADDR = 0x90000000
|
||||
TEXT0_SECTIONS = .isr_vector .text .data
|
||||
TEXT0_SECTIONS = .isr_vector .text .data .ARM
|
||||
TEXT1_SECTIONS = .text_qspi
|
||||
|
||||
else
|
||||
|
||||
@ -240,7 +240,7 @@ def main():
|
||||
argv = sys.argv[1:]
|
||||
|
||||
c_table = False
|
||||
mcu_series = "f4"
|
||||
mcu_series = "stm32f4"
|
||||
hse = None
|
||||
hsi = None
|
||||
|
||||
@ -271,13 +271,13 @@ def main():
|
||||
hse = int(argv[0])
|
||||
|
||||
# Select MCU parameters
|
||||
if mcu_series == "h7":
|
||||
if mcu_series.startswith("stm32h7"):
|
||||
mcu = mcu_h7
|
||||
else:
|
||||
mcu = mcu_default
|
||||
|
||||
# Relax constraight on PLLQ being 48MHz on F7 and H7 MCUs, which have separate PLLs for 48MHz
|
||||
relax_pll48 = mcu_series in ("f7", "h7")
|
||||
# Relax constraint on PLLQ being 48MHz on MCUs which have separate PLLs for 48MHz
|
||||
relax_pll48 = mcu_series.startswith(("stm32f413", "stm32f7", "stm32h7"))
|
||||
|
||||
hse_valid_plls = compute_pll_table(hse, relax_pll48)
|
||||
if hsi is not None:
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Port,Pin,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,,
|
||||
,,SPI1/SPI2/I2S2/USART1/2/LPUART1/USB/LPTIM1/TSC/TIM2/21/22/EVENTOUT/SYS_AF,SPI1/SPI2/I2S2/I2C1/TIM2/21,SPI1/SPI2/I2S2/LPUART1/USART5/USB/LPTIM1/TIM2/3/EVENTOUT/SYS_AF,I2C1/TSC/EVENTOUT,I2C1/USART1/2/LPUART1/TIM3/22/EVENTOUT,SPI2/I2S2/I2C2/USART1/TIM2/21/22,I2C1/2/LPUART1/USART4/UASRT5/TIM21/EVENTOUT,I2C3/LPUART1/COMP1/2/TIM3,,ADC
|
||||
PortA,PA0,,,TIM2_CH1,TSC_G1_IO1,USART2_CTS,TIM2_ETR,USART4_TX,COMP1_OUT,,ADC_IN0
|
||||
PortA,PA1,EVENTOUT,,TIM2_CH2,TSC_G1_IO2,USART2_RTS_DE,TIM21_ETR,USART4_RX,,,ADC_IN1
|
||||
PortA,PA1,EVENTOUT,,TIM2_CH2,TSC_G1_IO2,USART2_RTS/USART2_DE,TIM21_ETR,USART4_RX,,,ADC_IN1
|
||||
PortA,PA2,TIM21_CH1,,TIM2_CH3,TSC_G1_IO3,USART2_TX,,LPUART1_TX,COMP2_OUT,,ADC_IN2
|
||||
PortA,PA3,TIM21_CH2,,TIM2_CH4,TSC_G1_IO4,USART2_RX,,LPUART1_RX,,,ADC_IN3
|
||||
PortA,PA4,SPI1_NSS,,,TSC_G2_IO1,USART2_CK,TIM22_ETR,,,,ADC_IN4
|
||||
@ -12,25 +12,25 @@ PortA,PA8,MCO,,USB_CRS_SYNC,EVENTOUT,USART1_CK,,,I2C3_SCL,,
|
||||
PortA,PA9,MCO,,,TSC_G4_IO1,USART1_TX,,I2C1_SCL,I2C3_SMBA,,
|
||||
PortA,PA10,,,,TSC_G4_IO2,USART1_RX,,I2C1_SDA,,,
|
||||
PortA,PA11,SPI1_MISO,,EVENTOUT,TSC_G4_IO3,USART1_CTS,,,COMP1_OUT,,
|
||||
PortA,PA12,SPI1_MOSI,,EVENTOUT,TSC_G4_IO4,USART1_RTS_DE,,,COMP2_OUT,,
|
||||
PortA,PA12,SPI1_MOSI,,EVENTOUT,TSC_G4_IO4,USART1_RTS/USART1_DE,,,COMP2_OUT,,
|
||||
PortA,PA13,SWDIO,,USB_NOE,,,,LPUART1_RX,,,
|
||||
PortA,PA14,SWCLK,,,,USART2_TX,,LPUART1_TX,,,
|
||||
PortA,PA15,SPI1_NSS,,TIM2_ETR,EVENTOUT,USART2_RX,TIM2_CH1,USART4_RTS_DE,,,
|
||||
PortA,PA15,SPI1_NSS,,TIM2_ETR,EVENTOUT,USART2_RX,TIM2_CH1,USART4_RTS/USART4_DE,,,
|
||||
PortB,PB0,EVENTOUT,,TIM3_CH3,TSC_G3_IO2,,,,,,ADC_IN8
|
||||
PortB,PB1,,,TIM3_CH4,TSC_G3_IO3,LPUART1_RTS_DE,,,,,ADC_IN9
|
||||
PortB,PB1,,,TIM3_CH4,TSC_G3_IO3,LPUART1_RTS/LPUART1_DE,,,,,ADC_IN9
|
||||
PortB,PB2,,,LPTIM1_OUT,TSC_G3_IO4,,,,I2C3_SMBA,,
|
||||
PortB,PB3,SPI1_SCK,,TIM2_CH2,TSC_G5_IO1,EVENTOUT,USART1_RTS_DE,USART5_TX,,,
|
||||
PortB,PB3,SPI1_SCK,,TIM2_CH2,TSC_G5_IO1,EVENTOUT,USART1_RTS/USART1_DE,USART5_TX,,,
|
||||
PortB,PB4,SPI1_MISO,,TIM3_CH1,TSC_G5_IO2,TIM22_CH1,USART1_CTS,USART5_RX,I2C3_SDA,,
|
||||
PortB,PB5,SPI1_MOSI,,LPTIM1_IN1,I2C1_SMBA,TIM3_CH2/TIM22_CH2,USART1_CK,USART5_CK/USART5_RTS_DE,,,
|
||||
PortB,PB5,SPI1_MOSI,,LPTIM1_IN1,I2C1_SMBA,TIM3_CH2/TIM22_CH2,USART1_CK,USART5_CK/USART5_RTS/USART5_DE,,,
|
||||
PortB,PB6,USART1_TX,I2C1_SCL,LPTIM1_ETR,TSC_G5_IO3,,,,,,
|
||||
PortB,PB7,USART1_RX,I2C1_SDA,LPTIM1_IN2,TSC_G5_IO4,,,USART4_CTS,,,
|
||||
PortB,PB8,,,,TSC_SYNC,I2C1_SCL,,,,,
|
||||
PortB,PB9,,,EVENTOUT,,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,
|
||||
PortB,PB10,,,TIM2_CH3,TSC_SYNC,LPUART1_TX,SPI2_SCK,I2C2_SCL,LPUART1_RX,,
|
||||
PortB,PB11,EVENTOUT,,TIM2_CH4,TSC_G6_IO1,LPUART1_RX,,I2C2_SDA,LPUART1_TX,,
|
||||
PortB,PB12,SPI2_NSS/I2S2_WS,,LPUART1_RTS_DE,TSC_G6_IO2,I2C2_SMBA,,EVENTOUT,,,
|
||||
PortB,PB12,SPI2_NSS/I2S2_WS,,LPUART1_RTS/LPUART1_DE,TSC_G6_IO2,I2C2_SMBA,,EVENTOUT,,,
|
||||
PortB,PB13,SPI2_SCK/I2S2_CK,,MCO,TSC_G6_IO3,LPUART1_CTS,I2C2_SCL,TIM21_CH1,,,
|
||||
PortB,PB14,SPI2_MISO/I2S2_MCK,,RTC_OUT,TSC_G6_IO4,LPUART1_RTS_DE,I2C2_SDA,TIM21_CH2,,,
|
||||
PortB,PB14,SPI2_MISO/I2S2_MCK,,RTC_OUT,TSC_G6_IO4,LPUART1_RTS/LPUART1_DE,I2C2_SDA,TIM21_CH2,,,
|
||||
PortB,PB15,SPI2_MOSI/I2S2_SD,,RTC_REFIN,,,,,,,
|
||||
PortC,PC0,LPTIM1_IN1,,EVENTOUT,TSC_G7_IO1,,,LPUART1_RX,I2C3_SCL,,ADC_IN10
|
||||
PortC,PC1,LPTIM1_OUT,,EVENTOUT,TSC_G7_IO2,,,LPUART1_TX,I2C3_SDA,,ADC_IN11
|
||||
@ -50,9 +50,9 @@ PortC,PC14,,,,,,,,,,
|
||||
PortC,PC15,,,,,,,,,,
|
||||
PortD,PD0,TIM21_CH1,SPI2_NSS/I2S2_WS,,,,,,,,
|
||||
PortD,PD1,,SPI2_SCK/I2S2_CK,,,,,,,,
|
||||
PortD,PD2,LPUART1_RTS_DE,,TIM3_ETR,,,,USART5_RX,,,
|
||||
PortD,PD2,LPUART1_RTS/LPUART1_DE,,TIM3_ETR,,,,USART5_RX,,,
|
||||
PortD,PD3,USART2_CTS,,SPI2_MISO/I2S2_MCK,,,,,,,
|
||||
PortD,PD4,USART2_RTS_DE,SPI2_MOSI/I2S2_SD,,,,,,,,
|
||||
PortD,PD4,USART2_RTS/USART2_DE,SPI2_MOSI/I2S2_SD,,,,,,,,
|
||||
PortD,PD5,USART2_TX,,,,,,,,,
|
||||
PortD,PD6,USART2_RX,,,,,,,,,
|
||||
PortD,PD7,USART2_CK,TIM21_CH2,,,,,,,,
|
||||
@ -60,7 +60,7 @@ PortD,PD8,LPUART1_TX,,,,,,,,,
|
||||
PortD,PD9,LPUART1_RX,,,,,,,,,
|
||||
PortD,PD10,,,,,,,,,,
|
||||
PortD,PD11,LPUART1_CTS,,,,,,,,,
|
||||
PortD,PD12,LPUART1_RTS_DE,,,,,,,,,
|
||||
PortD,PD12,LPUART1_RTS/LPUART1_DE,,,,,,,,,
|
||||
PortD,PD13,,,,,,,,,,
|
||||
PortD,PD14,,,,,,,,,,
|
||||
PortD,PD15,USB_CRS_SYNC,,,,,,,,,
|
||||
@ -71,7 +71,7 @@ PortE,PE3,TIM22_CH1,,TIM3_CH1,,,,,,,
|
||||
PortE,PE4,TIM22_CH2,,TIM3_CH2,,,,,,,
|
||||
PortE,PE5,TIM21_CH1,,TIM3_CH3,,,,,,,
|
||||
PortE,PE6,TIM21_CH2,,TIM3_CH4,,,,,,,
|
||||
PortE,PE7,,,,,,,USART5_CK/USART5_RTS_DE,,,
|
||||
PortE,PE7,,,,,,,USART5_CK/USART5_RTS/USART5_DE,,,
|
||||
PortE,PE8,,,,,,,USART4_TX,,,
|
||||
PortE,PE9,TIM2_CH1,,TIM2_ETR,,,,USART4_RX,,,
|
||||
PortE,PE10,TIM2_CH2,,,,,,USART5_TX,,,
|
||||
|
||||
|
@ -30,7 +30,7 @@ PortB,PB10,,TIM2_CH3,,I2C4_SCL,I2C2_SCL,SPI2_SCK,,USART3_TX,LPUART1_RX,TSC_SYNC,
|
||||
PortB,PB11,,TIM2_CH4,,I2C4_SDA,I2C2_SDA,,,USART3_RX,LPUART1_TX,,QUADSPI_NCS,,COMP2_OUT,,,EVENTOUT,,,
|
||||
PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS/LPUART1_DE,TSC_G1_IO1,CAN1_RX,,,SAI1_FS_A,TIM15_BKIN,EVENTOUT,,,
|
||||
PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,CAN1_TX,,,SAI1_SCK_A,TIM15_CH1N,EVENTOUT,,,
|
||||
PortB,PB14,,TIM1_CH2N,,,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,,,SAI1_MCLK_A,TIM15_CH1,EVENTOUT,,,
|
||||
PortB,PB14,,TIM1_CH2N,,,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS/USART3_DE,,TSC_G1_IO3,,,,SAI1_MCLK_A,TIM15_CH1,EVENTOUT,,,
|
||||
PortB,PB15,RTC_REFIN,TIM1_CH3N,,,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,,,SAI1_SD_A,TIM15_CH2,EVENTOUT,,,
|
||||
PortC,PC0,,LPTIM1_IN1,I2C4_SCL,,I2C3_SCL,,,,LPUART1_RX,,,,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1,,
|
||||
PortC,PC1,TRACED0,LPTIM1_OUT,I2C4_SDA,,I2C3_SDA,,,,LPUART1_TX,,,,,,,EVENTOUT,ADC123_IN2,,
|
||||
|
||||
|
@ -30,7 +30,7 @@ PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK,DFSDM_DATIN7,USART3_TX,LPUART1_RX,,QUAD
|
||||
PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,DFSDM_CKIN7,USART3_RX,LPUART1_TX,,QUADSPI_NCS,LCD_SEG11,COMP2_OUT,,,EVENTOUT,,
|
||||
PortB,PB12,,TIM1_BKIN,,TIM1_BKIN_COMP2,I2C2_SMBA,SPI2_NSS,DFSDM_DATIN1,USART3_CK,LPUART1_RTS/LPUART1_DE,TSC_G1_IO1,,LCD_SEG12,SWPMI1_IO,SAI2_FS_A,TIM15_BKIN,EVENTOUT,,
|
||||
PortB,PB13,,TIM1_CH1N,,,I2C2_SCL,SPI2_SCK,DFSDM_CKIN1,USART3_CTS,LPUART1_CTS,TSC_G1_IO2,,LCD_SEG13,SWPMI1_TX,SAI2_SCK_A,TIM15_CH1N,EVENTOUT,,
|
||||
PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS_DE,,TSC_G1_IO3,,LCD_SEG14,SWPMI1_RX,SAI2_MCLK_A,TIM15_CH1,EVENTOUT,,
|
||||
PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,I2C2_SDA,SPI2_MISO,DFSDM_DATIN2,USART3_RTS/USART3_DE,,TSC_G1_IO3,,LCD_SEG14,SWPMI1_RX,SAI2_MCLK_A,TIM15_CH1,EVENTOUT,,
|
||||
PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI,DFSDM_CKIN2,,,TSC_G1_IO4,,LCD_SEG15,SWPMI1_SUSPEND,SAI2_SD_A,TIM15_CH2,EVENTOUT,,
|
||||
PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,DFSDM_DATIN4,,LPUART1_RX,,,LCD_SEG18,,,LPTIM2_IN1,EVENTOUT,ADC123_IN1,
|
||||
PortC,PC1,,LPTIM1_OUT,,,I2C3_SDA,,DFSDM_CKIN4,,LPUART1_TX,,,LCD_SEG19,,,,EVENTOUT,ADC123_IN2,
|
||||
|
||||
|
@ -12,14 +12,14 @@ PortA,PA8,MCO,TIM1_CH1,,SAI1_PDM_CK2,,,,USART1_CK,,,,LCD_COM0,,SAI1_SCK_A,LPTIM2
|
||||
PortA,PA9,,TIM1_CH2,,SAI1_PDM_DI2,I2C1_SCL,SPI2_SCK,,USART1_TX,,,,LCD_COM1,,SAI1_FS_A,,EVENTOUT,ADC1_IN16
|
||||
PortA,PA10,,TIM1_CH3,,SAI1_PDM_DI1,I2C1_SDA,,,USART1_RX,,,USB_CRS_SYNC,LCD_COM2,,SAI1_SD_A,TIM17_BKIN,EVENTOUT,
|
||||
PortA,PA11,,TIM1_CH4,TIM1_BKIN2,,,SPI1_MISO,,USART1_CTS,,,USB_DM,,TIM1_BKIN2,,,EVENTOUT,
|
||||
PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS_DE,LPUART1_RX,,USB_DP,,,,,EVENTOUT,
|
||||
PortA,PA12,,TIM1_ETR,,,,SPI1_MOSI,,USART1_RTS/USART1_DE,LPUART1_RX,,USB_DP,,,,,EVENTOUT,
|
||||
PortA,PA13,JTMS/SWDIO,,,,,,,,IR_OUT,,USB_NOE,,,SAI1_SD_B,,EVENTOUT,
|
||||
PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,LCD_SEG5,,SAI1_FS_B,,EVENTOUT,
|
||||
PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,,SPI1_NSS,,,,TSC_G3_IO1,,LCD_SEG17,,,,EVENTOUT,
|
||||
PortB,PB0,,,,,,,EXT_PA_TX,,,,,,COMP1_OUT,,,EVENTOUT,
|
||||
PortB,PB1,,,,,,,,,LPUART1_RTS_DE,,,,,,LPTIM2_IN1,EVENTOUT,
|
||||
PortB,PB1,,,,,,,,,LPUART1_RTS/LPUART1_DE,,,,,,LPTIM2_IN1,EVENTOUT,
|
||||
PortB,PB2,RTC_OUT,LPTIM1_OUT,,,I2C3_SMBA,SPI1_NSS,,,,,,LCD_VLCD,,SAI1_EXTCLK,,EVENTOUT,
|
||||
PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,,USART1_RTS_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT,
|
||||
PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,,USART1_RTS/USART1_DE,,,,LCD_SEG7,,SAI1_SCK_B,,EVENTOUT,
|
||||
PortB,PB4,NJTRST,,,,I2C3_SDA,SPI1_MISO,,USART1_CTS,,TSC_G2_IO1,,LCD_SEG8,,SAI1_MCLK_B,TIM17_BKIN,EVENTOUT,
|
||||
PortB,PB5,,LPTIM1_IN1,,,I2C1_SMBA,SPI1_MOSI,,USART1_CK,LPUART1_TX,TSC_G2_IO2,,LCD_SEG9,COMP2_OUT,SAI1_SD_B,TIM16_BKIN,EVENTOUT,
|
||||
PortB,PB6,MCO,LPTIM1_ETR,,,I2C1_SCL,,,USART1_TX,,TSC_G2_IO3,,LCD_SEG6,,SAI1_FS_B,TIM16_CH1N,EVENTOUT,
|
||||
|
||||
|
@ -469,9 +469,7 @@ void stm32_main(uint32_t reset_mode) {
|
||||
|
||||
boardctrl_state_t state;
|
||||
state.reset_mode = reset_mode;
|
||||
state.run_boot_py = false;
|
||||
state.run_main_py = false;
|
||||
state.last_ret = 0;
|
||||
state.log_soft_reset = false;
|
||||
|
||||
MICROPY_BOARD_BEFORE_SOFT_RESET_LOOP(&state);
|
||||
|
||||
@ -566,20 +564,11 @@ soft_reset:
|
||||
// reset config variables; they should be set by boot.py
|
||||
MP_STATE_PORT(pyb_config_main) = MP_OBJ_NULL;
|
||||
|
||||
MICROPY_BOARD_BEFORE_BOOT_PY(&state);
|
||||
|
||||
// run boot.py, if it exists
|
||||
// TODO perhaps have pyb.reboot([bootpy]) function to soft-reboot and execute custom boot.py
|
||||
if (state.run_boot_py) {
|
||||
const char *boot_py = "boot.py";
|
||||
state.last_ret = pyexec_file_if_exists(boot_py);
|
||||
if (state.last_ret & PYEXEC_FORCED_EXIT) {
|
||||
goto soft_reset_exit;
|
||||
}
|
||||
// Run boot.py (or whatever else a board configures at this stage).
|
||||
if (MICROPY_BOARD_RUN_BOOT_PY(&state) == BOARDCTRL_GOTO_SOFT_RESET_EXIT) {
|
||||
goto soft_reset_exit;
|
||||
}
|
||||
|
||||
MICROPY_BOARD_AFTER_BOOT_PY(&state);
|
||||
|
||||
// Now we initialise sub-systems that need configuration from boot.py,
|
||||
// or whose initialisation can be safely deferred until after running
|
||||
// boot.py.
|
||||
@ -613,24 +602,11 @@ soft_reset:
|
||||
|
||||
// At this point everything is fully configured and initialised.
|
||||
|
||||
MICROPY_BOARD_BEFORE_MAIN_PY(&state);
|
||||
|
||||
// Run the main script from the current directory.
|
||||
if (state.run_main_py) {
|
||||
const char *main_py;
|
||||
if (MP_STATE_PORT(pyb_config_main) == MP_OBJ_NULL) {
|
||||
main_py = "main.py";
|
||||
} else {
|
||||
main_py = mp_obj_str_get_str(MP_STATE_PORT(pyb_config_main));
|
||||
}
|
||||
state.last_ret = pyexec_file_if_exists(main_py);
|
||||
if (state.last_ret & PYEXEC_FORCED_EXIT) {
|
||||
goto soft_reset_exit;
|
||||
}
|
||||
// Run main.py (or whatever else a board configures at this stage).
|
||||
if (MICROPY_BOARD_RUN_MAIN_PY(&state) == BOARDCTRL_GOTO_SOFT_RESET_EXIT) {
|
||||
goto soft_reset_exit;
|
||||
}
|
||||
|
||||
MICROPY_BOARD_AFTER_MAIN_PY(&state);
|
||||
|
||||
#if MICROPY_ENABLE_COMPILER
|
||||
// Main script is finished, so now go into REPL mode.
|
||||
// The REPL mode can change, or it can request a soft reset.
|
||||
|
||||
@ -310,6 +310,25 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Configure the default bus clock divider values
|
||||
#ifndef MICROPY_HW_CLK_AHB_DIV
|
||||
#if defined(STM32H7)
|
||||
#define MICROPY_HW_CLK_AHB_DIV (RCC_HCLK_DIV2)
|
||||
#define MICROPY_HW_CLK_APB1_DIV (RCC_APB1_DIV2)
|
||||
#define MICROPY_HW_CLK_APB2_DIV (RCC_APB2_DIV2)
|
||||
#define MICROPY_HW_CLK_APB3_DIV (RCC_APB3_DIV2)
|
||||
#define MICROPY_HW_CLK_APB4_DIV (RCC_APB4_DIV2)
|
||||
#elif defined(STM32L4)
|
||||
#define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1)
|
||||
#define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV1)
|
||||
#define MICROPY_HW_CLK_APB2_DIV (RCC_HCLK_DIV1)
|
||||
#else
|
||||
#define MICROPY_HW_CLK_AHB_DIV (RCC_SYSCLK_DIV1)
|
||||
#define MICROPY_HW_CLK_APB1_DIV (RCC_HCLK_DIV4)
|
||||
#define MICROPY_HW_CLK_APB2_DIV (RCC_HCLK_DIV2)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If disabled then try normal (non-bypass) LSE first, with fallback to LSI.
|
||||
// If enabled first try LSE in bypass mode. If that fails to start, try non-bypass mode, with fallback to LSI.
|
||||
#ifndef MICROPY_HW_RTC_USE_BYPASS
|
||||
|
||||
@ -399,6 +399,10 @@ struct _mp_bluetooth_btstack_root_pointers_t;
|
||||
#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK
|
||||
#endif
|
||||
|
||||
#ifndef MICROPY_BOARD_ROOT_POINTERS
|
||||
#define MICROPY_BOARD_ROOT_POINTERS
|
||||
#endif
|
||||
|
||||
#define MICROPY_PORT_ROOT_POINTERS \
|
||||
LV_ROOTS \
|
||||
void *mp_lv_user_data; \
|
||||
@ -433,9 +437,13 @@ struct _mp_bluetooth_btstack_root_pointers_t;
|
||||
/* list of registered NICs */ \
|
||||
mp_obj_list_t mod_network_nic_list; \
|
||||
\
|
||||
/* root pointers for sub-systems */ \
|
||||
MICROPY_PORT_ROOT_POINTER_MBEDTLS \
|
||||
MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE \
|
||||
MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK \
|
||||
MICROPY_PORT_ROOT_POINTER_BLUETOOTH_BTSTACK \
|
||||
\
|
||||
/* root pointers defined by a board */ \
|
||||
MICROPY_BOARD_ROOT_POINTERS \
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
|
||||
@ -50,6 +50,22 @@
|
||||
#define RCC_SR_RMVF RCC_CSR_RMVF
|
||||
#endif
|
||||
|
||||
// Whether this MCU has an independent PLL which can generate 48MHz for USB.
|
||||
#if defined(STM32F413xx)
|
||||
// STM32F413 uses PLLI2S as secondary PLL.
|
||||
#define HAVE_PLL48 1
|
||||
#define RCC_CR_PLL48_ON RCC_CR_PLLI2SON
|
||||
#define RCC_CR_PLL48_RDY RCC_CR_PLLI2SRDY
|
||||
#elif defined(STM32F7)
|
||||
// STM32F7 uses PLLSAI as secondary PLL.
|
||||
#define HAVE_PLL48 1
|
||||
#define RCC_CR_PLL48_ON RCC_CR_PLLSAION
|
||||
#define RCC_CR_PLL48_RDY RCC_CR_PLLSAIRDY
|
||||
#else
|
||||
// MCU does not have a secondary PLL.
|
||||
#define HAVE_PLL48 0
|
||||
#endif
|
||||
|
||||
// Location in RAM of bootloader state (just after the top of the stack)
|
||||
extern uint32_t _estack[];
|
||||
#define BL_STATE ((uint32_t *)&_estack)
|
||||
@ -141,13 +157,24 @@ STATIC int powerctrl_config_vos(uint32_t sysclk_mhz) {
|
||||
}
|
||||
|
||||
// Assumes that PLL is used as the SYSCLK source
|
||||
int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) {
|
||||
int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pll48) {
|
||||
uint32_t flash_latency;
|
||||
|
||||
#if defined(STM32F7)
|
||||
if (need_pllsai) {
|
||||
// Configure PLLSAI at 48MHz for those peripherals that need this freq
|
||||
// (calculation assumes it can get an integral value of PLLSAIN)
|
||||
#if HAVE_PLL48
|
||||
if (need_pll48) {
|
||||
// Configure secondary PLL at 48MHz for those peripherals that need this freq
|
||||
// (the calculation assumes it can get an integral value of PLL-N).
|
||||
|
||||
#if defined(STM32F413xx)
|
||||
const uint32_t plli2sm = HSE_VALUE / 1000000;
|
||||
const uint32_t plli2sq = 2;
|
||||
const uint32_t plli2sr = 2;
|
||||
const uint32_t plli2sn = 48 * plli2sq;
|
||||
RCC->PLLI2SCFGR = plli2sr << RCC_PLLI2SCFGR_PLLI2SR_Pos
|
||||
| plli2sq << RCC_PLLI2SCFGR_PLLI2SQ_Pos
|
||||
| plli2sn << RCC_PLLI2SCFGR_PLLI2SN_Pos
|
||||
| plli2sm << RCC_PLLI2SCFGR_PLLI2SM_Pos;
|
||||
#else
|
||||
const uint32_t pllm = (RCC->PLLCFGR >> RCC_PLLCFGR_PLLM_Pos) & 0x3f;
|
||||
const uint32_t pllsaip = 4;
|
||||
const uint32_t pllsaiq = 2;
|
||||
@ -155,13 +182,18 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk
|
||||
RCC->PLLSAICFGR = pllsaiq << RCC_PLLSAICFGR_PLLSAIQ_Pos
|
||||
| (pllsaip / 2 - 1) << RCC_PLLSAICFGR_PLLSAIP_Pos
|
||||
| pllsain << RCC_PLLSAICFGR_PLLSAIN_Pos;
|
||||
RCC->CR |= RCC_CR_PLLSAION;
|
||||
#endif
|
||||
|
||||
// Turn on the PLL and wait for it to be ready.
|
||||
RCC->CR |= RCC_CR_PLL48_ON;
|
||||
uint32_t ticks = mp_hal_ticks_ms();
|
||||
while (!(RCC->CR & RCC_CR_PLLSAIRDY)) {
|
||||
while (!(RCC->CR & RCC_CR_PLL48_RDY)) {
|
||||
if (mp_hal_ticks_ms() - ticks > 200) {
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
// Select the alternate 48MHz source.
|
||||
RCC->DCKCFGR2 |= RCC_DCKCFGR2_CK48MSEL;
|
||||
}
|
||||
#endif
|
||||
@ -317,7 +349,7 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t
|
||||
// Default PLL parameters that give 48MHz on PLL48CK
|
||||
uint32_t m = MICROPY_HW_CLK_VALUE / 1000000, n = 336, p = 2, q = 7;
|
||||
uint32_t sysclk_source;
|
||||
bool need_pllsai = false;
|
||||
bool need_pll48 = false;
|
||||
|
||||
// Search for a valid PLL configuration that keeps USB at 48MHz
|
||||
uint32_t sysclk_mhz = sysclk / 1000000;
|
||||
@ -338,8 +370,8 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t
|
||||
uint32_t vco_out = sys * p;
|
||||
n = vco_out * m / (MICROPY_HW_CLK_VALUE / 1000000);
|
||||
q = vco_out / 48;
|
||||
#if defined(STM32F7)
|
||||
need_pllsai = vco_out % 48 != 0;
|
||||
#if HAVE_PLL48
|
||||
need_pll48 = vco_out % 48 != 0;
|
||||
#endif
|
||||
}
|
||||
goto set_clk;
|
||||
@ -377,8 +409,8 @@ set_clk:
|
||||
RCC_ClkInitStruct.APB2CLKDivider = calc_apb2_div(ahb / apb2);
|
||||
#if defined(STM32H7)
|
||||
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
|
||||
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
|
||||
RCC_ClkInitStruct.APB3CLKDivider = MICROPY_HW_CLK_APB3_DIV;
|
||||
RCC_ClkInitStruct.APB4CLKDivider = MICROPY_HW_CLK_APB4_DIV;
|
||||
#endif
|
||||
|
||||
#if MICROPY_HW_CLK_LAST_FREQ
|
||||
@ -393,11 +425,11 @@ set_clk:
|
||||
return -MP_EIO;
|
||||
}
|
||||
|
||||
#if defined(STM32F7)
|
||||
#if HAVE_PLL48
|
||||
// Deselect PLLSAI as 48MHz source if we were using it
|
||||
RCC->DCKCFGR2 &= ~RCC_DCKCFGR2_CK48MSEL;
|
||||
// Turn PLLSAI off because we are changing PLLM (which drives PLLSAI)
|
||||
RCC->CR &= ~RCC_CR_PLLSAION;
|
||||
RCC->CR &= ~RCC_CR_PLL48_ON;
|
||||
#endif
|
||||
|
||||
// Re-configure PLL
|
||||
@ -440,7 +472,7 @@ set_clk:
|
||||
// Set PLL as system clock source if wanted
|
||||
if (sysclk_source == RCC_SYSCLKSOURCE_PLLCLK) {
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
|
||||
int ret = powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pllsai);
|
||||
int ret = powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pll48);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
@ -607,11 +639,11 @@ void powerctrl_enter_stop_mode(void) {
|
||||
|
||||
powerctrl_disable_hsi_if_unused();
|
||||
|
||||
#if defined(STM32F7)
|
||||
#if HAVE_PLL48
|
||||
if (RCC->DCKCFGR2 & RCC_DCKCFGR2_CK48MSEL) {
|
||||
// Enable PLLSAI if it is selected as 48MHz source
|
||||
RCC->CR |= RCC_CR_PLLSAION;
|
||||
while (!(RCC->CR & RCC_CR_PLLSAIRDY)) {
|
||||
RCC->CR |= RCC_CR_PLL48_ON;
|
||||
while (!(RCC->CR & RCC_CR_PLL48_RDY)) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -417,6 +417,12 @@ STATIC void tl_process_msg(volatile tl_list_node_t *head, unsigned int ch, parse
|
||||
|
||||
// If this node is allocated from the memmgr event pool, then place it into the free buffer.
|
||||
if ((uint8_t *)cur >= ipcc_membuf_memmgr_evt_pool && (uint8_t *)cur < ipcc_membuf_memmgr_evt_pool + sizeof(ipcc_membuf_memmgr_evt_pool)) {
|
||||
// Wait for C2 to indicate that it has finished using the free buffer,
|
||||
// so that we can link the newly-freed memory in to this buffer.
|
||||
// If waiting is needed then it is typically between 5 and 20 microseconds.
|
||||
while (LL_C1_IPCC_IsActiveFlag_CHx(IPCC, IPCC_CH_MM)) {
|
||||
}
|
||||
|
||||
// Place memory back in free pool.
|
||||
tl_list_append(&ipcc_mem_memmgr_free_buf_queue, cur);
|
||||
added_to_free_queue = true;
|
||||
@ -604,6 +610,24 @@ void rfcore_ble_hci_cmd(size_t len, const uint8_t *src) {
|
||||
tl_list_node_t *n;
|
||||
uint32_t ch;
|
||||
if (src[0] == HCI_KIND_BT_CMD) {
|
||||
// The STM32WB has a problem when address resolution is enabled: under certain
|
||||
// conditions the MCU can get into a state where it draws an additional 10mA
|
||||
// or so and eventually ends up with a broken BLE RX path in the silicon. A
|
||||
// simple way to reproduce this is to enable address resolution (which is the
|
||||
// default for NimBLE) and start the device advertising. If there is enough
|
||||
// BLE activity in the vicinity then the device will at some point enter the
|
||||
// bad state and, if left long enough, will have permanent BLE RX damage.
|
||||
//
|
||||
// STMicroelectronics are aware of this issue. The only known workaround at
|
||||
// this stage is to not enable address resolution. We do that here by
|
||||
// intercepting any command that enables address resolution and convert it
|
||||
// into a command that disables address resolution.
|
||||
//
|
||||
// OGF=0x08 OCF=0x002d HCI_LE_Set_Address_Resolution_Enable
|
||||
if (len == 5 && memcmp(src + 1, "\x2d\x20\x01\x01", 4) == 0) {
|
||||
src = (const uint8_t *)"\x01\x2d\x20\x01\x00";
|
||||
}
|
||||
|
||||
n = (tl_list_node_t *)&ipcc_membuf_ble_cmd_buf[0];
|
||||
ch = IPCC_CH_BLE;
|
||||
} else if (src[0] == HCI_KIND_BT_ACL) {
|
||||
|
||||
@ -73,7 +73,9 @@ bool sdram_init(void) {
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNRAS, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNRAS);
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_SDNWE, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_SDNWE);
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_BA0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_BA0);
|
||||
#ifdef MICROPY_HW_FMC_BA1
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_BA1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_BA1);
|
||||
#endif
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_NBL0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_NBL0);
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_NBL1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_NBL1);
|
||||
#ifdef MICROPY_HW_FMC_NBL2
|
||||
@ -91,7 +93,9 @@ bool sdram_init(void) {
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A8);
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A9);
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A10);
|
||||
#ifdef MICROPY_HW_FMC_A11
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A11);
|
||||
#endif
|
||||
#ifdef MICROPY_HW_FMC_A12
|
||||
mp_hal_pin_config_alt_static_speed(MICROPY_HW_FMC_A12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_NONE, MP_HAL_PIN_SPEED_VERY_HIGH, STATIC_AF_FMC_A12);
|
||||
#endif
|
||||
|
||||
@ -272,9 +272,9 @@ void SystemClock_Config(void) {
|
||||
n = MICROPY_HW_CLK_PLLN;
|
||||
p = MICROPY_HW_CLK_PLLP;
|
||||
q = MICROPY_HW_CLK_PLLQ;
|
||||
h = RCC_SYSCLK_DIV1;
|
||||
b1 = RCC_HCLK_DIV4;
|
||||
b2 = RCC_HCLK_DIV2;
|
||||
h = MICROPY_HW_CLK_AHB_DIV;
|
||||
b1 = MICROPY_HW_CLK_APB1_DIV;
|
||||
b2 = MICROPY_HW_CLK_APB2_DIV;
|
||||
} else {
|
||||
h <<= 4;
|
||||
b1 <<= 10;
|
||||
@ -285,9 +285,9 @@ void SystemClock_Config(void) {
|
||||
RCC_OscInitStruct.PLL.PLLP = p; // MICROPY_HW_CLK_PLLP;
|
||||
RCC_OscInitStruct.PLL.PLLQ = q; // MICROPY_HW_CLK_PLLQ;
|
||||
|
||||
RCC_ClkInitStruct.AHBCLKDivider = h; // RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = b1; // RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = b2; // RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = h;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = b1;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = b2;
|
||||
#else // defined(MICROPY_HW_CLK_LAST_FREQ) && MICROPY_HW_CLK_LAST_FREQ
|
||||
RCC_OscInitStruct.PLL.PLLM = MICROPY_HW_CLK_PLLM;
|
||||
RCC_OscInitStruct.PLL.PLLN = MICROPY_HW_CLK_PLLN;
|
||||
@ -304,20 +304,20 @@ void SystemClock_Config(void) {
|
||||
#endif
|
||||
|
||||
#if defined(STM32F4) || defined(STM32F7)
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = MICROPY_HW_CLK_AHB_DIV;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = MICROPY_HW_CLK_APB1_DIV;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = MICROPY_HW_CLK_APB2_DIV;
|
||||
#elif defined(STM32L4)
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = MICROPY_HW_CLK_AHB_DIV;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = MICROPY_HW_CLK_APB1_DIV;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = MICROPY_HW_CLK_APB2_DIV;
|
||||
#elif defined(STM32H7)
|
||||
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
|
||||
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
|
||||
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = MICROPY_HW_CLK_AHB_DIV;
|
||||
RCC_ClkInitStruct.APB3CLKDivider = MICROPY_HW_CLK_APB3_DIV;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = MICROPY_HW_CLK_APB1_DIV;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = MICROPY_HW_CLK_APB2_DIV;
|
||||
RCC_ClkInitStruct.APB4CLKDivider = MICROPY_HW_CLK_APB4_DIV;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -351,8 +351,8 @@ void SystemClock_Config(void) {
|
||||
|
||||
uint32_t vco_out = RCC_OscInitStruct.PLL.PLLN * (MICROPY_HW_CLK_VALUE / 1000000) / RCC_OscInitStruct.PLL.PLLM;
|
||||
uint32_t sysclk_mhz = vco_out / RCC_OscInitStruct.PLL.PLLP;
|
||||
bool need_pllsai = vco_out % 48 != 0;
|
||||
if (powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pllsai) != 0) {
|
||||
bool need_pll48 = vco_out % 48 != 0;
|
||||
if (powerctrl_rcc_clock_config_pll(&RCC_ClkInitStruct, sysclk_mhz, need_pll48) != 0) {
|
||||
__fatal_error("HAL_RCC_ClockConfig");
|
||||
}
|
||||
|
||||
|
||||
@ -711,16 +711,11 @@ uint32_t uart_get_source_freq(pyb_uart_obj_t *self) {
|
||||
}
|
||||
|
||||
uint32_t uart_get_baudrate(pyb_uart_obj_t *self) {
|
||||
// This formula assumes UART_OVERSAMPLING_16
|
||||
uint32_t source_freq = uart_get_source_freq(self);
|
||||
#if defined(LPUART1)
|
||||
if (self->uart_id == PYB_LPUART_1) {
|
||||
return source_freq / (self->uartx->BRR >> 8);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
return source_freq / self->uartx->BRR;
|
||||
}
|
||||
return LL_USART_GetBaudRate(self->uartx, uart_get_source_freq(self),
|
||||
#if defined(STM32H7) || defined(STM32WB)
|
||||
self->uartx->PRESC,
|
||||
#endif
|
||||
LL_USART_OVERSAMPLING_16);
|
||||
}
|
||||
|
||||
void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) {
|
||||
|
||||
@ -341,6 +341,9 @@ STATIC int invalid_args(void) {
|
||||
STATIC void pre_process_options(int argc, char **argv) {
|
||||
for (int a = 1; a < argc; a++) {
|
||||
if (argv[a][0] == '-') {
|
||||
if (strcmp(argv[a], "-c") == 0 || strcmp(argv[a], "-m") == 0) {
|
||||
break; // Everything after this is a command/module and arguments for it
|
||||
}
|
||||
if (strcmp(argv[a], "-h") == 0) {
|
||||
print_help(argv);
|
||||
exit(0);
|
||||
@ -400,6 +403,8 @@ STATIC void pre_process_options(int argc, char **argv) {
|
||||
}
|
||||
a++;
|
||||
}
|
||||
} else {
|
||||
break; // Not an option but a file
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -568,11 +573,10 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
if (a + 1 >= argc) {
|
||||
return invalid_args();
|
||||
}
|
||||
set_sys_argv(argv, a + 1, a); // The -c becomes first item of sys.argv, as in CPython
|
||||
set_sys_argv(argv, argc, a + 2); // Then what comes after the command
|
||||
ret = do_str(argv[a + 1]);
|
||||
if (ret & FORCED_EXIT) {
|
||||
break;
|
||||
}
|
||||
a += 1;
|
||||
break;
|
||||
} else if (strcmp(argv[a], "-m") == 0) {
|
||||
if (a + 1 >= argc) {
|
||||
return invalid_args();
|
||||
@ -592,7 +596,12 @@ MP_NOINLINE int main_(int argc, char **argv) {
|
||||
|
||||
mp_obj_t mod;
|
||||
nlr_buf_t nlr;
|
||||
bool subpkg_tried = false;
|
||||
|
||||
// Allocating subpkg_tried on the stack can lead to compiler warnings about this
|
||||
// variable being clobbered when nlr is implemented using setjmp/longjmp. Its
|
||||
// value must be preserved across calls to setjmp/longjmp.
|
||||
static bool subpkg_tried;
|
||||
subpkg_tried = false;
|
||||
|
||||
reimport:
|
||||
if (nlr_push(&nlr) == 0) {
|
||||
|
||||
@ -7,8 +7,7 @@ CFLAGS += \
|
||||
-fprofile-arcs -ftest-coverage \
|
||||
-Wformat -Wmissing-declarations -Wmissing-prototypes \
|
||||
-Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \
|
||||
-DMICROPY_UNIX_COVERAGE \
|
||||
-DMODULE_CEXAMPLE_ENABLED=1 -DMODULE_CPPEXAMPLE_ENABLED=1
|
||||
-DMICROPY_UNIX_COVERAGE
|
||||
|
||||
LDFLAGS += -fprofile-arcs -ftest-coverage
|
||||
|
||||
|
||||
@ -85,7 +85,7 @@ set(MICROPY_CPP_FLAGS_EXTRA ${includes} ${system_includes} ${definitions} ${opti
|
||||
zephyr_library_named(${MICROPY_TARGET})
|
||||
|
||||
zephyr_library_include_directories(
|
||||
${MICROPY_DIR}
|
||||
${MICROPY_INC_CORE}
|
||||
${MICROPY_PORT_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
@ -69,7 +69,7 @@ add_custom_command(
|
||||
# it was last run, but it looks like it's not possible to specify that with cmake.
|
||||
add_custom_command(
|
||||
OUTPUT ${MICROPY_QSTRDEFS_LAST}
|
||||
COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py pp ${CMAKE_C_COMPILER} -E output ${MICROPY_GENHDR_DIR}/qstr.i.last cflags ${MICROPY_CPP_FLAGS} -DNO_QSTR sources ${MICROPY_SOURCE_QSTR}
|
||||
COMMAND ${Python3_EXECUTABLE} ${MICROPY_PY_DIR}/makeqstrdefs.py pp ${CMAKE_C_COMPILER} -E output ${MICROPY_GENHDR_DIR}/qstr.i.last cflags ${MICROPY_CPP_FLAGS} -DNO_QSTR cxxflags ${MICROPY_CPP_FLAGS} -DNO_QSTR sources ${MICROPY_SOURCE_QSTR}
|
||||
DEPENDS ${MICROPY_MODULEDEFS}
|
||||
${MICROPY_SOURCE_QSTR}
|
||||
VERBATIM
|
||||
|
||||
@ -28,7 +28,7 @@
|
||||
|
||||
// Current version of MicroPython
|
||||
#define MICROPY_VERSION_MAJOR 1
|
||||
#define MICROPY_VERSION_MINOR 14
|
||||
#define MICROPY_VERSION_MINOR 15
|
||||
#define MICROPY_VERSION_MICRO 0
|
||||
|
||||
// Combined version as a 32-bit number for convenience
|
||||
@ -229,6 +229,11 @@
|
||||
#define MICROPY_MODULE_DICT_SIZE (1)
|
||||
#endif
|
||||
|
||||
// Initial size of sys.modules dict
|
||||
#ifndef MICROPY_LOADED_MODULES_DICT_SIZE
|
||||
#define MICROPY_LOADED_MODULES_DICT_SIZE (3)
|
||||
#endif
|
||||
|
||||
// Whether realloc/free should be passed allocated memory region size
|
||||
// You must enable this if MICROPY_MEM_STATS is enabled
|
||||
#ifndef MICROPY_MALLOC_USES_ALLOCATED_SIZE
|
||||
|
||||
@ -172,7 +172,7 @@ STATIC void code_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
|
||||
}
|
||||
}
|
||||
|
||||
const mp_obj_type_t mp_type_code = {
|
||||
const mp_obj_type_t mp_type_settrace_codeobj = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_code,
|
||||
.print = code_print,
|
||||
@ -185,7 +185,7 @@ mp_obj_t mp_obj_new_code(const mp_raw_code_t *rc) {
|
||||
if (o == NULL) {
|
||||
return MP_OBJ_NULL;
|
||||
}
|
||||
o->base.type = &mp_type_code;
|
||||
o->base.type = &mp_type_settrace_codeobj;
|
||||
o->rc = rc;
|
||||
o->dict_locals = mp_locals_get(); // this is a wrong! how to do this properly?
|
||||
o->lnotab = MP_OBJ_NULL;
|
||||
|
||||
24
py/py.cmake
24
py/py.cmake
@ -2,6 +2,8 @@
|
||||
|
||||
set(MICROPY_PY_DIR "${MICROPY_DIR}/py")
|
||||
|
||||
list(APPEND MICROPY_INC_CORE "${MICROPY_DIR}")
|
||||
|
||||
# All py/ source files
|
||||
set(MICROPY_SOURCE_PY
|
||||
${MICROPY_PY_DIR}/argcheck.c
|
||||
@ -122,3 +124,25 @@ set(MICROPY_SOURCE_PY
|
||||
${MICROPY_PY_DIR}/vstr.c
|
||||
${MICROPY_PY_DIR}/warning.c
|
||||
)
|
||||
|
||||
# Helper macro to collect include directories and compile definitions for qstr processing.
|
||||
macro(micropy_gather_target_properties targ)
|
||||
if(TARGET ${targ})
|
||||
get_target_property(type ${targ} TYPE)
|
||||
set(_inc OFF)
|
||||
set(_def OFF)
|
||||
if(${type} STREQUAL STATIC_LIBRARY)
|
||||
get_target_property(_inc ${targ} INCLUDE_DIRECTORIES)
|
||||
get_target_property(_def ${targ} COMPILE_DEFINITIONS)
|
||||
elseif(${type} STREQUAL INTERFACE_LIBRARY)
|
||||
get_target_property(_inc ${targ} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_target_property(_def ${targ} INTERFACE_COMPILE_DEFINITIONS)
|
||||
endif()
|
||||
if(_inc)
|
||||
list(APPEND MICROPY_CPP_INC_EXTRA ${_inc})
|
||||
endif()
|
||||
if(_def)
|
||||
list(APPEND MICROPY_CPP_DEF_EXTRA ${_def})
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@ -91,7 +91,7 @@ void mp_init(void) {
|
||||
#endif
|
||||
|
||||
// init global module dict
|
||||
mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), 3);
|
||||
mp_obj_dict_init(&MP_STATE_VM(mp_loaded_modules_dict), MICROPY_LOADED_MODULES_DICT_SIZE);
|
||||
|
||||
// initialise the __main__ module
|
||||
mp_obj_dict_init(&MP_STATE_VM(dict_main), 1);
|
||||
|
||||
52
py/usermod.cmake
Normal file
52
py/usermod.cmake
Normal file
@ -0,0 +1,52 @@
|
||||
# Create a target for all user modules to link against.
|
||||
add_library(usermod INTERFACE)
|
||||
|
||||
function(usermod_gather_sources SOURCES_VARNAME INCLUDE_DIRECTORIES_VARNAME INCLUDED_VARNAME LIB)
|
||||
if (NOT ${LIB} IN_LIST ${INCLUDED_VARNAME})
|
||||
list(APPEND ${INCLUDED_VARNAME} ${LIB})
|
||||
|
||||
# Gather library sources
|
||||
get_target_property(lib_sources ${LIB} INTERFACE_SOURCES)
|
||||
if (lib_sources)
|
||||
list(APPEND ${SOURCES_VARNAME} ${lib_sources})
|
||||
endif()
|
||||
|
||||
# Gather library includes
|
||||
get_target_property(lib_include_directories ${LIB} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if (lib_include_directories)
|
||||
list(APPEND ${INCLUDE_DIRECTORIES_VARNAME} ${lib_include_directories})
|
||||
endif()
|
||||
|
||||
# Recurse linked libraries
|
||||
get_target_property(trans_depend ${LIB} INTERFACE_LINK_LIBRARIES)
|
||||
if (trans_depend)
|
||||
foreach(SUB_LIB ${trans_depend})
|
||||
usermod_gather_sources(
|
||||
${SOURCES_VARNAME}
|
||||
${INCLUDE_DIRECTORIES_VARNAME}
|
||||
${INCLUDED_VARNAME}
|
||||
${SUB_LIB})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(${SOURCES_VARNAME} ${${SOURCES_VARNAME}} PARENT_SCOPE)
|
||||
set(${INCLUDE_DIRECTORIES_VARNAME} ${${INCLUDE_DIRECTORIES_VARNAME}} PARENT_SCOPE)
|
||||
set(${INCLUDED_VARNAME} ${${INCLUDED_VARNAME}} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Include CMake files for user modules.
|
||||
if (USER_C_MODULES)
|
||||
foreach(USER_C_MODULE_PATH ${USER_C_MODULES})
|
||||
message("Including User C Module(s) from ${USER_C_MODULE_PATH}")
|
||||
include(${USER_C_MODULE_PATH})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# Recursively gather sources for QSTR scanning - doesn't support generator expressions.
|
||||
usermod_gather_sources(MICROPY_SOURCE_USERMOD MICROPY_INC_USERMOD found_modules usermod)
|
||||
|
||||
# Report found modules.
|
||||
list(REMOVE_ITEM found_modules "usermod")
|
||||
list(JOIN found_modules ", " found_modules)
|
||||
message("Found User C Module(s): ${found_modules}")
|
||||
@ -1,2 +1,2 @@
|
||||
# cmdline: -c print("test") -i
|
||||
# cmdline: -i -c print("test")
|
||||
# -c option combined with -i option results in REPL
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
test
|
||||
MicroPython \.\+ version
|
||||
Use \.\+
|
||||
>>> # cmdline: -c print("test") -i
|
||||
>>> # cmdline: -i -c print("test")
|
||||
>>> # -c option combined with -i option results in REPL
|
||||
>>>
|
||||
|
||||
34
tests/extmod/ure_limit.py
Normal file
34
tests/extmod/ure_limit.py
Normal file
@ -0,0 +1,34 @@
|
||||
# Test overflow in ure.compile output code.
|
||||
|
||||
try:
|
||||
import ure as re
|
||||
except ImportError:
|
||||
print("SKIP")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
def test_re(r):
|
||||
try:
|
||||
re.compile(r)
|
||||
except:
|
||||
print("Error")
|
||||
|
||||
|
||||
# too many chars in []
|
||||
test_re("[" + "a" * 256 + "]")
|
||||
|
||||
# too many groups
|
||||
test_re("(a)" * 256)
|
||||
|
||||
# jump too big for ?
|
||||
test_re("(" + "a" * 62 + ")?")
|
||||
|
||||
# jump too big for *
|
||||
test_re("(" + "a" * 60 + ".)*")
|
||||
test_re("(" + "a" * 60 + "..)*")
|
||||
|
||||
# jump too big for +
|
||||
test_re("(" + "a" * 62 + ")+")
|
||||
|
||||
# jump too big for |
|
||||
test_re("b" * 63 + "|a")
|
||||
7
tests/extmod/ure_limit.py.exp
Normal file
7
tests/extmod/ure_limit.py.exp
Normal file
@ -0,0 +1,7 @@
|
||||
Error
|
||||
Error
|
||||
Error
|
||||
Error
|
||||
Error
|
||||
Error
|
||||
Error
|
||||
@ -1,3 +1,6 @@
|
||||
# check if async/await keywords are supported
|
||||
async def foo():
|
||||
await 1
|
||||
|
||||
|
||||
print("async")
|
||||
|
||||
@ -1 +1,2 @@
|
||||
x = const(1)
|
||||
print(x)
|
||||
|
||||
@ -2,3 +2,7 @@
|
||||
@micropython.native
|
||||
def f():
|
||||
pass
|
||||
|
||||
|
||||
f()
|
||||
print("native")
|
||||
|
||||
@ -1,2 +1,2 @@
|
||||
# check if set literal syntax is supported
|
||||
{1}
|
||||
print({1})
|
||||
|
||||
@ -5,6 +5,7 @@ b'Content-Length: 54'
|
||||
b'Connection: close'
|
||||
b'Vary: Accept-Encoding'
|
||||
b'ETag: "54306c85-36"'
|
||||
b'Strict-Transport-Security: max-age=15768000'
|
||||
b'Accept-Ranges: bytes'
|
||||
close
|
||||
done
|
||||
|
||||
@ -279,7 +279,7 @@ def run_tests(pyb, tests, args, result_dir):
|
||||
|
||||
# Check if micropython.native is supported, and skip such tests if it's not
|
||||
output = run_feature_check(pyb, args, base_path, "native_check.py")
|
||||
if output == b"CRASH":
|
||||
if output != b"native\n":
|
||||
skip_native = True
|
||||
|
||||
# Check if arbitrary-precision integers are supported, and skip such tests if it's not
|
||||
@ -294,7 +294,7 @@ def run_tests(pyb, tests, args, result_dir):
|
||||
|
||||
# Check if set type (and set literals) is supported, and skip such tests if it's not
|
||||
output = run_feature_check(pyb, args, base_path, "set_check.py")
|
||||
if output == b"CRASH":
|
||||
if output != b"{1}\n":
|
||||
skip_set_type = True
|
||||
|
||||
# Check if slice is supported, and skip such tests if it's not
|
||||
@ -304,12 +304,12 @@ def run_tests(pyb, tests, args, result_dir):
|
||||
|
||||
# Check if async/await keywords are supported, and skip such tests if it's not
|
||||
output = run_feature_check(pyb, args, base_path, "async_check.py")
|
||||
if output == b"CRASH":
|
||||
if output != b"async\n":
|
||||
skip_async = True
|
||||
|
||||
# Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not
|
||||
output = run_feature_check(pyb, args, base_path, "const.py")
|
||||
if output == b"CRASH":
|
||||
if output != b"1\n":
|
||||
skip_const = True
|
||||
|
||||
# Check if __rOP__ special methods are supported, and skip such tests if it's not
|
||||
@ -334,10 +334,10 @@ def run_tests(pyb, tests, args, result_dir):
|
||||
|
||||
upy_byteorder = run_feature_check(pyb, args, base_path, "byteorder.py")
|
||||
upy_float_precision = run_feature_check(pyb, args, base_path, "float.py")
|
||||
if upy_float_precision == b"CRASH":
|
||||
upy_float_precision = 0
|
||||
else:
|
||||
try:
|
||||
upy_float_precision = int(upy_float_precision)
|
||||
except ValueError:
|
||||
upy_float_precision = 0
|
||||
has_complex = run_feature_check(pyb, args, base_path, "complex.py") == b"complex\n"
|
||||
has_coverage = run_feature_check(pyb, args, base_path, "coverage.py") == b"coverage\n"
|
||||
cpy_byteorder = subprocess.check_output(
|
||||
|
||||
23
tools/ci.sh
23
tools/ci.sh
@ -82,24 +82,37 @@ function ci_cc3200_build {
|
||||
########################################################################################
|
||||
# ports/esp32
|
||||
|
||||
function ci_esp32_setup {
|
||||
function ci_esp32_setup_helper {
|
||||
git clone https://github.com/espressif/esp-idf.git
|
||||
git -C esp-idf checkout v4.0.2
|
||||
git -C esp-idf checkout $1
|
||||
git -C esp-idf submodule update --init \
|
||||
components/bt/controller/lib \
|
||||
components/bt/host/nimble/nimble \
|
||||
components/esp_wifi/lib_esp32 \
|
||||
components/esp_wifi \
|
||||
components/esptool_py/esptool \
|
||||
components/lwip/lwip \
|
||||
components/mbedtls/mbedtls
|
||||
./esp-idf/install.sh
|
||||
}
|
||||
|
||||
function ci_esp32_idf402_setup {
|
||||
ci_esp32_setup_helper v4.0.2
|
||||
}
|
||||
|
||||
function ci_esp32_idf43_setup {
|
||||
ci_esp32_setup_helper v4.3-beta2
|
||||
}
|
||||
|
||||
function ci_esp32_build {
|
||||
source esp-idf/export.sh
|
||||
make ${MAKEOPTS} -C mpy-cross
|
||||
make ${MAKEOPTS} -C ports/esp32 submodules
|
||||
make ${MAKEOPTS} -C ports/esp32
|
||||
make ${MAKEOPTS} -C ports/esp32 clean
|
||||
make ${MAKEOPTS} -C ports/esp32 USER_C_MODULES=../../../examples/usercmodule/micropython.cmake
|
||||
if [ -d $IDF_PATH/components/esp32s2 ]; then
|
||||
make ${MAKEOPTS} -C ports/esp32 BOARD=GENERIC_S2
|
||||
fi
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
@ -181,6 +194,8 @@ function ci_rp2_build {
|
||||
make ${MAKEOPTS} -C mpy-cross
|
||||
git submodule update --init lib/pico-sdk lib/tinyusb
|
||||
make ${MAKEOPTS} -C ports/rp2
|
||||
make ${MAKEOPTS} -C ports/rp2 clean
|
||||
make ${MAKEOPTS} -C ports/rp2 USER_C_MODULES=../../examples/usercmodule/micropython.cmake
|
||||
}
|
||||
|
||||
########################################################################################
|
||||
@ -207,7 +222,7 @@ function ci_stm32_pyb_build {
|
||||
make ${MAKEOPTS} -C mpy-cross
|
||||
make ${MAKEOPTS} -C ports/stm32 submodules
|
||||
git submodule update --init lib/btstack
|
||||
make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 USER_C_MODULES=../../examples/usercmodule CFLAGS_EXTRA="-DMODULE_CEXAMPLE_ENABLED=1 -DMODULE_CPPEXAMPLE_ENABLED=1"
|
||||
make ${MAKEOPTS} -C ports/stm32 BOARD=PYBV11 MICROPY_PY_WIZNET5K=5200 MICROPY_PY_CC3K=1 USER_C_MODULES=../../examples/usercmodule
|
||||
make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF2
|
||||
make ${MAKEOPTS} -C ports/stm32 BOARD=PYBD_SF6 NANBOX=1 MICROPY_BLUETOOTH_NIMBLE=0 MICROPY_BLUETOOTH_BTSTACK=1
|
||||
make ${MAKEOPTS} -C ports/stm32/mboot BOARD=PYBV10 CFLAGS_EXTRA='-DMBOOT_FSLOAD=1 -DMBOOT_VFS_LFS2=1'
|
||||
|
||||
@ -65,7 +65,7 @@ port_data = {
|
||||
"s": PortData("stm32", "stm32", "build-PYBV10/firmware.elf", "BOARD=PYBV10"),
|
||||
"c": PortData("cc3200", "cc3200", "build/WIPY/release/application.axf", "BTARGET=application"),
|
||||
"8": PortData("esp8266", "esp8266", "build-GENERIC/firmware.elf"),
|
||||
"3": PortData("esp32", "esp32", "build-GENERIC/application.elf"),
|
||||
"3": PortData("esp32", "esp32", "build-GENERIC/micropython.elf"),
|
||||
"r": PortData("nrf", "nrf", "build-pca10040/firmware.elf"),
|
||||
"d": PortData("samd", "samd", "build-ADAFRUIT_ITSYBITSY_M4_EXPRESS/firmware.elf"),
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user