diff --git a/.gitattributes b/.gitattributes index e6d31d6aa3..fe0c4b47e0 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8,6 +8,7 @@ # These are binary so should never be modified by git. *.a binary +*.ico binary *.png binary *.jpg binary *.dxf binary diff --git a/CODECONVENTIONS.md b/CODECONVENTIONS.md index d44b382b25..d6b0a5926b 100644 --- a/CODECONVENTIONS.md +++ b/CODECONVENTIONS.md @@ -53,13 +53,16 @@ are then certifying and signing off against the following: Code auto-formatting ==================== -Both C and Python code are auto-formatted using the `tools/codeformat.py` -script. This uses [uncrustify](https://github.com/uncrustify/uncrustify) to -format C code and [black](https://github.com/psf/black) to format Python code. -After making changes, and before committing, run this tool to reformat your -changes to the correct style. Without arguments this tool will reformat all -source code (and may take some time to run). Otherwise pass as arguments to -the tool the files that changed and it will only reformat those. +Both C and Python code formatting are controlled for consistency across the +MicroPython codebase. C code is formatted using the `tools/codeformat.py` +script which uses [uncrustify](https://github.com/uncrustify/uncrustify). +Python code is linted and formatted using +[ruff & ruff format](https://github.com/astral-sh/ruff). +After making changes, and before committing, run `tools/codeformat.py` to +reformat your C code and `ruff format` for any Python code. Without +arguments this tool will reformat all source code (and may take some time +to run). Otherwise pass as arguments to the tool the files that changed, +and it will only reformat those. uncrustify ========== @@ -151,12 +154,22 @@ Tips: * To ignore the pre-commit message format check temporarily, start the commit message subject line with "WIP" (for "Work In Progress"). +Running pre-commit manually +=========================== + +Once pre-commit is installed as per the previous section it can be manually +run against the MicroPython python codebase to update file formatting on +demand, with either: +* `pre-commit run --all-files` to fix all files in the MicroPython codebase +* `pre-commit run --file ./path/to/my/file` to fix just one file +* `pre-commit run --file ./path/to/my/folder/*` to fix just one folder + Python code conventions ======================= Python code follows [PEP 8](https://legacy.python.org/dev/peps/pep-0008/) and -is auto-formatted using [black](https://github.com/psf/black) with a line-length -of 99 characters. +is auto-formatted using [ruff format](https://docs.astral.sh/ruff/formatter) +with a line-length of 99 characters. Naming conventions: - Module names are short and all lowercase; eg pyb, stm. diff --git a/docs/library/esp32.rst b/docs/library/esp32.rst index 7701f43539..422329bf1e 100644 --- a/docs/library/esp32.rst +++ b/docs/library/esp32.rst @@ -193,7 +193,7 @@ numbers specified in ``write_pulses`` are multiplied by the resolution to define the pulses. ``clock_div`` is an 8-bit divider (0-255) and each pulse can be defined by -multiplying the resolution by a 15-bit (0-32,768) number. There are eight +multiplying the resolution by a 15-bit (1-``PULSE_MAX``) number. There are eight channels (0-7) and each can have a different clock divider. So, in the example above, the 80MHz clock is divided by 8. Thus the @@ -226,7 +226,7 @@ For more details see Espressif's `ESP-IDF RMT documentation. ``100``) and the output level to apply the carrier to (a boolean as per *idle_level*). -.. method:: RMT.source_freq() +.. classmethod:: RMT.source_freq() Returns the source clock frequency. Currently the source clock is not configurable so this will always return 80MHz. @@ -264,10 +264,10 @@ For more details see Espressif's `ESP-IDF RMT documentation. **Mode 3:** *duration* and *data* are lists or tuples of equal length, specifying individual durations and the output level for each. - Durations are in integer units of the channel resolution (as described - above), between 1 and 32767 units. Output levels are any value that can - be converted to a boolean, with ``True`` representing high voltage and - ``False`` representing low. + Durations are in integer units of the channel resolution (as + described above), between 1 and ``PULSE_MAX`` units. Output levels + are any value that can be converted to a boolean, with ``True`` + representing high voltage and ``False`` representing low. If transmission of an earlier sequence is in progress then this method will block until that transmission is complete before beginning the new sequence. @@ -290,6 +290,13 @@ For more details see Espressif's `ESP-IDF RMT documentation. Passing in no argument will not change the channel. This function returns the current channel number. +Constants +--------- + +.. data:: RMT.PULSE_MAX + + Maximum integer that can be set for a pulse duration. + Ultra-Low-Power co-processor ---------------------------- diff --git a/docs/library/machine.ADCBlock.rst b/docs/library/machine.ADCBlock.rst index 56a468dd62..eb94362d55 100644 --- a/docs/library/machine.ADCBlock.rst +++ b/docs/library/machine.ADCBlock.rst @@ -39,9 +39,9 @@ Methods Configure the ADC peripheral. *bits* will set the resolution of the conversion process. -.. method:: ADCBlock.connect(channel) - ADCBlock.connect(source) - ADCBlock.connect(channel, source) +.. method:: ADCBlock.connect(channel, *, ...) + ADCBlock.connect(source, *, ...) + ADCBlock.connect(channel, source, *, ...) Connect up a channel on the ADC peripheral so it is ready for sampling, and return an :ref:`ADC ` object that represents that connection. @@ -56,3 +56,6 @@ Methods If both *channel* and *source* are given then they are connected together and made ready for sampling. + + Any additional keyword arguments are used to configure the returned ADC object, + via its :meth:`init ` method. diff --git a/docs/mimxrt/pinout.rst b/docs/mimxrt/pinout.rst index b5a7fbbfe0..16bb472273 100644 --- a/docs/mimxrt/pinout.rst +++ b/docs/mimxrt/pinout.rst @@ -28,7 +28,7 @@ MIMXRT1060-EVK Debug USB D0/D1 D7/D6 D8/D9 MIMXRT1064-EVK Debug USB D0/D1 D7/D6 D8/D9 MIMXRT1170-EVK Debug USB D0/D1 D12/D11 D10/D13 Adafruit Metro M7 - D0/D1 D7/D3 A1/A0 -Olimex RT1010Py - RxD/TxD D5/D6 - +Olimex RT1010Py - RxD/TxD D7/D8 D5/D6 Seeed ARCH MIX - J3_19/J3_20 J4_16/J4_17 J4_06/J4_07 ================= =========== =========== =========== =========== diff --git a/docs/mimxrt/quickref.rst b/docs/mimxrt/quickref.rst index ab8bf8831b..578364c55a 100644 --- a/docs/mimxrt/quickref.rst +++ b/docs/mimxrt/quickref.rst @@ -92,9 +92,7 @@ Use the :ref:`machine.Pin ` class:: Available Pins follow the ranges and labelling of the respective board, like: -- 0-33 for Teensy 4.0, -- 0-21 for the MIMXRT10xx-EVK board, or 'D0-Dxx', or 'A0-Ann', -- 0-14 for the Olimex RT1010Py board, or 'D0'-'Dxx' and 'A0'-'Ann' +- 'D0-Dxx', or 'A0-Ann' for Teensy 4.0, MIMXRT10xx-EVK ns Olimex board, - 'J3_xx', 'J4_xx', 'J5_xx' for the Seeed ARCH MIX board, or the pin names of the Pin.board or Pin.cpu classes. @@ -106,9 +104,9 @@ Notes: * At the MIMXRT1010_EVK, pins D4, D5 and D9 of the Arduino connector are by default not connected to the MCU. For details refer to the schematics. * At the MIMXRT1170_EVK board, the inner rows of the Arduino connectors are assigned as follows: - - D16 - D23: J9, odd pin numbers; D17 is by default not connected. - - D24 - D27: J26, odd pin numbers; J63-J66 have to be closed to enable these pins. - - D29 - D36: J25, odd pin numbers; D29 and D30 are by default not connected. + - 'D16' - 'D23': J9, odd pin numbers; 'D17' is by default not connected. + - 'D24' - 'D27': J26, odd pin numbers; J63-J66 have to be closed to enable these pins. + - 'D29' - 'D36': J25, odd pin numbers; 'D29' and 'D30' are by default not connected. There's a higher-level abstraction :ref:`machine.Signal ` which can be used to invert a pin. Useful for illuminating active-low LEDs @@ -146,22 +144,22 @@ handling signal groups. :: from machine import Pin, PWM # create PWM object from a pin and set the frequency and duty cycle - pwm2 = PWM(Pin(2), freq=2000, duty_u16=32768) + pwm2 = PWM(Pin('D2'), freq=2000, duty_u16=32768) pwm2.freq() # get the current frequency pwm2.freq(1000) # set/change the frequency pwm2.duty_u16() # get the current duty cycle, range 0-65535 pwm2.duty_u16(200) # set the duty cycle, range 0-65535 pwm2.deinit() # turn off PWM on the pin # create a complementary signal pair on Pin 2 and 3 - pwm2 = PWM((2, 3), freq=2000, duty_ns=20000) + pwm2 = PWM(('D2', 'D3'), freq=2000, duty_ns=20000) # Create a group of four synchronized signals. - # Start with Pin(4) at submodule 0, which creates the sync pulse. - pwm4 = PWM(Pin(4), freq=1000, align=PWM.HEAD) - # Pins 5, 6, and 9 are pins at the same module - pwm5 = PWM(Pin(5), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True) - pwm6 = PWM(Pin(6), freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True) - pwm9 = PWM(Pin(9), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True) + # Start with Pin('D4') at submodule 0, which creates the sync pulse. + pwm4 = PWM(Pin('D4'), freq=1000, align=PWM.HEAD) + # Pins D5, D6, and D9 are pins at the same module + pwm5 = PWM(Pin('D5'), freq=1000, duty_u16=10000, align=PWM.HEAD, sync=True) + pwm6 = PWM(Pin('D6', freq=1000, duty_u16=20000, align=PWM.HEAD, sync=True) + pwm9 = PWM(Pin('D9'), freq=1000, duty_u16=30000, align=PWM.HEAD, sync=True) pwm3 # show the PWM objects properties @@ -256,7 +254,7 @@ Use the :ref:`machine.ADC ` class:: from machine import ADC - adc = ADC(Pin(32)) # create ADC object on ADC pin + adc = ADC(Pin('A2')) # create ADC object on ADC pin adc.read_u16() # read value, 0-65536 across voltage range 0.0v - 3.3v The resolution of the ADC is 12 bit with 10 to 11 bit accuracy, irrespective of the @@ -274,7 +272,7 @@ Software SPI (using bit-banging) works on all pins, and is accessed via the # construct a SoftSPI bus on the given pins # polarity is the idle state of SCK # phase=0 means sample on the first edge of SCK, phase=1 means the second - spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4)) + spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin('D0'), mosi=Pin('D2'), miso=Pin('D4')) spi.init(baudrate=200000) # set the baudrate @@ -303,7 +301,7 @@ rates (up to 30Mhz). Hardware SPI is accessed via the from machine import SPI, Pin spi = SPI(0, 10000000) - cs_pin = Pin(6, Pin.OUT, value=1) + cs_pin = Pin('D6', Pin.OUT, value=1) cs_pin(0) spi.write('Hello World') cs_pin(1) @@ -331,7 +329,7 @@ accessed via the :ref:`machine.SoftI2C ` class:: from machine import Pin, SoftI2C - i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=100000) + i2c = SoftI2C(scl=Pin('D5'), sda=Pin('D4'), freq=100000) i2c.scan() # scan for devices @@ -365,7 +363,7 @@ See :ref:`machine.I2S `. Example using a Teensy 4.1 board with a si external Codec like UDA1334.:: from machine import I2S, Pin - i2s = I2S(2, sck=Pin(26), ws=Pin(27), sd=Pin(7), + i2s = I2S(2, sck=Pin('D26'), ws=Pin('D27'), sd=Pin('D7'), mode=I2S.TX, bts=16,format=I2S.STEREO, rate=44100,ibuf=40000) i2s.write(buf) # write buffer of audio samples to I2S device @@ -397,7 +395,7 @@ Example using the Teensy audio shield:: from machine import I2C, I2S, Pin from sgtl5000 import CODEC - i2s = I2S(1, sck=Pin(21), ws=Pin(20), sd=Pin(7), mck=Pin(23), + i2s = I2S(1, sck=Pin('D21'), ws=Pin('D20'), sd=Pin('D7'), mck=Pin('D23'), mode=I2S.TX, bits=16,rate=44100,format=I2S.STEREO, ibuf=40000, ) @@ -475,7 +473,7 @@ The OneWire driver is implemented in software and works on all pins:: from machine import Pin import onewire - ow = onewire.OneWire(Pin(12)) # create a OneWire bus on GPIO12 + ow = onewire.OneWire(Pin('D12')) # create a OneWire bus on GPIO12 ow.scan() # return a list of devices on the bus ow.reset() # reset the bus ow.readbyte() # read a byte @@ -505,12 +503,12 @@ The DHT driver is implemented in software and works on all pins:: import dht import machine - d = dht.DHT11(machine.Pin(4)) + d = dht.DHT11(machine.Pin('D4')) d.measure() d.temperature() # eg. 23 (°C) d.humidity() # eg. 41 (% RH) - d = dht.DHT22(machine.Pin(4)) + d = dht.DHT22(machine.Pin('D4')) d.measure() d.temperature() # eg. 23.6 (°C) d.humidity() # eg. 41.3 (% RH) diff --git a/docs/samd/pinout.rst b/docs/samd/pinout.rst index 5fe1e14ecb..272f7c58df 100644 --- a/docs/samd/pinout.rst +++ b/docs/samd/pinout.rst @@ -17,44 +17,53 @@ Adafruit ItsyBitsy M0 Express pin assignment table === ==== ============ ==== ==== ====== ====== ====== ====== Pin GPIO Pin name IRQ ADC Serial Serial TCC/TC TCC/TC === ==== ============ ==== ==== ====== ====== ====== ====== - 0 PA11 D0 11 19 0/3 2/3 1/1 0/3 - 1 PA10 D1 10 18 0/2 2/2 1/0 0/2 - 2 PA14 D2 14 - 2/2 4/2 3/0 0/4 - 3 PA09 D3 9 17 0/1 2/1 0/1 1/3 - 4 PA08 D4 - 16 0/0 2/0 0/0 1/2 - 5 PA15 D5 15 - 2/3 4/3 3/1 0/5 - 7 PA21 D7 5 - 5/3 3/3 7/1 0/7 - 9 PA07 D9 7 7 - 0/3 1/1 - - 10 PA18 D10 2 - 1/2 3/2 3/0 0/2 - 11 PA16 D11 0 - 1/0 3/0 2/0 0/6 - 12 PA19 D12 3 - 1/3 3/3 3/1 0/3 - 13 PA17 D13 1 - 1/1 3/1 2/1 0/7 - 14 PA02 A0 2 0 - - - - - 15 PB08 A1 8 2 - 4/0 4/0 - - 16 PB09 A2 9 3 - 4/1 4/1 - - 17 PA04 A3 4 4 - 0/0 0/0 - - 18 PA05 A4 5 5 - 0/1 0/1 - - 19 PB02 A5 2 - - 5/0 6/0 - - 20 PA22 SDA 6 - 3/0 5/0 4/0 0/4 - 21 PA23 SCL 7 - 3/1 5/1 4/1 0/5 - 22 PB10 MOSI 10 - - 4/2 5/0 0/4 - 23 PA12 MISO 12 - 2/0 4/0 2/0 0/6 - 24 PB11 SCK 11 - - 4/3 5/1 0/5 - 25 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 - - 26 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 - - 27 PB22 FLASH_MOSI 6 - - 5/2 7/0 - - 28 PB03 FLASH_MISO 3 - - 5/1 6/1 - - 29 PB23 FLASH_SCK 7 - - 5/3 7/1 - + 2 PA02 A0 2 0 - - - - + 40 PB08 A1 8 2 - 4/0 4/0 - + 41 PB09 A2 9 3 - 4/1 4/1 - + 4 PA04 A3 4 4 - 0/0 0/0 - + 5 PA05 A4 5 5 - 0/1 0/1 - + 34 PB02 A5 2 10 - 5/0 6/0 - + 11 PA11 D0 11 19 0/3 2/3 1/1 0/3 + 10 PA10 D1 10 18 0/2 2/2 1/0 0/2 + 14 PA14 D2 14 - 2/2 4/2 3/0 0/4 + 9 PA09 D3 9 17 0/1 2/1 0/1 1/3 + 8 PA08 D4 - 16 0/0 2/0 0/0 1/2 + 15 PA15 D5 15 - 2/3 4/3 3/1 0/5 + 21 PA21 D7 5 - 5/3 3/3 7/1 0/7 + 7 PA07 D9 7 7 - 0/3 1/1 - + 18 PA18 D10 2 - 1/2 3/2 3/0 0/2 + 16 PA16 D11 0 - 1/0 3/0 2/0 0/6 + 19 PA19 D12 3 - 1/3 3/3 3/1 0/3 + 17 PA17 D13 1 - 1/1 3/1 2/1 0/7 + 0 PA00 DOTSTAR_CLK 0 - - 1/0 2/0 - + 1 PA01 DOTSTAR_DATA 1 - - 1/1 2/1 - + 27 PA27 FLASH_CS 15 - - - - - + 35 PB03 FLASH_MISO 3 11 - 5/1 6/1 - + 54 PB22 FLASH_MOSI 6 - - 5/2 7/0 - + 55 PB23 FLASH_SCK 7 - - 5/3 7/1 - + 12 PA12 MISO 12 - 2/0 4/0 2/0 0/6 + 42 PB10 MOSI 10 - - 4/2 5/0 0/4 + 43 PB11 SCK 11 - - 4/3 5/1 0/5 + 23 PA23 SCL 7 - 3/1 5/1 4/1 0/5 + 22 PA22 SDA 6 - 3/0 5/0 4/0 0/4 + 30 PA30 SWCLK 10 - - 1/2 1/0 - + 31 PA31 SWDIO 11 - - 1/3 1/1 - + 24 PA24 USB_DM 12 - 3/2 5/2 5/0 1/2 + 25 PA25 USB_DP 13 - 3/3 5/3 5/1 1/3 + 3 PA03 3 1 - - - - + 6 PA06 6 6 - 0/2 1/0 - + 13 PA13 13 - 2/1 4/1 2/0 0/7 + 20 PA20 4 - 5/2 3/2 7/0 0/4 + 28 PA28 8 - - - - - === ==== ============ ==== ==== ====== ====== ====== ====== Description of the columns: - *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given - as a number. This is NOT the GPIO number, but the board pin number, as - given in the board specific definition file. -- *GPIO* - The GPIO number. -- *Pin Name* - The name of a Pin which is expected argument to ``machine.Pin("name")``. + as a number. +- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``. +- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``. - *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When using ``Pin.irq()``, different pins must use different IRQs - *ADC* - The ADC channel assigned to the pin. When using ADC, different pins must @@ -183,10 +192,9 @@ Pin GPIO Pin name IRQ ADC ADC Serial Serial TC PWM PWM Description of the columns: - *Pin* - The number that is expected at ``machine.Pin(n)``, if the pin is given - as a number. This is NOT the GPIO number, but the board pin number, as - given in the board specific definition file. -- *GPIO* - The GPIO number. -- *Pin Name* The name of a Pin which is expected argument to ``machine.Pin("name")``. + as a number. +- *GPIO* - The GPIO name, which can be used as argument to ``machine.Pin("name")``. +- *Pin Name* - The boards name, which can be used as argument to ``machine.Pin("name")``. - *IRQ* - The IRQ number assigned to that GPIO, used internally by ``Pin.irq()``. When using ``Pin.irq()``, different pins must use different IRQs - *ADC* - The ADC0/1 channel assigned to the pin. When using ADC, different pins must diff --git a/extmod/extmod.cmake b/extmod/extmod.cmake index a1a0a9f736..5bfdf65513 100644 --- a/extmod/extmod.cmake +++ b/extmod/extmod.cmake @@ -8,6 +8,7 @@ set(MICROPY_SOURCE_EXTMOD ${MICROPY_DIR}/shared/libc/printf.c ${MICROPY_EXTMOD_DIR}/btstack/modbluetooth_btstack.c ${MICROPY_EXTMOD_DIR}/machine_adc.c + ${MICROPY_EXTMOD_DIR}/machine_adc_block.c ${MICROPY_EXTMOD_DIR}/machine_bitstream.c ${MICROPY_EXTMOD_DIR}/machine_i2c.c ${MICROPY_EXTMOD_DIR}/machine_i2s.c diff --git a/extmod/extmod.mk b/extmod/extmod.mk index c4b2c3d9c5..a04856bce2 100644 --- a/extmod/extmod.mk +++ b/extmod/extmod.mk @@ -3,6 +3,7 @@ SRC_EXTMOD_C += \ extmod/machine_adc.c \ + extmod/machine_adc_block.c \ extmod/machine_bitstream.c \ extmod/machine_i2c.c \ extmod/machine_i2s.c \ diff --git a/extmod/machine_adc_block.c b/extmod/machine_adc_block.c new file mode 100644 index 0000000000..f80e2dae4c --- /dev/null +++ b/extmod/machine_adc_block.c @@ -0,0 +1,128 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Jonathan Hogg + * Copyright (c) 2023 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" + +#if MICROPY_PY_MACHINE_ADC_BLOCK + +#include "py/mphal.h" +#include "extmod/modmachine.h" + +// The port must provide implementations of these low-level ADCBlock functions. +STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self); +STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit); +STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits); +STATIC machine_adc_obj_t *mp_machine_adc_block_connect(machine_adc_block_obj_t *self, mp_int_t channel_id, mp_hal_pin_obj_t pin, mp_map_t *kw_args); + +// The port provides implementations of the above in this file. +#include MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE + +STATIC void machine_adc_block_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_machine_adc_block_print(print, self); +} + +STATIC void machine_adc_block_init_helper(machine_adc_block_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { + ARG_bits, + }; + + static const mp_arg_t allowed_args[] = { + { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t bits = args[ARG_bits].u_int; + mp_machine_adc_block_bits_set(self, bits); +} + +STATIC mp_obj_t machine_adc_block_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) { + mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true); + mp_int_t unit = mp_obj_get_int(args[0]); + machine_adc_block_obj_t *self = mp_machine_adc_block_get(unit); + if (self == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid block id")); + } + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args); + machine_adc_block_init_helper(self, n_pos_args - 1, args + 1, &kw_args); + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t machine_adc_block_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + machine_adc_block_obj_t *self = pos_args[0]; + machine_adc_block_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_init_obj, 1, machine_adc_block_init); + +STATIC mp_obj_t machine_adc_block_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + mp_int_t channel_id = -1; + mp_hal_pin_obj_t pin = -1; + if (n_pos_args == 2) { + if (mp_obj_is_int(pos_args[1])) { + channel_id = mp_obj_get_int(pos_args[1]); + } else { + pin = mp_hal_get_pin_obj(pos_args[1]); + } + } else if (n_pos_args == 3) { + channel_id = mp_obj_get_int(pos_args[1]); + pin = mp_hal_get_pin_obj(pos_args[2]); + } else { + mp_raise_TypeError(MP_ERROR_TEXT("too many positional args")); + } + + machine_adc_obj_t *adc = mp_machine_adc_block_connect(self, channel_id, pin, kw_args); + if (adc == NULL) { + mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC")); + } + + return MP_OBJ_FROM_PTR(adc); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_connect_obj, 2, machine_adc_block_connect); + +STATIC const mp_rom_map_elem_t machine_adc_block_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_adc_block_init_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&machine_adc_block_connect_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(machine_adc_block_locals_dict, machine_adc_block_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + machine_adc_block_type, + MP_QSTR_ADCBlock, + MP_TYPE_FLAG_NONE, + make_new, machine_adc_block_make_new, + print, machine_adc_block_print, + locals_dict, &machine_adc_block_locals_dict + ); + +#endif // MICROPY_PY_MACHINE_ADC_BLOCK diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index 44e6921309..6cc2aa5bbf 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -328,7 +328,12 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { if (ret == 0) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } - #ifdef MICROPY_EVENT_POLL_HOOK + // This scan loop may run for some time, so process any pending events/exceptions, + // or allow the port to run any necessary background tasks. But do it as fast as + // possible, in particular we are not waiting on any events. + #if defined(MICROPY_EVENT_POLL_HOOK_FAST) + MICROPY_EVENT_POLL_HOOK_FAST; + #elif defined(MICROPY_EVENT_POLL_HOOK) MICROPY_EVENT_POLL_HOOK #endif } diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 3417df7a27..cef5151cc9 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1276,6 +1276,7 @@ STATIC mp_obj_t invoke_irq_handler(uint16_t event, mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan mp_stack_set_limit(MICROPY_PY_BLUETOOTH_SYNC_EVENT_STACK_SIZE - 1024); ts.gc_lock_depth = 0; + ts.nlr_jump_callback_top = NULL; ts.mp_pending_exception = MP_OBJ_NULL; mp_locals_set(mp_state_ctx.thread.dict_locals); // set from the outer context mp_globals_set(mp_state_ctx.thread.dict_globals); // set from the outer context diff --git a/extmod/modmachine.h b/extmod/modmachine.h index 6cace4f851..0744ef7889 100644 --- a/extmod/modmachine.h +++ b/extmod/modmachine.h @@ -128,6 +128,7 @@ // A port must provide these types, but they are otherwise opaque. typedef struct _machine_adc_obj_t machine_adc_obj_t; +typedef struct _machine_adc_block_obj_t machine_adc_block_obj_t; typedef struct _machine_i2s_obj_t machine_i2s_obj_t; typedef struct _machine_pwm_obj_t machine_pwm_obj_t; typedef struct _machine_uart_obj_t machine_uart_obj_t; @@ -200,6 +201,7 @@ extern const machine_mem_obj_t machine_mem32_obj; // Their Python bindings are implemented in extmod, and their implementation // is provided by a port. extern const mp_obj_type_t machine_adc_type; +extern const mp_obj_type_t machine_adc_block_type; extern const mp_obj_type_t machine_i2c_type; extern const mp_obj_type_t machine_i2s_type; extern const mp_obj_type_t machine_mem_type; diff --git a/extmod/modre.c b/extmod/modre.c index 7f00b1c23c..c24c07d095 100644 --- a/extmod/modre.c +++ b/extmod/modre.c @@ -207,12 +207,12 @@ STATIC mp_obj_t re_exec(bool is_anchored, uint n_args, const mp_obj_t *args) { subj.begin_line = subj.begin = mp_obj_str_get_data(args[1], &len); subj.end = subj.begin + len; int caps_num = (self->re.sub + 1) * 2; - mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, char *, caps_num); + mp_obj_match_t *match = m_new_obj_var(mp_obj_match_t, caps, char *, caps_num); // cast is a workaround for a bug in msvc: it treats const char** as a const pointer instead of a pointer to pointer to const char memset((char *)match->caps, 0, caps_num * sizeof(char *)); int res = re1_5_recursiveloopprog(&self->re, &subj, match->caps, caps_num, is_anchored); if (res == 0) { - m_del_var(mp_obj_match_t, char *, caps_num, match); + m_del_var(mp_obj_match_t, caps, char *, caps_num, match); return mp_const_none; } diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index 5e3e38ea67..3cdf4d1a78 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -1701,7 +1701,7 @@ STATIC int create_l2cap_channel(uint16_t mtu, mp_bluetooth_nimble_l2cap_channel_ // multiply that by the "MTUs per channel" (set to 3 above). const size_t buf_blocks = MP_CEIL_DIVIDE(mtu, L2CAP_BUF_BLOCK_SIZE) * L2CAP_BUF_SIZE_MTUS_PER_CHANNEL; - mp_bluetooth_nimble_l2cap_channel_t *chan = m_new_obj_var(mp_bluetooth_nimble_l2cap_channel_t, uint8_t, OS_MEMPOOL_SIZE(buf_blocks, L2CAP_BUF_BLOCK_SIZE) * sizeof(os_membuf_t)); + mp_bluetooth_nimble_l2cap_channel_t *chan = m_new_obj_var(mp_bluetooth_nimble_l2cap_channel_t, sdu_mem, uint8_t, OS_MEMPOOL_SIZE(buf_blocks, L2CAP_BUF_BLOCK_SIZE) * sizeof(os_membuf_t)); MP_STATE_PORT(bluetooth_nimble_root_pointers)->l2cap_chan = chan; // Will be set in BLE_L2CAP_EVENT_COC_CONNECTED or BLE_L2CAP_EVENT_COC_ACCEPT. diff --git a/extmod/vfs_lfsx_file.c b/extmod/vfs_lfsx_file.c index 879ba78973..b9f3323397 100644 --- a/extmod/vfs_lfsx_file.c +++ b/extmod/vfs_lfsx_file.c @@ -90,9 +90,9 @@ mp_obj_t MP_VFS_LFSx(file_open)(mp_obj_t self_in, mp_obj_t path_in, mp_obj_t mod } #if LFS_BUILD_VERSION == 1 - MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->prog_size); + MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->prog_size); #else - MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, uint8_t, self->lfs.cfg->cache_size); + MP_OBJ_VFS_LFSx_FILE *o = m_new_obj_var_with_finaliser(MP_OBJ_VFS_LFSx_FILE, file_buffer, uint8_t, self->lfs.cfg->cache_size); #endif o->base.type = type; o->vfs = self; diff --git a/extmod/vfs_posix_file.c b/extmod/vfs_posix_file.c index 81a608d2b6..2f70789543 100644 --- a/extmod/vfs_posix_file.c +++ b/extmod/vfs_posix_file.c @@ -279,14 +279,14 @@ STATIC const mp_stream_p_t vfs_posix_textio_stream_p = { #if MICROPY_PY_SYS_STDIO_BUFFER -const mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO}; +mp_obj_vfs_posix_file_t mp_sys_stdin_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDIN_FILENO}; +mp_obj_vfs_posix_file_t mp_sys_stdout_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDOUT_FILENO}; +mp_obj_vfs_posix_file_t mp_sys_stderr_buffer_obj = {{&mp_type_vfs_posix_fileio}, STDERR_FILENO}; // Forward declarations. -const mp_obj_vfs_posix_file_t mp_sys_stdin_obj; -const mp_obj_vfs_posix_file_t mp_sys_stdout_obj; -const mp_obj_vfs_posix_file_t mp_sys_stderr_obj; +mp_obj_vfs_posix_file_t mp_sys_stdin_obj; +mp_obj_vfs_posix_file_t mp_sys_stdout_obj; +mp_obj_vfs_posix_file_t mp_sys_stderr_obj; STATIC void vfs_posix_textio_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { if (dest[0] != MP_OBJ_NULL) { @@ -332,8 +332,8 @@ MP_DEFINE_CONST_OBJ_TYPE( locals_dict, &vfs_posix_rawfile_locals_dict ); -const mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO}; -const mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO}; +mp_obj_vfs_posix_file_t mp_sys_stdin_obj = {{&mp_type_vfs_posix_textio}, STDIN_FILENO}; +mp_obj_vfs_posix_file_t mp_sys_stdout_obj = {{&mp_type_vfs_posix_textio}, STDOUT_FILENO}; +mp_obj_vfs_posix_file_t mp_sys_stderr_obj = {{&mp_type_vfs_posix_textio}, STDERR_FILENO}; #endif // MICROPY_VFS_POSIX diff --git a/extmod/vfs_reader.c b/extmod/vfs_reader.c index 3c6ff52a99..13fc31bee5 100644 --- a/extmod/vfs_reader.c +++ b/extmod/vfs_reader.c @@ -26,6 +26,7 @@ #include #include +#include #include "py/runtime.h" #include "py/stream.h" @@ -34,33 +35,39 @@ #if MICROPY_READER_VFS +#ifndef MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE +#define MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE (2 * MICROPY_BYTES_PER_GC_BLOCK - offsetof(mp_reader_vfs_t, buf)) +#endif +#define MICROPY_READER_VFS_MIN_BUFFER_SIZE (MICROPY_BYTES_PER_GC_BLOCK - offsetof(mp_reader_vfs_t, buf)) +#define MICROPY_READER_VFS_MAX_BUFFER_SIZE (255) + typedef struct _mp_reader_vfs_t { mp_obj_t file; - uint16_t len; - uint16_t pos; - byte buf[24]; + uint8_t bufpos; + uint8_t buflen; + uint8_t bufsize; + byte buf[]; } mp_reader_vfs_t; STATIC mp_uint_t mp_reader_vfs_readbyte(void *data) { mp_reader_vfs_t *reader = (mp_reader_vfs_t *)data; - if (reader->pos >= reader->len) { - if (reader->len < sizeof(reader->buf)) { + if (reader->bufpos >= reader->buflen) { + if (reader->buflen < reader->bufsize) { return MP_READER_EOF; } else { int errcode; - reader->len = mp_stream_rw(reader->file, reader->buf, sizeof(reader->buf), - &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); + reader->buflen = mp_stream_rw(reader->file, reader->buf, reader->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); if (errcode != 0) { // TODO handle errors properly return MP_READER_EOF; } - if (reader->len == 0) { + if (reader->buflen == 0) { return MP_READER_EOF; } - reader->pos = 0; + reader->bufpos = 0; } } - return reader->buf[reader->pos++]; + return reader->buf[reader->bufpos++]; } STATIC void mp_reader_vfs_close(void *data) { @@ -70,18 +77,31 @@ STATIC void mp_reader_vfs_close(void *data) { } void mp_reader_new_file(mp_reader_t *reader, qstr filename) { - mp_reader_vfs_t *rf = m_new_obj(mp_reader_vfs_t); mp_obj_t args[2] = { MP_OBJ_NEW_QSTR(filename), MP_OBJ_NEW_QSTR(MP_QSTR_rb), }; - rf->file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); - int errcode; - rf->len = mp_stream_rw(rf->file, rf->buf, sizeof(rf->buf), &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); + mp_obj_t file = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); + + const mp_stream_p_t *stream_p = mp_get_stream(file); + int errcode = 0; + mp_uint_t bufsize = stream_p->ioctl(file, MP_STREAM_GET_BUFFER_SIZE, 0, &errcode); + if (bufsize == MP_STREAM_ERROR || bufsize == 0) { + // bufsize == 0 is included here to support mpremote v1.21 and older where mount file ioctl + // returned 0 by default. + bufsize = MICROPY_READER_VFS_DEFAULT_BUFFER_SIZE; + } else { + bufsize = MIN(MICROPY_READER_VFS_MAX_BUFFER_SIZE, MAX(MICROPY_READER_VFS_MIN_BUFFER_SIZE, bufsize)); + } + + mp_reader_vfs_t *rf = m_new_obj_var(mp_reader_vfs_t, buf, byte, bufsize); + rf->file = file; + rf->bufsize = bufsize; + rf->buflen = mp_stream_rw(rf->file, rf->buf, rf->bufsize, &errcode, MP_STREAM_RW_READ | MP_STREAM_RW_ONCE); if (errcode != 0) { mp_raise_OSError(errcode); } - rf->pos = 0; + rf->bufpos = 0; reader->data = rf; reader->readbyte = mp_reader_vfs_readbyte; reader->close = mp_reader_vfs_close; diff --git a/logo/vector-logo-2.ico b/logo/vector-logo-2.ico new file mode 100644 index 0000000000..24b12812cf Binary files /dev/null and b/logo/vector-logo-2.ico differ diff --git a/ports/bare-arm/lib.c b/ports/bare-arm/lib.c index 61d3be64e3..1574d5c902 100644 --- a/ports/bare-arm/lib.c +++ b/ports/bare-arm/lib.c @@ -110,8 +110,9 @@ char *strchr(const char *s, int c) { } int strncmp(const char *s1, const char *s2, size_t n) { - while (*s1 && *s2 && n-- > 0) { + while (n > 0 && *s1 && *s2) { int c = *s1++ - *s2++; + --n; if (c) { return c; } diff --git a/ports/esp32/adc.c b/ports/esp32/adc.c new file mode 100644 index 0000000000..c5886624ec --- /dev/null +++ b/ports/esp32/adc.c @@ -0,0 +1,92 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017 Nick Moore + * Copyright (c) 2021 Jonathan Hogg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mphal.h" +#include "adc.h" +#include "driver/adc.h" + +#define DEFAULT_VREF 1100 + +void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits) { + switch (bits) { + #if CONFIG_IDF_TARGET_ESP32 + case 9: + self->width = ADC_WIDTH_BIT_9; + break; + case 10: + self->width = ADC_WIDTH_BIT_10; + break; + case 11: + self->width = ADC_WIDTH_BIT_11; + break; + #endif + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + case 12: + self->width = ADC_WIDTH_BIT_12; + break; + #endif + #if CONFIG_IDF_TARGET_ESP32S2 + case 13: + self->width = ADC_WIDTH_BIT_13; + break; + #endif + default: + mp_raise_ValueError(MP_ERROR_TEXT("invalid bits")); + } + self->bits = bits; + + if (self->unit_id == ADC_UNIT_1) { + adc1_config_width(self->width); + } + for (adc_atten_t atten = ADC_ATTEN_DB_0; atten < ADC_ATTEN_MAX; atten++) { + if (self->characteristics[atten] != NULL) { + esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, self->characteristics[atten]); + } + } +} + +mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id) { + int raw; + if (self->unit_id == ADC_UNIT_1) { + raw = adc1_get_raw(channel_id); + } else { + check_esp_err(adc2_get_raw(channel_id, self->width, &raw)); + } + return raw; +} + +mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) { + int raw = madcblock_read_helper(self, channel_id); + esp_adc_cal_characteristics_t *adc_chars = self->characteristics[atten]; + if (adc_chars == NULL) { + adc_chars = malloc(sizeof(esp_adc_cal_characteristics_t)); + esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, adc_chars); + self->characteristics[atten] = adc_chars; + } + mp_int_t uv = esp_adc_cal_raw_to_voltage(raw, adc_chars) * 1000; + return uv; +} diff --git a/ports/esp32/adc.h b/ports/esp32/adc.h new file mode 100644 index 0000000000..ae5c0d3c37 --- /dev/null +++ b/ports/esp32/adc.h @@ -0,0 +1,60 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * Development of the code in this file was sponsored by Microbric Pty Ltd + * + * The MIT License (MIT) + * + * Copyright (c) 2023 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_ADC_H +#define MICROPY_INCLUDED_ESP32_ADC_H + +#include "py/runtime.h" +#include "esp_adc_cal.h" + +#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM + +typedef struct _machine_adc_block_obj_t { + mp_obj_base_t base; + adc_unit_t unit_id; + mp_int_t bits; + adc_bits_width_t width; + esp_adc_cal_characteristics_t *characteristics[ADC_ATTEN_MAX]; +} machine_adc_block_obj_t; + +typedef struct _machine_adc_obj_t { + mp_obj_base_t base; + machine_adc_block_obj_t *block; + adc_channel_t channel_id; + gpio_num_t gpio_id; +} machine_adc_obj_t; + +extern machine_adc_block_obj_t madcblock_obj[]; + +void madcblock_bits_helper(machine_adc_block_obj_t *self, mp_int_t bits); +mp_int_t madcblock_read_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id); +mp_int_t madcblock_read_uv_helper(machine_adc_block_obj_t *self, adc_channel_t channel_id, adc_atten_t atten); + +const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id); +void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args); + +#endif // MICROPY_INCLUDED_ESP32_ADC_H diff --git a/ports/esp32/esp32_common.cmake b/ports/esp32/esp32_common.cmake index f66c59e341..40ae98822d 100644 --- a/ports/esp32/esp32_common.cmake +++ b/ports/esp32/esp32_common.cmake @@ -53,6 +53,7 @@ list(APPEND MICROPY_SOURCE_DRIVERS ) list(APPEND MICROPY_SOURCE_PORT + adc.c main.c ppp_set_auth.c uart.c @@ -66,7 +67,6 @@ list(APPEND MICROPY_SOURCE_PORT machine_timer.c machine_pin.c machine_touchpad.c - machine_adcblock.c machine_dac.c machine_i2c.c modmachine.c diff --git a/ports/esp32/esp32_rmt.c b/ports/esp32/esp32_rmt.c index f92af636f5..5d53018f4b 100644 --- a/ports/esp32/esp32_rmt.c +++ b/ports/esp32/esp32_rmt.c @@ -206,10 +206,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_deinit_obj, esp32_rmt_deinit); // Return the source frequency. // Currently only the APB clock (80MHz) can be used but it is possible other // clock sources will added in the future. -STATIC mp_obj_t esp32_rmt_source_freq(mp_obj_t self_in) { +STATIC mp_obj_t esp32_rmt_source_freq() { return mp_obj_new_int(APB_CLK_FREQ); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp32_rmt_source_freq_obj, esp32_rmt_source_freq); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp32_rmt_source_freq_obj, esp32_rmt_source_freq); +STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(esp32_rmt_source_obj, MP_ROM_PTR(&esp32_rmt_source_freq_obj)); // Return the clock divider. STATIC mp_obj_t esp32_rmt_clock_div(mp_obj_t self_in) { @@ -357,7 +358,6 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(esp32_rmt_bitstream_channel_obj, MP_ROM_ STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&esp32_rmt_deinit_obj) }, { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&esp32_rmt_deinit_obj) }, - { MP_ROM_QSTR(MP_QSTR_source_freq), MP_ROM_PTR(&esp32_rmt_source_freq_obj) }, { MP_ROM_QSTR(MP_QSTR_clock_div), MP_ROM_PTR(&esp32_rmt_clock_div_obj) }, { MP_ROM_QSTR(MP_QSTR_wait_done), MP_ROM_PTR(&esp32_rmt_wait_done_obj) }, { MP_ROM_QSTR(MP_QSTR_loop), MP_ROM_PTR(&esp32_rmt_loop_obj) }, @@ -365,6 +365,12 @@ STATIC const mp_rom_map_elem_t esp32_rmt_locals_dict_table[] = { // Static methods { MP_ROM_QSTR(MP_QSTR_bitstream_channel), MP_ROM_PTR(&esp32_rmt_bitstream_channel_obj) }, + + // Class methods + { MP_ROM_QSTR(MP_QSTR_source_freq), MP_ROM_PTR(&esp32_rmt_source_obj) }, + + // Constants + { MP_ROM_QSTR(MP_QSTR_PULSE_MAX), MP_ROM_INT(32767) }, }; STATIC MP_DEFINE_CONST_DICT(esp32_rmt_locals_dict, esp32_rmt_locals_dict_table); diff --git a/ports/esp32/machine_adc.c b/ports/esp32/machine_adc.c index 42746cb4bd..b5233e4dda 100644 --- a/ports/esp32/machine_adc.c +++ b/ports/esp32/machine_adc.c @@ -28,13 +28,9 @@ // This file is never compiled standalone, it's included directly from // extmod/machine_adc.c via MICROPY_PY_MACHINE_ADC_INCLUDEFILE. -#include "esp_log.h" - -#include "driver/gpio.h" -#include "driver/adc.h" - #include "py/mphal.h" -#include "machine_adc.h" +#include "adc.h" +#include "driver/adc.h" #define ADCBLOCK1 (&madcblock_obj[0]) #define ADCBLOCK2 (&madcblock_obj[1]) @@ -136,7 +132,7 @@ static inline void madc_atten_set(const machine_adc_obj_t *self, adc_atten_t att madc_obj_atten[self - &madc_obj[0]] = atten + 1; } -const machine_adc_obj_t *madc_search_helper(madcblock_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) { +const machine_adc_obj_t *madc_search_helper(machine_adc_block_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id) { for (int i = 0; i < MP_ARRAY_SIZE(madc_obj); i++) { const machine_adc_obj_t *adc = &madc_obj[i]; if ((block == NULL || block == adc->block) && (channel_id == -1 || channel_id == adc->channel_id) && (gpio_id == -1 || gpio_id == adc->gpio_id)) { diff --git a/ports/esp32/machine_adc.h b/ports/esp32/machine_adc.h deleted file mode 100644 index 6d06486c30..0000000000 --- a/ports/esp32/machine_adc.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef MICROPY_INCLUDED_MACHINE_ADC_H -#define MICROPY_INCLUDED_MACHINE_ADC_H - -#include "machine_adcblock.h" - -typedef struct _machine_adc_obj_t { - mp_obj_base_t base; - madcblock_obj_t *block; - adc_channel_t channel_id; - gpio_num_t gpio_id; -} machine_adc_obj_t; - -const machine_adc_obj_t *madc_search_helper(madcblock_obj_t *block, adc_channel_t channel_id, gpio_num_t gpio_id); -void madc_init_helper(const machine_adc_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args); - -#endif // MICROPY_INCLUDED_MACHINE_ADC_H diff --git a/ports/esp32/machine_adc_block.c b/ports/esp32/machine_adc_block.c new file mode 100644 index 0000000000..f2975ff2f2 --- /dev/null +++ b/ports/esp32/machine_adc_block.c @@ -0,0 +1,72 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Jonathan Hogg + * + * 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. + */ + +// This file is never compiled standalone, it's included directly from +// extmod/machine_adc_block.c via MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE. + +#include "py/mphal.h" +#include "adc.h" +#include "driver/adc.h" + +machine_adc_block_obj_t madcblock_obj[] = { + #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 + {{&machine_adc_block_type}, ADC_UNIT_1, 12, -1, {0}}, + {{&machine_adc_block_type}, ADC_UNIT_2, 12, -1, {0}}, + #elif CONFIG_IDF_TARGET_ESP32S2 + {{&machine_adc_block_type}, ADC_UNIT_1, 13, -1, {0}}, + {{&machine_adc_block_type}, ADC_UNIT_2, 13, -1, {0}}, + #endif +}; + +STATIC void mp_machine_adc_block_print(const mp_print_t *print, machine_adc_block_obj_t *self) { + mp_printf(print, "ADCBlock(%u, bits=%u)", self->unit_id, self->bits); +} + +STATIC void mp_machine_adc_block_bits_set(machine_adc_block_obj_t *self, mp_int_t bits) { + if (bits != -1) { + madcblock_bits_helper(self, bits); + } else if (self->width == -1) { + madcblock_bits_helper(self, self->bits); + } +} + +STATIC machine_adc_block_obj_t *mp_machine_adc_block_get(mp_int_t unit) { + for (int i = 0; i < MP_ARRAY_SIZE(madcblock_obj); i++) { + if (unit == madcblock_obj[i].unit_id) { + return &madcblock_obj[i]; + } + } + return NULL; +} + +STATIC machine_adc_obj_t *mp_machine_adc_block_connect(machine_adc_block_obj_t *self, mp_int_t channel_id, mp_hal_pin_obj_t gpio_id, mp_map_t *kw_args) { + const machine_adc_obj_t *adc = madc_search_helper(self, channel_id, gpio_id); + if (adc == NULL) { + return NULL; + } + madc_init_helper(adc, 0, NULL, kw_args); + return (machine_adc_obj_t *)adc; +} diff --git a/ports/esp32/machine_adcblock.c b/ports/esp32/machine_adcblock.c deleted file mode 100644 index 8d5296e2e5..0000000000 --- a/ports/esp32/machine_adcblock.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2021 Jonathan Hogg - * - * 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 - -#include "esp_log.h" - -#include "driver/gpio.h" -#include "driver/adc.h" - -#include "py/runtime.h" -#include "py/mphal.h" -#include "modmachine.h" -#include "machine_adc.h" -#include "machine_adcblock.h" - -#define DEFAULT_VREF 1100 - -madcblock_obj_t madcblock_obj[] = { - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - {{&machine_adcblock_type}, ADC_UNIT_1, 12, -1, {0}}, - {{&machine_adcblock_type}, ADC_UNIT_2, 12, -1, {0}}, - #elif CONFIG_IDF_TARGET_ESP32S2 - {{&machine_adcblock_type}, ADC_UNIT_1, 13, -1, {0}}, - {{&machine_adcblock_type}, ADC_UNIT_2, 13, -1, {0}}, - #endif -}; - -STATIC void madcblock_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - madcblock_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "ADCBlock(%u, bits=%u)", self->unit_id, self->bits); -} - -void madcblock_bits_helper(madcblock_obj_t *self, mp_int_t bits) { - switch (bits) { - #if CONFIG_IDF_TARGET_ESP32 - case 9: - self->width = ADC_WIDTH_BIT_9; - break; - case 10: - self->width = ADC_WIDTH_BIT_10; - break; - case 11: - self->width = ADC_WIDTH_BIT_11; - break; - #endif - #if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - case 12: - self->width = ADC_WIDTH_BIT_12; - break; - #endif - #if CONFIG_IDF_TARGET_ESP32S2 - case 13: - self->width = ADC_WIDTH_BIT_13; - break; - #endif - default: - mp_raise_ValueError(MP_ERROR_TEXT("invalid bits")); - } - self->bits = bits; - - if (self->unit_id == ADC_UNIT_1) { - adc1_config_width(self->width); - } - for (adc_atten_t atten = ADC_ATTEN_DB_0; atten < ADC_ATTEN_MAX; atten++) { - if (self->characteristics[atten] != NULL) { - esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, self->characteristics[atten]); - } - } -} - -STATIC void madcblock_init_helper(madcblock_obj_t *self, size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { - ARG_bits, - }; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_bits, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} }, - }; - - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_pos_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - mp_int_t bits = args[ARG_bits].u_int; - if (bits != -1) { - madcblock_bits_helper(self, bits); - } else if (self->width == -1) { - madcblock_bits_helper(self, self->bits); - } -} - -STATIC mp_obj_t madcblock_make_new(const mp_obj_type_t *type, size_t n_pos_args, size_t n_kw_args, const mp_obj_t *args) { - mp_arg_check_num(n_pos_args, n_kw_args, 1, MP_OBJ_FUN_ARGS_MAX, true); - adc_unit_t unit = mp_obj_get_int(args[0]); - madcblock_obj_t *self = NULL; - for (int i = 0; i < MP_ARRAY_SIZE(madcblock_obj); i++) { - if (unit == madcblock_obj[i].unit_id) { - self = &madcblock_obj[i]; - break; - } - } - if (!self) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid block id")); - } - - mp_map_t kw_args; - mp_map_init_fixed_table(&kw_args, n_kw_args, args + n_pos_args); - madcblock_init_helper(self, n_pos_args - 1, args + 1, &kw_args); - - return MP_OBJ_FROM_PTR(self); -} - -STATIC mp_obj_t madcblock_init(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - madcblock_obj_t *self = pos_args[0]; - madcblock_init_helper(self, n_pos_args - 1, pos_args + 1, kw_args); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madcblock_init_obj, 1, madcblock_init); - -STATIC mp_obj_t madcblock_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - madcblock_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - adc_channel_t channel_id = -1; - gpio_num_t gpio_id = -1; - if (n_pos_args == 2) { - if (mp_obj_is_int(pos_args[1])) { - channel_id = mp_obj_get_int(pos_args[1]); - } else { - gpio_id = machine_pin_get_id(pos_args[1]); - } - } else if (n_pos_args == 3) { - channel_id = mp_obj_get_int(pos_args[1]); - gpio_id = machine_pin_get_id(pos_args[2]); - } else { - mp_raise_TypeError(MP_ERROR_TEXT("too many positional args")); - } - - const machine_adc_obj_t *adc = madc_search_helper(self, channel_id, gpio_id); - if (adc != NULL) { - madc_init_helper(adc, 0, pos_args + n_pos_args, kw_args); - return MP_OBJ_FROM_PTR(adc); - } - mp_raise_ValueError(MP_ERROR_TEXT("no matching ADC")); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(madcblock_connect_obj, 2, madcblock_connect); - -mp_int_t madcblock_read_helper(madcblock_obj_t *self, adc_channel_t channel_id) { - int raw; - if (self->unit_id == ADC_UNIT_1) { - raw = adc1_get_raw(channel_id); - } else { - check_esp_err(adc2_get_raw(channel_id, self->width, &raw)); - } - return raw; -} - -mp_int_t madcblock_read_uv_helper(madcblock_obj_t *self, adc_channel_t channel_id, adc_atten_t atten) { - int raw = madcblock_read_helper(self, channel_id); - esp_adc_cal_characteristics_t *adc_chars = self->characteristics[atten]; - if (adc_chars == NULL) { - adc_chars = malloc(sizeof(esp_adc_cal_characteristics_t)); - esp_adc_cal_characterize(self->unit_id, atten, self->width, DEFAULT_VREF, adc_chars); - self->characteristics[atten] = adc_chars; - } - mp_int_t uv = esp_adc_cal_raw_to_voltage(raw, adc_chars) * 1000; - return uv; -} - -STATIC const mp_rom_map_elem_t madcblock_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&madcblock_init_obj) }, - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&madcblock_connect_obj) }, -}; -STATIC MP_DEFINE_CONST_DICT(madcblock_locals_dict, madcblock_locals_dict_table); - -MP_DEFINE_CONST_OBJ_TYPE( - machine_adcblock_type, - MP_QSTR_ADCBlock, - MP_TYPE_FLAG_NONE, - make_new, madcblock_make_new, - print, madcblock_print, - locals_dict, &madcblock_locals_dict - ); diff --git a/ports/esp32/machine_adcblock.h b/ports/esp32/machine_adcblock.h deleted file mode 100644 index 7c9249b072..0000000000 --- a/ports/esp32/machine_adcblock.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MICROPY_INCLUDED_MACHINE_ADCBLOCK_H -#define MICROPY_INCLUDED_MACHINE_ADCBLOCK_H - -#include "esp_adc_cal.h" - -#define ADC_ATTEN_MAX SOC_ADC_ATTEN_NUM - -typedef struct _madcblock_obj_t { - mp_obj_base_t base; - adc_unit_t unit_id; - mp_int_t bits; - adc_bits_width_t width; - esp_adc_cal_characteristics_t *characteristics[ADC_ATTEN_MAX]; -} madcblock_obj_t; - -extern madcblock_obj_t madcblock_obj[]; - -extern void madcblock_bits_helper(madcblock_obj_t *self, mp_int_t bits); -extern mp_int_t madcblock_read_helper(madcblock_obj_t *self, adc_channel_t channel_id); -extern mp_int_t madcblock_read_uv_helper(madcblock_obj_t *self, adc_channel_t channel_id, adc_atten_t atten); - -#endif // MICROPY_INCLUDED_MACHINE_ADCBLOCK_H diff --git a/ports/esp32/modmachine.c b/ports/esp32/modmachine.c index 1e83935a8b..461ddacdad 100644 --- a/ports/esp32/modmachine.c +++ b/ports/esp32/modmachine.c @@ -312,7 +312,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { #if MICROPY_PY_MACHINE_ADC { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) }, #endif - { MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adcblock_type) }, + #if MICROPY_PY_MACHINE_ADC_BLOCK + { MP_ROM_QSTR(MP_QSTR_ADCBlock), MP_ROM_PTR(&machine_adc_block_type) }, + #endif #if MICROPY_PY_MACHINE_DAC { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) }, #endif diff --git a/ports/esp32/modmachine.h b/ports/esp32/modmachine.h index 7b26df609d..06a1d7b0e2 100644 --- a/ports/esp32/modmachine.h +++ b/ports/esp32/modmachine.h @@ -10,7 +10,6 @@ typedef enum { } wake_type_t; extern const mp_obj_type_t machine_touchpad_type; -extern const mp_obj_type_t machine_adcblock_type; extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/esp32/mpconfigport.h b/ports/esp32/mpconfigport.h index b4ec082092..706baae5b2 100644 --- a/ports/esp32/mpconfigport.h +++ b/ports/esp32/mpconfigport.h @@ -99,10 +99,11 @@ #define MICROPY_PY_MACHINE_ADC (1) #define MICROPY_PY_MACHINE_ADC_INCLUDEFILE "ports/esp32/machine_adc.c" #define MICROPY_PY_MACHINE_ADC_ATTEN_WIDTH (1) -#define MICROPY_PY_MACHINE_ADC_BLOCK (1) #define MICROPY_PY_MACHINE_ADC_INIT (1) #define MICROPY_PY_MACHINE_ADC_READ (1) #define MICROPY_PY_MACHINE_ADC_READ_UV (1) +#define MICROPY_PY_MACHINE_ADC_BLOCK (1) +#define MICROPY_PY_MACHINE_ADC_BLOCK_INCLUDEFILE "ports/esp32/machine_adc_block.c" #define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new #define MICROPY_PY_MACHINE_BITSTREAM (1) #define MICROPY_PY_MACHINE_PULSE (1) diff --git a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h index 324cee9b14..1ad2e9df5e 100644 --- a/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h +++ b/ports/mimxrt/boards/OLIMEX_RT1010/mpconfigboard.h @@ -18,18 +18,18 @@ // LPUART4 on D5/D6 -> 2 #define MICROPY_HW_UART_NUM (sizeof(uart_index_table) / sizeof(uart_index_table)[0]) -#define MICROPY_HW_UART_INDEX { 0, 1, 4 } +#define MICROPY_HW_UART_INDEX { 0, 1, 3, 4 } #define IOMUX_TABLE_UART \ { IOMUXC_GPIO_10_LPUART1_TXD }, { IOMUXC_GPIO_09_LPUART1_RXD }, \ { 0 }, { 0 }, \ - { 0 }, { 0 }, \ + { IOMUXC_GPIO_08_LPUART3_TXD }, { IOMUXC_GPIO_07_LPUART3_RXD }, \ { IOMUXC_GPIO_06_LPUART4_TXD }, { IOMUXC_GPIO_05_LPUART4_RXD }, #define IOMUX_TABLE_UART_CTS_RTS \ { IOMUXC_GPIO_08_LPUART1_CTS_B }, { IOMUXC_GPIO_07_LPUART1_RTS_B }, \ { 0 }, { 0 }, \ - { 0 }, { 0 }, \ + { IOMUXC_GPIO_AD_14_LPUART3_CTS_B }, { IOMUXC_GPIO_AD_13_LPUART3_RTS_B }, \ { IOMUXC_GPIO_AD_14_LPUART4_CTS_B }, { IOMUXC_GPIO_AD_13_LPUART4_RTS_B }, #define MICROPY_HW_SPI_INDEX { 0, 1, 2 } diff --git a/ports/mimxrt/modmachine.c b/ports/mimxrt/modmachine.c index aa12f44d47..57090bda27 100644 --- a/ports/mimxrt/modmachine.c +++ b/ports/mimxrt/modmachine.c @@ -121,10 +121,10 @@ STATIC mp_obj_t machine_deepsleep(size_t n_args, const mp_obj_t *args) { } #ifdef MIMXRT117x_SERIES - machine_pin_config(&pin_WAKEUP_DIG, PIN_MODE_IT_RISING, PIN_PULL_DISABLED, PIN_DRIVE_OFF, 0, PIN_AF_MODE_ALT5); + machine_pin_config(pin_WAKEUP_DIG, PIN_MODE_IT_RISING, PIN_PULL_DISABLED, PIN_DRIVE_OFF, 0, PIN_AF_MODE_ALT5); GPC_CM_EnableIrqWakeup(GPC_CPU_MODE_CTRL_0, GPIO13_Combined_0_31_IRQn, true); #elif defined IOMUXC_SNVS_WAKEUP_GPIO5_IO00 - machine_pin_config(&pin_WAKEUP, PIN_MODE_IT_RISING, PIN_PULL_DISABLED, PIN_DRIVE_OFF, 0, PIN_AF_MODE_ALT5); + machine_pin_config(pin_WAKEUP, PIN_MODE_IT_RISING, PIN_PULL_DISABLED, PIN_DRIVE_OFF, 0, PIN_AF_MODE_ALT5); GPC_EnableIRQ(GPC, GPIO5_Combined_0_15_IRQn); #endif diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test index e0f3a54169..cb5b0927c8 100644 --- a/ports/qemu-arm/Makefile.test +++ b/ports/qemu-arm/Makefile.test @@ -13,10 +13,12 @@ CFLAGS += -DTEST .PHONY: $(BUILD)/genhdr/tests.h +TESTS_PROFILE = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/tests_profile.txt + $(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h $(BUILD)/genhdr/tests.h: (cd $(TOP)/tests; ./run-tests.py --target=qemu-arm --write-exp) - $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py $(addprefix --exclude ,$(TESTS_EXCLUDE))) > $@ + $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py --profile $(TESTS_PROFILE) $(addprefix --exclude ,$(TESTS_EXCLUDE))) > $@ $(BUILD)/lib/tinytest/tinytest.o: CFLAGS += -DNO_FORKING diff --git a/ports/qemu-arm/tests_profile.txt b/ports/qemu-arm/tests_profile.txt new file mode 100644 index 0000000000..c55185a0eb --- /dev/null +++ b/ports/qemu-arm/tests_profile.txt @@ -0,0 +1,16 @@ +# Port-specific test directories. + +test_dirs.add(("inlineasm", "qemu-arm")) + +# Port-specific tests exclusion list. + +exclude_tests.add( + ( + # inline asm FP tests (require Cortex-M4) + "inlineasm/asmfpaddsub.py", + "inlineasm/asmfpcmp.py", + "inlineasm/asmfpldrstr.py", + "inlineasm/asmfpmuldiv.py", + "inlineasm/asmfpsqrt.py", + ) +) diff --git a/ports/renesas-ra/modmachine.h b/ports/renesas-ra/modmachine.h index 9bb3196b37..22d1fc475e 100644 --- a/ports/renesas-ra/modmachine.h +++ b/ports/renesas-ra/modmachine.h @@ -30,7 +30,6 @@ #include "py/obj.h" extern const mp_obj_type_t machine_touchpad_type; -extern const mp_obj_type_t machine_adcblock_type; extern const mp_obj_type_t machine_dac_type; extern const mp_obj_type_t machine_sdcard_type; diff --git a/ports/renesas-ra/mpconfigport.h b/ports/renesas-ra/mpconfigport.h index d3bc3235fd..222d5b919d 100644 --- a/ports/renesas-ra/mpconfigport.h +++ b/ports/renesas-ra/mpconfigport.h @@ -272,7 +272,7 @@ static inline mp_uint_t disable_irq(void) { #define MICROPY_END_ATOMIC_SECTION(state) enable_irq(state) #if MICROPY_HW_ENABLE_USBDEV -#define MICROPY_HW_USBDEV_TASK_HOOK extern void usbd_task(void); usbd_task(); +#define MICROPY_HW_USBDEV_TASK_HOOK extern void mp_usbd_task(void); mp_usbd_task(); #define MICROPY_VM_HOOK_COUNT (10) #define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; #define MICROPY_VM_HOOK_POLL if (--vm_hook_divisor == 0) { \ diff --git a/ports/rp2/CMakeLists.txt b/ports/rp2/CMakeLists.txt index 4f76c5864f..15f6f6ca1c 100644 --- a/ports/rp2/CMakeLists.txt +++ b/ports/rp2/CMakeLists.txt @@ -406,6 +406,7 @@ target_compile_options(${MICROPY_TARGET} PRIVATE target_link_options(${MICROPY_TARGET} PRIVATE -Wl,--defsym=__micropy_c_heap_size__=${MICROPY_C_HEAP_SIZE} + -Wl,--wrap=dcd_event_handler ) set_source_files_properties( diff --git a/ports/rp2/machine_adc.c b/ports/rp2/machine_adc.c index 80c4d0533e..3a7a71a741 100644 --- a/ports/rp2/machine_adc.c +++ b/ports/rp2/machine_adc.c @@ -69,21 +69,21 @@ STATIC mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args mp_obj_t source = all_args[0]; - uint32_t channel; + uint32_t channel = -1; bool is_ext = false; const machine_pin_obj_t *pin = NULL; if (mp_obj_is_int(source)) { // Get and validate channel number. channel = mp_obj_get_int(source); - if (!((channel >= 0 && channel <= ADC_CHANNEL_TEMPSENSOR) || ADC_IS_VALID_GPIO(channel))) { + if (ADC_IS_VALID_GPIO(channel)) { + channel = ADC_CHANNEL_FROM_GPIO(channel); + } else if (!(channel >= 0 && channel <= ADC_CHANNEL_TEMPSENSOR)) { mp_raise_ValueError(MP_ERROR_TEXT("invalid channel")); } - } else { // Get GPIO and check it has ADC capabilities. pin = machine_pin_find(source); - channel = pin->id; bool valid_adc_pin = false; #if MICROPY_HW_ADC_EXT_COUNT is_ext = pin->is_ext; @@ -92,7 +92,7 @@ STATIC mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args } else #endif { - valid_adc_pin = ADC_IS_VALID_GPIO(channel); + valid_adc_pin = ADC_IS_VALID_GPIO(pin->id); } if (!valid_adc_pin) { mp_raise_ValueError(MP_ERROR_TEXT("Pin doesn't have ADC capabilities")); @@ -104,16 +104,18 @@ STATIC mp_obj_t mp_machine_adc_make_new(const mp_obj_type_t *type, size_t n_args adc_init(); } - if (is_ext) { - #if MICROPY_HW_ADC_EXT_COUNT - // Note external pins are mutable. - machine_pin_ext_config((machine_pin_obj_t *)pin, MACHINE_PIN_MODE_ANALOG, 0); - channel = machine_pin_ext_to_adc_channel(pin); - #endif - } else if (ADC_IS_VALID_GPIO(channel)) { - // Configure the GPIO pin in ADC mode. - adc_gpio_init(channel); - channel = ADC_CHANNEL_FROM_GPIO(channel); + if (pin) { + if (is_ext) { + #if MICROPY_HW_ADC_EXT_COUNT + // Note external pins are mutable. + machine_pin_ext_config((machine_pin_obj_t *)pin, MACHINE_PIN_MODE_ANALOG, 0); + channel = machine_pin_ext_to_adc_channel(pin); + #endif + } else { + // Configure the GPIO pin in ADC mode. + adc_gpio_init(pin->id); + channel = ADC_CHANNEL_FROM_GPIO(pin->id); + } } else if (channel == ADC_CHANNEL_TEMPSENSOR) { // Enable temperature sensor. adc_set_temp_sensor_enabled(1); diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index 044c905ff2..dae57012a8 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -140,8 +140,27 @@ static inline void read_mutex_unlock(machine_uart_obj_t *u) { STATIC void uart_drain_rx_fifo(machine_uart_obj_t *self) { if (read_mutex_try_lock(self)) { while (uart_is_readable(self->uart) && ringbuf_free(&self->read_buffer) > 0) { - // get a byte from uart and put into the buffer - ringbuf_put(&(self->read_buffer), uart_get_hw(self->uart)->dr); + // Get a byte from uart and put into the buffer. Every entry from + // the FIFO is accompanied by 4 error bits, that may be used for + // error handling. + uint16_t c = uart_get_hw(self->uart)->dr; + if (c & UART_UARTDR_OE_BITS) { + // Overrun Error: We missed at least one byte. Not much we can do here. + } + if (c & UART_UARTDR_BE_BITS) { + // Break Error: RX was held low for longer than one character + // (11 bits). We did *not* read the zero byte that we seemed to + // read from dr. + continue; + } + if (c & UART_UARTDR_PE_BITS) { + // Parity Error: The byte we read is invalid. + } + if (c & UART_UARTDR_FE_BITS) { + // Framing Error: We did not receive a valid stop bit. + } + + ringbuf_put(&(self->read_buffer), c); } read_mutex_unlock(self); } diff --git a/ports/rp2/modmachine.c b/ports/rp2/modmachine.c index 29a8dbed2c..4c428cbddf 100644 --- a/ports/rp2/modmachine.c +++ b/ports/rp2/modmachine.c @@ -111,7 +111,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_freq_obj, 0, 1, machine_freq); STATIC mp_obj_t machine_idle(void) { - best_effort_wfe_or_timeout(make_timeout_time_ms(1)); + __wfe(); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle); diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 0a63312734..61749f108a 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -250,23 +250,8 @@ extern void mp_thread_end_atomic_section(uint32_t); #define MICROPY_PY_LWIP_REENTER lwip_lock_acquire(); #define MICROPY_PY_LWIP_EXIT lwip_lock_release(); -#if MICROPY_HW_ENABLE_USBDEV -#define MICROPY_HW_USBDEV_TASK_HOOK extern void usbd_task(void); usbd_task(); -#define MICROPY_VM_HOOK_COUNT (10) -#define MICROPY_VM_HOOK_INIT static uint vm_hook_divisor = MICROPY_VM_HOOK_COUNT; -#define MICROPY_VM_HOOK_POLL if (get_core_num() == 0 && --vm_hook_divisor == 0) { \ - vm_hook_divisor = MICROPY_VM_HOOK_COUNT; \ - MICROPY_HW_USBDEV_TASK_HOOK \ -} -#define MICROPY_VM_HOOK_LOOP MICROPY_VM_HOOK_POLL -#define MICROPY_VM_HOOK_RETURN MICROPY_VM_HOOK_POLL -#else -#define MICROPY_HW_USBDEV_TASK_HOOK -#endif - #define MICROPY_EVENT_POLL_HOOK_FAST \ do { \ - if (get_core_num() == 0) { MICROPY_HW_USBDEV_TASK_HOOK } \ extern void mp_handle_pending(bool); \ mp_handle_pending(true); \ } while (0) @@ -274,7 +259,7 @@ extern void mp_thread_end_atomic_section(uint32_t); #define MICROPY_EVENT_POLL_HOOK \ do { \ MICROPY_EVENT_POLL_HOOK_FAST; \ - best_effort_wfe_or_timeout(make_timeout_time_ms(1)); \ + __wfe(); \ } while (0); #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index d1bba43642..4b1c1fa1f5 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -30,6 +30,7 @@ #include "extmod/misc.h" #include "shared/runtime/interrupt_char.h" #include "shared/timeutils/timeutils.h" +#include "shared/tinyusb/mp_usbd.h" #include "tusb.h" #include "uart.h" #include "hardware/rtc.h" @@ -54,6 +55,19 @@ ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) }; #endif +#if MICROPY_HW_USB_CDC +// Explicitly run the USB stack in case the scheduler is locked (eg we are in an +// interrupt handler) and there is in/out data pending on the USB CDC interface. +#define MICROPY_EVENT_POLL_HOOK_WITH_USB \ + do { \ + MICROPY_EVENT_POLL_HOOK; \ + mp_usbd_task(); \ + } while (0) + +#else +#define MICROPY_EVENT_POLL_HOOK_WITH_USB MICROPY_EVENT_POLL_HOOK +#endif + #if MICROPY_HW_USB_CDC uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll @@ -135,7 +149,7 @@ int mp_hal_stdin_rx_chr(void) { return dupterm_c; } #endif - MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK_WITH_USB; } } @@ -155,7 +169,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { int timeout = 0; // Wait with a max of USC_CDC_TIMEOUT ms while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) { - MICROPY_EVENT_POLL_HOOK + MICROPY_EVENT_POLL_HOOK_WITH_USB; } if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) { break; diff --git a/ports/samd/Makefile b/ports/samd/Makefile index 291a894ab7..12223e6ded 100644 --- a/ports/samd/Makefile +++ b/ports/samd/Makefile @@ -93,6 +93,8 @@ LIBSTDCPP_FILE_NAME = "$(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)" LDFLAGS += -L"$(shell dirname $(LIBSTDCPP_FILE_NAME))" endif +LDFLAGS += --wrap=dcd_event_handler + MPY_CROSS_FLAGS += -march=$(MPY_CROSS_MCU_ARCH) SRC_C += \ @@ -131,6 +133,7 @@ SHARED_SRC_C += \ shared/runtime/sys_stdio_mphal.c \ shared/timeutils/timeutils.c \ shared/tinyusb/mp_cdc_common.c \ + shared/tinyusb/mp_usbd.c ASF4_SRC_C += $(addprefix lib/asf4/$(MCU_SERIES_LOWER)/,\ hal/src/hal_atomic.c \ diff --git a/ports/samd/machine_uart.c b/ports/samd/machine_uart.c index ada193020b..de6c92c5f5 100644 --- a/ports/samd/machine_uart.c +++ b/ports/samd/machine_uart.c @@ -49,6 +49,7 @@ typedef struct _machine_uart_obj_t { uint8_t bits; uint8_t parity; uint8_t stop; + uint8_t flow_control; uint8_t tx; uint8_t rx; sercom_pad_config_t tx_pad_config; @@ -112,6 +113,85 @@ void common_uart_irq_handler(int uart_id) { } } +// Configure the Sercom device +STATIC void machine_sercom_configure(machine_uart_obj_t *self) { + Sercom *uart = sercom_instance[self->id]; + + // Reset (clear) the peripheral registers. + while (uart->USART.SYNCBUSY.bit.SWRST) { + } + uart->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral + while (uart->USART.SYNCBUSY.bit.SWRST) { + } + + uint8_t txpo = self->tx_pad_config.pad_nr; + #if defined(MCU_SAMD21) + if (self->tx_pad_config.pad_nr == 2) { // Map pad 2 to TXPO = 1 + txpo = 1; + } else + #endif + if (self->tx_pad_config.pad_nr != 0) { + mp_raise_ValueError(MP_ERROR_TEXT("invalid UART pin")); + } + #if MICROPY_HW_UART_RTSCTS + if ((self->flow_control & FLOW_CONTROL_RTS) && self->rts_pad_config.pad_nr == 2) { + txpo = 2; + mp_hal_set_pin_mux(self->rts, self->rts_pad_config.alt_fct); + } + if ((self->flow_control & FLOW_CONTROL_CTS) && self->cts_pad_config.pad_nr == 3) { + txpo = 2; + mp_hal_set_pin_mux(self->cts, self->cts_pad_config.alt_fct); + } + #endif + + uart->USART.CTRLA.reg = + SERCOM_USART_CTRLA_DORD // Data order + | SERCOM_USART_CTRLA_FORM(self->parity != 0 ? 1 : 0) // Enable parity or not + | SERCOM_USART_CTRLA_RXPO(self->rx_pad_config.pad_nr) // Set Pad# + | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad# + | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock + ; + uart->USART.CTRLB.reg = + SERCOM_USART_CTRLB_RXEN // Enable Rx & Tx + | SERCOM_USART_CTRLB_TXEN + | ((self->parity & 1) << SERCOM_USART_CTRLB_PMODE_Pos) + | (self->stop << SERCOM_USART_CTRLB_SBMODE_Pos) + | SERCOM_USART_CTRLB_CHSIZE((self->bits & 7) | (self->bits & 1)) + ; + while (uart->USART.SYNCBUSY.bit.CTRLB) { + } + + // USART is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq() + // baud rate; 65536 * (1 - 16 * 115200/bus_freq) + uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_peripheral_freq() / 2) / get_peripheral_freq(); + uart->USART.BAUD.bit.BAUD = baud; // Set Baud + + sercom_register_irq(self->id, &common_uart_irq_handler); + + // Enable RXC interrupt + uart->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC; + #if defined(MCU_SAMD21) + NVIC_EnableIRQ(SERCOM0_IRQn + self->id); + #elif defined(MCU_SAMD51) + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); + #endif + #if MICROPY_HW_UART_TXBUF + // Enable DRE interrupt + // SAMD21 has just 1 IRQ for all USART events, so no need for an additional NVIC enable + #if defined(MCU_SAMD51) + NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 0); + #endif + #endif + + sercom_enable(uart, 1); +} + +void machine_uart_set_baudrate(mp_obj_t self_in, uint32_t baudrate) { + machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); + self->baudrate = baudrate; + machine_sercom_configure(self); +} + STATIC void mp_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, " @@ -194,22 +274,22 @@ STATIC void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, if (args[ARG_rx].u_obj != mp_const_none) { self->rx = mp_hal_get_pin_obj(args[ARG_rx].u_obj); } + self->flow_control = 0; #if MICROPY_HW_UART_RTSCTS - uint8_t flow_control = 0; // Set RTS/CTS pins if configured. if (args[ARG_rts].u_obj != mp_const_none) { self->rts = mp_hal_get_pin_obj(args[ARG_rts].u_obj); self->rts_pad_config = get_sercom_config(self->rts, self->id); - flow_control = FLOW_CONTROL_RTS; + self->flow_control = FLOW_CONTROL_RTS; } if (args[ARG_cts].u_obj != mp_const_none) { self->cts = mp_hal_get_pin_obj(args[ARG_cts].u_obj); self->cts_pad_config = get_sercom_config(self->cts, self->id); - flow_control |= FLOW_CONTROL_CTS; + self->flow_control |= FLOW_CONTROL_CTS; } // rts only flow control is not allowed. Otherwise the state of the // cts pin is undefined. - if (flow_control == FLOW_CONTROL_RTS) { + if (self->flow_control == FLOW_CONTROL_RTS) { mp_raise_ValueError(MP_ERROR_TEXT("cts missing for flow control")); } #endif @@ -278,75 +358,8 @@ STATIC void mp_machine_uart_init_helper(machine_uart_obj_t *self, size_t n_args, // Next: Set up the clocks enable_sercom_clock(self->id); - // Next: Configure the USART - Sercom *uart = sercom_instance[self->id]; - // Reset (clear) the peripheral registers. - while (uart->USART.SYNCBUSY.bit.SWRST) { - } - uart->USART.CTRLA.bit.SWRST = 1; // Reset all Registers, disable peripheral - while (uart->USART.SYNCBUSY.bit.SWRST) { - } - - uint8_t txpo = self->tx_pad_config.pad_nr; - #if defined(MCU_SAMD21) - if (self->tx_pad_config.pad_nr == 2) { // Map pad 2 to TXPO = 1 - txpo = 1; - } else - #endif - if (self->tx_pad_config.pad_nr != 0) { - mp_raise_ValueError(MP_ERROR_TEXT("invalid UART pin")); - } - #if MICROPY_HW_UART_RTSCTS - if ((flow_control & FLOW_CONTROL_RTS) && self->rts_pad_config.pad_nr == 2) { - txpo = 2; - mp_hal_set_pin_mux(self->rts, self->rts_pad_config.alt_fct); - } - if ((flow_control & FLOW_CONTROL_CTS) && self->cts_pad_config.pad_nr == 3) { - txpo = 2; - mp_hal_set_pin_mux(self->cts, self->cts_pad_config.alt_fct); - } - #endif - - uart->USART.CTRLA.reg = - SERCOM_USART_CTRLA_DORD // Data order - | SERCOM_USART_CTRLA_FORM(self->parity != 0 ? 1 : 0) // Enable parity or not - | SERCOM_USART_CTRLA_RXPO(self->rx_pad_config.pad_nr) // Set Pad# - | SERCOM_USART_CTRLA_TXPO(txpo) // Set Pad# - | SERCOM_USART_CTRLA_MODE(1) // USART with internal clock - ; - uart->USART.CTRLB.reg = - SERCOM_USART_CTRLB_RXEN // Enable Rx & Tx - | SERCOM_USART_CTRLB_TXEN - | ((self->parity & 1) << SERCOM_USART_CTRLB_PMODE_Pos) - | (self->stop << SERCOM_USART_CTRLB_SBMODE_Pos) - | SERCOM_USART_CTRLB_CHSIZE((self->bits & 7) | (self->bits & 1)) - ; - while (uart->USART.SYNCBUSY.bit.CTRLB) { - } - - // USART is driven by the clock of GCLK Generator 2, freq by get_peripheral_freq() - // baud rate; 65536 * (1 - 16 * 115200/bus_freq) - uint32_t baud = 65536 - ((uint64_t)(65536 * 16) * self->baudrate + get_peripheral_freq() / 2) / get_peripheral_freq(); - uart->USART.BAUD.bit.BAUD = baud; // Set Baud - - sercom_register_irq(self->id, &common_uart_irq_handler); - - // Enable RXC interrupt - uart->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC; - #if defined(MCU_SAMD21) - NVIC_EnableIRQ(SERCOM0_IRQn + self->id); - #elif defined(MCU_SAMD51) - NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 2); - #endif - #if MICROPY_HW_UART_TXBUF - // Enable DRE interrupt - // SAMD21 has just 1 IRQ for all USART events, so no need for an additional NVIC enable - #if defined(MCU_SAMD51) - NVIC_EnableIRQ(SERCOM0_0_IRQn + 4 * self->id + 0); - #endif - #endif - - sercom_enable(uart, 1); + // Configure the sercom module + machine_sercom_configure(self); } } diff --git a/ports/samd/mpconfigport.h b/ports/samd/mpconfigport.h index 801408ed47..91a7c1a10d 100644 --- a/ports/samd/mpconfigport.h +++ b/ports/samd/mpconfigport.h @@ -56,6 +56,7 @@ #define MICROPY_PY_BUILTINS_HELP (1) #define MICROPY_PY_BUILTINS_HELP_TEXT samd_help_text #define MICROPY_PY_BUILTINS_HELP_MODULES (1) +#define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_ENABLE_SCHEDULER (1) #define MICROPY_SCHEDULER_STATIC_NODES (1) #define MICROPY_HW_ENABLE_USBDEV (1) diff --git a/ports/samd/pin_af.c b/ports/samd/pin_af.c index ca11e3b7a8..a73c6591dd 100644 --- a/ports/samd/pin_af.c +++ b/ports/samd/pin_af.c @@ -112,7 +112,7 @@ adc_config_t get_adc_config(int pin_id, int32_t flag) { const machine_pin_obj_t *pct_ptr = pin_find_by_id(pin_id); if (pct_ptr->adc0 != 0xff && (flag & (1 << pct_ptr->adc0)) == 0) { return (adc_config_t) {0, pct_ptr->adc0}; - #if defined(MUC_SAMD51) + #if defined(MCU_SAMD51) } else if (pct_ptr->adc1 != 0xff && (flag & (1 << (pct_ptr->adc1 + 16))) == 0) { return (adc_config_t) {1, pct_ptr->adc1}; #endif diff --git a/ports/samd/samd_isr.c b/ports/samd/samd_isr.c index a12140313b..7c4c1d060f 100644 --- a/ports/samd/samd_isr.c +++ b/ports/samd/samd_isr.c @@ -310,10 +310,10 @@ const ISR isr_vector[] __attribute__((section(".isr_vector"))) = { &Sercom7_Handler, // 77 Serial Communication Interface 7 (SERCOM7): SERCOM7_3 - 6 0, // 78 Control Area Network 0 (CAN0) 0, // 79 Control Area Network 1 (CAN1) - &USB_0_Handler_wrapper, // 80 Universal Serial Bus (USB): USB_EORSM_DNRS, ... - &USB_1_Handler_wrapper, // 81 Universal Serial Bus (USB): USB_SOF_HSOF - &USB_2_Handler_wrapper, // 82 Universal Serial Bus (USB): USB_TRCPT0_0 - _7 - &USB_3_Handler_wrapper, // 83 Universal Serial Bus (USB): USB_TRCPT1_0 - _7 + &USB_Handler_wrapper, // 80 Universal Serial Bus (USB): USB_EORSM_DNRS, ... + &USB_Handler_wrapper, // 81 Universal Serial Bus (USB): USB_SOF_HSOF + &USB_Handler_wrapper, // 82 Universal Serial Bus (USB): USB_TRCPT0_0 - _7 + &USB_Handler_wrapper, // 83 Universal Serial Bus (USB): USB_TRCPT1_0 - _7 0, // 84 Ethernet MAC (GMAC) 0, // 85 Timer Counter Control 0 (TCC0): TCC0_CNT_A ... 0, // 86 Timer Counter Control 0 (TCC0): TCC0_MC_0 diff --git a/ports/samd/samd_soc.h b/ports/samd/samd_soc.h index 1848cf7db1..90a5a57ffa 100644 --- a/ports/samd/samd_soc.h +++ b/ports/samd/samd_soc.h @@ -36,10 +36,6 @@ void samd_init(void); void samd_main(void); void USB_Handler_wrapper(void); -void USB_0_Handler_wrapper(void); -void USB_1_Handler_wrapper(void); -void USB_2_Handler_wrapper(void); -void USB_3_Handler_wrapper(void); void sercom_enable(Sercom *spi, int state); void sercom_register_irq(int sercom_id, void (*sercom_irq_handler)); diff --git a/ports/samd/tusb_port.c b/ports/samd/tusb_port.c index 2098334fba..e56ef0fd6a 100644 --- a/ports/samd/tusb_port.c +++ b/ports/samd/tusb_port.c @@ -117,33 +117,6 @@ const uint16_t *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { return desc_str; } -#if defined(MCU_SAMD21) - void USB_Handler_wrapper(void) { tud_int_handler(0); - tud_task(); } - -#elif defined(MCU_SAMD51) - -void USB_0_Handler_wrapper(void) { - tud_int_handler(0); - tud_task(); -} - -void USB_1_Handler_wrapper(void) { - tud_int_handler(0); - tud_task(); -} - -void USB_2_Handler_wrapper(void) { - tud_int_handler(0); - tud_task(); -} - -void USB_3_Handler_wrapper(void) { - tud_int_handler(0); - tud_task(); -} - -#endif diff --git a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h index a9b8cbfc7b..ec9bbed5ea 100644 --- a/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_GIGA/mpconfigboard.h @@ -104,6 +104,12 @@ void GIGA_board_low_power(int mode); // SMPS configuration #define MICROPY_HW_PWR_SMPS_CONFIG (PWR_LDO_SUPPLY) +// Configure the analog switches for dual-pad pins. +#define MICROPY_HW_ANALOG_SWITCH_PA0 (SYSCFG_SWITCH_PA0_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PA1 (SYSCFG_SWITCH_PA1_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_OPEN) + // There is an external 32kHz oscillator #define RTC_ASYNCH_PREDIV (0) #define RTC_SYNCH_PREDIV (0x7fff) diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c b/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c index ed8c609275..ec78b09de3 100644 --- a/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c +++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/board_init.c @@ -65,11 +65,6 @@ void NICLAV_board_early_init(void) { } #endif - // Make sure PC2 and PC3 and PC2_C and PC3_C pads are connected - // through the analog switch for ULPI NXT and DIR pins. - HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, SYSCFG_SWITCH_PC2_CLOSE); - HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, SYSCFG_SWITCH_PC3_CLOSE); - #if MICROPY_HW_USB_HS_ULPI3320 // Make sure UPLI is Not in low-power mode. ulpi_leave_low_power(); diff --git a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h index 7cb3d85d3d..3cae9b25fa 100644 --- a/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_NICLA_VISION/mpconfigboard.h @@ -107,6 +107,13 @@ void NICLAV_board_osc_enable(int enable); // SMPS configuration #define MICROPY_HW_PWR_SMPS_CONFIG (PWR_LDO_SUPPLY) +// Configure the analog switches for dual-pad pins. +#define MICROPY_HW_ANALOG_SWITCH_PA0 (SYSCFG_SWITCH_PA0_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PA1 (SYSCFG_SWITCH_PA1_OPEN) +// PC2_C and PC3_C, which are connected to ULPI NXT and DIR pins. +#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_CLOSE) +#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_CLOSE) + // There is an external 32kHz oscillator #define RTC_ASYNCH_PREDIV (0) #define RTC_SYNCH_PREDIV (0x7fff) diff --git a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h index 349ca9e001..133158c60a 100644 --- a/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h +++ b/ports/stm32/boards/ARDUINO_PORTENTA_H7/mpconfigboard.h @@ -109,6 +109,12 @@ void PORTENTA_board_osc_enable(int enable); // SMPS configuration #define MICROPY_HW_PWR_SMPS_CONFIG (PWR_SMPS_1V8_SUPPLIES_LDO) +// Configure the analog switches for dual-pad pins. +#define MICROPY_HW_ANALOG_SWITCH_PA0 (SYSCFG_SWITCH_PA0_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PA1 (SYSCFG_SWITCH_PA1_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PC2 (SYSCFG_SWITCH_PC2_OPEN) +#define MICROPY_HW_ANALOG_SWITCH_PC3 (SYSCFG_SWITCH_PC3_OPEN) + // There is an external 32kHz oscillator #define RTC_ASYNCH_PREDIV (0) #define RTC_SYNCH_PREDIV (0x7fff) diff --git a/ports/stm32/boards/NUCLEO_WL55/manifest.py b/ports/stm32/boards/NUCLEO_WL55/manifest.py new file mode 100644 index 0000000000..8998166a3e --- /dev/null +++ b/ports/stm32/boards/NUCLEO_WL55/manifest.py @@ -0,0 +1,6 @@ +# Don't include default frozen modules because MCU is tight on flash space. + +# Only install the sync version of the LoRa driver because this board doesn't +# have asyncio by default. +require("lora-sync") +require("lora-stm32wl5") diff --git a/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.mk b/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.mk index 210f3058c1..ced2e7619b 100644 --- a/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.mk +++ b/ports/stm32/boards/NUCLEO_WL55/mpconfigboard.mk @@ -9,5 +9,5 @@ TEXT0_ADDR = 0x08000000 MICROPY_VFS_FAT = 0 MICROPY_VFS_LFS2 = 1 -# Don't include default frozen modules because MCU is tight on flash space -FROZEN_MANIFEST ?= +# Board-specific manifest (doesn't include default modules, adds LoRa driver). +FROZEN_MANIFEST ?= $(BOARD_DIR)/manifest.py diff --git a/ports/stm32/boards/make-pins.py b/ports/stm32/boards/make-pins.py index 31e7bdb0e2..bfa22d7974 100755 --- a/ports/stm32/boards/make-pins.py +++ b/ports/stm32/boards/make-pins.py @@ -49,6 +49,11 @@ PinAf = namedtuple( ], ) +# Only support ADC1, ADC2, ADC3 for now (e.g. cannot support ADC4 & ADC5 on +# STM32G4). +MIN_ADC_UNIT = 1 +MAX_ADC_UNIT = 3 + class Stm32Pin(boardgen.Pin): def __init__(self, cpu_pin_name): @@ -134,8 +139,12 @@ class Stm32Pin(boardgen.Pin): raise boardgen.PinGeneratorError( "Invalid adc '{:s}' for pin '{:s}'".format(adc_name, self.name()) ) - adc_units = [int(x) for x in m.group(1)] - _adc_mode = m.group(2) + adc_units = [int(x) for x in m.group(1) if MIN_ADC_UNIT <= int(x) <= MAX_ADC_UNIT] + adc_mode = m.group(2) + if adc_mode == "INN": + # On H7 we have INN/INP, all other parts use IN only. Only use + # IN or INP channels. + continue adc_channel = int(m.group(3)) # Pick the entry with the most ADC units, e.g. "ADC1_INP16/ADC12_INN1/ADC12_INP0" --> "ADC12_INN1". @@ -247,6 +256,8 @@ class Stm32PinGenerator(boardgen.PinGenerator): ) # Don't include pins that weren't in pins.csv. for pin in self.available_pins(): + if pin._hidden: + continue if adc_unit in pin._adc_units: print( " [{:d}] = {:s},".format(pin._adc_channel, self._cpu_pin_pointer(pin)), diff --git a/ports/stm32/boards/stm32f429_af.csv b/ports/stm32/boards/stm32f429_af.csv index e9cf2880b4..afa3250e11 100644 --- a/ports/stm32/boards/stm32f429_af.csv +++ b/ports/stm32/boards/stm32f429_af.csv @@ -1,170 +1,170 @@ -Port ,Pin ,AF0 ,AF1 ,AF2 ,AF3 ,AF4 ,AF5 ,AF6 ,AF7 ,AF8 ,AF9 ,AF10 ,AF11 ,AF12 ,AF13 ,AF14 ,AF15 ,ADC - , ,SYS ,TIM1/2 ,TIM3/4/5,TIM8/9/10/11,I2C1/2/3 ,SPI1/2/3/4/5/6 ,SPI2/3/SAI1 ,SPI3/USART1/2/3,USART6/UART4/5/7/8,CAN1/2/TIM12/13/14/LCD,OTG2_HS/OTG1_FS,ETH ,FMC/SDIO/OTG2_FS ,DCMI ,LCD ,SYS , -PortA,PA0 , ,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR , , , ,USART2_CTS ,UART4_TX , , ,ETH_MII_CRS , , , ,EVENTOUT, -PortA,PA1 , ,TIM2_CH2 ,TIM5_CH2, , , , ,USART2_RTS ,UART4_RX , , ,ETH_MII_RX_CLK/ETH_RMII_REF_CLK, , , ,EVENTOUT,ADC123_IN1 -PortA,PA2 , ,TIM2_CH3 ,TIM5_CH3,TIM9_CH1 , , , ,USART2_TX , , , ,ETH_MDIO , , , ,EVENTOUT,ADC123_IN2 -PortA,PA3 , ,TIM2_CH4 ,TIM5_CH4,TIM9_CH2 , , , ,USART2_RX , , ,OTG_HS_ULPI_D0 ,ETH_MII_COL , , ,LCD_B5 ,EVENTOUT,ADC123_IN3 -PortA,PA4 , , , , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS ,USART2_CK , , , , ,OTG_HS_SOF ,DCMI_HSYNC ,LCD_VSYNC,EVENTOUT,ADC12_IN4 -PortA,PA5 , ,TIM2_CH1/TIM2_ETR, ,TIM8_CH1N , ,SPI1_SCK , , , , ,OTG_HS_ULPI_CK , , , , ,EVENTOUT,ADC12_IN5 -PortA,PA6 , ,TIM1_BKIN ,TIM3_CH1,TIM8_BKIN , ,SPI1_MISO , , , ,TIM13_CH1 , , , ,DCMI_PIXCLK ,LCD_G2 ,EVENTOUT,ADC12_IN6 -PortA,PA7 , ,TIM1_CH1N ,TIM3_CH2,TIM8_CH1N , ,SPI1_MOSI , , , ,TIM14_CH1 , ,ETH_MII_RX_DV/ETH_RMII_CRS_DV , , , ,EVENTOUT,ADC12_IN7 -PortA,PA8 ,MCO1 ,TIM1_CH1 , , ,I2C3_SCL , , ,USART1_CK , , ,OTG_FS_SOF , , , ,LCD_R6 ,EVENTOUT, -PortA,PA9 , ,TIM1_CH2 , , ,I2C3_SMBA, , ,USART1_TX , , , , , ,DCMI_D0 , ,EVENTOUT, -PortA,PA10, ,TIM1_CH3 , , , , , ,USART1_RX , , ,OTG_FS_ID , , ,DCMI_D1 , ,EVENTOUT, -PortA,PA11, ,TIM1_CH4 , , , , , ,USART1_CTS , ,CAN1_RX ,OTG_FS_DM , , , ,LCD_R4 ,EVENTOUT, -PortA,PA12, ,TIM1_ETR , , , , , ,USART1_RTS , ,CAN1_TX ,OTG_FS_DP , , , ,LCD_R5 ,EVENTOUT, -PortA,PA13,JTMS/SWDIO , , , , , , , , , , , , , , ,EVENTOUT, -PortA,PA14,JTCK/SWCLK , , , , , , , , , , , , , , ,EVENTOUT, -PortA,PA15,JTDI ,TIM2_CH1/TIM2_ETR, , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS , , , , , , , , ,EVENTOUT, -PortB,PB0 , ,TIM1_CH2N ,TIM3_CH3,TIM8_CH2N , , , , , ,LCD_R3 ,OTG_HS_ULPI_D1 ,ETH_MII_RXD2 , , , ,EVENTOUT,ADC12_IN8 -PortB,PB1 , ,TIM1_CH3N ,TIM3_CH4,TIM8_CH3N , , , , , ,LCD_R6 ,OTG_HS_ULPI_D2 ,ETH_MII_RXD3 , , , ,EVENTOUT,ADC12_IN9 -PortB,PB2 , , , , , , , , , , , , , , , ,EVENTOUT, -PortB,PB3 ,JTDO/TRACESWO,TIM2_CH2 , , , ,SPI1_SCK ,SPI3_SCK/I2S3_CK , , , , , , , , ,EVENTOUT, -PortB,PB4 ,NJTRST , ,TIM3_CH1, , ,SPI1_MISO ,SPI3_MISO ,I2S3ext_SD , , , , , , , ,EVENTOUT, -PortB,PB5 , , ,TIM3_CH2, ,I2C1_SMBA,SPI1_MOSI ,SPI3_MOSI/I2S3_SD, , ,CAN2_RX ,OTG_HS_ULPI_D7 ,ETH_PPS_OUT ,FMC_SDCKE1 ,DCMI_D10 , ,EVENTOUT, -PortB,PB6 , , ,TIM4_CH1, ,I2C1_SCL , , ,USART1_TX , ,CAN2_TX , , ,FMC_SDNE1 ,DCMI_D5 , ,EVENTOUT, -PortB,PB7 , , ,TIM4_CH2, ,I2C1_SDA , , ,USART1_RX , , , , ,FMC_NL ,DCMI_VSYNC , ,EVENTOUT, -PortB,PB8 , , ,TIM4_CH3,TIM10_CH1 ,I2C1_SCL , , , , ,CAN1_RX , ,ETH_MII_TXD3 ,SDIO_D4 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, -PortB,PB9 , , ,TIM4_CH4,TIM11_CH1 ,I2C1_SDA ,SPI2_NSS/I2S2_WS , , , ,CAN1_TX , , ,SDIO_D5 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, -PortB,PB10, ,TIM2_CH3 , , ,I2C2_SCL ,SPI2_SCK/I2S2_CK , ,USART3_TX , , ,OTG_HS_ULPI_D3 ,ETH_MII_RX_ER , , ,LCD_G4 ,EVENTOUT, -PortB,PB11, ,TIM2_CH4 , , ,I2C2_SDA , , ,USART3_RX , , ,OTG_HS_ULPI_D4 ,ETH_MII_TX_EN/ETH_RMII_TX_EN , , ,LCD_G5 ,EVENTOUT, -PortB,PB12, ,TIM1_BKIN , , ,I2C2_SMBA,SPI2_NSS/I2S2_WS , ,USART3_CK , ,CAN2_RX ,OTG_HS_ULPI_D5 ,ETH_MII_TXD0/ETH_RMII_TXD0 ,OTG_HS_ID , , ,EVENTOUT, -PortB,PB13, ,TIM1_CH1N , , , ,SPI2_SCK/I2S2_CK , ,USART3_CTS , ,CAN2_TX ,OTG_HS_ULPI_D6 ,ETH_MII_TXD1/ETH_RMII_TXD1 , , , ,EVENTOUT, -PortB,PB14, ,TIM1_CH2N , ,TIM8_CH2N , ,SPI2_MISO ,I2S2ext_SD ,USART3_RTS , ,TIM12_CH1 , , ,OTG_HS_DM , , ,EVENTOUT, -PortB,PB15,RTC_REFIN ,TIM1_CH3N , ,TIM8_CH3N , ,SPI2_MOSI/I2S2_SD, , , ,TIM12_CH2 , , ,OTG_HS_DP , , ,EVENTOUT, -PortC,PC0 , , , , , , , , , , ,OTG_HS_ULPI_STP, ,FMC_SDNWE , , ,EVENTOUT,ADC123_IN10 -PortC,PC1 , , , , , , , , , , , ,ETH_MDC , , , ,EVENTOUT,ADC123_IN11 -PortC,PC2 , , , , , ,SPI2_MISO ,I2S2ext_SD , , , ,OTG_HS_ULPI_DIR,ETH_MII_TXD2 ,FMC_SDNE0 , , ,EVENTOUT,ADC123_IN12 -PortC,PC3 , , , , , ,SPI2_MOSI/I2S2_SD, , , , ,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK ,FMC_SDCKE0 , , ,EVENTOUT,ADC123_IN13 -PortC,PC4 , , , , , , , , , , , ,ETH_MII_RXD0/ETH_RMII_RXD0 , , , ,EVENTOUT,ADC12_IN14 -PortC,PC5 , , , , , , , , , , , ,ETH_MII_RXD1/ETH_RMII_RXD1 , , , ,EVENTOUT,ADC12_IN15 -PortC,PC6 , , ,TIM3_CH1,TIM8_CH1 , ,I2S2_MCK , , ,USART6_TX , , , ,SDIO_D6 ,DCMI_D0 ,LCD_HSYNC,EVENTOUT, -PortC,PC7 , , ,TIM3_CH2,TIM8_CH2 , , ,I2S3_MCK , ,USART6_RX , , , ,SDIO_D7 ,DCMI_D1 ,LCD_G6 ,EVENTOUT, -PortC,PC8 , , ,TIM3_CH3,TIM8_CH3 , , , , ,USART6_CK , , , ,SDIO_D0 ,DCMI_D2 , ,EVENTOUT, -PortC,PC9 ,MCO2 , ,TIM3_CH4,TIM8_CH4 ,I2C3_SDA ,I2S_CKIN , , , , , , ,SDIO_D1 ,DCMI_D3 , ,EVENTOUT, -PortC,PC10, , , , , , ,SPI3_SCK/I2S3_CK ,USART3_TX ,UART4_TX , , , ,SDIO_D2 ,DCMI_D8 ,LCD_R2 ,EVENTOUT, -PortC,PC11, , , , , ,I2S3ext_SD ,SPI3_MISO ,USART3_RX ,UART4_RX , , , ,SDIO_D3 ,DCMI_D4 , ,EVENTOUT, -PortC,PC12, , , , , , ,SPI3_MOSI/I2S3_SD,USART3_CK ,UART5_TX , , , ,SDIO_CK ,DCMI_D9 , ,EVENTOUT, -PortC,PC13, , , , , , , , , , , , , , , ,EVENTOUT, -PortC,PC14, , , , , , , , , , , , , , , ,EVENTOUT, -PortC,PC15, , , , , , , , , , , , , , , ,EVENTOUT, -PortD,PD0 , , , , , , , , , ,CAN1_RX , , ,FMC_D2 , , ,EVENTOUT, -PortD,PD1 , , , , , , , , , ,CAN1_TX , , ,FMC_D3 , , ,EVENTOUT, -PortD,PD2 , , ,TIM3_ETR, , , , , ,UART5_RX , , , ,SDIO_CMD ,DCMI_D11 , ,EVENTOUT, -PortD,PD3 , , , , , ,SPI2_SCK/I2S2_CK , ,USART2_CTS , , , , ,FMC_CLK ,DCMI_D5 ,LCD_G7 ,EVENTOUT, -PortD,PD4 , , , , , , , ,USART2_RTS , , , , ,FMC_NOE , , ,EVENTOUT, -PortD,PD5 , , , , , , , ,USART2_TX , , , , ,FMC_NWE , , ,EVENTOUT, -PortD,PD6 , , , , , ,SPI3_MOSI/I2S3_SD,SAI1_SD_A ,USART2_RX , , , , ,FMC_NWAIT ,DCMI_D10 ,LCD_B2 ,EVENTOUT, -PortD,PD7 , , , , , , , ,USART2_CK , , , , ,FMC_NE1/FMC_NCE2 , , ,EVENTOUT, -PortD,PD8 , , , , , , , ,USART3_TX , , , , ,FMC_D13 , , ,EVENTOUT, -PortD,PD9 , , , , , , , ,USART3_RX , , , , ,FMC_D14 , , ,EVENTOUT, -PortD,PD10, , , , , , , ,USART3_CK , , , , ,FMC_D15 , ,LCD_B3 ,EVENTOUT, -PortD,PD11, , , , , , , ,USART3_CTS , , , , ,FMC_A16 , , ,EVENTOUT, -PortD,PD12, , ,TIM4_CH1, , , , ,USART3_RTS , , , , ,FMC_A17 , , ,EVENTOUT, -PortD,PD13, , ,TIM4_CH2, , , , , , , , , ,FMC_A18 , , ,EVENTOUT, -PortD,PD14, , ,TIM4_CH3, , , , , , , , , ,FMC_D0 , , ,EVENTOUT, -PortD,PD15, , ,TIM4_CH4, , , , , , , , , ,FMC_D1 , , ,EVENTOUT, -PortE,PE0 , , ,TIM4_ETR, , , , , ,UART8_RX , , , ,FMC_NBL0 ,DCMI_D2 , ,EVENTOUT, -PortE,PE1 , , , , , , , , ,UART8_TX , , , ,FMC_NBL1 ,DCMI_D3 , ,EVENTOUT, -PortE,PE2 ,TRACECLK , , , , ,SPI4_SCK ,SAI1_MCLK_A , , , , ,ETH_MII_TXD3 ,FMC_A23 , , ,EVENTOUT, -PortE,PE3 ,TRACED0 , , , , , ,SAI1_SD_B , , , , , ,FMC_A19 , , ,EVENTOUT, -PortE,PE4 ,TRACED1 , , , , ,SPI4_NSS ,SAI1_FS_A , , , , , ,FMC_A20 ,DCMI_D4 ,LCD_B0 ,EVENTOUT, -PortE,PE5 ,TRACED2 , , ,TIM9_CH1 , ,SPI4_MISO ,SAI1_SCK_A , , , , , ,FMC_A21 ,DCMI_D6 ,LCD_G0 ,EVENTOUT, -PortE,PE6 ,TRACED3 , , ,TIM9_CH2 , ,SPI4_MOSI ,SAI1_SD_A , , , , , ,FMC_A22 ,DCMI_D7 ,LCD_G1 ,EVENTOUT, -PortE,PE7 , ,TIM1_ETR , , , , , , ,UART7_RX , , , ,FMC_D4 , , ,EVENTOUT, -PortE,PE8 , ,TIM1_CH1N , , , , , , ,UART7_TX , , , ,FMC_D5 , , ,EVENTOUT, -PortE,PE9 , ,TIM1_CH1 , , , , , , , , , , ,FMC_D6 , , ,EVENTOUT, -PortE,PE10, ,TIM1_CH2N , , , , , , , , , , ,FMC_D7 , , ,EVENTOUT, -PortE,PE11, ,TIM1_CH2 , , , ,SPI4_NSS , , , , , , ,FMC_D8 , ,LCD_G3 ,EVENTOUT, -PortE,PE12, ,TIM1_CH3N , , , ,SPI4_SCK , , , , , , ,FMC_D9 , ,LCD_B4 ,EVENTOUT, -PortE,PE13, ,TIM1_CH3 , , , ,SPI4_MISO , , , , , , ,FMC_D10 , ,LCD_DE ,EVENTOUT, -PortE,PE14, ,TIM1_CH4 , , , ,SPI4_MOSI , , , , , , ,FMC_D11 , ,LCD_CLK ,EVENTOUT, -PortE,PE15, ,TIM1_BKIN , , , , , , , , , , ,FMC_D12 , ,LCD_R7 ,EVENTOUT, -PortF,PF0 , , , , ,I2C2_SDA , , , , , , , ,FMC_A0 , , ,EVENTOUT, -PortF,PF1 , , , , ,I2C2_SCL , , , , , , , ,FMC_A1 , , ,EVENTOUT, -PortF,PF2 , , , , ,I2C2_SMBA, , , , , , , ,FMC_A2 , , ,EVENTOUT, -PortF,PF3 , , , , , , , , , , , , ,FMC_A3 , , ,EVENTOUT,ADC3_IN9 -PortF,PF4 , , , , , , , , , , , , ,FMC_A4 , , ,EVENTOUT,ADC3_IN14 -PortF,PF5 , , , , , , , , , , , , ,FMC_A5 , , ,EVENTOUT,ADC3_IN15 -PortF,PF6 , , , ,TIM10_CH1 , ,SPI5_NSS ,SAI1_SD_B , ,UART7_RX , , , ,FMC_NIORD , , ,EVENTOUT,ADC3_IN4 -PortF,PF7 , , , ,TIM11_CH1 , ,SPI5_SCK ,SAI1_MCLK_B , ,UART7_TX , , , ,FMC_NREG , , ,EVENTOUT,ADC3_IN5 -PortF,PF8 , , , , , ,SPI5_MISO ,SAI1_SCK_B , , ,TIM13_CH1 , , ,FMC_NIOWR , , ,EVENTOUT,ADC3_IN6 -PortF,PF9 , , , , , ,SPI5_MOSI ,SAI1_FS_B , , ,TIM14_CH1 , , ,FMC_CD , , ,EVENTOUT,ADC3_IN7 -PortF,PF10, , , , , , , , , , , , ,FMC_INTR ,DCMI_D11 ,LCD_DE ,EVENTOUT,ADC3_IN8 -PortF,PF11, , , , , ,SPI5_MOSI , , , , , , ,FMC_SDNRAS ,DCMI_D12 , ,EVENTOUT, -PortF,PF12, , , , , , , , , , , , ,FMC_A6 , , ,EVENTOUT, -PortF,PF13, , , , , , , , , , , , ,FMC_A7 , , ,EVENTOUT, -PortF,PF14, , , , , , , , , , , , ,FMC_A8 , , ,EVENTOUT, -PortF,PF15, , , , , , , , , , , , ,FMC_A9 , , ,EVENTOUT, -PortG,PG0 , , , , , , , , , , , , ,FMC_A10 , , ,EVENTOUT, -PortG,PG1 , , , , , , , , , , , , ,FMC_A11 , , ,EVENTOUT, -PortG,PG2 , , , , , , , , , , , , ,FMC_A12 , , ,EVENTOUT, -PortG,PG3 , , , , , , , , , , , , ,FMC_A13 , , ,EVENTOUT, -PortG,PG4 , , , , , , , , , , , , ,FMC_A14/FMC_BA0 , , ,EVENTOUT, -PortG,PG5 , , , , , , , , , , , , ,FMC_A15/FMC_BA1 , , ,EVENTOUT, -PortG,PG6 , , , , , , , , , , , , ,FMC_INT2 ,DCMI_D12 ,LCD_R7 ,EVENTOUT, -PortG,PG7 , , , , , , , , ,USART6_CK , , , ,FMC_INT3 ,DCMI_D13 ,LCD_CLK ,EVENTOUT, -PortG,PG8 , , , , , ,SPI6_NSS , , ,USART6_RTS , , ,ETH_PPS_OUT ,FMC_SDCLK , , ,EVENTOUT, -PortG,PG9 , , , , , , , , ,USART6_RX , , , ,FMC_NE2/FMC_NCE3 ,DCMI_VSYNC(1), ,EVENTOUT, -PortG,PG10, , , , , , , , , ,LCD_G3 , , ,FMC_NCE4_1/FMC_NE3,DCMI_D2 ,LCD_B2 ,EVENTOUT, -PortG,PG11, , , , , , , , , , , ,ETH_MII_TX_EN/ETH_RMII_TX_EN ,FMC_NCE4_2 ,DCMI_D3 ,LCD_B3 ,EVENTOUT, -PortG,PG12, , , , , ,SPI6_MISO , , ,USART6_RTS ,LCD_B4 , , ,FMC_NE4 , ,LCD_B1 ,EVENTOUT, -PortG,PG13, , , , , ,SPI6_SCK , , ,USART6_CTS , , ,ETH_MII_TXD0/ETH_RMII_TXD0 ,FMC_A24 , , ,EVENTOUT, -PortG,PG14, , , , , ,SPI6_MOSI , , ,USART6_TX , , ,ETH_MII_TXD1/ETH_RMII_TXD1 ,FMC_A25 , , ,EVENTOUT, -PortG,PG15, , , , , , , , ,USART6_CTS , , , ,FMC_SDNCAS ,DCMI_D13 , ,EVENTOUT, -PortH,PH0 , , , , , , , , , , , , , , , ,EVENTOUT, -PortH,PH1 , , , , , , , , , , , , , , , ,EVENTOUT, -PortH,PH2 , , , , , , , , , , , ,ETH_MII_CRS ,FMC_SDCKE0 , ,LCD_R0 ,EVENTOUT, -PortH,PH3 , , , , , , , , , , , ,ETH_MII_COL ,FMC_SDNE0 , ,LCD_R1 ,EVENTOUT, -PortH,PH4 , , , , ,I2C2_SCL , , , , , ,OTG_HS_ULPI_NXT, , , , ,EVENTOUT, -PortH,PH5 , , , , ,I2C2_SDA ,SPI5_NSS , , , , , , ,FMC_SDNWE , , ,EVENTOUT, -PortH,PH6 , , , , ,I2C2_SMBA,SPI5_SCK , , , ,TIM12_CH1 , , ,FMC_SDNE1 ,DCMI_D8 , , , -PortH,PH7 , , , , ,I2C3_SCL ,SPI5_MISO , , , , , ,ETH_MII_RXD3 ,FMC_SDCKE1 ,DCMI_D9 , , , -PortH,PH8 , , , , ,I2C3_SDA , , , , , , , ,FMC_D16 ,DCMI_HSYNC ,LCD_R2 ,EVENTOUT, -PortH,PH9 , , , , ,I2C3_SMBA, , , , ,TIM12_CH2 , , ,FMC_D17 ,DCMI_D0 ,LCD_R3 ,EVENTOUT, -PortH,PH10, , ,TIM5_CH1, , , , , , , , , ,FMC_D18 ,DCMI_D1 ,LCD_R4 ,EVENTOUT, -PortH,PH11, , ,TIM5_CH2, , , , , , , , , ,FMC_D19 ,DCMI_D2 ,LCD_R5 ,EVENTOUT, -PortH,PH12, , ,TIM5_CH3, , , , , , , , , ,FMC_D20 ,DCMI_D3 ,LCD_R6 ,EVENTOUT, -PortH,PH13, , , ,TIM8_CH1N , , , , , ,CAN1_TX , , ,FMC_D21 , ,LCD_G2 ,EVENTOUT, -PortH,PH14, , , ,TIM8_CH2N , , , , , , , , ,FMC_D22 ,DCMI_D4 ,LCD_G3 ,EVENTOUT, -PortH,PH15, , , ,TIM8_CH3N , , , , , , , , ,FMC_D23 ,DCMI_D11 ,LCD_G4 ,EVENTOUT, -PortI,PI0 , , ,TIM5_CH4, , ,SPI2_NSS/I2S2_WS , , , , , , ,FMC_D24 ,DCMI_D13 ,LCD_G5 ,EVENTOUT, -PortI,PI1 , , , , , ,SPI2_SCK/I2S2_CK , , , , , , ,FMC_D25 ,DCMI_D8 ,LCD_G6 ,EVENTOUT, -PortI,PI2 , , , ,TIM8_CH4 , ,SPI2_MISO ,I2S2ext_SD , , , , , ,FMC_D26 ,DCMI_D9 ,LCD_G7 ,EVENTOUT, -PortI,PI3 , , , ,TIM8_ETR , ,SPI2_MOSI/I2S2_SD, , , , , , ,FMC_D27 ,DCMI_D10 , ,EVENTOUT, -PortI,PI4 , , , ,TIM8_BKIN , , , , , , , , ,FMC_NBL2 ,DCMI_D5 ,LCD_B4 ,EVENTOUT, -PortI,PI5 , , , ,TIM8_CH1 , , , , , , , , ,FMC_NBL3 ,DCMI_VSYNC ,LCD_B5 ,EVENTOUT, -PortI,PI6 , , , ,TIM8_CH2 , , , , , , , , ,FMC_D28 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, -PortI,PI7 , , , ,TIM8_CH3 , , , , , , , , ,FMC_D29 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, -PortI,PI8 , , , , , , , , , , , , , , , ,EVENTOUT, -PortI,PI9 , , , , , , , , , ,CAN1_RX , , ,FMC_D30 , ,LCD_VSYNC,EVENTOUT, -PortI,PI10, , , , , , , , , , , ,ETH_MII_RX_ER ,FMC_D31 , ,LCD_HSYNC,EVENTOUT, -PortI,PI11, , , , , , , , , , ,OTG_HS_ULPI_DIR, , , , ,EVENTOUT, -PortI,PI12, , , , , , , , , , , , , , ,LCD_HSYNC,EVENTOUT, -PortI,PI13, , , , , , , , , , , , , , ,LCD_VSYNC,EVENTOUT, -PortI,PI14, , , , , , , , , , , , , , ,LCD_CLK ,EVENTOUT, -PortI,PI15, , , , , , , , , , , , , , ,LCD_R0 ,EVENTOUT, -PortJ,PJ0 , , , , , , , , , , , , , , ,LCD_R1 ,EVENTOUT, -PortJ,PJ1 , , , , , , , , , , , , , , ,LCD_R2 ,EVENTOUT, -PortJ,PJ2 , , , , , , , , , , , , , , ,LCD_R3 ,EVENTOUT, -PortJ,PJ3 , , , , , , , , , , , , , , ,LCD_R4 ,EVENTOUT, -PortJ,PJ4 , , , , , , , , , , , , , , ,LCD_R5 ,EVENTOUT, -PortJ,PJ5 , , , , , , , , , , , , , , ,LCD_R6 ,EVENTOUT, -PortJ,PJ6 , , , , , , , , , , , , , , ,LCD_R7 ,EVENTOUT, -PortJ,PJ7 , , , , , , , , , , , , , , ,LCD_G0 ,EVENTOUT, -PortJ,PJ8 , , , , , , , , , , , , , , ,LCD_G1 ,EVENTOUT, -PortJ,PJ9 , , , , , , , , , , , , , , ,LCD_G2 ,EVENTOUT, -PortJ,PJ10, , , , , , , , , , , , , , ,LCD_G3 ,EVENTOUT, -PortJ,PJ11, , , , , , , , , , , , , , ,LCD_G4 ,EVENTOUT, -PortJ,PJ12, , , , , , , , , , , , , , ,LCD_B0 ,EVENTOUT, -PortJ,PJ13, , , , , , , , , , , , , , ,LCD_B1 ,EVENTOUT, -PortJ,PJ14, , , , , , , , , , , , , , ,LCD_B2 ,EVENTOUT, -PortJ,PJ15, , , , , , , , , , , , , , ,LCD_B3 ,EVENTOUT, -PortK,PK0 , , , , , , , , , , , , , , ,LCD_G5 ,EVENTOUT, -PortK,PK1 , , , , , , , , , , , , , , ,LCD_G6 ,EVENTOUT, -PortK,PK2 , , , , , , , , , , , , , , ,LCD_G7 ,EVENTOUT, -PortK,PK3 , , , , , , , , , , , , , , ,LCD_B4 ,EVENTOUT, -PortK,PK4 , , , , , , , , , , , , , , ,LCD_B5 ,EVENTOUT, -PortK,PK5 , , , , , , , , , , , , , , ,LCD_B6 ,EVENTOUT, -PortK,PK6 , , , , , , , , , , , , , , ,LCD_B7 ,EVENTOUT, -PortK,PK7 , , , , , , , , , , , , , , ,LCD_DE ,EVENTOUT, +Port ,Pin ,AF0 ,AF1 ,AF2 ,AF3 ,AF4 ,AF5 ,AF6 ,AF7 ,AF8 ,AF9 ,AF10 ,AF11 ,AF12 ,AF13 ,AF14 ,AF15 ,ADC + , ,SYS ,TIM1/2 ,TIM3/4/5,TIM8/9/10/11,I2C1/2/3 ,SPI1/2/3/4/5/6 ,SPI2/3/SAI1 ,SPI3/USART1/2/3,USART6/UART4/5/7/8,CAN1/2/TIM12/13/14/LCD,OTG2_HS/OTG1_FS,ETH ,FMC/SDIO/OTG2_FS ,DCMI ,LCD ,SYS , +PortA,PA0 , ,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR , , , ,USART2_CTS ,UART4_TX , , ,ETH_MII_CRS , , , ,EVENTOUT, +PortA,PA1 , ,TIM2_CH2 ,TIM5_CH2, , , , ,USART2_RTS ,UART4_RX , , ,ETH_MII_RX_CLK/ETH_RMII_REF_CLK, , , ,EVENTOUT,ADC123_IN1 +PortA,PA2 , ,TIM2_CH3 ,TIM5_CH3,TIM9_CH1 , , , ,USART2_TX , , , ,ETH_MDIO , , , ,EVENTOUT,ADC123_IN2 +PortA,PA3 , ,TIM2_CH4 ,TIM5_CH4,TIM9_CH2 , , , ,USART2_RX , , ,OTG_HS_ULPI_D0 ,ETH_MII_COL , , ,LCD_B5 ,EVENTOUT,ADC123_IN3 +PortA,PA4 , , , , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS ,USART2_CK , , , , ,OTG_HS_SOF ,DCMI_HSYNC ,LCD_VSYNC,EVENTOUT,ADC12_IN4 +PortA,PA5 , ,TIM2_CH1/TIM2_ETR, ,TIM8_CH1N , ,SPI1_SCK , , , , ,OTG_HS_ULPI_CK , , , , ,EVENTOUT,ADC12_IN5 +PortA,PA6 , ,TIM1_BKIN ,TIM3_CH1,TIM8_BKIN , ,SPI1_MISO , , , ,TIM13_CH1 , , , ,DCMI_PIXCLK,LCD_G2 ,EVENTOUT,ADC12_IN6 +PortA,PA7 , ,TIM1_CH1N ,TIM3_CH2,TIM8_CH1N , ,SPI1_MOSI , , , ,TIM14_CH1 , ,ETH_MII_RX_DV/ETH_RMII_CRS_DV , , , ,EVENTOUT,ADC12_IN7 +PortA,PA8 ,MCO1 ,TIM1_CH1 , , ,I2C3_SCL , , ,USART1_CK , , ,OTG_FS_SOF , , , ,LCD_R6 ,EVENTOUT, +PortA,PA9 , ,TIM1_CH2 , , ,I2C3_SMBA, , ,USART1_TX , , , , , ,DCMI_D0 , ,EVENTOUT, +PortA,PA10, ,TIM1_CH3 , , , , , ,USART1_RX , , ,OTG_FS_ID , , ,DCMI_D1 , ,EVENTOUT, +PortA,PA11, ,TIM1_CH4 , , , , , ,USART1_CTS , ,CAN1_RX ,OTG_FS_DM , , , ,LCD_R4 ,EVENTOUT, +PortA,PA12, ,TIM1_ETR , , , , , ,USART1_RTS , ,CAN1_TX ,OTG_FS_DP , , , ,LCD_R5 ,EVENTOUT, +PortA,PA13,JTMS/SWDIO , , , , , , , , , , , , , , ,EVENTOUT, +PortA,PA14,JTCK/SWCLK , , , , , , , , , , , , , , ,EVENTOUT, +PortA,PA15,JTDI ,TIM2_CH1/TIM2_ETR, , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS , , , , , , , , ,EVENTOUT, +PortB,PB0 , ,TIM1_CH2N ,TIM3_CH3,TIM8_CH2N , , , , , ,LCD_R3 ,OTG_HS_ULPI_D1 ,ETH_MII_RXD2 , , , ,EVENTOUT,ADC12_IN8 +PortB,PB1 , ,TIM1_CH3N ,TIM3_CH4,TIM8_CH3N , , , , , ,LCD_R6 ,OTG_HS_ULPI_D2 ,ETH_MII_RXD3 , , , ,EVENTOUT,ADC12_IN9 +PortB,PB2 , , , , , , , , , , , , , , , ,EVENTOUT, +PortB,PB3 ,JTDO/TRACESWO,TIM2_CH2 , , , ,SPI1_SCK ,SPI3_SCK/I2S3_CK , , , , , , , , ,EVENTOUT, +PortB,PB4 ,NJTRST , ,TIM3_CH1, , ,SPI1_MISO ,SPI3_MISO ,I2S3ext_SD , , , , , , , ,EVENTOUT, +PortB,PB5 , , ,TIM3_CH2, ,I2C1_SMBA,SPI1_MOSI ,SPI3_MOSI/I2S3_SD, , ,CAN2_RX ,OTG_HS_ULPI_D7 ,ETH_PPS_OUT ,FMC_SDCKE1 ,DCMI_D10 , ,EVENTOUT, +PortB,PB6 , , ,TIM4_CH1, ,I2C1_SCL , , ,USART1_TX , ,CAN2_TX , , ,FMC_SDNE1 ,DCMI_D5 , ,EVENTOUT, +PortB,PB7 , , ,TIM4_CH2, ,I2C1_SDA , , ,USART1_RX , , , , ,FMC_NL ,DCMI_VSYNC , ,EVENTOUT, +PortB,PB8 , , ,TIM4_CH3,TIM10_CH1 ,I2C1_SCL , , , , ,CAN1_RX , ,ETH_MII_TXD3 ,SDIO_D4 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, +PortB,PB9 , , ,TIM4_CH4,TIM11_CH1 ,I2C1_SDA ,SPI2_NSS/I2S2_WS , , , ,CAN1_TX , , ,SDIO_D5 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, +PortB,PB10, ,TIM2_CH3 , , ,I2C2_SCL ,SPI2_SCK/I2S2_CK , ,USART3_TX , , ,OTG_HS_ULPI_D3 ,ETH_MII_RX_ER , , ,LCD_G4 ,EVENTOUT, +PortB,PB11, ,TIM2_CH4 , , ,I2C2_SDA , , ,USART3_RX , , ,OTG_HS_ULPI_D4 ,ETH_MII_TX_EN/ETH_RMII_TX_EN , , ,LCD_G5 ,EVENTOUT, +PortB,PB12, ,TIM1_BKIN , , ,I2C2_SMBA,SPI2_NSS/I2S2_WS , ,USART3_CK , ,CAN2_RX ,OTG_HS_ULPI_D5 ,ETH_MII_TXD0/ETH_RMII_TXD0 ,OTG_HS_ID , , ,EVENTOUT, +PortB,PB13, ,TIM1_CH1N , , , ,SPI2_SCK/I2S2_CK , ,USART3_CTS , ,CAN2_TX ,OTG_HS_ULPI_D6 ,ETH_MII_TXD1/ETH_RMII_TXD1 , , , ,EVENTOUT, +PortB,PB14, ,TIM1_CH2N , ,TIM8_CH2N , ,SPI2_MISO ,I2S2ext_SD ,USART3_RTS , ,TIM12_CH1 , , ,OTG_HS_DM , , ,EVENTOUT, +PortB,PB15,RTC_REFIN ,TIM1_CH3N , ,TIM8_CH3N , ,SPI2_MOSI/I2S2_SD, , , ,TIM12_CH2 , , ,OTG_HS_DP , , ,EVENTOUT, +PortC,PC0 , , , , , , , , , , ,OTG_HS_ULPI_STP, ,FMC_SDNWE , , ,EVENTOUT,ADC123_IN10 +PortC,PC1 , , , , , , , , , , , ,ETH_MDC , , , ,EVENTOUT,ADC123_IN11 +PortC,PC2 , , , , , ,SPI2_MISO ,I2S2ext_SD , , , ,OTG_HS_ULPI_DIR,ETH_MII_TXD2 ,FMC_SDNE0 , , ,EVENTOUT,ADC123_IN12 +PortC,PC3 , , , , , ,SPI2_MOSI/I2S2_SD, , , , ,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK ,FMC_SDCKE0 , , ,EVENTOUT,ADC123_IN13 +PortC,PC4 , , , , , , , , , , , ,ETH_MII_RXD0/ETH_RMII_RXD0 , , , ,EVENTOUT,ADC12_IN14 +PortC,PC5 , , , , , , , , , , , ,ETH_MII_RXD1/ETH_RMII_RXD1 , , , ,EVENTOUT,ADC12_IN15 +PortC,PC6 , , ,TIM3_CH1,TIM8_CH1 , ,I2S2_MCK , , ,USART6_TX , , , ,SDIO_D6 ,DCMI_D0 ,LCD_HSYNC,EVENTOUT, +PortC,PC7 , , ,TIM3_CH2,TIM8_CH2 , , ,I2S3_MCK , ,USART6_RX , , , ,SDIO_D7 ,DCMI_D1 ,LCD_G6 ,EVENTOUT, +PortC,PC8 , , ,TIM3_CH3,TIM8_CH3 , , , , ,USART6_CK , , , ,SDIO_D0 ,DCMI_D2 , ,EVENTOUT, +PortC,PC9 ,MCO2 , ,TIM3_CH4,TIM8_CH4 ,I2C3_SDA ,I2S_CKIN , , , , , , ,SDIO_D1 ,DCMI_D3 , ,EVENTOUT, +PortC,PC10, , , , , , ,SPI3_SCK/I2S3_CK ,USART3_TX ,UART4_TX , , , ,SDIO_D2 ,DCMI_D8 ,LCD_R2 ,EVENTOUT, +PortC,PC11, , , , , ,I2S3ext_SD ,SPI3_MISO ,USART3_RX ,UART4_RX , , , ,SDIO_D3 ,DCMI_D4 , ,EVENTOUT, +PortC,PC12, , , , , , ,SPI3_MOSI/I2S3_SD,USART3_CK ,UART5_TX , , , ,SDIO_CK ,DCMI_D9 , ,EVENTOUT, +PortC,PC13, , , , , , , , , , , , , , , ,EVENTOUT, +PortC,PC14, , , , , , , , , , , , , , , ,EVENTOUT, +PortC,PC15, , , , , , , , , , , , , , , ,EVENTOUT, +PortD,PD0 , , , , , , , , , ,CAN1_RX , , ,FMC_D2 , , ,EVENTOUT, +PortD,PD1 , , , , , , , , , ,CAN1_TX , , ,FMC_D3 , , ,EVENTOUT, +PortD,PD2 , , ,TIM3_ETR, , , , , ,UART5_RX , , , ,SDIO_CMD ,DCMI_D11 , ,EVENTOUT, +PortD,PD3 , , , , , ,SPI2_SCK/I2S2_CK , ,USART2_CTS , , , , ,FMC_CLK ,DCMI_D5 ,LCD_G7 ,EVENTOUT, +PortD,PD4 , , , , , , , ,USART2_RTS , , , , ,FMC_NOE , , ,EVENTOUT, +PortD,PD5 , , , , , , , ,USART2_TX , , , , ,FMC_NWE , , ,EVENTOUT, +PortD,PD6 , , , , , ,SPI3_MOSI/I2S3_SD,SAI1_SD_A ,USART2_RX , , , , ,FMC_NWAIT ,DCMI_D10 ,LCD_B2 ,EVENTOUT, +PortD,PD7 , , , , , , , ,USART2_CK , , , , ,FMC_NE1/FMC_NCE2 , , ,EVENTOUT, +PortD,PD8 , , , , , , , ,USART3_TX , , , , ,FMC_D13 , , ,EVENTOUT, +PortD,PD9 , , , , , , , ,USART3_RX , , , , ,FMC_D14 , , ,EVENTOUT, +PortD,PD10, , , , , , , ,USART3_CK , , , , ,FMC_D15 , ,LCD_B3 ,EVENTOUT, +PortD,PD11, , , , , , , ,USART3_CTS , , , , ,FMC_A16 , , ,EVENTOUT, +PortD,PD12, , ,TIM4_CH1, , , , ,USART3_RTS , , , , ,FMC_A17 , , ,EVENTOUT, +PortD,PD13, , ,TIM4_CH2, , , , , , , , , ,FMC_A18 , , ,EVENTOUT, +PortD,PD14, , ,TIM4_CH3, , , , , , , , , ,FMC_D0 , , ,EVENTOUT, +PortD,PD15, , ,TIM4_CH4, , , , , , , , , ,FMC_D1 , , ,EVENTOUT, +PortE,PE0 , , ,TIM4_ETR, , , , , ,UART8_RX , , , ,FMC_NBL0 ,DCMI_D2 , ,EVENTOUT, +PortE,PE1 , , , , , , , , ,UART8_TX , , , ,FMC_NBL1 ,DCMI_D3 , ,EVENTOUT, +PortE,PE2 ,TRACECLK , , , , ,SPI4_SCK ,SAI1_MCLK_A , , , , ,ETH_MII_TXD3 ,FMC_A23 , , ,EVENTOUT, +PortE,PE3 ,TRACED0 , , , , , ,SAI1_SD_B , , , , , ,FMC_A19 , , ,EVENTOUT, +PortE,PE4 ,TRACED1 , , , , ,SPI4_NSS ,SAI1_FS_A , , , , , ,FMC_A20 ,DCMI_D4 ,LCD_B0 ,EVENTOUT, +PortE,PE5 ,TRACED2 , , ,TIM9_CH1 , ,SPI4_MISO ,SAI1_SCK_A , , , , , ,FMC_A21 ,DCMI_D6 ,LCD_G0 ,EVENTOUT, +PortE,PE6 ,TRACED3 , , ,TIM9_CH2 , ,SPI4_MOSI ,SAI1_SD_A , , , , , ,FMC_A22 ,DCMI_D7 ,LCD_G1 ,EVENTOUT, +PortE,PE7 , ,TIM1_ETR , , , , , , ,UART7_RX , , , ,FMC_D4 , , ,EVENTOUT, +PortE,PE8 , ,TIM1_CH1N , , , , , , ,UART7_TX , , , ,FMC_D5 , , ,EVENTOUT, +PortE,PE9 , ,TIM1_CH1 , , , , , , , , , , ,FMC_D6 , , ,EVENTOUT, +PortE,PE10, ,TIM1_CH2N , , , , , , , , , , ,FMC_D7 , , ,EVENTOUT, +PortE,PE11, ,TIM1_CH2 , , , ,SPI4_NSS , , , , , , ,FMC_D8 , ,LCD_G3 ,EVENTOUT, +PortE,PE12, ,TIM1_CH3N , , , ,SPI4_SCK , , , , , , ,FMC_D9 , ,LCD_B4 ,EVENTOUT, +PortE,PE13, ,TIM1_CH3 , , , ,SPI4_MISO , , , , , , ,FMC_D10 , ,LCD_DE ,EVENTOUT, +PortE,PE14, ,TIM1_CH4 , , , ,SPI4_MOSI , , , , , , ,FMC_D11 , ,LCD_CLK ,EVENTOUT, +PortE,PE15, ,TIM1_BKIN , , , , , , , , , , ,FMC_D12 , ,LCD_R7 ,EVENTOUT, +PortF,PF0 , , , , ,I2C2_SDA , , , , , , , ,FMC_A0 , , ,EVENTOUT, +PortF,PF1 , , , , ,I2C2_SCL , , , , , , , ,FMC_A1 , , ,EVENTOUT, +PortF,PF2 , , , , ,I2C2_SMBA, , , , , , , ,FMC_A2 , , ,EVENTOUT, +PortF,PF3 , , , , , , , , , , , , ,FMC_A3 , , ,EVENTOUT,ADC3_IN9 +PortF,PF4 , , , , , , , , , , , , ,FMC_A4 , , ,EVENTOUT,ADC3_IN14 +PortF,PF5 , , , , , , , , , , , , ,FMC_A5 , , ,EVENTOUT,ADC3_IN15 +PortF,PF6 , , , ,TIM10_CH1 , ,SPI5_NSS ,SAI1_SD_B , ,UART7_RX , , , ,FMC_NIORD , , ,EVENTOUT,ADC3_IN4 +PortF,PF7 , , , ,TIM11_CH1 , ,SPI5_SCK ,SAI1_MCLK_B , ,UART7_TX , , , ,FMC_NREG , , ,EVENTOUT,ADC3_IN5 +PortF,PF8 , , , , , ,SPI5_MISO ,SAI1_SCK_B , , ,TIM13_CH1 , , ,FMC_NIOWR , , ,EVENTOUT,ADC3_IN6 +PortF,PF9 , , , , , ,SPI5_MOSI ,SAI1_FS_B , , ,TIM14_CH1 , , ,FMC_CD , , ,EVENTOUT,ADC3_IN7 +PortF,PF10, , , , , , , , , , , , ,FMC_INTR ,DCMI_D11 ,LCD_DE ,EVENTOUT,ADC3_IN8 +PortF,PF11, , , , , ,SPI5_MOSI , , , , , , ,FMC_SDNRAS ,DCMI_D12 , ,EVENTOUT, +PortF,PF12, , , , , , , , , , , , ,FMC_A6 , , ,EVENTOUT, +PortF,PF13, , , , , , , , , , , , ,FMC_A7 , , ,EVENTOUT, +PortF,PF14, , , , , , , , , , , , ,FMC_A8 , , ,EVENTOUT, +PortF,PF15, , , , , , , , , , , , ,FMC_A9 , , ,EVENTOUT, +PortG,PG0 , , , , , , , , , , , , ,FMC_A10 , , ,EVENTOUT, +PortG,PG1 , , , , , , , , , , , , ,FMC_A11 , , ,EVENTOUT, +PortG,PG2 , , , , , , , , , , , , ,FMC_A12 , , ,EVENTOUT, +PortG,PG3 , , , , , , , , , , , , ,FMC_A13 , , ,EVENTOUT, +PortG,PG4 , , , , , , , , , , , , ,FMC_A14/FMC_BA0 , , ,EVENTOUT, +PortG,PG5 , , , , , , , , , , , , ,FMC_A15/FMC_BA1 , , ,EVENTOUT, +PortG,PG6 , , , , , , , , , , , , ,FMC_INT2 ,DCMI_D12 ,LCD_R7 ,EVENTOUT, +PortG,PG7 , , , , , , , , ,USART6_CK , , , ,FMC_INT3 ,DCMI_D13 ,LCD_CLK ,EVENTOUT, +PortG,PG8 , , , , , ,SPI6_NSS , , ,USART6_RTS , , ,ETH_PPS_OUT ,FMC_SDCLK , , ,EVENTOUT, +PortG,PG9 , , , , , , , , ,USART6_RX , , , ,FMC_NE2/FMC_NCE3 ,DCMI_VSYNC , ,EVENTOUT, +PortG,PG10, , , , , , , , , ,LCD_G3 , , ,FMC_NCE4_1/FMC_NE3,DCMI_D2 ,LCD_B2 ,EVENTOUT, +PortG,PG11, , , , , , , , , , , ,ETH_MII_TX_EN/ETH_RMII_TX_EN ,FMC_NCE4_2 ,DCMI_D3 ,LCD_B3 ,EVENTOUT, +PortG,PG12, , , , , ,SPI6_MISO , , ,USART6_RTS ,LCD_B4 , , ,FMC_NE4 , ,LCD_B1 ,EVENTOUT, +PortG,PG13, , , , , ,SPI6_SCK , , ,USART6_CTS , , ,ETH_MII_TXD0/ETH_RMII_TXD0 ,FMC_A24 , , ,EVENTOUT, +PortG,PG14, , , , , ,SPI6_MOSI , , ,USART6_TX , , ,ETH_MII_TXD1/ETH_RMII_TXD1 ,FMC_A25 , , ,EVENTOUT, +PortG,PG15, , , , , , , , ,USART6_CTS , , , ,FMC_SDNCAS ,DCMI_D13 , ,EVENTOUT, +PortH,PH0 , , , , , , , , , , , , , , , ,EVENTOUT, +PortH,PH1 , , , , , , , , , , , , , , , ,EVENTOUT, +PortH,PH2 , , , , , , , , , , , ,ETH_MII_CRS ,FMC_SDCKE0 , ,LCD_R0 ,EVENTOUT, +PortH,PH3 , , , , , , , , , , , ,ETH_MII_COL ,FMC_SDNE0 , ,LCD_R1 ,EVENTOUT, +PortH,PH4 , , , , ,I2C2_SCL , , , , , ,OTG_HS_ULPI_NXT, , , , ,EVENTOUT, +PortH,PH5 , , , , ,I2C2_SDA ,SPI5_NSS , , , , , , ,FMC_SDNWE , , ,EVENTOUT, +PortH,PH6 , , , , ,I2C2_SMBA,SPI5_SCK , , , ,TIM12_CH1 , , ,FMC_SDNE1 ,DCMI_D8 , , , +PortH,PH7 , , , , ,I2C3_SCL ,SPI5_MISO , , , , , ,ETH_MII_RXD3 ,FMC_SDCKE1 ,DCMI_D9 , , , +PortH,PH8 , , , , ,I2C3_SDA , , , , , , , ,FMC_D16 ,DCMI_HSYNC ,LCD_R2 ,EVENTOUT, +PortH,PH9 , , , , ,I2C3_SMBA, , , , ,TIM12_CH2 , , ,FMC_D17 ,DCMI_D0 ,LCD_R3 ,EVENTOUT, +PortH,PH10, , ,TIM5_CH1, , , , , , , , , ,FMC_D18 ,DCMI_D1 ,LCD_R4 ,EVENTOUT, +PortH,PH11, , ,TIM5_CH2, , , , , , , , , ,FMC_D19 ,DCMI_D2 ,LCD_R5 ,EVENTOUT, +PortH,PH12, , ,TIM5_CH3, , , , , , , , , ,FMC_D20 ,DCMI_D3 ,LCD_R6 ,EVENTOUT, +PortH,PH13, , , ,TIM8_CH1N , , , , , ,CAN1_TX , , ,FMC_D21 , ,LCD_G2 ,EVENTOUT, +PortH,PH14, , , ,TIM8_CH2N , , , , , , , , ,FMC_D22 ,DCMI_D4 ,LCD_G3 ,EVENTOUT, +PortH,PH15, , , ,TIM8_CH3N , , , , , , , , ,FMC_D23 ,DCMI_D11 ,LCD_G4 ,EVENTOUT, +PortI,PI0 , , ,TIM5_CH4, , ,SPI2_NSS/I2S2_WS , , , , , , ,FMC_D24 ,DCMI_D13 ,LCD_G5 ,EVENTOUT, +PortI,PI1 , , , , , ,SPI2_SCK/I2S2_CK , , , , , , ,FMC_D25 ,DCMI_D8 ,LCD_G6 ,EVENTOUT, +PortI,PI2 , , , ,TIM8_CH4 , ,SPI2_MISO ,I2S2ext_SD , , , , , ,FMC_D26 ,DCMI_D9 ,LCD_G7 ,EVENTOUT, +PortI,PI3 , , , ,TIM8_ETR , ,SPI2_MOSI/I2S2_SD, , , , , , ,FMC_D27 ,DCMI_D10 , ,EVENTOUT, +PortI,PI4 , , , ,TIM8_BKIN , , , , , , , , ,FMC_NBL2 ,DCMI_D5 ,LCD_B4 ,EVENTOUT, +PortI,PI5 , , , ,TIM8_CH1 , , , , , , , , ,FMC_NBL3 ,DCMI_VSYNC ,LCD_B5 ,EVENTOUT, +PortI,PI6 , , , ,TIM8_CH2 , , , , , , , , ,FMC_D28 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, +PortI,PI7 , , , ,TIM8_CH3 , , , , , , , , ,FMC_D29 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, +PortI,PI8 , , , , , , , , , , , , , , , ,EVENTOUT, +PortI,PI9 , , , , , , , , , ,CAN1_RX , , ,FMC_D30 , ,LCD_VSYNC,EVENTOUT, +PortI,PI10, , , , , , , , , , , ,ETH_MII_RX_ER ,FMC_D31 , ,LCD_HSYNC,EVENTOUT, +PortI,PI11, , , , , , , , , , ,OTG_HS_ULPI_DIR, , , , ,EVENTOUT, +PortI,PI12, , , , , , , , , , , , , , ,LCD_HSYNC,EVENTOUT, +PortI,PI13, , , , , , , , , , , , , , ,LCD_VSYNC,EVENTOUT, +PortI,PI14, , , , , , , , , , , , , , ,LCD_CLK ,EVENTOUT, +PortI,PI15, , , , , , , , , , , , , , ,LCD_R0 ,EVENTOUT, +PortJ,PJ0 , , , , , , , , , , , , , , ,LCD_R1 ,EVENTOUT, +PortJ,PJ1 , , , , , , , , , , , , , , ,LCD_R2 ,EVENTOUT, +PortJ,PJ2 , , , , , , , , , , , , , , ,LCD_R3 ,EVENTOUT, +PortJ,PJ3 , , , , , , , , , , , , , , ,LCD_R4 ,EVENTOUT, +PortJ,PJ4 , , , , , , , , , , , , , , ,LCD_R5 ,EVENTOUT, +PortJ,PJ5 , , , , , , , , , , , , , , ,LCD_R6 ,EVENTOUT, +PortJ,PJ6 , , , , , , , , , , , , , , ,LCD_R7 ,EVENTOUT, +PortJ,PJ7 , , , , , , , , , , , , , , ,LCD_G0 ,EVENTOUT, +PortJ,PJ8 , , , , , , , , , , , , , , ,LCD_G1 ,EVENTOUT, +PortJ,PJ9 , , , , , , , , , , , , , , ,LCD_G2 ,EVENTOUT, +PortJ,PJ10, , , , , , , , , , , , , , ,LCD_G3 ,EVENTOUT, +PortJ,PJ11, , , , , , , , , , , , , , ,LCD_G4 ,EVENTOUT, +PortJ,PJ12, , , , , , , , , , , , , , ,LCD_B0 ,EVENTOUT, +PortJ,PJ13, , , , , , , , , , , , , , ,LCD_B1 ,EVENTOUT, +PortJ,PJ14, , , , , , , , , , , , , , ,LCD_B2 ,EVENTOUT, +PortJ,PJ15, , , , , , , , , , , , , , ,LCD_B3 ,EVENTOUT, +PortK,PK0 , , , , , , , , , , , , , , ,LCD_G5 ,EVENTOUT, +PortK,PK1 , , , , , , , , , , , , , , ,LCD_G6 ,EVENTOUT, +PortK,PK2 , , , , , , , , , , , , , , ,LCD_G7 ,EVENTOUT, +PortK,PK3 , , , , , , , , , , , , , , ,LCD_B4 ,EVENTOUT, +PortK,PK4 , , , , , , , , , , , , , , ,LCD_B5 ,EVENTOUT, +PortK,PK5 , , , , , , , , , , , , , , ,LCD_B6 ,EVENTOUT, +PortK,PK6 , , , , , , , , , , , , , , ,LCD_B7 ,EVENTOUT, +PortK,PK7 , , , , , , , , , , , , , , ,LCD_DE ,EVENTOUT, diff --git a/ports/stm32/boards/stm32f439_af.csv b/ports/stm32/boards/stm32f439_af.csv index 94466c6c1a..f7069fb579 100644 --- a/ports/stm32/boards/stm32f439_af.csv +++ b/ports/stm32/boards/stm32f439_af.csv @@ -1,170 +1,170 @@ -Port ,Pin ,AF0 ,AF1 ,AF2 ,AF3 ,AF4 ,AF5 ,AF6 ,AF7 ,AF8 ,AF9 ,AF10 ,AF11 ,AF12 ,AF13 ,AF14 ,AF15 ,ADC - , ,SYS ,TIM1/2 ,TIM3/4/5,TIM8/9/10/11,I2C1/2/3 ,SPI1/2/3/4/5/6 ,SPI2/3/SAI1 ,SPI3/USART1/2/3,USART6/UART4/5/7/8,CAN1/2/TIM12/13/14/LCD,OTG2_HS/OTG1_FS,ETH ,FMC/SDIO/OTG2_FS ,DCMI ,LCD ,SYS , -PortA,PA0 , ,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR , , , ,USART2_CTS ,UART4_TX , , ,ETH_MII_CRS , , , ,EVENTOUT,ADC123_IN0 -PortA,PA1 , ,TIM2_CH2 ,TIM5_CH2, , , , ,USART2_RTS ,UART4_RX , , ,ETH_MII_RX_CLK/ETH_RMII_REF_CLK, , , ,EVENTOUT,ADC123_IN1 -PortA,PA2 , ,TIM2_CH3 ,TIM5_CH3,TIM9_CH1 , , , ,USART2_TX , , , ,ETH_MDIO , , , ,EVENTOUT,ADC123_IN2 -PortA,PA3 , ,TIM2_CH4 ,TIM5_CH4,TIM9_CH2 , , , ,USART2_RX , , ,OTG_HS_ULPI_D0 ,ETH_MII_COL , , ,LCD_B5 ,EVENTOUT,ADC123_IN3 -PortA,PA4 , , , , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS ,USART2_CK , , , , ,OTG_HS_SOF ,DCMI_HSYNC ,LCD_VSYNC,EVENTOUT,ADC12_IN4 -PortA,PA5 , ,TIM2_CH1/TIM2_ETR, ,TIM8_CH1N , ,SPI1_SCK , , , , ,OTG_HS_ULPI_CK , , , , ,EVENTOUT,ADC12_IN5 -PortA,PA6 , ,TIM1_BKIN ,TIM3_CH1,TIM8_BKIN , ,SPI1_MISO , , , ,TIM13_CH1 , , , ,DCMI_PIXCLK ,LCD_G2 ,EVENTOUT,ADC12_IN6 -PortA,PA7 , ,TIM1_CH1N ,TIM3_CH2,TIM8_CH1N , ,SPI1_MOSI , , , ,TIM14_CH1 , ,ETH_MII_RX_DV/ETH_RMII_CRS_DV , , , ,EVENTOUT,ADC12_IN7 -PortA,PA8 ,MCO1 ,TIM1_CH1 , , ,I2C3_SCL , , ,USART1_CK , , ,OTG_FS_SOF , , , ,LCD_R6 ,EVENTOUT, -PortA,PA9 , ,TIM1_CH2 , , ,I2C3_SMBA, , ,USART1_TX , , , , , ,DCMI_D0 , ,EVENTOUT, -PortA,PA10, ,TIM1_CH3 , , , , , ,USART1_RX , , ,OTG_FS_ID , , ,DCMI_D1 , ,EVENTOUT, -PortA,PA11, ,TIM1_CH4 , , , , , ,USART1_CTS , ,CAN1_RX ,OTG_FS_DM , , , ,LCD_R4 ,EVENTOUT, -PortA,PA12, ,TIM1_ETR , , , , , ,USART1_RTS , ,CAN1_TX ,OTG_FS_DP , , , ,LCD_R5 ,EVENTOUT, -PortA,PA13,JTMS/SWDIO , , , , , , , , , , , , , , ,EVENTOUT, -PortA,PA14,JTCK/SWCLK , , , , , , , , , , , , , , ,EVENTOUT, -PortA,PA15,JTDI ,TIM2_CH1/TIM2_ETR, , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS , , , , , , , , ,EVENTOUT, -PortB,PB0 , ,TIM1_CH2N ,TIM3_CH3,TIM8_CH2N , , , , , ,LCD_R3 ,OTG_HS_ULPI_D1 ,ETH_MII_RXD2 , , , ,EVENTOUT,ADC12_IN8 -PortB,PB1 , ,TIM1_CH3N ,TIM3_CH4,TIM8_CH3N , , , , , ,LCD_R6 ,OTG_HS_ULPI_D2 ,ETH_MII_RXD3 , , , ,EVENTOUT,ADC12_IN9 -PortB,PB2 , , , , , , , , , , , , , , , ,EVENTOUT, -PortB,PB3 ,JTDO/TRACESWO,TIM2_CH2 , , , ,SPI1_SCK ,SPI3_SCK/I2S3_CK , , , , , , , , ,EVENTOUT, -PortB,PB4 ,NJTRST , ,TIM3_CH1, , ,SPI1_MISO ,SPI3_MISO ,I2S3ext_SD , , , , , , , ,EVENTOUT, -PortB,PB5 , , ,TIM3_CH2, ,I2C1_SMBA,SPI1_MOSI ,SPI3_MOSI/I2S3_SD, , ,CAN2_RX ,OTG_HS_ULPI_D7 ,ETH_PPS_OUT ,FMC_SDCKE1 ,DCMI_D10 , ,EVENTOUT, -PortB,PB6 , , ,TIM4_CH1, ,I2C1_SCL , , ,USART1_TX , ,CAN2_TX , , ,FMC_SDNE1 ,DCMI_D5 , ,EVENTOUT, -PortB,PB7 , , ,TIM4_CH2, ,I2C1_SDA , , ,USART1_RX , , , , ,FMC_NL ,DCMI_VSYNC , ,EVENTOUT, -PortB,PB8 , , ,TIM4_CH3,TIM10_CH1 ,I2C1_SCL , , , , ,CAN1_RX , ,ETH_MII_TXD3 ,SDIO_D4 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, -PortB,PB9 , , ,TIM4_CH4,TIM11_CH1 ,I2C1_SDA ,SPI2_NSS/I2S2_WS , , , ,CAN1_TX , , ,SDIO_D5 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, -PortB,PB10, ,TIM2_CH3 , , ,I2C2_SCL ,SPI2_SCK/I2S2_CK , ,USART3_TX , , ,OTG_HS_ULPI_D3 ,ETH_MII_RX_ER , , ,LCD_G4 ,EVENTOUT, -PortB,PB11, ,TIM2_CH4 , , ,I2C2_SDA , , ,USART3_RX , , ,OTG_HS_ULPI_D4 ,ETH_MII_TX_EN/ETH_RMII_TX_EN , , ,LCD_G5 ,EVENTOUT, -PortB,PB12, ,TIM1_BKIN , , ,I2C2_SMBA,SPI2_NSS/I2S2_WS , ,USART3_CK , ,CAN2_RX ,OTG_HS_ULPI_D5 ,ETH_MII_TXD0/ETH_RMII_TXD0 ,OTG_HS_ID , , ,EVENTOUT, -PortB,PB13, ,TIM1_CH1N , , , ,SPI2_SCK/I2S2_CK , ,USART3_CTS , ,CAN2_TX ,OTG_HS_ULPI_D6 ,ETH_MII_TXD1/ETH_RMII_TXD1 , , , ,EVENTOUT, -PortB,PB14, ,TIM1_CH2N , ,TIM8_CH2N , ,SPI2_MISO ,I2S2ext_SD ,USART3_RTS , ,TIM12_CH1 , , ,OTG_HS_DM , , ,EVENTOUT, -PortB,PB15,RTC_REFIN ,TIM1_CH3N , ,TIM8_CH3N , ,SPI2_MOSI/I2S2_SD, , , ,TIM12_CH2 , , ,OTG_HS_DP , , ,EVENTOUT, -PortC,PC0 , , , , , , , , , , ,OTG_HS_ULPI_STP, ,FMC_SDNWE , , ,EVENTOUT,ADC123_IN10 -PortC,PC1 , , , , , , , , , , , ,ETH_MDC , , , ,EVENTOUT,ADC123_IN11 -PortC,PC2 , , , , , ,SPI2_MISO ,I2S2ext_SD , , , ,OTG_HS_ULPI_DIR,ETH_MII_TXD2 ,FMC_SDNE0 , , ,EVENTOUT,ADC123_IN12 -PortC,PC3 , , , , , ,SPI2_MOSI/I2S2_SD, , , , ,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK ,FMC_SDCKE0 , , ,EVENTOUT,ADC123_IN13 -PortC,PC4 , , , , , , , , , , , ,ETH_MII_RXD0/ETH_RMII_RXD0 , , , ,EVENTOUT,ADC12_IN14 -PortC,PC5 , , , , , , , , , , , ,ETH_MII_RXD1/ETH_RMII_RXD1 , , , ,EVENTOUT,ADC12_IN15 -PortC,PC6 , , ,TIM3_CH1,TIM8_CH1 , ,I2S2_MCK , , ,USART6_TX , , , ,SDIO_D6 ,DCMI_D0 ,LCD_HSYNC,EVENTOUT, -PortC,PC7 , , ,TIM3_CH2,TIM8_CH2 , , ,I2S3_MCK , ,USART6_RX , , , ,SDIO_D7 ,DCMI_D1 ,LCD_G6 ,EVENTOUT, -PortC,PC8 , , ,TIM3_CH3,TIM8_CH3 , , , , ,USART6_CK , , , ,SDIO_D0 ,DCMI_D2 , ,EVENTOUT, -PortC,PC9 ,MCO2 , ,TIM3_CH4,TIM8_CH4 ,I2C3_SDA ,I2S_CKIN , , , , , , ,SDIO_D1 ,DCMI_D3 , ,EVENTOUT, -PortC,PC10, , , , , , ,SPI3_SCK/I2S3_CK ,USART3_TX ,UART4_TX , , , ,SDIO_D2 ,DCMI_D8 ,LCD_R2 ,EVENTOUT, -PortC,PC11, , , , , ,I2S3ext_SD ,SPI3_MISO ,USART3_RX ,UART4_RX , , , ,SDIO_D3 ,DCMI_D4 , ,EVENTOUT, -PortC,PC12, , , , , , ,SPI3_MOSI/I2S3_SD,USART3_CK ,UART5_TX , , , ,SDIO_CK ,DCMI_D9 , ,EVENTOUT, -PortC,PC13, , , , , , , , , , , , , , , ,EVENTOUT, -PortC,PC14, , , , , , , , , , , , , , , ,EVENTOUT, -PortC,PC15, , , , , , , , , , , , , , , ,EVENTOUT, -PortD,PD0 , , , , , , , , , ,CAN1_RX , , ,FMC_D2 , , ,EVENTOUT, -PortD,PD1 , , , , , , , , , ,CAN1_TX , , ,FMC_D3 , , ,EVENTOUT, -PortD,PD2 , , ,TIM3_ETR, , , , , ,UART5_RX , , , ,SDIO_CMD ,DCMI_D11 , ,EVENTOUT, -PortD,PD3 , , , , , ,SPI2_SCK/I2S2_CK , ,USART2_CTS , , , , ,FMC_CLK ,DCMI_D5 ,LCD_G7 ,EVENTOUT, -PortD,PD4 , , , , , , , ,USART2_RTS , , , , ,FMC_NOE , , ,EVENTOUT, -PortD,PD5 , , , , , , , ,USART2_TX , , , , ,FMC_NWE , , ,EVENTOUT, -PortD,PD6 , , , , , ,I2S3_SD ,SAI1_SD_A ,USART2_RX , , , , ,FMC_NWAIT ,DCMI_D10 ,LCD_B2 ,EVENTOUT, -PortD,PD7 , , , , , , , ,USART2_CK , , , , ,FMC_NE1/FMC_NCE2 , , ,EVENTOUT, -PortD,PD8 , , , , , , , ,USART3_TX , , , , ,FMC_D13 , , ,EVENTOUT, -PortD,PD9 , , , , , , , ,USART3_RX , , , , ,FMC_D14 , , ,EVENTOUT, -PortD,PD10, , , , , , , ,USART3_CK , , , , ,FMC_D15 , ,LCD_B3 ,EVENTOUT, -PortD,PD11, , , , , , , ,USART3_CTS , , , , ,FMC_A16 , , ,EVENTOUT, -PortD,PD12, , ,TIM4_CH1, , , , ,USART3_RTS , , , , ,FMC_A17 , , ,EVENTOUT, -PortD,PD13, , ,TIM4_CH2, , , , , , , , , ,FMC_A18 , , ,EVENTOUT, -PortD,PD14, , ,TIM4_CH3, , , , , , , , , ,FMC_D0 , , ,EVENTOUT, -PortD,PD15, , ,TIM4_CH4, , , , , , , , , ,FMC_D1 , , ,EVENTOUT, -PortE,PE0 , , ,TIM4_ETR, , , , , ,UART8_RX , , , ,FMC_NBL0 ,DCMI_D2 , ,EVENTOUT, -PortE,PE1 , , , , , , , , ,UART8_TX , , , ,FMC_NBL1 ,DCMI_D3 , ,EVENTOUT, -PortE,PE2 ,TRACECLK , , , , ,SPI4_SCK ,SAI1_MCLK_A , , , , ,ETH_MII_TXD3 ,FMC_A23 , , ,EVENTOUT, -PortE,PE3 ,TRACED0 , , , , , ,SAI1_SD_B , , , , , ,FMC_A19 , , ,EVENTOUT, -PortE,PE4 ,TRACED1 , , , , ,SPI4_NSS ,SAI1_FS_A , , , , , ,FMC_A20 ,DCMI_D4 ,LCD_B0 ,EVENTOUT, -PortE,PE5 ,TRACED2 , , ,TIM9_CH1 , ,SPI4_MISO ,SAI1_SCK_A , , , , , ,FMC_A21 ,DCMI_D6 ,LCD_G0 ,EVENTOUT, -PortE,PE6 ,TRACED3 , , ,TIM9_CH2 , ,SPI4_MOSI ,SAI1_SD_A , , , , , ,FMC_A22 ,DCMI_D7 ,LCD_G1 ,EVENTOUT, -PortE,PE7 , ,TIM1_ETR , , , , , , ,UART7_RX , , , ,FMC_D4 , , ,EVENTOUT, -PortE,PE8 , ,TIM1_CH1N , , , , , , ,UART7_TX , , , ,FMC_D5 , , ,EVENTOUT, -PortE,PE9 , ,TIM1_CH1 , , , , , , , , , , ,FMC_D6 , , ,EVENTOUT, -PortE,PE10, ,TIM1_CH2N , , , , , , , , , , ,FMC_D7 , , ,EVENTOUT, -PortE,PE11, ,TIM1_CH2 , , , ,SPI4_NSS ,SPI3_NSS , , , , , ,FMC_D8 , ,LCD_G3 ,EVENTOUT, -PortE,PE12, ,TIM1_CH3N , , , ,SPI4_SCK ,SPI3_SCK , , , , , ,FMC_D9 , ,LCD_B4 ,EVENTOUT, -PortE,PE13, ,TIM1_CH3 , , , ,SPI4_MISO ,SPI3_MISO , , , , , ,FMC_D10 , ,LCD_DE ,EVENTOUT, -PortE,PE14, ,TIM1_CH4 , , , ,SPI4_MOSI ,SP3_MOSI , , , , , ,FMC_D11 , ,LCD_CLK ,EVENTOUT, -PortE,PE15, ,TIM1_BKIN , , , , , , , , , , ,FMC_D12 , ,LCD_R7 ,EVENTOUT, -PortF,PF0 , , , , ,I2C2_SDA , , , , , , , ,FMC_A0 , , ,EVENTOUT, -PortF,PF1 , , , , ,I2C2_SCL , , , , , , , ,FMC_A1 , , ,EVENTOUT, -PortF,PF2 , , , , ,I2C2_SMBA, , , , , , , ,FMC_A2 , , ,EVENTOUT, -PortF,PF3 , , , , , , , , , , , , ,FMC_A3 , , ,EVENTOUT,ADC3_IN9 -PortF,PF4 , , , , , , , , , , , , ,FMC_A4 , , ,EVENTOUT,ADC3_IN14 -PortF,PF5 , , , , , , , , , , , , ,FMC_A5 , , ,EVENTOUT,ADC3_IN15 -PortF,PF6 , , , ,TIM10_CH1 , ,SPI5_NSS ,SAI1_SD_B , ,UART7_RX , , , ,FMC_NIORD , , ,EVENTOUT,ADC3_IN4 -PortF,PF7 , , , ,TIM11_CH1 , ,SPI5_SCK ,SAI1_MCLK_B , ,UART7_TX , , , ,FMC_NREG , , ,EVENTOUT,ADC3_IN5 -PortF,PF8 , , , , , ,SPI5_MISO ,SAI1_SCK_B , , ,TIM13_CH1 , , ,FMC_NIOWR , , ,EVENTOUT,ADC3_IN6 -PortF,PF9 , , , , , ,SPI5_MOSI ,SAI1_FS_B , , ,TIM14_CH1 , , ,FMC_CD , , ,EVENTOUT,ADC3_IN7 -PortF,PF10, , , , , , , , , , , , ,FMC_INTR ,DCMI_D11 ,LCD_DE ,EVENTOUT,ADC3_IN8 -PortF,PF11, , , , , ,SPI5_MOSI , , , , , , ,FMC_SDNRAS ,DCMI_D12 , ,EVENTOUT, -PortF,PF12, , , , , , , , , , , , ,FMC_A6 , , ,EVENTOUT, -PortF,PF13, , , , , , , , , , , , ,FMC_A7 , , ,EVENTOUT, -PortF,PF14, , , , , , , , , , , , ,FMC_A8 , , ,EVENTOUT, -PortF,PF15, , , , , , , , , , , , ,FMC_A9 , , ,EVENTOUT, -PortG,PG0 , , , , , , , , , , , , ,FMC_A10 , , ,EVENTOUT, -PortG,PG1 , , , , , , , , , , , , ,FMC_A11 , , ,EVENTOUT, -PortG,PG2 , , , , , , , , , , , , ,FMC_A12 , , ,EVENTOUT, -PortG,PG3 , , , , , , , , , , , , ,FMC_A13 , , ,EVENTOUT, -PortG,PG4 , , , , , , , , , , , , ,FMC_A14/FMC_BA0 , , ,EVENTOUT, -PortG,PG5 , , , , , , , , , , , , ,FMC_A15/FMC_BA1 , , ,EVENTOUT, -PortG,PG6 , , , , , , , , , , , , ,FMC_INT2 ,DCMI_D12 ,LCD_R7 ,EVENTOUT, -PortG,PG7 , , , , , , , , ,USART6_CK , , , ,FMC_INT3 ,DCMI_D13 ,LCD_CLK ,EVENTOUT, -PortG,PG8 , , , , , ,SPI6_NSS , , ,USART6_RTS , , ,ETH_PPS_OUT ,FMC_SDCLK , , ,EVENTOUT, -PortG,PG9 , , , , , , , , ,USART6_RX , , , ,FMC_NE2/FMC_NCE3 ,DCMI_VSYNC(1), ,EVENTOUT, -PortG,PG10, , , , , , , , , ,LCD_G3 , , ,FMC_NCE4_1/FMC_NE3,DCMI_D2 ,LCD_B2 ,EVENTOUT, -PortG,PG11, , , , , , , , , , , ,ETH_MII_TX_EN/ETH_RMII_TX_EN ,FMC_NCE4_2 ,DCMI_D3 ,LCD_B3 ,EVENTOUT, -PortG,PG12, , , , , ,SPI6_MISO , , ,USART6_RTS ,LCD_B4 , , ,FMC_NE4 , ,LCD_B1 ,EVENTOUT, -PortG,PG13, , , , , ,SPI6_SCK , , ,USART6_CTS , , ,ETH_MII_TXD0/ETH_RMII_TXD0 ,FMC_A24 , , ,EVENTOUT, -PortG,PG14, , , , , ,SPI6_MOSI , , ,USART6_TX , , ,ETH_MII_TXD1/ETH_RMII_TXD1 ,FMC_A25 , , ,EVENTOUT, -PortG,PG15, , , , , , , , ,USART6_CTS , , , ,FMC_SDNCAS ,DCMI_D13 , ,EVENTOUT, -PortH,PH0 , , , , , , , , , , , , , , , ,EVENTOUT, -PortH,PH1 , , , , , , , , , , , , , , , ,EVENTOUT, -PortH,PH2 , , , , , , , , , , , ,ETH_MII_CRS ,FMC_SDCKE0 , ,LCD_R0 ,EVENTOUT, -PortH,PH3 , , , , , , , , , , , ,ETH_MII_COL ,FMC_SDNE0 , ,LCD_R1 ,EVENTOUT, -PortH,PH4 , , , , ,I2C2_SCL , , , , , ,OTG_HS_ULPI_NXT, , , , ,EVENTOUT, -PortH,PH5 , , , , ,I2C2_SDA ,SPI5_NSS , , , , , , ,FMC_SDNWE , , ,EVENTOUT, -PortH,PH6 , , , , ,I2C2_SMBA,SPI5_SCK , , , ,TIM12_CH1 , , ,FMC_SDNE1 ,DCMI_D8 , , , -PortH,PH7 , , , , ,I2C3_SCL ,SPI5_MISO , , , , , ,ETH_MII_RXD3 ,FMC_SDCKE1 ,DCMI_D9 , , , -PortH,PH8 , , , , ,I2C3_SDA , , , , , , , ,FMC_D16 ,DCMI_HSYNC ,LCD_R2 ,EVENTOUT, -PortH,PH9 , , , , ,I2C3_SMBA, , , , ,TIM12_CH2 , , ,FMC_D17 ,DCMI_D0 ,LCD_R3 ,EVENTOUT, -PortH,PH10, , ,TIM5_CH1, , , , , , , , , ,FMC_D18 ,DCMI_D1 ,LCD_R4 ,EVENTOUT, -PortH,PH11, , ,TIM5_CH2, , , , , , , , , ,FMC_D19 ,DCMI_D2 ,LCD_R5 ,EVENTOUT, -PortH,PH12, , ,TIM5_CH3, , , , , , , , , ,FMC_D20 ,DCMI_D3 ,LCD_R6 ,EVENTOUT, -PortH,PH13, , , ,TIM8_CH1N , , , , , ,CAN1_TX , , ,FMC_D21 , ,LCD_G2 ,EVENTOUT, -PortH,PH14, , , ,TIM8_CH2N , , , , , , , , ,FMC_D22 ,DCMI_D4 ,LCD_G3 ,EVENTOUT, -PortH,PH15, , , ,TIM8_CH3N , , , , , , , , ,FMC_D23 ,DCMI_D11 ,LCD_G4 ,EVENTOUT, -PortI,PI0 , , ,TIM5_CH4, , ,SPI2_NSS/I2S2_WS , , , , , , ,FMC_D24 ,DCMI_D13 ,LCD_G5 ,EVENTOUT, -PortI,PI1 , , , , , ,SPI2_SCK/I2S2_CK , , , , , , ,FMC_D25 ,DCMI_D8 ,LCD_G6 ,EVENTOUT, -PortI,PI2 , , , ,TIM8_CH4 , ,SPI2_MISO ,I2S2ext_SD , , , , , ,FMC_D26 ,DCMI_D9 ,LCD_G7 ,EVENTOUT, -PortI,PI3 , , , ,TIM8_ETR , ,SPI2_MOSI/I2S2_SD, , , , , , ,FMC_D27 ,DCMI_D10 , ,EVENTOUT, -PortI,PI4 , , , ,TIM8_BKIN , , , , , , , , ,FMC_NBL2 ,DCMI_D5 ,LCD_B4 ,EVENTOUT, -PortI,PI5 , , , ,TIM8_CH1 , , , , , , , , ,FMC_NBL3 ,DCMI_VSYNC ,LCD_B5 ,EVENTOUT, -PortI,PI6 , , , ,TIM8_CH2 , , , , , , , , ,FMC_D28 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, -PortI,PI7 , , , ,TIM8_CH3 , , , , , , , , ,FMC_D29 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, -PortI,PI8 , , , , , , , , , , , , , , , ,EVENTOUT, -PortI,PI9 , , , , , , , , , ,CAN1_RX , , ,FMC_D30 , ,LCD_VSYNC,EVENTOUT, -PortI,PI10, , , , , , , , , , , ,ETH_MII_RX_ER ,FMC_D31 , ,LCD_HSYNC,EVENTOUT, -PortI,PI11, , , , , , , , , , ,OTG_HS_ULPI_DIR, , , , ,EVENTOUT, -PortI,PI12, , , , , , , , , , , , , , ,LCD_HSYNC,EVENTOUT, -PortI,PI13, , , , , , , , , , , , , , ,LCD_VSYNC,EVENTOUT, -PortI,PI14, , , , , , , , , , , , , , ,LCD_CLK ,EVENTOUT, -PortI,PI15, , , , , , , , , , , , , , ,LCD_R0 ,EVENTOUT, -PortJ,PJ0 , , , , , , , , , , , , , , ,LCD_R1 ,EVENTOUT, -PortJ,PJ1 , , , , , , , , , , , , , , ,LCD_R2 ,EVENTOUT, -PortJ,PJ2 , , , , , , , , , , , , , , ,LCD_R3 ,EVENTOUT, -PortJ,PJ3 , , , , , , , , , , , , , , ,LCD_R4 ,EVENTOUT, -PortJ,PJ4 , , , , , , , , , , , , , , ,LCD_R5 ,EVENTOUT, -PortJ,PJ5 , , , , , , , , , , , , , , ,LCD_R6 ,EVENTOUT, -PortJ,PJ6 , , , , , , , , , , , , , , ,LCD_R7 ,EVENTOUT, -PortJ,PJ7 , , , , , , , , , , , , , , ,LCD_G0 ,EVENTOUT, -PortJ,PJ8 , , , , , , , , , , , , , , ,LCD_G1 ,EVENTOUT, -PortJ,PJ9 , , , , , , , , , , , , , , ,LCD_G2 ,EVENTOUT, -PortJ,PJ10, , , , , , , , , , , , , , ,LCD_G3 ,EVENTOUT, -PortJ,PJ11, , , , , , , , , , , , , , ,LCD_G4 ,EVENTOUT, -PortJ,PJ12, , , , , , , , , , , , , , ,LCD_B0 ,EVENTOUT, -PortJ,PJ13, , , , , , , , , , , , , , ,LCD_B1 ,EVENTOUT, -PortJ,PJ14, , , , , , , , , , , , , , ,LCD_B2 ,EVENTOUT, -PortJ,PJ15, , , , , , , , , , , , , , ,LCD_B3 ,EVENTOUT, -PortK,PK0 , , , , , , , , , , , , , , ,LCD_G5 ,EVENTOUT, -PortK,PK1 , , , , , , , , , , , , , , ,LCD_G6 ,EVENTOUT, -PortK,PK2 , , , , , , , , , , , , , , ,LCD_G7 ,EVENTOUT, -PortK,PK3 , , , , , , , , , , , , , , ,LCD_B4 ,EVENTOUT, -PortK,PK4 , , , , , , , , , , , , , , ,LCD_B5 ,EVENTOUT, -PortK,PK5 , , , , , , , , , , , , , , ,LCD_B6 ,EVENTOUT, -PortK,PK6 , , , , , , , , , , , , , , ,LCD_B7 ,EVENTOUT, -PortK,PK7 , , , , , , , , , , , , , , ,LCD_DE ,EVENTOUT, +Port ,Pin ,AF0 ,AF1 ,AF2 ,AF3 ,AF4 ,AF5 ,AF6 ,AF7 ,AF8 ,AF9 ,AF10 ,AF11 ,AF12 ,AF13 ,AF14 ,AF15 ,ADC + , ,SYS ,TIM1/2 ,TIM3/4/5,TIM8/9/10/11,I2C1/2/3 ,SPI1/2/3/4/5/6 ,SPI2/3/SAI1 ,SPI3/USART1/2/3,USART6/UART4/5/7/8,CAN1/2/TIM12/13/14/LCD,OTG2_HS/OTG1_FS,ETH ,FMC/SDIO/OTG2_FS ,DCMI ,LCD ,SYS , +PortA,PA0 , ,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR , , , ,USART2_CTS ,UART4_TX , , ,ETH_MII_CRS , , , ,EVENTOUT,ADC123_IN0 +PortA,PA1 , ,TIM2_CH2 ,TIM5_CH2, , , , ,USART2_RTS ,UART4_RX , , ,ETH_MII_RX_CLK/ETH_RMII_REF_CLK, , , ,EVENTOUT,ADC123_IN1 +PortA,PA2 , ,TIM2_CH3 ,TIM5_CH3,TIM9_CH1 , , , ,USART2_TX , , , ,ETH_MDIO , , , ,EVENTOUT,ADC123_IN2 +PortA,PA3 , ,TIM2_CH4 ,TIM5_CH4,TIM9_CH2 , , , ,USART2_RX , , ,OTG_HS_ULPI_D0 ,ETH_MII_COL , , ,LCD_B5 ,EVENTOUT,ADC123_IN3 +PortA,PA4 , , , , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS ,USART2_CK , , , , ,OTG_HS_SOF ,DCMI_HSYNC ,LCD_VSYNC,EVENTOUT,ADC12_IN4 +PortA,PA5 , ,TIM2_CH1/TIM2_ETR, ,TIM8_CH1N , ,SPI1_SCK , , , , ,OTG_HS_ULPI_CK , , , , ,EVENTOUT,ADC12_IN5 +PortA,PA6 , ,TIM1_BKIN ,TIM3_CH1,TIM8_BKIN , ,SPI1_MISO , , , ,TIM13_CH1 , , , ,DCMI_PIXCLK,LCD_G2 ,EVENTOUT,ADC12_IN6 +PortA,PA7 , ,TIM1_CH1N ,TIM3_CH2,TIM8_CH1N , ,SPI1_MOSI , , , ,TIM14_CH1 , ,ETH_MII_RX_DV/ETH_RMII_CRS_DV , , , ,EVENTOUT,ADC12_IN7 +PortA,PA8 ,MCO1 ,TIM1_CH1 , , ,I2C3_SCL , , ,USART1_CK , , ,OTG_FS_SOF , , , ,LCD_R6 ,EVENTOUT, +PortA,PA9 , ,TIM1_CH2 , , ,I2C3_SMBA, , ,USART1_TX , , , , , ,DCMI_D0 , ,EVENTOUT, +PortA,PA10, ,TIM1_CH3 , , , , , ,USART1_RX , , ,OTG_FS_ID , , ,DCMI_D1 , ,EVENTOUT, +PortA,PA11, ,TIM1_CH4 , , , , , ,USART1_CTS , ,CAN1_RX ,OTG_FS_DM , , , ,LCD_R4 ,EVENTOUT, +PortA,PA12, ,TIM1_ETR , , , , , ,USART1_RTS , ,CAN1_TX ,OTG_FS_DP , , , ,LCD_R5 ,EVENTOUT, +PortA,PA13,JTMS/SWDIO , , , , , , , , , , , , , , ,EVENTOUT, +PortA,PA14,JTCK/SWCLK , , , , , , , , , , , , , , ,EVENTOUT, +PortA,PA15,JTDI ,TIM2_CH1/TIM2_ETR, , , ,SPI1_NSS ,SPI3_NSS/I2S3_WS , , , , , , , , ,EVENTOUT, +PortB,PB0 , ,TIM1_CH2N ,TIM3_CH3,TIM8_CH2N , , , , , ,LCD_R3 ,OTG_HS_ULPI_D1 ,ETH_MII_RXD2 , , , ,EVENTOUT,ADC12_IN8 +PortB,PB1 , ,TIM1_CH3N ,TIM3_CH4,TIM8_CH3N , , , , , ,LCD_R6 ,OTG_HS_ULPI_D2 ,ETH_MII_RXD3 , , , ,EVENTOUT,ADC12_IN9 +PortB,PB2 , , , , , , , , , , , , , , , ,EVENTOUT, +PortB,PB3 ,JTDO/TRACESWO,TIM2_CH2 , , , ,SPI1_SCK ,SPI3_SCK/I2S3_CK , , , , , , , , ,EVENTOUT, +PortB,PB4 ,NJTRST , ,TIM3_CH1, , ,SPI1_MISO ,SPI3_MISO ,I2S3ext_SD , , , , , , , ,EVENTOUT, +PortB,PB5 , , ,TIM3_CH2, ,I2C1_SMBA,SPI1_MOSI ,SPI3_MOSI/I2S3_SD, , ,CAN2_RX ,OTG_HS_ULPI_D7 ,ETH_PPS_OUT ,FMC_SDCKE1 ,DCMI_D10 , ,EVENTOUT, +PortB,PB6 , , ,TIM4_CH1, ,I2C1_SCL , , ,USART1_TX , ,CAN2_TX , , ,FMC_SDNE1 ,DCMI_D5 , ,EVENTOUT, +PortB,PB7 , , ,TIM4_CH2, ,I2C1_SDA , , ,USART1_RX , , , , ,FMC_NL ,DCMI_VSYNC , ,EVENTOUT, +PortB,PB8 , , ,TIM4_CH3,TIM10_CH1 ,I2C1_SCL , , , , ,CAN1_RX , ,ETH_MII_TXD3 ,SDIO_D4 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, +PortB,PB9 , , ,TIM4_CH4,TIM11_CH1 ,I2C1_SDA ,SPI2_NSS/I2S2_WS , , , ,CAN1_TX , , ,SDIO_D5 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, +PortB,PB10, ,TIM2_CH3 , , ,I2C2_SCL ,SPI2_SCK/I2S2_CK , ,USART3_TX , , ,OTG_HS_ULPI_D3 ,ETH_MII_RX_ER , , ,LCD_G4 ,EVENTOUT, +PortB,PB11, ,TIM2_CH4 , , ,I2C2_SDA , , ,USART3_RX , , ,OTG_HS_ULPI_D4 ,ETH_MII_TX_EN/ETH_RMII_TX_EN , , ,LCD_G5 ,EVENTOUT, +PortB,PB12, ,TIM1_BKIN , , ,I2C2_SMBA,SPI2_NSS/I2S2_WS , ,USART3_CK , ,CAN2_RX ,OTG_HS_ULPI_D5 ,ETH_MII_TXD0/ETH_RMII_TXD0 ,OTG_HS_ID , , ,EVENTOUT, +PortB,PB13, ,TIM1_CH1N , , , ,SPI2_SCK/I2S2_CK , ,USART3_CTS , ,CAN2_TX ,OTG_HS_ULPI_D6 ,ETH_MII_TXD1/ETH_RMII_TXD1 , , , ,EVENTOUT, +PortB,PB14, ,TIM1_CH2N , ,TIM8_CH2N , ,SPI2_MISO ,I2S2ext_SD ,USART3_RTS , ,TIM12_CH1 , , ,OTG_HS_DM , , ,EVENTOUT, +PortB,PB15,RTC_REFIN ,TIM1_CH3N , ,TIM8_CH3N , ,SPI2_MOSI/I2S2_SD, , , ,TIM12_CH2 , , ,OTG_HS_DP , , ,EVENTOUT, +PortC,PC0 , , , , , , , , , , ,OTG_HS_ULPI_STP, ,FMC_SDNWE , , ,EVENTOUT,ADC123_IN10 +PortC,PC1 , , , , , , , , , , , ,ETH_MDC , , , ,EVENTOUT,ADC123_IN11 +PortC,PC2 , , , , , ,SPI2_MISO ,I2S2ext_SD , , , ,OTG_HS_ULPI_DIR,ETH_MII_TXD2 ,FMC_SDNE0 , , ,EVENTOUT,ADC123_IN12 +PortC,PC3 , , , , , ,SPI2_MOSI/I2S2_SD, , , , ,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK ,FMC_SDCKE0 , , ,EVENTOUT,ADC123_IN13 +PortC,PC4 , , , , , , , , , , , ,ETH_MII_RXD0/ETH_RMII_RXD0 , , , ,EVENTOUT,ADC12_IN14 +PortC,PC5 , , , , , , , , , , , ,ETH_MII_RXD1/ETH_RMII_RXD1 , , , ,EVENTOUT,ADC12_IN15 +PortC,PC6 , , ,TIM3_CH1,TIM8_CH1 , ,I2S2_MCK , , ,USART6_TX , , , ,SDIO_D6 ,DCMI_D0 ,LCD_HSYNC,EVENTOUT, +PortC,PC7 , , ,TIM3_CH2,TIM8_CH2 , , ,I2S3_MCK , ,USART6_RX , , , ,SDIO_D7 ,DCMI_D1 ,LCD_G6 ,EVENTOUT, +PortC,PC8 , , ,TIM3_CH3,TIM8_CH3 , , , , ,USART6_CK , , , ,SDIO_D0 ,DCMI_D2 , ,EVENTOUT, +PortC,PC9 ,MCO2 , ,TIM3_CH4,TIM8_CH4 ,I2C3_SDA ,I2S_CKIN , , , , , , ,SDIO_D1 ,DCMI_D3 , ,EVENTOUT, +PortC,PC10, , , , , , ,SPI3_SCK/I2S3_CK ,USART3_TX ,UART4_TX , , , ,SDIO_D2 ,DCMI_D8 ,LCD_R2 ,EVENTOUT, +PortC,PC11, , , , , ,I2S3ext_SD ,SPI3_MISO ,USART3_RX ,UART4_RX , , , ,SDIO_D3 ,DCMI_D4 , ,EVENTOUT, +PortC,PC12, , , , , , ,SPI3_MOSI/I2S3_SD,USART3_CK ,UART5_TX , , , ,SDIO_CK ,DCMI_D9 , ,EVENTOUT, +PortC,PC13, , , , , , , , , , , , , , , ,EVENTOUT, +PortC,PC14, , , , , , , , , , , , , , , ,EVENTOUT, +PortC,PC15, , , , , , , , , , , , , , , ,EVENTOUT, +PortD,PD0 , , , , , , , , , ,CAN1_RX , , ,FMC_D2 , , ,EVENTOUT, +PortD,PD1 , , , , , , , , , ,CAN1_TX , , ,FMC_D3 , , ,EVENTOUT, +PortD,PD2 , , ,TIM3_ETR, , , , , ,UART5_RX , , , ,SDIO_CMD ,DCMI_D11 , ,EVENTOUT, +PortD,PD3 , , , , , ,SPI2_SCK/I2S2_CK , ,USART2_CTS , , , , ,FMC_CLK ,DCMI_D5 ,LCD_G7 ,EVENTOUT, +PortD,PD4 , , , , , , , ,USART2_RTS , , , , ,FMC_NOE , , ,EVENTOUT, +PortD,PD5 , , , , , , , ,USART2_TX , , , , ,FMC_NWE , , ,EVENTOUT, +PortD,PD6 , , , , , ,I2S3_SD ,SAI1_SD_A ,USART2_RX , , , , ,FMC_NWAIT ,DCMI_D10 ,LCD_B2 ,EVENTOUT, +PortD,PD7 , , , , , , , ,USART2_CK , , , , ,FMC_NE1/FMC_NCE2 , , ,EVENTOUT, +PortD,PD8 , , , , , , , ,USART3_TX , , , , ,FMC_D13 , , ,EVENTOUT, +PortD,PD9 , , , , , , , ,USART3_RX , , , , ,FMC_D14 , , ,EVENTOUT, +PortD,PD10, , , , , , , ,USART3_CK , , , , ,FMC_D15 , ,LCD_B3 ,EVENTOUT, +PortD,PD11, , , , , , , ,USART3_CTS , , , , ,FMC_A16 , , ,EVENTOUT, +PortD,PD12, , ,TIM4_CH1, , , , ,USART3_RTS , , , , ,FMC_A17 , , ,EVENTOUT, +PortD,PD13, , ,TIM4_CH2, , , , , , , , , ,FMC_A18 , , ,EVENTOUT, +PortD,PD14, , ,TIM4_CH3, , , , , , , , , ,FMC_D0 , , ,EVENTOUT, +PortD,PD15, , ,TIM4_CH4, , , , , , , , , ,FMC_D1 , , ,EVENTOUT, +PortE,PE0 , , ,TIM4_ETR, , , , , ,UART8_RX , , , ,FMC_NBL0 ,DCMI_D2 , ,EVENTOUT, +PortE,PE1 , , , , , , , , ,UART8_TX , , , ,FMC_NBL1 ,DCMI_D3 , ,EVENTOUT, +PortE,PE2 ,TRACECLK , , , , ,SPI4_SCK ,SAI1_MCLK_A , , , , ,ETH_MII_TXD3 ,FMC_A23 , , ,EVENTOUT, +PortE,PE3 ,TRACED0 , , , , , ,SAI1_SD_B , , , , , ,FMC_A19 , , ,EVENTOUT, +PortE,PE4 ,TRACED1 , , , , ,SPI4_NSS ,SAI1_FS_A , , , , , ,FMC_A20 ,DCMI_D4 ,LCD_B0 ,EVENTOUT, +PortE,PE5 ,TRACED2 , , ,TIM9_CH1 , ,SPI4_MISO ,SAI1_SCK_A , , , , , ,FMC_A21 ,DCMI_D6 ,LCD_G0 ,EVENTOUT, +PortE,PE6 ,TRACED3 , , ,TIM9_CH2 , ,SPI4_MOSI ,SAI1_SD_A , , , , , ,FMC_A22 ,DCMI_D7 ,LCD_G1 ,EVENTOUT, +PortE,PE7 , ,TIM1_ETR , , , , , , ,UART7_RX , , , ,FMC_D4 , , ,EVENTOUT, +PortE,PE8 , ,TIM1_CH1N , , , , , , ,UART7_TX , , , ,FMC_D5 , , ,EVENTOUT, +PortE,PE9 , ,TIM1_CH1 , , , , , , , , , , ,FMC_D6 , , ,EVENTOUT, +PortE,PE10, ,TIM1_CH2N , , , , , , , , , , ,FMC_D7 , , ,EVENTOUT, +PortE,PE11, ,TIM1_CH2 , , , ,SPI4_NSS ,SPI3_NSS , , , , , ,FMC_D8 , ,LCD_G3 ,EVENTOUT, +PortE,PE12, ,TIM1_CH3N , , , ,SPI4_SCK ,SPI3_SCK , , , , , ,FMC_D9 , ,LCD_B4 ,EVENTOUT, +PortE,PE13, ,TIM1_CH3 , , , ,SPI4_MISO ,SPI3_MISO , , , , , ,FMC_D10 , ,LCD_DE ,EVENTOUT, +PortE,PE14, ,TIM1_CH4 , , , ,SPI4_MOSI ,SP3_MOSI , , , , , ,FMC_D11 , ,LCD_CLK ,EVENTOUT, +PortE,PE15, ,TIM1_BKIN , , , , , , , , , , ,FMC_D12 , ,LCD_R7 ,EVENTOUT, +PortF,PF0 , , , , ,I2C2_SDA , , , , , , , ,FMC_A0 , , ,EVENTOUT, +PortF,PF1 , , , , ,I2C2_SCL , , , , , , , ,FMC_A1 , , ,EVENTOUT, +PortF,PF2 , , , , ,I2C2_SMBA, , , , , , , ,FMC_A2 , , ,EVENTOUT, +PortF,PF3 , , , , , , , , , , , , ,FMC_A3 , , ,EVENTOUT,ADC3_IN9 +PortF,PF4 , , , , , , , , , , , , ,FMC_A4 , , ,EVENTOUT,ADC3_IN14 +PortF,PF5 , , , , , , , , , , , , ,FMC_A5 , , ,EVENTOUT,ADC3_IN15 +PortF,PF6 , , , ,TIM10_CH1 , ,SPI5_NSS ,SAI1_SD_B , ,UART7_RX , , , ,FMC_NIORD , , ,EVENTOUT,ADC3_IN4 +PortF,PF7 , , , ,TIM11_CH1 , ,SPI5_SCK ,SAI1_MCLK_B , ,UART7_TX , , , ,FMC_NREG , , ,EVENTOUT,ADC3_IN5 +PortF,PF8 , , , , , ,SPI5_MISO ,SAI1_SCK_B , , ,TIM13_CH1 , , ,FMC_NIOWR , , ,EVENTOUT,ADC3_IN6 +PortF,PF9 , , , , , ,SPI5_MOSI ,SAI1_FS_B , , ,TIM14_CH1 , , ,FMC_CD , , ,EVENTOUT,ADC3_IN7 +PortF,PF10, , , , , , , , , , , , ,FMC_INTR ,DCMI_D11 ,LCD_DE ,EVENTOUT,ADC3_IN8 +PortF,PF11, , , , , ,SPI5_MOSI , , , , , , ,FMC_SDNRAS ,DCMI_D12 , ,EVENTOUT, +PortF,PF12, , , , , , , , , , , , ,FMC_A6 , , ,EVENTOUT, +PortF,PF13, , , , , , , , , , , , ,FMC_A7 , , ,EVENTOUT, +PortF,PF14, , , , , , , , , , , , ,FMC_A8 , , ,EVENTOUT, +PortF,PF15, , , , , , , , , , , , ,FMC_A9 , , ,EVENTOUT, +PortG,PG0 , , , , , , , , , , , , ,FMC_A10 , , ,EVENTOUT, +PortG,PG1 , , , , , , , , , , , , ,FMC_A11 , , ,EVENTOUT, +PortG,PG2 , , , , , , , , , , , , ,FMC_A12 , , ,EVENTOUT, +PortG,PG3 , , , , , , , , , , , , ,FMC_A13 , , ,EVENTOUT, +PortG,PG4 , , , , , , , , , , , , ,FMC_A14/FMC_BA0 , , ,EVENTOUT, +PortG,PG5 , , , , , , , , , , , , ,FMC_A15/FMC_BA1 , , ,EVENTOUT, +PortG,PG6 , , , , , , , , , , , , ,FMC_INT2 ,DCMI_D12 ,LCD_R7 ,EVENTOUT, +PortG,PG7 , , , , , , , , ,USART6_CK , , , ,FMC_INT3 ,DCMI_D13 ,LCD_CLK ,EVENTOUT, +PortG,PG8 , , , , , ,SPI6_NSS , , ,USART6_RTS , , ,ETH_PPS_OUT ,FMC_SDCLK , , ,EVENTOUT, +PortG,PG9 , , , , , , , , ,USART6_RX , , , ,FMC_NE2/FMC_NCE3 ,DCMI_VSYNC , ,EVENTOUT, +PortG,PG10, , , , , , , , , ,LCD_G3 , , ,FMC_NCE4_1/FMC_NE3,DCMI_D2 ,LCD_B2 ,EVENTOUT, +PortG,PG11, , , , , , , , , , , ,ETH_MII_TX_EN/ETH_RMII_TX_EN ,FMC_NCE4_2 ,DCMI_D3 ,LCD_B3 ,EVENTOUT, +PortG,PG12, , , , , ,SPI6_MISO , , ,USART6_RTS ,LCD_B4 , , ,FMC_NE4 , ,LCD_B1 ,EVENTOUT, +PortG,PG13, , , , , ,SPI6_SCK , , ,USART6_CTS , , ,ETH_MII_TXD0/ETH_RMII_TXD0 ,FMC_A24 , , ,EVENTOUT, +PortG,PG14, , , , , ,SPI6_MOSI , , ,USART6_TX , , ,ETH_MII_TXD1/ETH_RMII_TXD1 ,FMC_A25 , , ,EVENTOUT, +PortG,PG15, , , , , , , , ,USART6_CTS , , , ,FMC_SDNCAS ,DCMI_D13 , ,EVENTOUT, +PortH,PH0 , , , , , , , , , , , , , , , ,EVENTOUT, +PortH,PH1 , , , , , , , , , , , , , , , ,EVENTOUT, +PortH,PH2 , , , , , , , , , , , ,ETH_MII_CRS ,FMC_SDCKE0 , ,LCD_R0 ,EVENTOUT, +PortH,PH3 , , , , , , , , , , , ,ETH_MII_COL ,FMC_SDNE0 , ,LCD_R1 ,EVENTOUT, +PortH,PH4 , , , , ,I2C2_SCL , , , , , ,OTG_HS_ULPI_NXT, , , , ,EVENTOUT, +PortH,PH5 , , , , ,I2C2_SDA ,SPI5_NSS , , , , , , ,FMC_SDNWE , , ,EVENTOUT, +PortH,PH6 , , , , ,I2C2_SMBA,SPI5_SCK , , , ,TIM12_CH1 , , ,FMC_SDNE1 ,DCMI_D8 , , , +PortH,PH7 , , , , ,I2C3_SCL ,SPI5_MISO , , , , , ,ETH_MII_RXD3 ,FMC_SDCKE1 ,DCMI_D9 , , , +PortH,PH8 , , , , ,I2C3_SDA , , , , , , , ,FMC_D16 ,DCMI_HSYNC ,LCD_R2 ,EVENTOUT, +PortH,PH9 , , , , ,I2C3_SMBA, , , , ,TIM12_CH2 , , ,FMC_D17 ,DCMI_D0 ,LCD_R3 ,EVENTOUT, +PortH,PH10, , ,TIM5_CH1, , , , , , , , , ,FMC_D18 ,DCMI_D1 ,LCD_R4 ,EVENTOUT, +PortH,PH11, , ,TIM5_CH2, , , , , , , , , ,FMC_D19 ,DCMI_D2 ,LCD_R5 ,EVENTOUT, +PortH,PH12, , ,TIM5_CH3, , , , , , , , , ,FMC_D20 ,DCMI_D3 ,LCD_R6 ,EVENTOUT, +PortH,PH13, , , ,TIM8_CH1N , , , , , ,CAN1_TX , , ,FMC_D21 , ,LCD_G2 ,EVENTOUT, +PortH,PH14, , , ,TIM8_CH2N , , , , , , , , ,FMC_D22 ,DCMI_D4 ,LCD_G3 ,EVENTOUT, +PortH,PH15, , , ,TIM8_CH3N , , , , , , , , ,FMC_D23 ,DCMI_D11 ,LCD_G4 ,EVENTOUT, +PortI,PI0 , , ,TIM5_CH4, , ,SPI2_NSS/I2S2_WS , , , , , , ,FMC_D24 ,DCMI_D13 ,LCD_G5 ,EVENTOUT, +PortI,PI1 , , , , , ,SPI2_SCK/I2S2_CK , , , , , , ,FMC_D25 ,DCMI_D8 ,LCD_G6 ,EVENTOUT, +PortI,PI2 , , , ,TIM8_CH4 , ,SPI2_MISO ,I2S2ext_SD , , , , , ,FMC_D26 ,DCMI_D9 ,LCD_G7 ,EVENTOUT, +PortI,PI3 , , , ,TIM8_ETR , ,SPI2_MOSI/I2S2_SD, , , , , , ,FMC_D27 ,DCMI_D10 , ,EVENTOUT, +PortI,PI4 , , , ,TIM8_BKIN , , , , , , , , ,FMC_NBL2 ,DCMI_D5 ,LCD_B4 ,EVENTOUT, +PortI,PI5 , , , ,TIM8_CH1 , , , , , , , , ,FMC_NBL3 ,DCMI_VSYNC ,LCD_B5 ,EVENTOUT, +PortI,PI6 , , , ,TIM8_CH2 , , , , , , , , ,FMC_D28 ,DCMI_D6 ,LCD_B6 ,EVENTOUT, +PortI,PI7 , , , ,TIM8_CH3 , , , , , , , , ,FMC_D29 ,DCMI_D7 ,LCD_B7 ,EVENTOUT, +PortI,PI8 , , , , , , , , , , , , , , , ,EVENTOUT, +PortI,PI9 , , , , , , , , , ,CAN1_RX , , ,FMC_D30 , ,LCD_VSYNC,EVENTOUT, +PortI,PI10, , , , , , , , , , , ,ETH_MII_RX_ER ,FMC_D31 , ,LCD_HSYNC,EVENTOUT, +PortI,PI11, , , , , , , , , , ,OTG_HS_ULPI_DIR, , , , ,EVENTOUT, +PortI,PI12, , , , , , , , , , , , , , ,LCD_HSYNC,EVENTOUT, +PortI,PI13, , , , , , , , , , , , , , ,LCD_VSYNC,EVENTOUT, +PortI,PI14, , , , , , , , , , , , , , ,LCD_CLK ,EVENTOUT, +PortI,PI15, , , , , , , , , , , , , , ,LCD_R0 ,EVENTOUT, +PortJ,PJ0 , , , , , , , , , , , , , , ,LCD_R1 ,EVENTOUT, +PortJ,PJ1 , , , , , , , , , , , , , , ,LCD_R2 ,EVENTOUT, +PortJ,PJ2 , , , , , , , , , , , , , , ,LCD_R3 ,EVENTOUT, +PortJ,PJ3 , , , , , , , , , , , , , , ,LCD_R4 ,EVENTOUT, +PortJ,PJ4 , , , , , , , , , , , , , , ,LCD_R5 ,EVENTOUT, +PortJ,PJ5 , , , , , , , , , , , , , , ,LCD_R6 ,EVENTOUT, +PortJ,PJ6 , , , , , , , , , , , , , , ,LCD_R7 ,EVENTOUT, +PortJ,PJ7 , , , , , , , , , , , , , , ,LCD_G0 ,EVENTOUT, +PortJ,PJ8 , , , , , , , , , , , , , , ,LCD_G1 ,EVENTOUT, +PortJ,PJ9 , , , , , , , , , , , , , , ,LCD_G2 ,EVENTOUT, +PortJ,PJ10, , , , , , , , , , , , , , ,LCD_G3 ,EVENTOUT, +PortJ,PJ11, , , , , , , , , , , , , , ,LCD_G4 ,EVENTOUT, +PortJ,PJ12, , , , , , , , , , , , , , ,LCD_B0 ,EVENTOUT, +PortJ,PJ13, , , , , , , , , , , , , , ,LCD_B1 ,EVENTOUT, +PortJ,PJ14, , , , , , , , , , , , , , ,LCD_B2 ,EVENTOUT, +PortJ,PJ15, , , , , , , , , , , , , , ,LCD_B3 ,EVENTOUT, +PortK,PK0 , , , , , , , , , , , , , , ,LCD_G5 ,EVENTOUT, +PortK,PK1 , , , , , , , , , , , , , , ,LCD_G6 ,EVENTOUT, +PortK,PK2 , , , , , , , , , , , , , , ,LCD_G7 ,EVENTOUT, +PortK,PK3 , , , , , , , , , , , , , , ,LCD_B4 ,EVENTOUT, +PortK,PK4 , , , , , , , , , , , , , , ,LCD_B5 ,EVENTOUT, +PortK,PK5 , , , , , , , , , , , , , , ,LCD_B6 ,EVENTOUT, +PortK,PK6 , , , , , , , , , , , , , , ,LCD_B7 ,EVENTOUT, +PortK,PK7 , , , , , , , , , , , , , , ,LCD_DE ,EVENTOUT, diff --git a/ports/stm32/boards/stm32g474_af.csv b/ports/stm32/boards/stm32g474_af.csv index 34ab285837..5853f5f900 100644 --- a/ports/stm32/boards/stm32g474_af.csv +++ b/ports/stm32/boards/stm32g474_af.csv @@ -106,4 +106,4 @@ PortG,PG6 , , ,TIM20_BKIN PortG,PG7 , , , ,SAI1_CK1 ,I2C3_SCL , , , ,LPUART1_TX , , , ,FMC_INT ,SAI1_MCLK_A , ,EVENTOUT, PortG,PG8 , , , , ,I2C3_SDA , , , ,LPUART1_RX , , , ,FMC_NE3 , , ,EVENTOUT, PortG,PG9 , , , , , , ,SPI3_SCK ,USART1_TX , , , , ,FMC_NCE/FMC_NE2 , ,TIM15_CH1N ,EVENTOUT, -PortG,PG10,MCO , , , , , , , , , , , , , , , ,EVENTOUT +PortG,PG10,MCO , , , , , , , , , , , , , , ,EVENTOUT, diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index 83327bede0..67fcffb0f1 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -108,6 +108,12 @@ void machine_init(void) { reset_cause = PYB_RESET_DEEPSLEEP; PWR->CR1 |= PWR_CR1_CSBF; } else + #elif defined(STM32H5) + if (PWR->PMSR & PWR_PMSR_STOPF || PWR->PMSR & PWR_PMSR_SBF) { + // came out of standby or stop mode + reset_cause = PYB_RESET_DEEPSLEEP; + PWR->PMCR |= PWR_PMCR_CSSF; + } else #elif defined(STM32H7) if (PWR->CPUCR & PWR_CPUCR_SBF || PWR->CPUCR & PWR_CPUCR_STOPF) { // came out of standby or stop mode diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index 03224f4d8b..1bb66c9781 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -48,6 +48,8 @@ #define POWERCTRL_GET_VOLTAGE_SCALING() PWR_REGULATOR_VOLTAGE_SCALE0 #elif defined(STM32H723xx) #define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling() +#elif defined(STM32H5) +#define POWERCTRL_GET_VOLTAGE_SCALING() LL_PWR_GetRegulVoltageScaling() #else #define POWERCTRL_GET_VOLTAGE_SCALING() \ (((PWR->CSR1 & PWR_CSR1_ACTVOS) && (SYSCFG->PWRCR & SYSCFG_PWRCR_ODEN)) ? \ @@ -797,6 +799,14 @@ void powerctrl_enter_stop_mode(void) { HAL_PWREx_EnableFlashPowerDown(); #endif + #if defined(STM32H5) + // Save RCC CR to re-enable OSCs and PLLs after wake up from low power mode. + uint32_t rcc_cr = RCC->CR; + + // Save the current voltage scaling level to restore after exiting low power mode. + uint32_t vscaling = POWERCTRL_GET_VOLTAGE_SCALING(); + #endif + #if defined(STM32H7) // Save RCC CR to re-enable OSCs and PLLs after wake up from low power mode. uint32_t rcc_cr = RCC->CR; @@ -837,9 +847,9 @@ void powerctrl_enter_stop_mode(void) { while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_HSI48) { } - #else + #else // defined(STM32F0) - #if defined(STM32H7) + #if defined(STM32H5) || defined(STM32H7) // When exiting from Stop or Standby modes, the Run mode voltage scaling is reset to // the default VOS3 value. Restore the voltage scaling to the previous voltage scale. if (vscaling != POWERCTRL_GET_VOLTAGE_SCALING()) { @@ -879,7 +889,7 @@ void powerctrl_enter_stop_mode(void) { while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL1) { } - #else + #else // defined(STM32H5) // enable PLL __HAL_RCC_PLL_ENABLE(); @@ -899,7 +909,7 @@ void powerctrl_enter_stop_mode(void) { } #endif - #endif + #endif // defined(STM32H5) powerctrl_disable_hsi_if_unused(); @@ -912,6 +922,15 @@ void powerctrl_enter_stop_mode(void) { } #endif + #if defined(STM32H5) + if (rcc_cr & RCC_CR_HSI48ON) { + // Enable HSI48. + LL_RCC_HSI48_Enable(); + while (!LL_RCC_HSI48_IsReady()) { + } + } + #endif + #if defined(STM32H7) // Enable HSI if (rcc_cr & RCC_CR_HSION) { diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index c7802a5588..31dae527c1 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -298,6 +298,10 @@ void SystemClock_Config(void) { LL_RCC_SetUSBClockSource(LL_RCC_USB_CLKSOURCE_PLL3Q); #endif + + #ifdef NDEBUG + DBGMCU->CR = 0; + #endif } #elif defined(STM32L0) diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 3b05fb40eb..b209ea8354 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -756,9 +756,11 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // enable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; + #elif defined(STM32H5) + EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; @@ -768,8 +770,10 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { #endif // clear interrupt flags - #if defined(STM32G0) || defined(STM32G4) || defined(STM32H5) || defined(STM32WL) + #if defined(STM32G0) || defined(STM32G4) || defined(STM32WL) RTC->ICSR &= ~RTC_ICSR_WUTWF; + #elif defined(STM32H5) + RTC->SCR = RTC_SCR_CWUTF; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; #else diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index de1897b4a6..2cff36c3a6 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -587,6 +587,20 @@ MP_WEAK void SystemClock_Config(void) { // Enable the Debug Module in low-power modes. DBGMCU->CR |= (DBGMCU_CR_DBG_SLEEPD1 | DBGMCU_CR_DBG_STOPD1 | DBGMCU_CR_DBG_STANDBYD1); #endif + + // Configure the analog switches + #ifdef MICROPY_HW_ANALOG_SWITCH_PA0 + HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PA0, MICROPY_HW_ANALOG_SWITCH_PA0); + #endif + #ifdef MICROPY_HW_ANALOG_SWITCH_PA1 + HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PA1, MICROPY_HW_ANALOG_SWITCH_PA1); + #endif + #ifdef MICROPY_HW_ANALOG_SWITCH_PC2 + HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC2, MICROPY_HW_ANALOG_SWITCH_PC2); + #endif + #ifdef MICROPY_HW_ANALOG_SWITCH_PC3 + HAL_SYSCFG_AnalogSwitchConfig(SYSCFG_SWITCH_PC3, MICROPY_HW_ANALOG_SWITCH_PC3); + #endif } #endif diff --git a/ports/unix/coverage.c b/ports/unix/coverage.c index f3bb3d450f..88dd48bfab 100644 --- a/ports/unix/coverage.c +++ b/ports/unix/coverage.c @@ -545,7 +545,7 @@ STATIC mp_obj_t extra_coverage(void) { fun_bc.context = &context; fun_bc.child_table = NULL; fun_bc.bytecode = (const byte *)"\x01"; // just needed for n_state - mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, mp_obj_t, 1); + mp_code_state_t *code_state = m_new_obj_var(mp_code_state_t, state, mp_obj_t, 1); code_state->fun_bc = &fun_bc; code_state->ip = (const byte *)"\x00"; // just needed for an invalid opcode code_state->sp = &code_state->state[0]; diff --git a/ports/windows/Makefile b/ports/windows/Makefile index 47ce664d7b..2215ce38d1 100644 --- a/ports/windows/Makefile +++ b/ports/windows/Makefile @@ -102,3 +102,9 @@ test: $(BUILD)/$(PROG) $(TOP)/tests/run-tests.py test_full: test $(eval DIRNAME=ports/$(notdir $(CURDIR))) cd $(TOP)/tests && MICROPY_MICROPYTHON=../$(DIRNAME)/$(BUILD)/$(PROG) $(PYTHON) ./run-tests.py --via-mpy $(RUN_TESTS_MPY_CROSS_FLAGS) $(RUN_TESTS_SKIP) -d basics float micropython + +$(BUILD)/$(PROG): $(BUILD)/micropython.res + +$(BUILD)/%.res: %.rc + $(ECHO) "WINDRES $<" + $(Q)$(WINDRES) $< -O coff -o $@ diff --git a/ports/windows/README.md b/ports/windows/README.md index 7b5f92f10a..2b3ed44599 100644 --- a/ports/windows/README.md +++ b/ports/windows/README.md @@ -135,3 +135,13 @@ For more info, see https://www.winehq.org/docs/wineusr-guide/cui-programs . If built without line editing and history capabilities (MICROPY_USE_READLINE=0), the resulting binary can be run using the standard `wine` tool. + + +Generating the icon file +------------------------ +The windows builds use a .ico file for the executable logo. +To generate such file from a .png file use ImageMagick, as was done for the icons in the logo/ directory: + + magick convert vector-logo-2.png -define icon:auto-resize="256,128,96,64,48,32,16" vector-logo-2.ico + +Note that for versions prior to 7.0 the command is `convert` instead of `magick convert`. diff --git a/ports/windows/micropython.rc b/ports/windows/micropython.rc new file mode 100644 index 0000000000..8d92bb0d81 --- /dev/null +++ b/ports/windows/micropython.rc @@ -0,0 +1 @@ +app ICON "../../logo/vector-logo-2.ico" diff --git a/ports/windows/micropython.vcxproj b/ports/windows/micropython.vcxproj index de04975cd4..d5affd9e23 100644 --- a/ports/windows/micropython.vcxproj +++ b/ports/windows/micropython.vcxproj @@ -103,6 +103,9 @@ + + + diff --git a/py/lexer.c b/py/lexer.c index 9587f6b164..5e911a1a23 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -527,14 +527,14 @@ STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) vstr_cut_tail_bytes(&lex->vstr, n_closing); } +// This function returns whether it has crossed a newline or not. +// It therefore always return true if stop_at_newline is true STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) { - bool had_physical_newline = false; while (!is_end(lex)) { if (is_physical_newline(lex)) { if (stop_at_newline && lex->nested_bracket_level == 0) { - break; + return true; } - had_physical_newline = true; next_char(lex); } else if (is_whitespace(lex)) { next_char(lex); @@ -543,16 +543,16 @@ STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) { while (!is_end(lex) && !is_physical_newline(lex)) { next_char(lex); } - // had_physical_newline will be set on next loop + // will return true on next loop } else if (is_char_and(lex, '\\', '\n')) { - // line-continuation, so don't set had_physical_newline + // line-continuation, so don't return true next_char(lex); next_char(lex); } else { break; } } - return had_physical_newline; + return false; } void mp_lexer_to_next(mp_lexer_t *lex) { @@ -577,7 +577,10 @@ void mp_lexer_to_next(mp_lexer_t *lex) { vstr_reset(&lex->vstr); // skip white space and comments - bool had_physical_newline = skip_whitespace(lex, false); + // set the newline tokens at the line and column of the preceding line: + // only advance on the pointer until a new line is crossed, save the + // line and column, and then readvance it + bool had_physical_newline = skip_whitespace(lex, true); // set token source information lex->tok_line = lex->line; @@ -591,7 +594,12 @@ void mp_lexer_to_next(mp_lexer_t *lex) { lex->tok_kind = MP_TOKEN_INDENT; lex->emit_dent -= 1; - } else if (had_physical_newline && lex->nested_bracket_level == 0) { + } else if (had_physical_newline) { + // The cursor is at the end of the previous line, pointing to a + // physical newline. Skip any remaining whitespace, comments, and + // newlines. + skip_whitespace(lex, false); + lex->tok_kind = MP_TOKEN_NEWLINE; size_t num_spaces = lex->column - 1; @@ -862,9 +870,10 @@ mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) { // preload first token mp_lexer_to_next(lex); - // Check that the first token is in the first column. If it's not then we - // convert the token kind to INDENT so that the parser gives a syntax error. - if (lex->tok_column != 1) { + // Check that the first token is in the first column unless it is a + // newline. Otherwise we convert the token kind to INDENT so that + // the parser gives a syntax error. + if (lex->tok_column != 1 && lex->tok_kind != MP_TOKEN_NEWLINE) { lex->tok_kind = MP_TOKEN_INDENT; } diff --git a/py/misc.h b/py/misc.h index 32061a009e..352a9f34c4 100644 --- a/py/misc.h +++ b/py/misc.h @@ -71,26 +71,26 @@ typedef unsigned int uint; #define m_new0(type, num) ((type *)(m_malloc0(sizeof(type) * (num)))) #define m_new_obj(type) (m_new(type, 1)) #define m_new_obj_maybe(type) (m_new_maybe(type, 1)) -#define m_new_obj_var(obj_type, var_type, var_num) ((obj_type *)m_malloc(sizeof(obj_type) + sizeof(var_type) * (var_num))) -#define m_new_obj_var0(obj_type, var_type, var_num) ((obj_type *)m_malloc0(sizeof(obj_type) + sizeof(var_type) * (var_num))) -#define m_new_obj_var_maybe(obj_type, var_type, var_num) ((obj_type *)m_malloc_maybe(sizeof(obj_type) + sizeof(var_type) * (var_num))) +#define m_new_obj_var(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) +#define m_new_obj_var0(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc0(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) +#define m_new_obj_var_maybe(obj_type, var_field, var_type, var_num) ((obj_type *)m_malloc_maybe(offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) #if MICROPY_ENABLE_FINALISER #define m_new_obj_with_finaliser(type) ((type *)(m_malloc_with_finaliser(sizeof(type)))) -#define m_new_obj_var_with_finaliser(type, var_type, var_num) ((type *)m_malloc_with_finaliser(sizeof(type) + sizeof(var_type) * (var_num))) +#define m_new_obj_var_with_finaliser(type, var_field, var_type, var_num) ((type *)m_malloc_with_finaliser(offsetof(type, var_field) + sizeof(var_type) * (var_num))) #else #define m_new_obj_with_finaliser(type) m_new_obj(type) -#define m_new_obj_var_with_finaliser(type, var_type, var_num) m_new_obj_var(type, var_type, var_num) +#define m_new_obj_var_with_finaliser(type, var_field, var_type, var_num) m_new_obj_var(type, var_field, var_type, var_num) #endif #if MICROPY_MALLOC_USES_ALLOCATED_SIZE #define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (old_num), sizeof(type) * (new_num), (allow_move)))) #define m_del(type, ptr, num) m_free(ptr, sizeof(type) * (num)) -#define m_del_var(obj_type, var_type, var_num, ptr) (m_free(ptr, sizeof(obj_type) + sizeof(var_type) * (var_num))) +#define m_del_var(obj_type, var_field, var_type, var_num, ptr) (m_free(ptr, offsetof(obj_type, var_field) + sizeof(var_type) * (var_num))) #else #define m_renew(type, ptr, old_num, new_num) ((type *)(m_realloc((ptr), sizeof(type) * (new_num)))) #define m_renew_maybe(type, ptr, old_num, new_num, allow_move) ((type *)(m_realloc_maybe((ptr), sizeof(type) * (new_num), (allow_move)))) #define m_del(type, ptr, num) ((void)(num), m_free(ptr)) -#define m_del_var(obj_type, var_type, var_num, ptr) ((void)(var_num), m_free(ptr)) +#define m_del_var(obj_type, var_field, var_type, var_num, ptr) ((void)(var_num), m_free(ptr)) #endif #define m_del_obj(type, ptr) (m_del(type, ptr, 1)) diff --git a/py/mkenv.mk b/py/mkenv.mk index d3dddcc32d..b52dafbc9d 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -54,6 +54,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy SIZE = $(CROSS_COMPILE)size STRIP = $(CROSS_COMPILE)strip AR = $(CROSS_COMPILE)ar +WINDRES = $(CROSS_COMPILE)windres MAKE_MANIFEST = $(PYTHON) $(TOP)/tools/makemanifest.py MAKE_FROZEN = $(PYTHON) $(TOP)/tools/make-frozen.py diff --git a/py/modthread.c b/py/modthread.c index e4dcccd259..3a8a1e03ce 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -235,7 +235,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) // check for keyword arguments if (n_args == 2) { // just position arguments - th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len); + th_args = m_new_obj_var(thread_entry_args_t, args, mp_obj_t, pos_args_len); th_args->n_kw = 0; } else { // positional and keyword arguments @@ -243,7 +243,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) mp_raise_TypeError(MP_ERROR_TEXT("expecting a dict for keyword args")); } mp_map_t *map = &((mp_obj_dict_t *)MP_OBJ_TO_PTR(args[2]))->map; - th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used); + th_args = m_new_obj_var(thread_entry_args_t, args, mp_obj_t, pos_args_len + 2 * map->used); th_args->n_kw = map->used; // copy across the keyword arguments for (size_t i = 0, n = pos_args_len; i < map->alloc; ++i) { diff --git a/py/objexcept.c b/py/objexcept.c index a90405c525..a54b81370d 100644 --- a/py/objexcept.c +++ b/py/objexcept.c @@ -221,7 +221,7 @@ mp_obj_t mp_obj_exception_make_new(const mp_obj_type_t *type, size_t n_args, siz o_tuple = (mp_obj_tuple_t *)&mp_const_empty_tuple_obj; } else { // Try to allocate memory for the tuple containing the args - o_tuple = m_new_obj_var_maybe(mp_obj_tuple_t, mp_obj_t, n_args); + o_tuple = m_new_obj_var_maybe(mp_obj_tuple_t, items, mp_obj_t, n_args); #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // If we are called by mp_obj_new_exception_msg_varg then it will have diff --git a/py/objfun.c b/py/objfun.c index 94b33cd5bd..e2136968b6 100644 --- a/py/objfun.c +++ b/py/objfun.c @@ -215,7 +215,7 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args // RuntimeError should be raised instead. So, we use m_new_obj_var_maybe(), // return NULL, then vm.c takes the needed action (either raise // RuntimeError or fallback to stack allocation). - code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); + code_state = m_new_obj_var_maybe(mp_code_state_t, state, byte, state_size); if (!code_state) { return NULL; } @@ -247,10 +247,10 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const // allocate state for locals and stack mp_code_state_t *code_state = NULL; #if MICROPY_ENABLE_PYSTACK - code_state = mp_pystack_alloc(sizeof(mp_code_state_t) + state_size); + code_state = mp_pystack_alloc(offsetof(mp_code_state_t, state) + state_size); #else if (state_size > VM_MAX_STATE_ON_STACK) { - code_state = m_new_obj_var_maybe(mp_code_state_t, byte, state_size); + code_state = m_new_obj_var_maybe(mp_code_state_t, state, byte, state_size); #if MICROPY_DEBUG_VM_STACK_OVERFLOW if (code_state != NULL) { memset(code_state->state, 0, state_size); @@ -258,7 +258,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const #endif } if (code_state == NULL) { - code_state = alloca(sizeof(mp_code_state_t) + state_size); + code_state = alloca(offsetof(mp_code_state_t, state) + state_size); #if MICROPY_DEBUG_VM_STACK_OVERFLOW memset(code_state->state, 0, state_size); #endif @@ -320,7 +320,7 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const #else // free the state if it was allocated on the heap if (state_size != 0) { - m_del_var(mp_code_state_t, byte, state_size, code_state); + m_del_var(mp_code_state_t, state, byte, state_size, code_state); } #endif diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 75e21494b4..e586f08945 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -143,7 +143,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args, } mp_obj_namedtuple_type_t *mp_obj_new_namedtuple_base(size_t n_fields, mp_obj_t *fields) { - mp_obj_namedtuple_type_t *o = m_new_obj_var0(mp_obj_namedtuple_type_t, qstr, n_fields); + mp_obj_namedtuple_type_t *o = m_new_obj_var0(mp_obj_namedtuple_type_t, fields, qstr, n_fields); o->n_fields = n_fields; for (size_t i = 0; i < n_fields; i++) { o->fields[i] = mp_obj_str_get_qstr(fields[i]); diff --git a/py/objtuple.c b/py/objtuple.c index 0318a35db6..969c488ee2 100644 --- a/py/objtuple.c +++ b/py/objtuple.c @@ -264,7 +264,7 @@ void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) { void mp_obj_tuple_del(mp_obj_t self_in) { assert(mp_obj_is_type(self_in, &mp_type_tuple)); mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in); - m_del_var(mp_obj_tuple_t, mp_obj_t, self->len, self); + m_del_var(mp_obj_tuple_t, items, mp_obj_t, self->len, self); } /******************************************************************************/ diff --git a/py/objtype.c b/py/objtype.c index 772f25d744..d21c2a4b5b 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -1155,7 +1155,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // (currently 10, plus 1 for base, plus 1 for base-protocol). // Note: mp_obj_type_t is (2 + 3 + #slots) words, so going from 11 to 12 slots // moves from 4 to 5 gc blocks. - mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, void *, 10 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0)); + mp_obj_type_t *o = m_new_obj_var0(mp_obj_type_t, slots, void *, 10 + (bases_len ? 1 : 0) + (base_protocol ? 1 : 0)); o->base.type = &mp_type_type; o->flags = base_flags; o->name = name; diff --git a/py/qstr.c b/py/qstr.c index 0ae08354a5..dc89013f86 100644 --- a/py/qstr.c +++ b/py/qstr.c @@ -233,6 +233,11 @@ STATIC qstr qstr_add(mp_uint_t hash, mp_uint_t len, const char *q_ptr) { } qstr qstr_find_strn(const char *str, size_t str_len) { + if (str_len == 0) { + // strncmp behaviour is undefined for str==NULL. + return MP_QSTR_; + } + // work out hash of str size_t str_hash = qstr_compute_hash((const byte *)str, str_len); diff --git a/py/stream.h b/py/stream.h index 6b5c85ab15..e6e6f283df 100644 --- a/py/stream.h +++ b/py/stream.h @@ -43,6 +43,7 @@ #define MP_STREAM_GET_DATA_OPTS (8) // Get data/message options #define MP_STREAM_SET_DATA_OPTS (9) // Set data/message options #define MP_STREAM_GET_FILENO (10) // Get fileno of underlying file +#define MP_STREAM_GET_BUFFER_SIZE (11) // Get preferred buffer size for file // These poll ioctl values are compatible with Linux #define MP_STREAM_POLL_RD (0x0001) diff --git a/shared/libc/string0.c b/shared/libc/string0.c index a3b268e441..3909f70ed8 100644 --- a/shared/libc/string0.c +++ b/shared/libc/string0.c @@ -154,7 +154,7 @@ int strcmp(const char *s1, const char *s2) { } int strncmp(const char *s1, const char *s2, size_t n) { - while (*s1 && *s2 && n > 0) { + while (n > 0 && *s1 && *s2) { char c1 = *s1++; // XXX UTF8 get char, next char char c2 = *s2++; // XXX UTF8 get char, next char n--; diff --git a/shared/tinyusb/mp_usbd.c b/shared/tinyusb/mp_usbd.c index ea1de674bc..55af3d4fb4 100644 --- a/shared/tinyusb/mp_usbd.c +++ b/shared/tinyusb/mp_usbd.c @@ -27,17 +27,39 @@ #include #include "py/mpconfig.h" +#include "py/runtime.h" #if MICROPY_HW_ENABLE_USBDEV #ifndef NO_QSTR #include "tusb.h" // TinyUSB is not available when running the string preprocessor +#include "device/dcd.h" #include "device/usbd.h" #include "device/usbd_pvt.h" #endif -void usbd_task(void) { +// TinyUSB task function wrapper, as scheduled from the USB IRQ +static void mp_usbd_task_callback(mp_sched_node_t *node); + +extern void __real_dcd_event_handler(dcd_event_t const *event, bool in_isr); + +void mp_usbd_task(void) { tud_task_ext(0, false); } +// If -Wl,--wrap=dcd_event_handler is passed to the linker, then this wrapper +// will be called and allows MicroPython to schedule the TinyUSB task when +// dcd_event_handler() is called from an ISR. +TU_ATTR_FAST_FUNC void __wrap_dcd_event_handler(dcd_event_t const *event, bool in_isr) { + static mp_sched_node_t usbd_task_node; + + __real_dcd_event_handler(event, in_isr); + mp_sched_schedule_node(&usbd_task_node, mp_usbd_task_callback); +} + +static void mp_usbd_task_callback(mp_sched_node_t *node) { + (void)node; + mp_usbd_task(); +} + #endif diff --git a/shared/tinyusb/mp_usbd.h b/shared/tinyusb/mp_usbd.h index 3a93b929c5..340637c95f 100644 --- a/shared/tinyusb/mp_usbd.h +++ b/shared/tinyusb/mp_usbd.h @@ -29,7 +29,7 @@ #include "py/obj.h" -// Call instead of tud_task() +// Call this to explicitly run the TinyUSB device task. void mp_usbd_task(void); // Function to be implemented in port code. diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp index 3049267c0b..6ec553b8a9 100644 --- a/tests/cmdline/cmd_parsetree.py.exp +++ b/tests/cmdline/cmd_parsetree.py.exp @@ -1,5 +1,5 @@ ---------------- -[ 4] \(rule\|file_input_2\)(1) (n=10) +[ 1] file_input_2(1) (n=10) tok(6) [ 4] \(rule\|for_stmt\)(22) (n=4) id(i) diff --git a/tests/extmod/vfs_userfs.py b/tests/extmod/vfs_userfs.py index 36f1088870..5c487315eb 100644 --- a/tests/extmod/vfs_userfs.py +++ b/tests/extmod/vfs_userfs.py @@ -16,6 +16,8 @@ except (ImportError, AttributeError): class UserFile(io.IOBase): + buffer_size = 16 + def __init__(self, mode, data): assert isinstance(data, bytes) self.is_text = mode.find("b") == -1 @@ -39,7 +41,11 @@ class UserFile(io.IOBase): def ioctl(self, req, arg): print("ioctl", req, arg) - return 0 + if req == 4: # MP_STREAM_CLOSE + return 0 + if req == 11: # MP_STREAM_GET_BUFFER_SIZE + return UserFile.buffer_size + return -1 class UserFS: @@ -70,6 +76,8 @@ user_files = { "/usermod2.py": b"print('in usermod2')", "/usermod3.py": b"syntax error", "/usermod4.mpy": b"syntax error", + "/usermod5.py": b"print('in usermod5')", + "/usermod6.py": b"print('in usermod6')", } os.mount(UserFS(user_files), "/userfs") @@ -93,6 +101,14 @@ try: except ValueError: print("ValueError in usermod4") +# Test an import with largest buffer size +UserFile.buffer_size = 255 +import usermod5 + +# Test an import with over-size buffer size (should be safely limited internally) +UserFile.buffer_size = 1024 +import usermod6 + # unmount and undo path addition os.umount("/userfs") sys.path.pop() diff --git a/tests/extmod/vfs_userfs.py.exp b/tests/extmod/vfs_userfs.py.exp index 05cff0452c..be8011d567 100644 --- a/tests/extmod/vfs_userfs.py.exp +++ b/tests/extmod/vfs_userfs.py.exp @@ -3,21 +3,37 @@ some data in a text file stat /usermod1 stat /usermod1.py open /usermod1.py rb +ioctl 11 0 ioctl 4 0 in usermod1 stat /usermod2 stat /usermod2.py open /usermod2.py rb +ioctl 11 0 ioctl 4 0 in usermod2 stat /usermod3 stat /usermod3.py open /usermod3.py rb +ioctl 11 0 ioctl 4 0 SyntaxError in usermod3 stat /usermod4 stat /usermod4.py stat /usermod4.mpy open /usermod4.mpy rb +ioctl 11 0 ioctl 4 0 ValueError in usermod4 +stat /usermod5 +stat /usermod5.py +open /usermod5.py rb +ioctl 11 0 +ioctl 4 0 +in usermod5 +stat /usermod6 +stat /usermod6.py +open /usermod6.py rb +ioctl 11 0 +ioctl 4 0 +in usermod6 diff --git a/tools/mpremote/mpremote/transport_serial.py b/tools/mpremote/mpremote/transport_serial.py index 23a379d16b..3b4cd00078 100644 --- a/tools/mpremote/mpremote/transport_serial.py +++ b/tools/mpremote/mpremote/transport_serial.py @@ -753,6 +753,13 @@ class RemoteFile(io.IOBase): machine.mem32[arg] = self.seek(machine.mem32[arg], machine.mem32[arg + 4]) elif request == 4: # CLOSE self.close() + elif request == 11: # BUFFER_SIZE + # This is used as the vfs_reader buffer. n + 4 should be less than 255 to + # fit in stdin ringbuffer on supported ports. n + 7 should be multiple of 16 + # to efficiently use gc blocks in mp_reader_vfs_t. + return 249 + else: + return -1 return 0 def flush(self): diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index 7f6c86243b..8178b56020 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -32,6 +32,12 @@ def script_to_map(test_file): return r +def load_profile(profile_file, test_dirs, exclude_tests): + profile_globals = {"test_dirs": test_dirs, "exclude_tests": exclude_tests} + exec(profile_file.read(), profile_globals) + return profile_globals["test_dirs"], profile_globals["exclude_tests"] + + test_function = ( "void {name}(void* data) {{\n" " static const char pystr[] = {script};\n" @@ -50,58 +56,55 @@ testgroup_struct = "struct testgroup_t groups[] = {{\n{body}\n END_OF_GROUPS\n} testgroup_member = ' {{ "{name}", {name}_tests }},' ## XXX: may be we could have `--without ` argument... -# currently these tests are selected because they pass on qemu-arm -test_dirs = ( - "basics", - "micropython", - "misc", - "extmod", - "float", - "inlineasm", - "qemu-arm", -) # 'import', 'io',) -exclude_tests = ( - # pattern matching in .exp - "basics/bytes_compare3.py", - "extmod/ticks_diff.py", - "extmod/time_ms_us.py", - # unicode char issue - "extmod/json_loads.py", - # doesn't output to python stdout - "extmod/re_debug.py", - "extmod/vfs_basic.py", - "extmod/vfs_fat_ramdisk.py", - "extmod/vfs_fat_fileio.py", - "extmod/vfs_fat_fsusermount.py", - "extmod/vfs_fat_oldproto.py", - # rounding issues - "float/float_divmod.py", - # requires double precision floating point to work - "float/float2int_doubleprec_intbig.py", - "float/float_format_ints_doubleprec.py", - "float/float_parse_doubleprec.py", - # inline asm FP tests (require Cortex-M4) - "inlineasm/asmfpaddsub.py", - "inlineasm/asmfpcmp.py", - "inlineasm/asmfpldrstr.py", - "inlineasm/asmfpmuldiv.py", - "inlineasm/asmfpsqrt.py", - # different filename in output - "micropython/emg_exc.py", - "micropython/heapalloc_traceback.py", - # don't have emergency exception buffer - "micropython/heapalloc_exc_compressed_emg_exc.py", - # pattern matching in .exp - "micropython/meminfo.py", - # needs sys stdfiles - "misc/print_exception.py", - # settrace .exp files are too large - "misc/sys_settrace_loop.py", - "misc/sys_settrace_generator.py", - "misc/sys_settrace_features.py", - # don't have f-string - "basics/string_fstring.py", - "basics/string_fstring_debug.py", + +test_dirs = set( + ( + "basics", + "extmod", + "float", + "micropython", + "misc", + ) +) + +exclude_tests = set( + ( + # pattern matching in .exp + "basics/bytes_compare3.py", + "extmod/ticks_diff.py", + "extmod/time_ms_us.py", + # unicode char issue + "extmod/json_loads.py", + # doesn't output to python stdout + "extmod/re_debug.py", + "extmod/vfs_basic.py", + "extmod/vfs_fat_ramdisk.py", + "extmod/vfs_fat_fileio.py", + "extmod/vfs_fat_fsusermount.py", + "extmod/vfs_fat_oldproto.py", + # rounding issues + "float/float_divmod.py", + # requires double precision floating point to work + "float/float2int_doubleprec_intbig.py", + "float/float_format_ints_doubleprec.py", + "float/float_parse_doubleprec.py", + # different filename in output + "micropython/emg_exc.py", + "micropython/heapalloc_traceback.py", + # don't have emergency exception buffer + "micropython/heapalloc_exc_compressed_emg_exc.py", + # pattern matching in .exp + "micropython/meminfo.py", + # needs sys stdfiles + "misc/print_exception.py", + # settrace .exp files are too large + "misc/sys_settrace_loop.py", + "misc/sys_settrace_generator.py", + "misc/sys_settrace_features.py", + # don't have f-string + "basics/string_fstring.py", + "basics/string_fstring_debug.py", + ) ) output = [] @@ -112,11 +115,18 @@ argparser = argparse.ArgumentParser( ) argparser.add_argument("--stdin", action="store_true", help="read list of tests from stdin") argparser.add_argument("--exclude", action="append", help="exclude test by name") +argparser.add_argument( + "--profile", + type=argparse.FileType("rt", encoding="utf-8"), + help="optional profile file providing test directories and exclusion list", +) args = argparser.parse_args() if not args.stdin: + if args.profile: + test_dirs, exclude_tests = load_profile(args.profile, test_dirs, exclude_tests) if args.exclude: - exclude_tests += tuple(args.exclude) + exclude_tests = exclude_tests.union(args.exclude) for group in test_dirs: tests += [test for test in glob("{}/*.py".format(group)) if test not in exclude_tests] else: