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:
Amir Gonnen 2021-04-23 01:36:52 +03:00
commit 070da978e2
93 changed files with 1339 additions and 367 deletions

View File

@ -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.

View File

@ -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

View File

@ -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 \
)

View File

@ -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

View File

@ -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);

View 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)

View File

@ -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);

View 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)

View 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)

View File

@ -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()

View File

@ -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)

View File

@ -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

View 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)

View 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)

View File

@ -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

View 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

View File

@ -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

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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

View File

@ -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},

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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 },

View File

@ -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) },

View File

@ -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) {

View File

@ -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")

View File

@ -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();
}

View File

@ -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
View 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
View 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

View File

@ -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)

View File

@ -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.

View File

@ -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:

View File

@ -0,0 +1 @@
# cmake file for Adafruit Feather RP2040

View 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)

View File

@ -0,0 +1 @@
# cmake file for Raspberry Pi Pico

View 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)

View File

@ -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 {

View File

@ -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;
}

View File

@ -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

View File

@ -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) },

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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),

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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,,,

1 Port Pin AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7
2 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
3 PortA PA0 TIM2_CH1 TSC_G1_IO1 USART2_CTS TIM2_ETR USART4_TX COMP1_OUT ADC_IN0
4 PortA PA1 EVENTOUT TIM2_CH2 TSC_G1_IO2 USART2_RTS_DE USART2_RTS/USART2_DE TIM21_ETR USART4_RX ADC_IN1
5 PortA PA2 TIM21_CH1 TIM2_CH3 TSC_G1_IO3 USART2_TX LPUART1_TX COMP2_OUT ADC_IN2
6 PortA PA3 TIM21_CH2 TIM2_CH4 TSC_G1_IO4 USART2_RX LPUART1_RX ADC_IN3
7 PortA PA4 SPI1_NSS TSC_G2_IO1 USART2_CK TIM22_ETR ADC_IN4
12 PortA PA9 MCO TSC_G4_IO1 USART1_TX I2C1_SCL I2C3_SMBA
13 PortA PA10 TSC_G4_IO2 USART1_RX I2C1_SDA
14 PortA PA11 SPI1_MISO EVENTOUT TSC_G4_IO3 USART1_CTS COMP1_OUT
15 PortA PA12 SPI1_MOSI EVENTOUT TSC_G4_IO4 USART1_RTS_DE USART1_RTS/USART1_DE COMP2_OUT
16 PortA PA13 SWDIO USB_NOE LPUART1_RX
17 PortA PA14 SWCLK USART2_TX LPUART1_TX
18 PortA PA15 SPI1_NSS TIM2_ETR EVENTOUT USART2_RX TIM2_CH1 USART4_RTS_DE USART4_RTS/USART4_DE
19 PortB PB0 EVENTOUT TIM3_CH3 TSC_G3_IO2 ADC_IN8
20 PortB PB1 TIM3_CH4 TSC_G3_IO3 LPUART1_RTS_DE LPUART1_RTS/LPUART1_DE ADC_IN9
21 PortB PB2 LPTIM1_OUT TSC_G3_IO4 I2C3_SMBA
22 PortB PB3 SPI1_SCK TIM2_CH2 TSC_G5_IO1 EVENTOUT USART1_RTS_DE USART1_RTS/USART1_DE USART5_TX
23 PortB PB4 SPI1_MISO TIM3_CH1 TSC_G5_IO2 TIM22_CH1 USART1_CTS USART5_RX I2C3_SDA
24 PortB PB5 SPI1_MOSI LPTIM1_IN1 I2C1_SMBA TIM3_CH2/TIM22_CH2 USART1_CK USART5_CK/USART5_RTS_DE USART5_CK/USART5_RTS/USART5_DE
25 PortB PB6 USART1_TX I2C1_SCL LPTIM1_ETR TSC_G5_IO3
26 PortB PB7 USART1_RX I2C1_SDA LPTIM1_IN2 TSC_G5_IO4 USART4_CTS
27 PortB PB8 TSC_SYNC I2C1_SCL
28 PortB PB9 EVENTOUT I2C1_SDA SPI2_NSS/I2S2_WS
29 PortB PB10 TIM2_CH3 TSC_SYNC LPUART1_TX SPI2_SCK I2C2_SCL LPUART1_RX
30 PortB PB11 EVENTOUT TIM2_CH4 TSC_G6_IO1 LPUART1_RX I2C2_SDA LPUART1_TX
31 PortB PB12 SPI2_NSS/I2S2_WS LPUART1_RTS_DE LPUART1_RTS/LPUART1_DE TSC_G6_IO2 I2C2_SMBA EVENTOUT
32 PortB PB13 SPI2_SCK/I2S2_CK MCO TSC_G6_IO3 LPUART1_CTS I2C2_SCL TIM21_CH1
33 PortB PB14 SPI2_MISO/I2S2_MCK RTC_OUT TSC_G6_IO4 LPUART1_RTS_DE LPUART1_RTS/LPUART1_DE I2C2_SDA TIM21_CH2
34 PortB PB15 SPI2_MOSI/I2S2_SD RTC_REFIN
35 PortC PC0 LPTIM1_IN1 EVENTOUT TSC_G7_IO1 LPUART1_RX I2C3_SCL ADC_IN10
36 PortC PC1 LPTIM1_OUT EVENTOUT TSC_G7_IO2 LPUART1_TX I2C3_SDA ADC_IN11
50 PortC PC15
51 PortD PD0 TIM21_CH1 SPI2_NSS/I2S2_WS
52 PortD PD1 SPI2_SCK/I2S2_CK
53 PortD PD2 LPUART1_RTS_DE LPUART1_RTS/LPUART1_DE TIM3_ETR USART5_RX
54 PortD PD3 USART2_CTS SPI2_MISO/I2S2_MCK
55 PortD PD4 USART2_RTS_DE USART2_RTS/USART2_DE SPI2_MOSI/I2S2_SD
56 PortD PD5 USART2_TX
57 PortD PD6 USART2_RX
58 PortD PD7 USART2_CK TIM21_CH2
60 PortD PD9 LPUART1_RX
61 PortD PD10
62 PortD PD11 LPUART1_CTS
63 PortD PD12 LPUART1_RTS_DE LPUART1_RTS/LPUART1_DE
64 PortD PD13
65 PortD PD14
66 PortD PD15 USB_CRS_SYNC
71 PortE PE4 TIM22_CH2 TIM3_CH2
72 PortE PE5 TIM21_CH1 TIM3_CH3
73 PortE PE6 TIM21_CH2 TIM3_CH4
74 PortE PE7 USART5_CK/USART5_RTS_DE USART5_CK/USART5_RTS/USART5_DE
75 PortE PE8 USART4_TX
76 PortE PE9 TIM2_CH1 TIM2_ETR USART4_RX
77 PortE PE10 TIM2_CH2 USART5_TX

View File

@ -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,,

1 Port AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15
30 PortB PB11 TIM2_CH4 I2C4_SDA I2C2_SDA USART3_RX LPUART1_TX QUADSPI_NCS COMP2_OUT EVENTOUT
31 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
32 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
33 PortB PB14 TIM1_CH2N I2C2_SDA SPI2_MISO DFSDM_DATIN2 USART3_RTS_DE USART3_RTS/USART3_DE TSC_G1_IO3 SAI1_MCLK_A TIM15_CH1 EVENTOUT
34 PortB PB15 RTC_REFIN TIM1_CH3N SPI2_MOSI DFSDM_CKIN2 TSC_G1_IO4 SAI1_SD_A TIM15_CH2 EVENTOUT
35 PortC PC0 LPTIM1_IN1 I2C4_SCL I2C3_SCL LPUART1_RX LPTIM2_IN1 EVENTOUT ADC123_IN1
36 PortC PC1 TRACED0 LPTIM1_OUT I2C4_SDA I2C3_SDA LPUART1_TX EVENTOUT ADC123_IN2

View File

@ -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,

1 Port AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15
30 PortB PB11 TIM2_CH4 I2C2_SDA DFSDM_CKIN7 USART3_RX LPUART1_TX QUADSPI_NCS LCD_SEG11 COMP2_OUT EVENTOUT
31 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
32 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
33 PortB PB14 TIM1_CH2N TIM8_CH2N I2C2_SDA SPI2_MISO DFSDM_DATIN2 USART3_RTS_DE USART3_RTS/USART3_DE TSC_G1_IO3 LCD_SEG14 SWPMI1_RX SAI2_MCLK_A TIM15_CH1 EVENTOUT
34 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
35 PortC PC0 LPTIM1_IN1 I2C3_SCL DFSDM_DATIN4 LPUART1_RX LCD_SEG18 LPTIM2_IN1 EVENTOUT ADC123_IN1
36 PortC PC1 LPTIM1_OUT I2C3_SDA DFSDM_CKIN4 LPUART1_TX LCD_SEG19 EVENTOUT ADC123_IN2

View File

@ -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,

1 Port AF0 AF1 AF2 AF3 AF4 AF5 AF6 AF7 AF8 AF9 AF10 AF11 AF12 AF13 AF14 AF15
12 PortA PA9 TIM1_CH2 SAI1_PDM_DI2 I2C1_SCL SPI2_SCK USART1_TX LCD_COM1 SAI1_FS_A EVENTOUT ADC1_IN16
13 PortA PA10 TIM1_CH3 SAI1_PDM_DI1 I2C1_SDA USART1_RX USB_CRS_SYNC LCD_COM2 SAI1_SD_A TIM17_BKIN EVENTOUT
14 PortA PA11 TIM1_CH4 TIM1_BKIN2 SPI1_MISO USART1_CTS USB_DM TIM1_BKIN2 EVENTOUT
15 PortA PA12 TIM1_ETR SPI1_MOSI USART1_RTS_DE USART1_RTS/USART1_DE LPUART1_RX USB_DP EVENTOUT
16 PortA PA13 JTMS/SWDIO IR_OUT USB_NOE SAI1_SD_B EVENTOUT
17 PortA PA14 JTCK/SWCLK LPTIM1_OUT I2C1_SMBA LCD_SEG5 SAI1_FS_B EVENTOUT
18 PortA PA15 JTDI TIM2_CH1 TIM2_ETR SPI1_NSS TSC_G3_IO1 LCD_SEG17 EVENTOUT
19 PortB PB0 EXT_PA_TX COMP1_OUT EVENTOUT
20 PortB PB1 LPUART1_RTS_DE LPUART1_RTS/LPUART1_DE LPTIM2_IN1 EVENTOUT
21 PortB PB2 RTC_OUT LPTIM1_OUT I2C3_SMBA SPI1_NSS LCD_VLCD SAI1_EXTCLK EVENTOUT
22 PortB PB3 JTDO/TRACESWO TIM2_CH2 SPI1_SCK USART1_RTS_DE USART1_RTS/USART1_DE LCD_SEG7 SAI1_SCK_B EVENTOUT
23 PortB PB4 NJTRST I2C3_SDA SPI1_MISO USART1_CTS TSC_G2_IO1 LCD_SEG8 SAI1_MCLK_B TIM17_BKIN EVENTOUT
24 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
25 PortB PB6 MCO LPTIM1_ETR I2C1_SCL USART1_TX TSC_G2_IO3 LCD_SEG6 SAI1_FS_B TIM16_CH1N EVENTOUT

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {

View File

@ -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

View File

@ -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");
}

View File

@ -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) {

View File

@ -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) {

View File

@ -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

View File

@ -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}
)

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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()

View File

@ -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
View 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}")

View File

@ -1,2 +1,2 @@
# cmdline: -c print("test") -i
# cmdline: -i -c print("test")
# -c option combined with -i option results in REPL

View File

@ -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
View 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")

View File

@ -0,0 +1,7 @@
Error
Error
Error
Error
Error
Error
Error

View File

@ -1,3 +1,6 @@
# check if async/await keywords are supported
async def foo():
await 1
print("async")

View File

@ -1 +1,2 @@
x = const(1)
print(x)

View File

@ -2,3 +2,7 @@
@micropython.native
def f():
pass
f()
print("native")

View File

@ -1,2 +1,2 @@
# check if set literal syntax is supported
{1}
print({1})

View File

@ -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

View File

@ -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(

View File

@ -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'

View File

@ -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"),
}