summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2020-08-02 11:36:38 -0400
committerDan Halbert <halbert@halwitz.org>2020-08-02 11:36:38 -0400
commit0a60aee3e4270d1da42d67f933578d60d56b8b52 (patch)
tree43beede01b4f2d94863f979365c08db64c6be882 /ports
parenta76ad3415c6aeae7bb9c915f20220d32001e8094 (diff)
parente7a78e08479e412dda16076986924e3b8cb19b75 (diff)
wip: compiles
Diffstat (limited to 'ports')
-rw-r--r--ports/atmel-samd/Makefile26
-rw-r--r--ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h24
-rw-r--r--ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h164
-rw-r--r--ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h24
-rw-r--r--ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h164
-rw-r--r--ports/atmel-samd/audio_dma.c54
-rw-r--r--ports/atmel-samd/audio_dma.h2
-rw-r--r--ports/atmel-samd/background.c64
-rw-r--r--ports/atmel-samd/background.h5
-rw-r--r--ports/atmel-samd/bindings/samd/Clock.c9
-rw-r--r--ports/atmel-samd/boards/8086_commander/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/blm_badge/board.c39
-rw-r--r--ports/atmel-samd/boards/blm_badge/mpconfigboard.h37
-rw-r--r--ports/atmel-samd/boards/blm_badge/mpconfigboard.mk24
-rw-r--r--ports/atmel-samd/boards/blm_badge/pins.c43
-rwxr-xr-xports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk1
-rwxr-xr-xports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/fluff_m0/pins.c5
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk10
-rw-r--r--ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/grandcentral_m4_express/pins.c17
-rw-r--r--ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk4
-rw-r--r--ports/atmel-samd/boards/loc_ber_m4_base_board/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/ndgarage_ndbit6_v2/board.c39
-rw-r--r--ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.h22
-rw-r--r--ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk14
-rw-r--r--ports/atmel-samd/boards/ndgarage_ndbit6_v2/pins.c36
-rw-r--r--ports/atmel-samd/boards/openbook_m4/board.c10
-rw-r--r--ports/atmel-samd/boards/openbook_m4/pins.c4
-rw-r--r--ports/atmel-samd/boards/pewpew10/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h2
-rw-r--r--ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk25
-rw-r--r--ports/atmel-samd/boards/pyruler/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/same54_xplained/pins.c17
-rw-r--r--ports/atmel-samd/boards/seeeduino_wio_terminal/board.c116
-rw-r--r--ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.h32
-rw-r--r--ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk14
-rw-r--r--ports/atmel-samd/boards/seeeduino_wio_terminal/pins.c93
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk6
-rw-r--r--ports/atmel-samd/boards/uchip/mpconfigboard.mk5
-rw-r--r--ports/atmel-samd/boards/ugame10/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk5
-rw-r--r--ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/bhb.c120
-rw-r--r--ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/micropython.mk6
-rw-r--r--ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/common-hal/analogio/AnalogOut.c2
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/I2SOut.c7
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/I2SOut.h5
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/PDMIn.c28
-rw-r--r--ports/atmel-samd/common-hal/board/__init__.c2
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.c4
-rw-r--r--ports/atmel-samd/common-hal/busio/UART.c8
-rw-r--r--ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c3
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PWMOut.c2
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseIn.c13
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseIn.h6
-rw-r--r--ports/atmel-samd/common-hal/pulseio/PulseOut.c2
-rw-r--r--ports/atmel-samd/common-hal/sdioio/SDCard.c272
-rw-r--r--ports/atmel-samd/common-hal/sdioio/SDCard.h40
-rw-r--r--ports/atmel-samd/common-hal/sdioio/__init__.c0
-rw-r--r--ports/atmel-samd/common-hal/sdioio/__init__.h0
-rw-r--r--ports/atmel-samd/fatfs_port.c2
-rw-r--r--ports/atmel-samd/mpconfigport.h18
-rw-r--r--ports/atmel-samd/mpconfigport.mk5
-rw-r--r--ports/atmel-samd/mphalport.h4
-rw-r--r--ports/atmel-samd/sd_mmc/conf_sd_mmc.h79
-rw-r--r--ports/atmel-samd/sd_mmc/sd_mmc.c1671
-rw-r--r--ports/atmel-samd/sd_mmc/sd_mmc.h310
-rw-r--r--ports/atmel-samd/sd_mmc/sd_mmc_protocol.h1001
-rw-r--r--ports/atmel-samd/supervisor/internal_flash.c2
-rw-r--r--ports/atmel-samd/supervisor/internal_flash.h2
-rw-r--r--ports/atmel-samd/supervisor/port.c38
-rw-r--r--ports/atmel-samd/supervisor/usb.c12
-rw-r--r--ports/atmel-samd/tools/gen_pin_name_table.py2
-rw-r--r--ports/cxd56/Makefile29
-rw-r--r--ports/cxd56/README.md4
-rw-r--r--ports/cxd56/background.c28
-rw-r--r--ports/cxd56/background.h3
-rw-r--r--ports/cxd56/boards/spresense/pins.c16
-rw-r--r--ports/cxd56/common-hal/busio/SPI.c2
-rw-r--r--ports/cxd56/common-hal/busio/UART.c4
-rw-r--r--ports/cxd56/common-hal/microcontroller/Pin.c6
-rw-r--r--ports/cxd56/common-hal/microcontroller/Pin.h6
-rw-r--r--ports/cxd56/common-hal/pulseio/PWMOut.h2
-rw-r--r--ports/cxd56/common-hal/sdioio/SDCard.c141
-rw-r--r--ports/cxd56/common-hal/sdioio/SDCard.h47
-rw-r--r--ports/cxd56/common-hal/sdioio/__init__.c0
-rw-r--r--ports/cxd56/configs/circuitpython/defconfig171
-rw-r--r--ports/cxd56/mkspk/elf32.h175
-rw-r--r--ports/cxd56/mkspk/mkspk.h12
-rw-r--r--ports/cxd56/mpconfigport.mk5
-rwxr-xr-xports/cxd56/tools/flash_writer.py580
-rw-r--r--ports/cxd56/tools/xmodem.py590
-rw-r--r--ports/esp32s2/CMakeLists.txt2
-rw-r--r--ports/esp32s2/Makefile47
-rw-r--r--ports/esp32s2/background.c31
-rw-r--r--ports/esp32s2/background.h3
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wroom/board.c8
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk2
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wrover/board.c8
-rw-r--r--ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk2
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/board.c56
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h36
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk21
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/pins.c57
-rw-r--r--ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig0
-rw-r--r--ports/esp32s2/common-hal/busio/I2C.c228
-rw-r--r--ports/esp32s2/common-hal/busio/I2C.h48
-rw-r--r--ports/esp32s2/common-hal/busio/OneWire.h33
-rw-r--r--ports/esp32s2/common-hal/busio/SPI.c358
-rw-r--r--ports/esp32s2/common-hal/busio/SPI.h62
-rw-r--r--ports/esp32s2/common-hal/busio/UART.c348
-rw-r--r--ports/esp32s2/common-hal/busio/UART.h49
-rw-r--r--ports/esp32s2/common-hal/busio/__init__.c1
-rw-r--r--ports/esp32s2/common-hal/digitalio/DigitalInOut.c4
-rw-r--r--ports/esp32s2/common-hal/displayio/ParallelBus.c66
-rw-r--r--ports/esp32s2/common-hal/displayio/ParallelBus.h36
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Pin.c9
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Pin.h5
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Processor.c22
-rw-r--r--ports/esp32s2/common-hal/microcontroller/Processor.h2
-rw-r--r--ports/esp32s2/common-hal/pulseio/PWMOut.c198
-rw-r--r--ports/esp32s2/common-hal/pulseio/PWMOut.h45
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseIn.c75
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseIn.h53
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseOut.c60
-rw-r--r--ports/esp32s2/common-hal/pulseio/PulseOut.h42
-rw-r--r--ports/esp32s2/common-hal/pulseio/__init__.c1
-rw-r--r--ports/esp32s2/fatfs_port.c2
-rw-r--r--ports/esp32s2/modules/wroom.c12
-rw-r--r--ports/esp32s2/modules/wrover.c14
-rw-r--r--ports/esp32s2/mpconfigport.mk10
-rw-r--r--ports/esp32s2/mphalport.c3
-rw-r--r--ports/esp32s2/sdkconfig.defaults28
-rw-r--r--ports/esp32s2/supervisor/internal_flash.c38
-rw-r--r--ports/esp32s2/supervisor/internal_flash.h2
-rw-r--r--ports/esp32s2/supervisor/port.c41
-rw-r--r--ports/litex/Makefile9
-rw-r--r--ports/litex/background.c37
-rw-r--r--ports/litex/background.h5
-rw-r--r--ports/litex/common-hal/digitalio/DigitalInOut.c4
-rw-r--r--ports/litex/common-hal/microcontroller/Pin.c7
-rw-r--r--ports/litex/fatfs_port.c2
-rw-r--r--ports/litex/mpconfigport.mk3
-rw-r--r--ports/litex/mphalport.c3
-rw-r--r--ports/litex/supervisor/internal_flash.c2
-rw-r--r--ports/litex/supervisor/internal_flash.h2
-rw-r--r--ports/mimxrt10xx/Makefile13
-rw-r--r--ports/mimxrt10xx/background.c63
-rw-r--r--ports/mimxrt10xx/background.h7
-rw-r--r--ports/mimxrt10xx/common-hal/analogio/AnalogOut.c2
-rw-r--r--ports/mimxrt10xx/common-hal/board/__init__.c2
-rw-r--r--ports/mimxrt10xx/common-hal/busio/SPI.c4
-rw-r--r--ports/mimxrt10xx/common-hal/busio/UART.c6
-rw-r--r--ports/mimxrt10xx/common-hal/pulseio/PWMOut.c2
-rw-r--r--ports/mimxrt10xx/common-hal/pulseio/PulseIn.c2
-rw-r--r--ports/mimxrt10xx/common-hal/pulseio/PulseOut.c2
-rw-r--r--ports/mimxrt10xx/fatfs_port.c2
-rw-r--r--ports/mimxrt10xx/mpconfigport.mk2
-rw-r--r--ports/mimxrt10xx/supervisor/internal_flash.c2
-rw-r--r--ports/mimxrt10xx/supervisor/internal_flash.h2
-rw-r--r--ports/mimxrt10xx/supervisor/usb.c3
-rwxr-xr-xports/nrf/Makefile10
-rw-r--r--ports/nrf/background.c27
-rw-r--r--ports/nrf/background.h5
-rw-r--r--ports/nrf/boards/bless_dev_board_multi_sensor/board.c12
-rw-r--r--ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.h17
-rw-r--r--ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.mk8
-rw-r--r--ports/nrf/boards/bless_dev_board_multi_sensor/pins.c45
-rw-r--r--ports/nrf/boards/ikigaisense_vita/board.c38
-rw-r--r--ports/nrf/boards/ikigaisense_vita/mpconfigboard.h20
-rw-r--r--ports/nrf/boards/ikigaisense_vita/mpconfigboard.mk8
-rw-r--r--ports/nrf/boards/ikigaisense_vita/pins.c36
-rw-r--r--ports/nrf/boards/makerdiary_m60_keyboard/README.md4
-rw-r--r--ports/nrf/boards/makerdiary_m60_keyboard/board.c38
-rw-r--r--ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h50
-rw-r--r--ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk12
-rw-r--r--ports/nrf/boards/makerdiary_m60_keyboard/pins.c41
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_m2_devkit/README.md8
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_m2_devkit/board.c103
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h57
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk12
-rw-r--r--ports/nrf/boards/makerdiary_nrf52840_m2_devkit/pins.c110
-rw-r--r--ports/nrf/boards/particle_argon/mpconfigboard.mk4
-rw-r--r--ports/nrf/boards/particle_boron/mpconfigboard.mk4
-rw-r--r--ports/nrf/boards/particle_xenon/mpconfigboard.mk4
-rw-r--r--ports/nrf/boards/pca10100/mpconfigboard.mk4
-rw-r--r--ports/nrf/boards/raytac_mdbt50q-db-40/board.c38
-rw-r--r--ports/nrf/boards/raytac_mdbt50q-db-40/bootloader/6.0.0/pca10056_bootloader_6.0.0_s140.zipbin0 -> 174550 bytes
-rw-r--r--ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.h30
-rw-r--r--ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.mk8
-rw-r--r--ports/nrf/boards/raytac_mdbt50q-db-40/pins.c80
-rw-r--r--ports/nrf/boards/simmel/mpconfigboard.mk3
-rw-r--r--ports/nrf/boards/tinkeringtech_scoutmakes_azul/README.md25
-rw-r--r--ports/nrf/boards/tinkeringtech_scoutmakes_azul/board.c38
-rw-r--r--ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.h63
-rw-r--r--ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk10
-rw-r--r--ports/nrf/boards/tinkeringtech_scoutmakes_azul/pins.c53
-rw-r--r--ports/nrf/common-hal/_bleio/__init__.c10
-rw-r--r--ports/nrf/common-hal/busio/SPI.c6
-rw-r--r--ports/nrf/common-hal/busio/UART.c6
-rw-r--r--ports/nrf/common-hal/microcontroller/__init__.c44
-rw-r--r--ports/nrf/examples/ubluepy_temp.py2
-rw-r--r--ports/nrf/fatfs_port.c2
-rw-r--r--ports/nrf/peripherals/nrf/nvm.c2
-rw-r--r--ports/nrf/peripherals/nrf/nvm.h2
-rw-r--r--ports/nrf/supervisor/internal_flash.c2
-rw-r--r--ports/nrf/supervisor/internal_flash.h2
-rw-r--r--ports/nrf/supervisor/port.c13
-rw-r--r--ports/nrf/supervisor/usb.c7
-rwxr-xr-xports/stm/Makefile15
-rw-r--r--ports/stm/background.c33
-rw-r--r--ports/stm/background.h5
-rw-r--r--ports/stm/boards/STM32F411_nvm.ld8
-rw-r--r--ports/stm/boards/thunderpack/mpconfigboard.h16
-rw-r--r--ports/stm/common-hal/analogio/AnalogIn.c4
-rw-r--r--ports/stm/common-hal/analogio/AnalogOut.c4
-rw-r--r--ports/stm/common-hal/busio/I2C.c6
-rw-r--r--ports/stm/common-hal/busio/SPI.c154
-rw-r--r--ports/stm/common-hal/busio/UART.c11
-rw-r--r--ports/stm/common-hal/digitalio/DigitalInOut.c3
-rw-r--r--ports/stm/common-hal/microcontroller/Pin.c19
-rw-r--r--ports/stm/common-hal/microcontroller/Pin.h2
-rw-r--r--ports/stm/common-hal/pulseio/PWMOut.c180
-rw-r--r--ports/stm/common-hal/pulseio/PulseIn.c84
-rw-r--r--ports/stm/common-hal/pulseio/PulseOut.c138
-rw-r--r--ports/stm/common-hal/rgbmatrix/RGBMatrix.c14
-rw-r--r--ports/stm/fatfs_port.c2
-rw-r--r--ports/stm/peripherals/stm32f4/stm32f405xx/periph.c182
-rw-r--r--ports/stm/peripherals/stm32f4/stm32f405xx/periph.h35
-rw-r--r--ports/stm/peripherals/stm32f4/stm32f405xx/pins.c205
-rw-r--r--ports/stm/peripherals/stm32f4/stm32f405xx/pins.h201
-rw-r--r--ports/stm/peripherals/timers.c460
-rw-r--r--ports/stm/peripherals/timers.h46
-rw-r--r--ports/stm/supervisor/internal_flash.c2
-rw-r--r--ports/stm/supervisor/internal_flash.h7
-rw-r--r--ports/stm/supervisor/port.c2
-rw-r--r--ports/stm/supervisor/usb.c7
-rw-r--r--ports/stm/tools/parse_af_csv.py4
-rw-r--r--ports/stm/tools/parse_pins_csv.py2
-rw-r--r--ports/stm/tools/pins.csv93
-rw-r--r--ports/stm/tools/stm32f767_af.csv168
-rw-r--r--ports/unix/fdfile.h2
-rw-r--r--ports/unix/file.c2
-rw-r--r--ports/unix/gccollect.c2
-rw-r--r--ports/unix/input.c2
-rw-r--r--ports/unix/main.c2
-rw-r--r--ports/unix/modffi.c2
-rw-r--r--ports/unix/modmachine.c2
-rw-r--r--ports/unix/modos.c2
-rw-r--r--ports/unix/modtime.c2
-rw-r--r--ports/unix/moduos_vfs.c2
-rw-r--r--ports/unix/moduselect.c2
-rw-r--r--ports/unix/modusocket.c2
-rw-r--r--ports/unix/mpconfigport.h2
-rw-r--r--ports/unix/mpconfigport_coverage.h2
-rw-r--r--ports/unix/mpconfigport_fast.h2
-rw-r--r--ports/unix/mpconfigport_freedos.h2
-rw-r--r--ports/unix/mpconfigport_minimal.h2
-rw-r--r--ports/unix/mpconfigport_nanbox.h2
-rw-r--r--ports/unix/mphalport.h2
-rw-r--r--ports/unix/mpthreadport.c2
-rw-r--r--ports/unix/mpthreadport.h2
-rw-r--r--ports/unix/qstrdefsport.h2
-rw-r--r--ports/unix/unix_mphal.c2
272 files changed, 10689 insertions, 1618 deletions
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index cce89a7ac..f63698eba 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2019 Dan Halbert for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -87,25 +87,28 @@ INC += -I. \
ifeq ($(CHIP_FAMILY), samd21)
PERIPHERALS_CHIP_FAMILY=samd21
-CFLAGS += -Os -DNDEBUG
+OPTIMIZATION_FLAGS ?= -Os
# TinyUSB defines
CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512
endif
ifeq ($(CHIP_FAMILY), samd51)
PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x
-CFLAGS += -Os -DNDEBUG
+OPTIMIZATION_FLAGS ?= -O2
# TinyUSB defines
CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
endif
ifeq ($(CHIP_FAMILY), same54)
PERIPHERALS_CHIP_FAMILY=sam_d5x_e5x
-CFLAGS += -Os -DNDEBUG
+OPTIMIZATION_FLAGS ?= -O2
# TinyUSB defines
CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
endif
+# option to override default optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS) -DNDEBUG
+
$(echo PERIPHERALS_CHIP_FAMILY=$(PERIPHERALS_CHIP_FAMILY))
#Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -246,6 +249,14 @@ SRC_ASF += \
endif
+ifeq ($(CIRCUITPY_SDIOIO),1)
+SRC_ASF += \
+ hal/src/hal_mci_sync.c \
+ hpl/sdhc/hpl_sdhc.c \
+
+$(BUILD)/asf4/$(CHIP_FAMILY)/hpl/sdhc/hpl_sdhc.o: CFLAGS += -Wno-cast-align
+endif
+
SRC_ASF := $(addprefix asf4/$(CHIP_FAMILY)/, $(SRC_ASF))
SRC_C += \
@@ -290,6 +301,9 @@ SRC_C += \
supervisor/shared/memory.c \
timer_handler.c \
+ifeq ($(CIRCUITPY_SDIOIO),1)
+SRC_C += ports/atmel-samd/sd_mmc/sd_mmc.c
+endif
ifeq ($(CIRCUITPY_NETWORK),1)
CFLAGS += -DMICROPY_PY_NETWORK=1
@@ -346,6 +360,10 @@ endif
OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_MOD:.c=.o))
+SRC_QSTR += $(HEADER_BUILD)/sdiodata.h
+$(HEADER_BUILD)/sdiodata.h: $(TOP)/tools/mksdiodata.py | $(HEADER_BUILD)
+ $(Q)$(PYTHON3) $< > $@
+
SRC_QSTR += $(SRC_C) $(SRC_SUPERVISOR) $(SRC_COMMON_HAL_EXPANDED) $(SRC_SHARED_MODULE_EXPANDED)
# Sources that only hold QSTRs after pre-processing.
SRC_QSTR_PREPROCESSOR += peripherals/samd/$(PERIPHERALS_CHIP_FAMILY)/clocks.c
diff --git a/ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h b/ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h
new file mode 100644
index 000000000..daa662051
--- /dev/null
+++ b/ports/atmel-samd/asf4_conf/samd51/hpl_sdhc_config.h
@@ -0,0 +1,24 @@
+/* Auto-generated config file hpl_sdhc_config.h */
+#ifndef HPL_SDHC_CONFIG_H
+#define HPL_SDHC_CONFIG_H
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+#include "peripheral_clk_config.h"
+
+#ifndef CONF_BASE_FREQUENCY
+#define CONF_BASE_FREQUENCY CONF_SDHC0_FREQUENCY
+#endif
+
+// <o> Clock Generator Select
+// <0=> Divided Clock mode
+// <1=> Programmable Clock mode
+// <i> This defines the clock generator mode in the SDCLK Frequency Select field
+// <id> sdhc_clk_gsel
+#ifndef CONF_SDHC0_CLK_GEN_SEL
+#define CONF_SDHC0_CLK_GEN_SEL 0
+#endif
+
+// <<< end of configuration section >>>
+
+#endif // HPL_SDHC_CONFIG_H
diff --git a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
index 030a90a7a..59fe8730e 100644
--- a/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
+++ b/ports/atmel-samd/asf4_conf/samd51/peripheral_clk_config.h
@@ -1001,6 +1001,170 @@
#define CONF_GCLK_USB_FREQUENCY 48000000
#endif
+// <h> SDHC Clock Settings
+// <y> SDHC Clock source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_gclk_selection
+#ifndef CONF_GCLK_SDHC0_SRC
+#define CONF_GCLK_SDHC0_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+
+// <y> SDHC clock slow source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_slow_gclk_selection
+#ifndef CONF_GCLK_SDHC0_SLOW_SRC
+#define CONF_GCLK_SDHC0_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+// </h>
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock frequency
+ */
+#ifndef CONF_SDHC0_FREQUENCY
+#define CONF_SDHC0_FREQUENCY 12000000
+#endif
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock slow frequency
+ */
+#ifndef CONF_SDHC0_SLOW_FREQUENCY
+#define CONF_SDHC0_SLOW_FREQUENCY 12000000
+#endif
+
+// <h> SDHC Clock Settings
+// <y> SDHC Clock source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_gclk_selection
+#ifndef CONF_GCLK_SDHC1_SRC
+#define CONF_GCLK_SDHC1_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+
+// <y> SDHC clock slow source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_slow_gclk_selection
+#ifndef CONF_GCLK_SDHC1_SLOW_SRC
+#define CONF_GCLK_SDHC1_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+// </h>
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock frequency
+ */
+#ifndef CONF_SDHC1_FREQUENCY
+#define CONF_SDHC1_FREQUENCY 12000000
+#endif
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock slow frequency
+ */
+#ifndef CONF_SDHC1_SLOW_FREQUENCY
+#define CONF_SDHC1_SLOW_FREQUENCY 12000000
+#endif
+
// <<< end of configuration section >>>
#endif // PERIPHERAL_CLK_CONFIG_H
diff --git a/ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h b/ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h
new file mode 100644
index 000000000..daa662051
--- /dev/null
+++ b/ports/atmel-samd/asf4_conf/same54/hpl_sdhc_config.h
@@ -0,0 +1,24 @@
+/* Auto-generated config file hpl_sdhc_config.h */
+#ifndef HPL_SDHC_CONFIG_H
+#define HPL_SDHC_CONFIG_H
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+#include "peripheral_clk_config.h"
+
+#ifndef CONF_BASE_FREQUENCY
+#define CONF_BASE_FREQUENCY CONF_SDHC0_FREQUENCY
+#endif
+
+// <o> Clock Generator Select
+// <0=> Divided Clock mode
+// <1=> Programmable Clock mode
+// <i> This defines the clock generator mode in the SDCLK Frequency Select field
+// <id> sdhc_clk_gsel
+#ifndef CONF_SDHC0_CLK_GEN_SEL
+#define CONF_SDHC0_CLK_GEN_SEL 0
+#endif
+
+// <<< end of configuration section >>>
+
+#endif // HPL_SDHC_CONFIG_H
diff --git a/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h b/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h
index 030a90a7a..59fe8730e 100644
--- a/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h
+++ b/ports/atmel-samd/asf4_conf/same54/peripheral_clk_config.h
@@ -1001,6 +1001,170 @@
#define CONF_GCLK_USB_FREQUENCY 48000000
#endif
+// <h> SDHC Clock Settings
+// <y> SDHC Clock source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_gclk_selection
+#ifndef CONF_GCLK_SDHC0_SRC
+#define CONF_GCLK_SDHC0_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+
+// <y> SDHC clock slow source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_slow_gclk_selection
+#ifndef CONF_GCLK_SDHC0_SLOW_SRC
+#define CONF_GCLK_SDHC0_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+// </h>
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock frequency
+ */
+#ifndef CONF_SDHC0_FREQUENCY
+#define CONF_SDHC0_FREQUENCY 12000000
+#endif
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock slow frequency
+ */
+#ifndef CONF_SDHC0_SLOW_FREQUENCY
+#define CONF_SDHC0_SLOW_FREQUENCY 12000000
+#endif
+
+// <h> SDHC Clock Settings
+// <y> SDHC Clock source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_gclk_selection
+#ifndef CONF_GCLK_SDHC1_SRC
+#define CONF_GCLK_SDHC1_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+
+// <y> SDHC clock slow source
+
+// <GCLK_PCHCTRL_GEN_GCLK0_Val"> Generic clock generator 0
+
+// <GCLK_PCHCTRL_GEN_GCLK1_Val"> Generic clock generator 1
+
+// <GCLK_PCHCTRL_GEN_GCLK2_Val"> Generic clock generator 2
+
+// <GCLK_PCHCTRL_GEN_GCLK3_Val"> Generic clock generator 3
+
+// <GCLK_PCHCTRL_GEN_GCLK4_Val"> Generic clock generator 4
+
+// <GCLK_PCHCTRL_GEN_GCLK5_Val"> Generic clock generator 5
+
+// <GCLK_PCHCTRL_GEN_GCLK6_Val"> Generic clock generator 6
+
+// <GCLK_PCHCTRL_GEN_GCLK7_Val"> Generic clock generator 7
+
+// <GCLK_PCHCTRL_GEN_GCLK8_Val"> Generic clock generator 8
+
+// <GCLK_PCHCTRL_GEN_GCLK9_Val"> Generic clock generator 9
+
+// <GCLK_PCHCTRL_GEN_GCLK10_Val"> Generic clock generator 10
+
+// <GCLK_PCHCTRL_GEN_GCLK11_Val"> Generic clock generator 11
+
+// <i> Select the clock source for SDHC.
+// <id> sdhc_slow_gclk_selection
+#ifndef CONF_GCLK_SDHC1_SLOW_SRC
+#define CONF_GCLK_SDHC1_SLOW_SRC GCLK_GENCTRL_SRC_DFLL_Val
+#endif
+// </h>
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock frequency
+ */
+#ifndef CONF_SDHC1_FREQUENCY
+#define CONF_SDHC1_FREQUENCY 12000000
+#endif
+
+/**
+ * \def SDHC FREQUENCY
+ * \brief SDHC's Clock slow frequency
+ */
+#ifndef CONF_SDHC1_SLOW_FREQUENCY
+#define CONF_SDHC1_SLOW_FREQUENCY 12000000
+#endif
+
// <<< end of configuration section >>>
#endif // PERIPHERAL_CLK_CONFIG_H
diff --git a/ports/atmel-samd/audio_dma.c b/ports/atmel-samd/audio_dma.c
index 93cd96b98..c6c636160 100644
--- a/ports/atmel-samd/audio_dma.c
+++ b/ports/atmel-samd/audio_dma.c
@@ -31,7 +31,7 @@
#include "shared-bindings/audiocore/RawSample.h"
#include "shared-bindings/audiocore/WaveFile.h"
-#include "supervisor/shared/tick.h"
+#include "supervisor/background_callback.h"
#include "py/mpstate.h"
#include "py/runtime.h"
@@ -61,7 +61,6 @@ void audio_dma_free_channel(uint8_t channel) {
assert(audio_dma_allocated[channel]);
audio_dma_disable_channel(channel);
audio_dma_allocated[channel] = false;
- supervisor_disable_tick();
}
void audio_dma_disable_channel(uint8_t channel) {
@@ -73,7 +72,6 @@ void audio_dma_disable_channel(uint8_t channel) {
void audio_dma_enable_channel(uint8_t channel) {
if (channel >= AUDIO_DMA_CHANNEL_COUNT)
return;
- supervisor_enable_tick();
dma_enable_channel(channel);
}
@@ -259,6 +257,15 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
dma->beat_size *= 2;
}
+#ifdef SAM_D5X_E5X
+ int irq = dma->event_channel < 4 ? EVSYS_0_IRQn + dma->event_channel : EVSYS_4_IRQn;
+#else
+ int irq = EVSYS_IRQn;
+#endif
+
+ NVIC_DisableIRQ(irq);
+ NVIC_ClearPendingIRQ(irq);
+
DmacDescriptor* first_descriptor = dma_descriptor(dma_channel);
setup_audio_descriptor(first_descriptor, dma->beat_size, output_spacing, output_register_address);
if (single_buffer) {
@@ -281,6 +288,8 @@ audio_dma_result audio_dma_setup_playback(audio_dma_t* dma,
dma_configure(dma_channel, dma_trigger_source, true);
audio_dma_enable_channel(dma_channel);
+ NVIC_EnableIRQ(irq);
+
return AUDIO_DMA_OK;
}
@@ -321,9 +330,6 @@ void audio_dma_reset(void) {
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
audio_dma_state[i] = NULL;
audio_dma_pending[i] = false;
- if (audio_dma_allocated[i]) {
- supervisor_disable_tick();
- }
audio_dma_allocated[i] = false;
audio_dma_disable_channel(i);
dma_descriptor(i)->BTCTRL.bit.VALID = false;
@@ -343,29 +349,39 @@ bool audio_dma_get_playing(audio_dma_t* dma) {
return (status & DMAC_CHINTFLAG_TERR) == 0;
}
-// WARN(tannewt): DO NOT print from here. Printing calls background tasks such as this and causes a
-// stack overflow.
+// WARN(tannewt): DO NOT print from here, or anything it calls. Printing calls
+// background tasks such as this and causes a stack overflow.
+STATIC void dma_callback_fun(void *arg) {
+ audio_dma_t* dma = arg;
+ if (dma == NULL) {
+ return;
+ }
+
+ audio_dma_load_next_block(dma);
+}
-void audio_dma_background(void) {
+void evsyshandler_common(void) {
for (uint8_t i = 0; i < AUDIO_DMA_CHANNEL_COUNT; i++) {
- if (audio_dma_pending[i]) {
- continue;
- }
audio_dma_t* dma = audio_dma_state[i];
if (dma == NULL) {
continue;
}
-
bool block_done = event_interrupt_active(dma->event_channel);
if (!block_done) {
continue;
}
-
- // audio_dma_load_next_block() can call Python code, which can call audio_dma_background()
- // recursively at the next background processing time. So disallow recursive calls to here.
- audio_dma_pending[i] = true;
- audio_dma_load_next_block(dma);
- audio_dma_pending[i] = false;
+ background_callback_add(&dma->callback, dma_callback_fun, (void*)dma);
}
}
+
+#ifdef SAM_D5X_E5X
+void EVSYS_0_Handler(void) { evsyshandler_common(); }
+void EVSYS_1_Handler(void) { evsyshandler_common(); }
+void EVSYS_2_Handler(void) { evsyshandler_common(); }
+void EVSYS_3_Handler(void) { evsyshandler_common(); }
+void EVSYS_4_Handler(void) { evsyshandler_common(); }
+#else
+void EVSYS_Handler(void) { evsyshandler_common(); }
+#endif
+
#endif
diff --git a/ports/atmel-samd/audio_dma.h b/ports/atmel-samd/audio_dma.h
index 1ebec6f7e..4fffd06b8 100644
--- a/ports/atmel-samd/audio_dma.h
+++ b/ports/atmel-samd/audio_dma.h
@@ -31,6 +31,7 @@
#include "py/obj.h"
#include "shared-module/audiocore/RawSample.h"
#include "shared-module/audiocore/WaveFile.h"
+#include "supervisor/background_callback.h"
typedef struct {
mp_obj_t sample;
@@ -49,6 +50,7 @@ typedef struct {
uint8_t* second_buffer;
bool first_descriptor_free;
DmacDescriptor* second_descriptor;
+ background_callback_t callback;
} audio_dma_t;
typedef enum {
diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c
index 0608cb9bd..62c233a3f 100644
--- a/ports/atmel-samd/background.c
+++ b/ports/atmel-samd/background.c
@@ -35,77 +35,25 @@
#include "supervisor/shared/stack.h"
#include "supervisor/port.h"
-#if CIRCUITPY_BLEIO
-#include "common-hal/_bleio/__init__.h"
-#endif
-
-#if CIRCUITPY_DISPLAYIO
+#ifdef CIRCUITPY_DISPLAYIO
#include "shared-module/displayio/__init__.h"
#endif
-volatile uint64_t last_finished_tick = 0;
-
-bool stack_ok_so_far = true;
-
-static bool running_background_tasks = false;
-
#ifdef MONITOR_BACKGROUND_TASKS
// PB03 is physical pin "SCL" on the Metro M4 express
// so you can't use this code AND an i2c peripheral
// at the same time unless you change this
-STATIC void start_background_task(void) {
+void port_start_background_task(void) {
REG_PORT_DIRSET1 = (1<<3);
REG_PORT_OUTSET1 = (1<<3);
}
-STATIC void finish_background_task(void) {
+void port_finish_background_task(void) {
REG_PORT_OUTCLR1 = (1<<3);
}
#else
-STATIC void start_background_task(void) {}
-STATIC void finish_background_task(void) {}
-#endif
-
-void background_tasks_reset(void) {
- running_background_tasks = false;
-}
-
-void run_background_tasks(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
-
- start_background_task();
-
- assert_heap_ok();
- running_background_tasks = true;
-
-#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
- audio_dma_background();
-#endif
-
-#if CIRCUITPY_BLEIO
- bleio_background();
+void port_start_background_task(void) {}
+void port_finish_background_task(void) {}
#endif
-#if CIRCUITPY_DISPLAYIO
- displayio_background();
-#endif
-
-#if CIRCUITPY_NETWORK
- network_module_background();
-#endif
-
- filesystem_background();
- usb_background();
- running_background_tasks = false;
- assert_heap_ok();
-
- last_finished_tick = port_get_raw_ticks(NULL);
- finish_background_task();
-}
-
-bool background_tasks_ok(void) {
- return port_get_raw_ticks(NULL) - last_finished_tick < 1024;
-}
+void port_background_task(void) {}
diff --git a/ports/atmel-samd/background.h b/ports/atmel-samd/background.h
index d9866a6ab..2a89c3b1b 100644
--- a/ports/atmel-samd/background.h
+++ b/ports/atmel-samd/background.h
@@ -29,9 +29,4 @@
#include <stdbool.h>
-void background_tasks_reset(void);
-void run_background_tasks(void);
-void run_background_vm_tasks(void);
-bool background_tasks_ok(void);
-
#endif // MICROPY_INCLUDED_ATMEL_SAMD_BACKGROUND_H
diff --git a/ports/atmel-samd/bindings/samd/Clock.c b/ports/atmel-samd/bindings/samd/Clock.c
index e1022c52f..478a10fcd 100644
--- a/ports/atmel-samd/bindings/samd/Clock.c
+++ b/ports/atmel-samd/bindings/samd/Clock.c
@@ -30,7 +30,6 @@
#include "py/objproperty.h"
#include "py/runtime.h"
-//| import typing
//| class Clock:
//| """Identifies a clock on the microcontroller.
//|
@@ -44,7 +43,7 @@ STATIC void samd_clock_print(const mp_print_t *print, mp_obj_t self_in, mp_print
mp_printf(print, "%q.%q.%q", MP_QSTR_samd, MP_QSTR_clock, self->name);
}
-//| enabled: bool = ...
+//| enabled: bool
//| """Is the clock enabled? (read-only)"""
//|
STATIC mp_obj_t samd_clock_get_enabled(mp_obj_t self_in) {
@@ -62,7 +61,7 @@ const mp_obj_property_t samd_clock_enabled_obj = {
},
};
-//| parent: typing.Union(Clock | None) = ...
+//| parent: Union[Clock, None]
//| """Clock parent. (read-only)"""
//|
STATIC mp_obj_t samd_clock_get_parent(mp_obj_t self_in) {
@@ -90,7 +89,7 @@ const mp_obj_property_t samd_clock_parent_obj = {
},
};
-//| frequency: int = ...
+//| frequency: int
//| """Clock frequency in Herz. (read-only)"""
//|
STATIC mp_obj_t samd_clock_get_frequency(mp_obj_t self_in) {
@@ -108,7 +107,7 @@ const mp_obj_property_t samd_clock_frequency_obj = {
},
};
-//| calibration: int = ...
+//| calibration: int
//| """Clock calibration. Not all clocks can be calibrated."""
//|
STATIC mp_obj_t samd_clock_get_calibration(mp_obj_t self_in) {
diff --git a/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk b/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
index 4b0377be2..9151040a0 100644
--- a/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/8086_commander/mpconfigboard.mk
@@ -18,6 +18,8 @@ SUPEROPT_GC = 0
CFLAGS_INLINE_LIMIT = 60
+CIRCUITPY_GAMEPAD = 1
+
# Include these Python libraries in firmware.
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_HID
diff --git a/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk b/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk
index 28b1434fb..34301da3f 100644
--- a/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/aloriumtech_evo_m51/mpconfigboard.mk
@@ -13,6 +13,4 @@ EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = GD25Q16C
LONGINT_IMPL = MPZ
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/blm_badge/board.c b/ports/atmel-samd/boards/blm_badge/board.c
new file mode 100644
index 000000000..ee353c810
--- /dev/null
+++ b/ports/atmel-samd/boards/blm_badge/board.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+#include "supervisor/shared/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+ board_reset_user_neopixels();
+}
diff --git a/ports/atmel-samd/boards/blm_badge/mpconfigboard.h b/ports/atmel-samd/boards/blm_badge/mpconfigboard.h
new file mode 100644
index 000000000..4f56d23b0
--- /dev/null
+++ b/ports/atmel-samd/boards/blm_badge/mpconfigboard.h
@@ -0,0 +1,37 @@
+#define MICROPY_HW_BOARD_NAME "Adafruit BLM Badge"
+#define MICROPY_HW_MCU_NAME "samd21e18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA03)
+
+#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA01)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA00)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA01)
+#define DEFAULT_UART_BUS_TX (&pin_PA00)
+
+#define USER_NEOPIXELS_PIN (&pin_PA05)
+
+#define IGNORE_PIN_PA09 1
+#define IGNORE_PIN_PA12 1
+#define IGNORE_PIN_PA13 1
+#define IGNORE_PIN_PA14 1
+#define IGNORE_PIN_PA15 1
+#define IGNORE_PIN_PA16 1
+#define IGNORE_PIN_PA17 1
+#define IGNORE_PIN_PA18 1
+#define IGNORE_PIN_PA19 1
+#define IGNORE_PIN_PA20 1
+#define IGNORE_PIN_PA21 1
+#define IGNORE_PIN_PA22 1
+#define IGNORE_PIN_PA23 1
+// USB is always used.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
+#define IGNORE_PIN_PA27 1
+#define IGNORE_PIN_PA28 1
+#define IGNORE_PIN_PA30 1
+#define IGNORE_PIN_PA31 1
diff --git a/ports/atmel-samd/boards/blm_badge/mpconfigboard.mk b/ports/atmel-samd/boards/blm_badge/mpconfigboard.mk
new file mode 100644
index 000000000..794e38d79
--- /dev/null
+++ b/ports/atmel-samd/boards/blm_badge/mpconfigboard.mk
@@ -0,0 +1,24 @@
+USB_VID = 0x239A
+USB_PID = 0x80C0
+USB_PRODUCT = "BLM Badge"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+CIRCUITPY_FULL_BUILD = 0
+
+CIRCUITPY_AUDIOIO = 1
+CIRCUITPY_AUDIOBUSIO = 1
+# Pins for I2SOut are not available.
+CIRCUITPY_AUDIOBUSIO_I2SOUT = 0
+CIRCUITPY_PULSEIO = 0
+CIRCUITPY_ROTARYIO = 0
+CIRCUITPY_RTC = 0
+CIRCUITPY_SAMD = 0
+CIRCUITPY_USB_HID = 1
+CIRCUITPY_USB_MIDI = 0
+
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/blm_badge/pins.c b/ports/atmel-samd/boards/blm_badge/pins.c
new file mode 100644
index 000000000..af1b69358
--- /dev/null
+++ b/ports/atmel-samd/boards/blm_badge/pins.c
@@ -0,0 +1,43 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA01) }, // pad 1
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA00) }, // pad 0
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA00) },
+
+ { MP_ROM_QSTR(MP_QSTR_CAP1), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+
+ { MP_ROM_QSTR(MP_QSTR_CAP2), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PA04) },
+
+ { MP_ROM_QSTR(MP_QSTR_CAP3), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA06) },
+
+ { MP_ROM_QSTR(MP_QSTR_CAP4), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA07) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PA05) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_CLOCK), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA10) },
+
+ { MP_ROM_QSTR(MP_QSTR_MICROPHONE_DATA), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA08) },
+
+ { MP_ROM_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA11) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA03) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk
index da5f1ffac..619b7d694 100755
--- a/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitbrains_basic_m0/mpconfigboard.mk
@@ -12,6 +12,7 @@ EXTERNAL_FLASH_DEVICES = "W25Q32JV_IQ"
LONGINT_IMPL = MPZ
CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_COUNTIO = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_VECTORIO = 0
diff --git a/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk b/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk
index 7a9e5a780..13ae59de4 100755
--- a/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitbrains_deluxe_m4/mpconfigboard.mk
@@ -11,6 +11,4 @@ EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, S25FL064L"
LONGINT_IMPL = MPZ
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
index 0c5e5b762..12c48b1e3 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
@@ -28,7 +28,7 @@
#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up"
// Increase stack size slightly due to CPX library import nesting
-#define CIRCUITPY_DEFAULT_STACK_SIZE (4760) //divisible by 8
+#define CIRCUITPY_DEFAULT_STACK_SIZE (4248) //divisible by 8
#define USER_NEOPIXELS_PIN (&pin_PB23)
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
index 312fd2626..95b4ec110 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h
@@ -30,7 +30,7 @@
#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up"
// Increase stack size slightly due to CPX library import nesting
-#define CIRCUITPY_DEFAULT_STACK_SIZE (4760) // divisible by 8
+#define CIRCUITPY_DEFAULT_STACK_SIZE (4248) // divisible by 8
#define DEFAULT_I2C_BUS_SCL (&pin_PB03)
#define DEFAULT_I2C_BUS_SDA (&pin_PB02)
diff --git a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
index 4796e90a5..d478ea38b 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
+++ b/ports/atmel-samd/boards/circuitplayground_express_displayio/mpconfigboard.h
@@ -28,7 +28,7 @@
#define BOARD_USER_SAFE_MODE_ACTION "pressing both buttons at start up"
// Increase stack size slightly due to CPX library import nesting.
-#define CIRCUITPY_DEFAULT_STACK_SIZE (4760) // divisible by 8
+#define CIRCUITPY_DEFAULT_STACK_SIZE (4248) // divisible by 8
#define USER_NEOPIXELS_PIN (&pin_PB23)
diff --git a/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk b/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk
index 8efc1b575..c040eb430 100644
--- a/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/fluff_m0/mpconfigboard.mk
@@ -14,5 +14,6 @@ SUPEROPT_GC = 0
CFLAGS_BOARD = --param max-inline-insns-auto=15
ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
CFLAGS_INLINE_LIMIT = 35
endif
diff --git a/ports/atmel-samd/boards/fluff_m0/pins.c b/ports/atmel-samd/boards/fluff_m0/pins.c
index d80d46b89..6b56297af 100644
--- a/ports/atmel-samd/boards/fluff_m0/pins.c
+++ b/ports/atmel-samd/boards/fluff_m0/pins.c
@@ -13,7 +13,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA31) },
{ MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_SDO), MP_ROM_PTR(&pin_PA00) },
{ MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA30) },
+ { MP_ROM_QSTR(MP_QSTR_SDI), MP_ROM_PTR(&pin_PA30) },
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) },
{ MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) },
@@ -30,6 +32,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA16) },
{ MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA19) },
{ MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_EN), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA28) },
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
index ca3eccbe4..0345417a9 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
@@ -11,3 +11,13 @@ LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
SUPEROPT_GC = 0
+
+CFLAGS_BOARD = --param max-inline-insns-auto=15
+ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
+CFLAGS_INLINE_LIMIT = 35
+endif
+ifeq ($(TRANSLATION), de_DE)
+RELEASE_NEEDS_CLEAN_BUILD = 1
+CFLAGS_INLINE_LIMIT = 35
+endif
diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
index ab81ec5a2..08eb5c98b 100644
--- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
@@ -10,3 +10,5 @@ QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C"
LONGINT_IMPL = MPZ
+
+CIRCUITPY_SDIOIO = 1
diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/pins.c b/ports/atmel-samd/boards/grandcentral_m4_express/pins.c
index 6b09c62bf..b125aca08 100644
--- a/ports/atmel-samd/boards/grandcentral_m4_express/pins.c
+++ b/ports/atmel-samd/boards/grandcentral_m4_express/pins.c
@@ -1,5 +1,18 @@
+#include "py/objtuple.h"
#include "shared-bindings/board/__init__.h"
+STATIC const mp_rom_obj_tuple_t sdio_data_tuple = {
+ {&mp_type_tuple},
+ 4,
+ {
+ MP_ROM_PTR(&pin_PB18),
+ MP_ROM_PTR(&pin_PB19),
+ MP_ROM_PTR(&pin_PB20),
+ MP_ROM_PTR(&pin_PB21),
+ }
+};
+
+
// This mapping only includes functional names because pins broken
// out on connectors are labeled with their MCU name available from
// microcontroller.pin.
@@ -129,5 +142,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
index febd2a6c3..18cef738e 100644
--- a/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/kicksat-sprite/mpconfigboard.mk
@@ -13,9 +13,11 @@ LONGINT_IMPL = MPZ
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_FRAMEBUFFERIO = 0
CIRCUITPY_DISPLAYIO = 0
-CIRCUITPY_NETWORK = 0
CIRCUITPY_RGBMATRIX = 0
CIRCUITPY_PS2IO = 0
CIRCUITPY_AUDIOMP3 = 0
CIRCUITPY_ULAB = 0
+
+# Override optimization to keep binary small
+OPTIMIZATION_FLAGS = -Os
diff --git a/ports/atmel-samd/boards/loc_ber_m4_base_board/mpconfigboard.mk b/ports/atmel-samd/boards/loc_ber_m4_base_board/mpconfigboard.mk
index 55d6fa78e..3c407f530 100644
--- a/ports/atmel-samd/boards/loc_ber_m4_base_board/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/loc_ber_m4_base_board/mpconfigboard.mk
@@ -15,3 +15,5 @@ LONGINT_IMPL = MPZ
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_BITBANG_APA102 = 1
+# Override optimization to keep binary small
+OPTIMIZATION_FLAGS = -Os
diff --git a/ports/atmel-samd/boards/ndgarage_ndbit6_v2/board.c b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/board.c
new file mode 100644
index 000000000..0f60736a2
--- /dev/null
+++ b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/board.c
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+#include "mpconfigboard.h"
+#include "hal/include/hal_gpio.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.h b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.h
new file mode 100644
index 000000000..0dc7f5d19
--- /dev/null
+++ b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.h
@@ -0,0 +1,22 @@
+#define MICROPY_HW_BOARD_NAME "ndGarage[n°] Bit6: FeatherSnow-v2"
+#define MICROPY_HW_MCU_NAME "samd21e18"
+
+#define MICROPY_HW_LED_STATUS (&pin_PA23)
+
+#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25)
+#define MICROPY_PORT_B (0)
+#define MICROPY_PORT_C (0)
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000 CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA17)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA16)
+
+#define DEFAULT_UART_BUS_RX (&pin_PA17)
+#define DEFAULT_UART_BUS_TX (&pin_PA16)
+
+// USB is always used.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
diff --git a/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk
new file mode 100644
index 000000000..193a0cf99
--- /dev/null
+++ b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/mpconfigboard.mk
@@ -0,0 +1,14 @@
+LD_FILE = boards/samd21x18-bootloader.ld
+USB_VID = 0x239A
+USB_PID = 0x80B9
+USB_PRODUCT = "Bit6"
+USB_MANUFACTURER = "ndGarage"
+
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = NONE
+CIRCUITPY_FULL_BUILD = 0
+
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/ndgarage_ndbit6_v2/pins.c b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/pins.c
new file mode 100644
index 000000000..f0615df5a
--- /dev/null
+++ b/ports/atmel-samd/boards/ndgarage_ndbit6_v2/pins.c
@@ -0,0 +1,36 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA27) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA06) },
+
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_PA18) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_PA28) },
+ { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_PA19) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA17) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA17) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA16) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_PA23) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/openbook_m4/board.c b/ports/atmel-samd/boards/openbook_m4/board.c
index 9c71ee564..f0010f6d7 100644
--- a/ports/atmel-samd/boards/openbook_m4/board.c
+++ b/ports/atmel-samd/boards/openbook_m4/board.c
@@ -76,13 +76,13 @@ void board_init(void) {
sizeof(start_sequence),
stop_sequence,
sizeof(stop_sequence),
- 400, // width
- 300, // height
- 400, // RAM width
- 300, // RAM height
+ 300, // width
+ 400, // height
+ 300, // RAM width
+ 400, // RAM height
0, // colstart
0, // rowstart
- 0, // rotation
+ 270, // rotation
NO_COMMAND, // set_column_window_command
NO_COMMAND, // set_row_window_command
NO_COMMAND, // set_current_column_command
diff --git a/ports/atmel-samd/boards/openbook_m4/pins.c b/ports/atmel-samd/boards/openbook_m4/pins.c
index 3fbb67860..47de3043d 100644
--- a/ports/atmel-samd/boards/openbook_m4/pins.c
+++ b/ports/atmel-samd/boards/openbook_m4/pins.c
@@ -53,6 +53,10 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_EBSY), MP_ROM_PTR(&pin_PA01) },
// Special named pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_PB01) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_USB), MP_ROM_PTR(&pin_PB00) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MICIN), MP_ROM_PTR(&pin_PB04) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MICOUT), MP_ROM_PTR(&pin_PA07) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_PA15) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_LOCK_BUTTON), MP_ROM_PTR(&pin_PA27) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_LATCH), MP_ROM_PTR(&pin_PB12) },
diff --git a/ports/atmel-samd/boards/pewpew10/mpconfigboard.h b/ports/atmel-samd/boards/pewpew10/mpconfigboard.h
index 6b3b4aa15..2cb097e8d 100644
--- a/ports/atmel-samd/boards/pewpew10/mpconfigboard.h
+++ b/ports/atmel-samd/boards/pewpew10/mpconfigboard.h
@@ -43,3 +43,5 @@
#define DEFAULT_UART_BUS_RX (&pin_PA01)
#define DEFAULT_UART_BUS_TX (&pin_PA00)
+
+#define SAMD21_BOD33_LEVEL (6)
diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h
index 60cd8d754..4b88c89f2 100644
--- a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h
+++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.h
@@ -40,3 +40,5 @@
#define IGNORE_PIN_PB09 1
#define IGNORE_PIN_PB10 1
#define IGNORE_PIN_PB11 1
+
+#define SAMD5x_E5x_BOD33_LEVEL (100)
diff --git a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk
index b6490433e..161477968 100644
--- a/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pewpew_m4/mpconfigboard.mk
@@ -10,45 +10,42 @@ INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
-# TODO: Turn off analogio for now for space reasons, but restore it
-# when frozen module gets smaller.
-CIRCUITPY_ANALOGIO = 0
CIRCUITPY_AUDIOBUSIO = 0
+CIRCUITPY_AUDIOPWMIO = 0
+CIRCUITPY_AUDIOMP3 = 0
CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_BITBANG_APA102 = 0
CIRCUITPY_FREQUENCYIO = 0
+CIRCUITPY_GAMEPADSHIFT = 0
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_NEOPIXEL_WRITE = 0
-CIRCUITPY_NETWORK = 0
CIRCUITPY_PIXELBUF = 0
CIRCUITPY_PS2IO = 0
+CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
+CIRCUITPY_SAMD = 0
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_USB_HID = 0
CIRCUITPY_USB_MIDI = 0
-CIRCUITPY_AUDIOPWMIO = 0
-CIRCUITPY_AUDIOMP3 = 0
-CIRCUITPY_BITBANG_APA102 = 0
-CIRCUITPY_BLEIO = 0
-CIRCUITPY_GAMEPADSHIFT = 0
-CIRCUITPY_NETWORK = 0
-CIRCUITPY_ROTARYIO = 0
-CIRCUITPY_SAMD = 0
-CIRCUITPY_TOUCHIO = 0
CIRCUITPY_VECTORIO = 0
+CIRCUITPY_ANALOGIO = 1
CIRCUITPY_AUDIOMIXER = 1
CIRCUITPY_AUDIOIO = 1
CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_GAMEPAD = 1
-CIRCUITPY_STAGE = 1
CIRCUITPY_MATH = 1
+CIRCUITPY_STAGE = 1
FROZEN_MPY_DIRS += $(TOP)/frozen/circuitpython-stage/pewpew_m4
CIRCUITPY_DISPLAY_FONT = $(TOP)/ports/atmel-samd/boards/ugame10/brutalist-6.bdf
# Tweak inlining depending on language.
ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
CFLAGS_INLINE_LIMIT = 45
else
CFLAGS_INLINE_LIMIT = 70
endif
+# Override optimization to keep binary small
+OPTIMIZATION_FLAGS = -Os
diff --git a/ports/atmel-samd/boards/pyruler/mpconfigboard.mk b/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
index 885f58e4e..4484b4ed9 100644
--- a/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pyruler/mpconfigboard.mk
@@ -15,5 +15,6 @@ SUPEROPT_GC = 0
CFLAGS_BOARD = --param max-inline-insns-auto=15
ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
CFLAGS_INLINE_LIMIT = 35
endif
diff --git a/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk b/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk
index ffc4f567f..7ac126514 100644
--- a/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/same54_xplained/mpconfigboard.mk
@@ -10,4 +10,5 @@ QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 2
EXTERNAL_FLASH_DEVICES = "N25Q256A"
LONGINT_IMPL = MPZ
-LONGINT_IMPL = MPZ
+
+CIRCUITPY_SDIOIO = 1
diff --git a/ports/atmel-samd/boards/same54_xplained/pins.c b/ports/atmel-samd/boards/same54_xplained/pins.c
index 5b9373724..8a864ab97 100644
--- a/ports/atmel-samd/boards/same54_xplained/pins.c
+++ b/ports/atmel-samd/boards/same54_xplained/pins.c
@@ -1,5 +1,18 @@
+#include "py/objtuple.h"
#include "shared-bindings/board/__init__.h"
+STATIC const mp_rom_obj_tuple_t sdio_data_tuple = {
+ {&mp_type_tuple},
+ 4,
+ {
+ MP_ROM_PTR(&pin_PB18),
+ MP_ROM_PTR(&pin_PB19),
+ MP_ROM_PTR(&pin_PB20),
+ MP_ROM_PTR(&pin_PB21),
+ }
+};
+
+
// This mapping only includes functional names because pins broken
// out on connectors are labeled with their MCU name available from
// microcontroller.pin.
@@ -95,5 +108,9 @@ STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c b/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c
new file mode 100644
index 000000000..b7fc736eb
--- /dev/null
+++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/board.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+#include "mpconfigboard.h"
+#include "hal/include/hal_gpio.h"
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+
+displayio_fourwire_obj_t board_display_obj;
+
+uint8_t display_init_sequence[] = {
+ 0x01, 0x80, 0x80, // Software reset then delay 0x80 (128ms)
+ 0xEF, 0x03, 0x03, 0x80, 0x02,
+ 0xCF, 0x03, 0x00, 0xC1, 0x30,
+ 0xED, 0x04, 0x64, 0x03, 0x12, 0x81,
+ 0xE8, 0x03, 0x85, 0x00, 0x78,
+ 0xCB, 0x05, 0x39, 0x2C, 0x00, 0x34, 0x02,
+ 0xF7, 0x01, 0x20,
+ 0xEA, 0x02, 0x00, 0x00,
+ 0xc0, 0x01, 0x23, // Power control VRH[5:0]
+ 0xc1, 0x01, 0x10, // Power control SAP[2:0];BT[3:0]
+ 0xc5, 0x02, 0x3e, 0x28, // VCM control
+ 0xc7, 0x01, 0x86, // VCM control2
+ 0x36, 0x01, 0x38, // Memory Access Control
+ 0x37, 0x01, 0x00, // Vertical scroll zero
+ 0x3a, 0x01, 0x55, // COLMOD: Pixel Format Set
+ 0xb1, 0x02, 0x00, 0x18, // Frame Rate Control (In Normal Mode/Full Colors)
+ 0xb6, 0x03, 0x08, 0x82, 0x27, // Display Function Control
+ 0xF2, 0x01, 0x00, // 3Gamma Function Disable
+ 0x26, 0x01, 0x01, // Gamma curve selected
+ 0xe0, 0x0f, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, // Set Gamma
+ 0xe1, 0x0f, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma
+ 0x11, 0x80, 0x78, // Exit Sleep then delay 0x78 (120ms)
+ 0x29, 0x80, 0x78, // Display on then delay 0x78 (120ms)
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_PB20, &pin_PB19, NULL);
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+ common_hal_displayio_fourwire_construct(bus,
+ spi,
+ &pin_PC06, // TFT_DC Command or data
+ &pin_PB21, // TFT_CS Chip select
+ &pin_PC07, // TFT_RST Reset
+ 60000000, // Baudrate
+ 0, // Polarity
+ 0); // Phase
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 320, // Width
+ 240, // Height
+ 0, // column start
+ 0, // row start
+ 180, // rotation
+ 16, // Color depth
+ false, // Grayscale
+ false, // pixels in a byte share a row. Only valid for depths < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ true, // reverse_pixels_in_word
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 0x37, // set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_PC05, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ true, // auto_refresh
+ 60, // native_frames_per_second
+ true); // backlight_on_high
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.h b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.h
new file mode 100644
index 000000000..f7d0448df
--- /dev/null
+++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.h
@@ -0,0 +1,32 @@
+#define MICROPY_HW_BOARD_NAME "Seeeduino Wio Terminal"
+#define MICROPY_HW_MCU_NAME "samd51p19"
+
+// Rev E
+
+#define MICROPY_HW_LED_STATUS (&pin_PA15)
+
+// These are pins not to reset.
+// QSPI Data pins
+#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11)
+// QSPI CS, QSPI SCK and NeoPixel pin
+#define MICROPY_PORT_B (PORT_PB03 | PORT_PB10 | PORT_PB11)
+#define MICROPY_PORT_C (0)
+#define MICROPY_PORT_D (0)
+
+#define EXTERNAL_FLASH_QSPI_DUAL
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_PA16)
+#define DEFAULT_I2C_BUS_SDA (&pin_PA17)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_PB03)
+#define DEFAULT_SPI_BUS_MOSI (&pin_PB02)
+#define DEFAULT_SPI_BUS_MISO (&pin_PB00)
+
+#define DEFAULT_UART_BUS_RX (&pin_PB27)
+#define DEFAULT_UART_BUS_TX (&pin_PB26)
+
+// USB is always used internally so skip the pin objects for it.
+#define IGNORE_PIN_PA24 1
+#define IGNORE_PIN_PA25 1
diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk
new file mode 100644
index 000000000..f57e016b4
--- /dev/null
+++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/mpconfigboard.mk
@@ -0,0 +1,14 @@
+USB_VID = 0x2886
+USB_PID = 0x802d
+USB_PRODUCT = "Seeeduino Wio Terminal"
+USB_MANUFACTURER = "Seeed"
+
+CHIP_VARIANT = SAMD51P19A
+CHIP_FAMILY = samd51
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "W25Q32JV_IQ"
+LONGINT_IMPL = MPZ
+
+CIRCUITPY_VECTORIO = 1
diff --git a/ports/atmel-samd/boards/seeeduino_wio_terminal/pins.c b/ports/atmel-samd/boards/seeeduino_wio_terminal/pins.c
new file mode 100644
index 000000000..0558191e6
--- /dev/null
+++ b/ports/atmel-samd/boards/seeeduino_wio_terminal/pins.c
@@ -0,0 +1,93 @@
+#include "shared-bindings/board/__init__.h"
+#include "shared-module/displayio/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+
+ // Analog pins
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_A6), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A7), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_A8), MP_ROM_PTR(&pin_PA06) },
+
+ // Digital pins
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PB04) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PB05) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PB06) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PB07) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) },
+
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA17) }, // MP_QSTR_SDA
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA16) }, //MP_QSTR_SCL
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_PA15) }, // MP_QSTR_LED
+
+ // UART pins
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PB26) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PB27) },
+
+ // SPI pins
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB03) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PB00) },
+ { MP_ROM_QSTR(MP_QSTR_CS), MP_ROM_PTR(&pin_PB01) },
+
+ // I2C pins
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA16) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA17) },
+
+ // LED pins
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_PA15) }, // status
+
+ // LCD Display
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MISO), MP_ROM_PTR(&pin_PB18) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_MOSI), MP_ROM_PTR(&pin_PB19) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_TFT_SCK), MP_ROM_PTR(&pin_PB20) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_CS), MP_ROM_PTR(&pin_PB21) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_DC), MP_ROM_PTR(&pin_PC06) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_BACKLIGHT), MP_ROM_PTR(&pin_PC05) },
+ { MP_ROM_QSTR(MP_QSTR_TFT_RESET), MP_ROM_PTR(&pin_PC07) },
+
+ // SD Card
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MISO), MP_ROM_PTR(&pin_PC18) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_MOSI), MP_ROM_PTR(&pin_PC16) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SD_SCK), MP_ROM_PTR(&pin_PC17) },
+ { MP_ROM_QSTR(MP_QSTR_SD_CS), MP_ROM_PTR(&pin_PC19) },
+ { MP_ROM_QSTR(MP_QSTR_SD_DET), MP_ROM_PTR(&pin_PC21) },
+
+ // Switch
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SWITCH_UP), MP_ROM_PTR(&pin_PD20) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SWITCH_LEFT), MP_ROM_PTR(&pin_PD12) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SWITCH_RIGHT), MP_ROM_PTR(&pin_PD09) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SWITCH_DOWN), MP_ROM_PTR(&pin_PD08) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SWITCH_PRESS), MP_ROM_PTR(&pin_PD10) },
+
+ // Button
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_1), MP_ROM_PTR(&pin_PC26) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_2), MP_ROM_PTR(&pin_PC27) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUTTON_3), MP_ROM_PTR(&pin_PC28) },
+
+ // Special named pins
+ { MP_OBJ_NEW_QSTR(MP_QSTR_LIGHT), MP_ROM_PTR(&pin_PD01) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_BUZZER), MP_ROM_PTR(&pin_PD11) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IR), MP_ROM_PTR(&pin_PB31) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_MIC), MP_ROM_PTR(&pin_PC30) },
+ { MP_ROM_QSTR(MP_QSTR_GYROSCOPE_SCL), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_GYROSCOPE_SDA), MP_ROM_PTR(&pin_PA13) },
+ { MP_ROM_QSTR(MP_QSTR_GYROSCOPE_INT), MP_ROM_PTR(&pin_PC21) },
+
+ // Comm objects
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk
index 13863e565..567f1db20 100644
--- a/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd51_thing_plus/mpconfigboard.mk
@@ -12,6 +12,4 @@ EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = AT25SF041A
LONGINT_IMPL = MPZ
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index aab5efd5d..735d42297 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -14,5 +14,11 @@ SUPEROPT_GC = 0
CFLAGS_BOARD = --param max-inline-insns-auto=15
ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
CFLAGS_INLINE_LIMIT = 35
endif
+ifeq ($(TRANSLATION), de_DE)
+RELEASE_NEEDS_CLEAN_BUILD = 1
+CFLAGS_INLINE_LIMIT = 35
+SUPEROPT_VM = 0
+endif
diff --git a/ports/atmel-samd/boards/uchip/mpconfigboard.mk b/ports/atmel-samd/boards/uchip/mpconfigboard.mk
index 90b5600dc..d08690a15 100644
--- a/ports/atmel-samd/boards/uchip/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/uchip/mpconfigboard.mk
@@ -9,3 +9,8 @@ CHIP_FAMILY = samd21
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_FULL_BUILD = 0
+
+# Always use aggressive inlining
+CFLAGS_INLINE_LIMIT = 45
+
+SUPEROPT_GC = 0
diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
index d641a89eb..bd320d9e4 100644
--- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk
@@ -35,6 +35,7 @@ CIRCUITPY_DISPLAY_FONT = $(TOP)/ports/atmel-samd/boards/ugame10/brutalist-6.bdf
# Tweak inlining depending on language.
ifeq ($(TRANSLATION), zh_Latn_pinyin)
+RELEASE_NEEDS_CLEAN_BUILD = 1
CFLAGS_INLINE_LIMIT = 45
else
CFLAGS_INLINE_LIMIT = 70
diff --git a/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk
index e06a2af7e..71586d6e0 100644
--- a/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/winterbloom_big_honking_button/mpconfigboard.mk
@@ -24,10 +24,13 @@ CIRCUITPY_BLEIO = 0
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_GAMEPAD = 0
CIRCUITPY_I2CPERIPHERAL = 0
-CIRCUITPY_NETWORK = 0
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_RGBMATRIX = 0
CIRCUITPY_PS2IO = 0
CIRCUITPY_USB_HID = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_RTC = 0
+
+# Enable board-specific modules
+USER_C_MODULES = boards/winterbloom_big_honking_button/usermods
+CFLAGS += -DMODULE_BHB_ENABLED=1
diff --git a/ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/bhb.c b/ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/bhb.c
new file mode 100644
index 000000000..54ce173d8
--- /dev/null
+++ b/ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/bhb.c
@@ -0,0 +1,120 @@
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "samd/pins.h"
+#include "sam.h"
+
+STATIC mp_obj_t _bhb_read_adc(void);
+
+STATIC mp_obj_t _bhb_init_adc(void) {
+ claim_pin(&pin_PB08);
+ common_hal_never_reset_pin(&pin_PB08);
+
+ /* Enable the APB clock for the ADC. */
+ PM->APBCMASK.reg |= PM_APBCMASK_ADC;
+
+ /* Enable GCLK0 for the ADC */
+ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN |
+ GCLK_CLKCTRL_GEN_GCLK0 |
+ GCLK_CLKCTRL_ID_ADC;
+
+ /* Wait for bus synchronization. */
+ while (GCLK->STATUS.bit.SYNCBUSY) {};
+
+ uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
+ uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
+ linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
+
+ /* Wait for bus synchronization. */
+ while (ADC->STATUS.bit.SYNCBUSY) {};
+
+ /* Write the calibration data. */
+ ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
+
+ /* Use the internal VCC reference. This is 1/2 of what's on VCCA.
+ since VCCA is 3.3v, this is 1.65v.
+ */
+ ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC1;
+
+ /* Capture 64 samples. */
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_64 | ADC_AVGCTRL_ADJRES(4);
+
+ /* Set the clock prescaler to 32, which is the same as the CircuitPython default.
+ Set the resolution to 16 for averaging
+ */
+ ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV32 |
+ ADC_CTRLB_RESSEL_16BIT;
+
+ /* Configure the input parameters.
+
+ - GAIN_DIV2 means that the input voltage is halved. This is important
+ because the voltage reference is 1/2 of VCCA. So if you want to
+ measure 0-3.3v, you need to halve the input as well.
+
+ - MUXNEG_GND means that the ADC should compare the input value to GND.
+
+ - MUXPOS_PIN3 means that the ADC should read from AIN2, or PB08.
+ */
+ ADC->INPUTCTRL.reg = ADC_INPUTCTRL_GAIN_DIV2 |
+ ADC_INPUTCTRL_MUXNEG_GND |
+ ADC_INPUTCTRL_MUXPOS_PIN2;
+
+
+ /* Set PB08 as an input pin. */
+ PORT->Group[1].DIRCLR.reg = PORT_PB08;
+
+ /* Enable the peripheral multiplexer for PB08. */
+ PORT->Group[1].PINCFG[8].reg |= PORT_PINCFG_PMUXEN;
+
+ /* Set PB08 to function B which is analog input. */
+ PORT->Group[1].PMUX[4].reg |= PORT_PMUX_PMUXE_B;
+
+ /* Wait for bus synchronization. */
+ while (ADC->STATUS.bit.SYNCBUSY) {};
+
+ /* Enable the ADC. */
+ ADC->CTRLA.bit.ENABLE = true;
+
+ /* Make one read and throw it away, as per the datasheet. */
+ _bhb_read_adc();
+
+ return mp_const_none;
+}
+
+STATIC mp_obj_t _bhb_read_adc(void) {
+ /* Wait for bus synchronization. */
+ while (ADC->STATUS.bit.SYNCBUSY) {};
+
+ /* Start the ADC using a software trigger. */
+ ADC->SWTRIG.bit.START = true;
+
+ /* Wait for the result ready flag to be set. */
+ while (ADC->INTFLAG.bit.RESRDY == 0);
+
+ /* Clear the flag. */
+ ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;
+
+ /* Read the value. */
+ uint32_t result = ADC->RESULT.reg;
+
+ return MP_OBJ_NEW_SMALL_INT(result);
+}
+
+
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(_bhb_init_adc_obj, _bhb_init_adc);
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(_bhb_read_adc_obj, _bhb_read_adc);
+
+STATIC const mp_rom_map_elem_t _bhb_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR__bhb) },
+ { MP_ROM_QSTR(MP_QSTR_init_adc), MP_ROM_PTR(&_bhb_init_adc_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read_adc), MP_ROM_PTR(&_bhb_read_adc_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(_bhb_module_globals, _bhb_module_globals_table);
+
+const mp_obj_module_t _bhb_user_cmodule = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&_bhb_module_globals,
+};
+
+MP_REGISTER_MODULE(MP_QSTR__bhb, _bhb_user_cmodule, MODULE_BHB_ENABLED);
diff --git a/ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/micropython.mk b/ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/micropython.mk
new file mode 100644
index 000000000..9374ec34e
--- /dev/null
+++ b/ports/atmel-samd/boards/winterbloom_big_honking_button/usermods/_bhb/micropython.mk
@@ -0,0 +1,6 @@
+USERMODULES_DIR := $(USERMOD_DIR)
+
+# Add all C files to SRC_USERMOD.
+SRC_USERMOD += $(USERMODULES_DIR)/bhb.c
+
+CFLAGS_USERMOD += -I$(USERMODULES_DIR)
diff --git a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk
index 11592073f..9217cdf23 100644
--- a/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/winterbloom_sol/mpconfigboard.mk
@@ -23,7 +23,6 @@ CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FRAMEBUFFERIO = 0
CIRCUITPY_GAMEPAD = 0
CIRCUITPY_I2CPERIPHERAL = 0
-CIRCUITPY_NETWORK = 0
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_RGBMATRIX = 0
CIRCUITPY_PS2IO = 0
diff --git a/ports/atmel-samd/common-hal/analogio/AnalogOut.c b/ports/atmel-samd/common-hal/analogio/AnalogOut.c
index e69a24071..fac4c6bfc 100644
--- a/ports/atmel-samd/common-hal/analogio/AnalogOut.c
+++ b/ports/atmel-samd/common-hal/analogio/AnalogOut.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
index 20fa624ed..0aa48c804 100644
--- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
+++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.c
@@ -27,6 +27,11 @@
#include <stdint.h>
#include <string.h>
+#include "mpconfigport.h"
+
+// Some boards don't implement I2SOut, so suppress any routines from here.
+#if CIRCUITPY_AUDIOBUSIO_I2SOUT
+
#include "extmod/vfs_fat.h"
#include "py/gc.h"
#include "py/mperrno.h"
@@ -382,3 +387,5 @@ bool common_hal_audiobusio_i2sout_get_playing(audiobusio_i2sout_obj_t* self) {
}
return still_playing;
}
+
+#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT
diff --git a/ports/atmel-samd/common-hal/audiobusio/I2SOut.h b/ports/atmel-samd/common-hal/audiobusio/I2SOut.h
index ce88f4de6..a66dae9bb 100644
--- a/ports/atmel-samd/common-hal/audiobusio/I2SOut.h
+++ b/ports/atmel-samd/common-hal/audiobusio/I2SOut.h
@@ -32,6 +32,9 @@
#include "audio_dma.h"
#include "py/obj.h"
+// Some boards don't implement I2SOut, so suppress any routines from here.
+#if CIRCUITPY_AUDIOBUSIO_I2SOUT
+
// We don't bit pack because we'll only have two at most. Its better to save code size instead.
typedef struct {
mp_obj_base_t base;
@@ -48,4 +51,6 @@ typedef struct {
void i2sout_reset(void);
+#endif // CIRCUITPY_AUDIOBUSIO_I2SOUT
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_AUDIOBUSIO_I2SOUT_H
diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
index 474512f5e..21474ab3b 100644
--- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
+++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@@ -84,12 +84,12 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
self->clock_pin = clock_pin; // PA10, PA20 -> SCK0, PB11 -> SCK1
#ifdef SAMD21
if (clock_pin == &pin_PA10
- #ifdef PIN_PA20
+ #if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20)
|| clock_pin == &pin_PA20
#endif
) {
self->clock_unit = 0;
- #ifdef PIN_PB11
+ #if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11)
} else if (clock_pin == &pin_PB11) {
self->clock_unit = 1;
#endif
@@ -98,7 +98,7 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
if (clock_pin == &pin_PA10 || clock_pin == &pin_PB16) {
self->clock_unit = 0;
} else if (clock_pin == &pin_PB12
- #ifdef PIN_PB28
+ #if defined(PIN_PB28) && !defined(IGNORE_PIN_PB28)
|| data_pin == &pin_PB28) {
#else
) {
@@ -112,14 +112,24 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
self->data_pin = data_pin; // PA07, PA19 -> SD0, PA08, PB16 -> SD1
#ifdef SAMD21
- if (data_pin == &pin_PA07 || data_pin == &pin_PA19) {
- self->serializer = 0;
- } else if (data_pin == &pin_PA08
- #ifdef PIN_PB16
- || data_pin == &pin_PB16) {
- #else
+ if (false
+ #if defined(PIN_PA07) && !defined(IGNORE_PIN_PA07)
+ || data_pin == &pin_PA07
+ #endif
+ #if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19)
+ || data_pin == &pin_PA19
+ #endif
) {
+ self->serializer = 0;
+ }
+ else if (false
+ #if defined(PIN_PA08) && !defined(IGNORE_PIN_PA08)
+ || data_pin == &pin_PA08
#endif
+ #if defined (PIN_PB16) && !defined(IGNORE_PIN_PB16)
+ || data_pin == &pin_PB16
+ #endif
+ ) {
self->serializer = 1;
#endif
#ifdef SAM_D5X_E5X
diff --git a/ports/atmel-samd/common-hal/board/__init__.c b/ports/atmel-samd/common-hal/board/__init__.c
index 634760335..92a172138 100644
--- a/ports/atmel-samd/common-hal/board/__init__.c
+++ b/ports/atmel-samd/common-hal/board/__init__.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c
index 1dc389027..921713d69 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.c
+++ b/ports/atmel-samd/common-hal/busio/SPI.c
@@ -341,7 +341,7 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
return status >= 0; // Status is number of chars read or an error code < 0.
}
-bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
if (len == 0) {
return true;
}
@@ -350,7 +350,7 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
status = sercom_dma_transfer(self->spi_desc.dev.prvt, data_out, data_in, len);
} else {
struct spi_xfer xfer;
- xfer.txbuf = data_out;
+ xfer.txbuf = (uint8_t*) data_out;
xfer.rxbuf = data_in;
xfer.size = len;
status = spi_m_sync_transfer(&self->spi_desc, &xfer);
diff --git a/ports/atmel-samd/common-hal/busio/UART.c b/ports/atmel-samd/common-hal/busio/UART.c
index b587eaaef..9557c3b5f 100644
--- a/ports/atmel-samd/common-hal/busio/UART.c
+++ b/ports/atmel-samd/common-hal/busio/UART.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 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
@@ -58,7 +58,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
- uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
bool sigint_enabled) {
@@ -195,7 +195,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
SERCOM_USART_CTRLA_FORM_Msk);
sercom->USART.CTRLA.reg |= SERCOM_USART_CTRLA_TXPO(tx_pad / 2) |
SERCOM_USART_CTRLA_RXPO(rx_pad) |
- (parity == PARITY_NONE ? 0 : SERCOM_USART_CTRLA_FORM(1));
+ (parity == BUSIO_UART_PARITY_NONE ? 0 : SERCOM_USART_CTRLA_FORM(1));
// Enable tx and/or rx based on whether the pins were specified.
// CHSIZE is 0 for 8 bits, 5, 6, 7 for 5, 6, 7 bits. 1 for 9 bits, but we don't support that.
@@ -206,7 +206,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
SERCOM_USART_CTRLB_CHSIZE_Msk);
sercom->USART.CTRLB.reg |= (have_tx ? SERCOM_USART_CTRLB_TXEN : 0) |
(have_rx ? SERCOM_USART_CTRLB_RXEN : 0) |
- (parity == PARITY_ODD ? SERCOM_USART_CTRLB_PMODE : 0) |
+ (parity == BUSIO_UART_PARITY_ODD ? SERCOM_USART_CTRLB_PMODE : 0) |
(stop > 1 ? SERCOM_USART_CTRLB_SBMODE : 0) |
SERCOM_USART_CTRLB_CHSIZE(bits % 8);
diff --git a/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
index 1952df563..02d0482dc 100644
--- a/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+++ b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
@@ -46,6 +46,7 @@
#include "hpl_gclk_config.h"
#include "shared-bindings/time/__init__.h"
+#include "supervisor/shared/tick.h"
#include "supervisor/shared/translate.h"
#ifdef SAMD21
@@ -132,7 +133,7 @@ void frequencyin_interrupt_handler(uint8_t index) {
}
// Check if we've reached the upper limit of detection
- if (!background_tasks_ok() || self->errored_too_fast) {
+ if (!supervisor_background_tasks_ok() || self->errored_too_fast) {
self->errored_too_fast = true;
frequencyin_emergency_cancel_capture(i);
}
diff --git a/ports/atmel-samd/common-hal/pulseio/PWMOut.c b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
index 752f6c214..e33437dad 100644
--- a/ports/atmel-samd/common-hal/pulseio/PWMOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PWMOut.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 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
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.c b/ports/atmel-samd/common-hal/pulseio/PulseIn.c
index 7ea20321b..ae58b089d 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseIn.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.c
@@ -42,6 +42,7 @@
#include "samd/timers.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/pulseio/PulseIn.h"
+#include "supervisor/shared/tick.h"
#include "supervisor/shared/translate.h"
// This timer is shared amongst all PulseIn objects as a higher resolution clock.
@@ -87,7 +88,7 @@ void pulsein_interrupt_handler(uint8_t channel) {
uint32_t current_count = tc->COUNT16.COUNT.reg;
pulseio_pulsein_obj_t* self = get_eic_channel_data(channel);
- if (!background_tasks_ok() || self->errored_too_fast) {
+ if (!supervisor_background_tasks_ok() || self->errored_too_fast) {
self->errored_too_fast = true;
common_hal_pulseio_pulsein_pause(self);
return;
@@ -125,6 +126,9 @@ void pulsein_interrupt_handler(uint8_t channel) {
}
void pulsein_reset() {
+#ifdef SAMD21
+ rtc_end_pulsein();
+#endif
refcount = 0;
pulsein_tc_index = 0xff;
overflow_count = 0;
@@ -221,6 +225,10 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self,
// Set config will enable the EIC.
pulsein_set_config(self, true);
+#ifdef SAMD21
+ rtc_start_pulsein();
+#endif
+
}
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
@@ -231,6 +239,9 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
if (common_hal_pulseio_pulsein_deinited(self)) {
return;
}
+#ifdef SAMD21
+ rtc_end_pulsein();
+#endif
set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
turn_off_eic_channel(self->channel);
reset_pin_number(self->pin);
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseIn.h b/ports/atmel-samd/common-hal/pulseio/PulseIn.h
index 89b61a83a..99358178f 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseIn.h
+++ b/ports/atmel-samd/common-hal/pulseio/PulseIn.h
@@ -50,5 +50,11 @@ void pulsein_reset(void);
void pulsein_interrupt_handler(uint8_t channel);
void pulsein_timer_interrupt_handler(uint8_t index);
+#ifdef SAMD21
+void rtc_set_continuous(void);
+void rtc_start_pulsein(void);
+void rtc_end_pulsein(void);
+#endif
+
#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PULSEIO_PULSEIN_H
diff --git a/ports/atmel-samd/common-hal/pulseio/PulseOut.c b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
index 5c829f84d..e9b2137cb 100644
--- a/ports/atmel-samd/common-hal/pulseio/PulseOut.c
+++ b/ports/atmel-samd/common-hal/pulseio/PulseOut.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 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
diff --git a/ports/atmel-samd/common-hal/sdioio/SDCard.c b/ports/atmel-samd/common-hal/sdioio/SDCard.c
new file mode 100644
index 000000000..8cd077ecd
--- /dev/null
+++ b/ports/atmel-samd/common-hal/sdioio/SDCard.c
@@ -0,0 +1,272 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Jeff Epler for Adafruit Industries
+ *
+ * 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 <stdbool.h>
+
+#include "py/mperrno.h"
+#include "py/runtime.h"
+
+#include "boards/board.h"
+#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/sdioio/SDCard.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "supervisor/shared/translate.h"
+
+#include "genhdr/sdiodata.h"
+
+#include "sd_mmc/sd_mmc.h"
+#include "sd_mmc/conf_sd_mmc.h"
+#include "peripheral_clk_config.h"
+
+#ifndef DEBUG_SDIO
+#define DEBUG_SDIO (0)
+#endif
+
+#if DEBUG_SDIO
+#define DEBUG_PRINT(...) ((void)mp_printf(&mp_plat_print, __VA_ARGS__))
+#define DEBUG_PRINT_OBJ(o) ((void)mp_obj_print_helper(&mp_plat_print, (mp_obj_t)o, PRINT_REPR))
+#else
+#define DEBUG_PRINT(...) ((void)0)
+#define DEBUG_PRINT_OBJ(...) ((void)0)
+#endif
+#define DEBUG_PRINT_OBJ_NL(o) (DEBUG_PRINT_OBJ(o), DEBUG_PRINT("\n"))
+
+#define GPIO_PIN_FUNCTION_SDIO (GPIO_PIN_FUNCTION_I)
+
+static Sdhc *sdhc_insts[] = SDHC_INSTS;
+
+STATIC pin_function_t *find_pin_function(pin_function_t *table, const mcu_pin_obj_t *pin, int instance, uint16_t name) {
+ DEBUG_PRINT("\n\n[inst=% 2d] %q: ", instance, name);
+ DEBUG_PRINT_OBJ_NL(pin);
+
+ for(; table->obj; table++) {
+ DEBUG_PRINT("[inst=% 2d] considering table @%p: ");
+ DEBUG_PRINT_OBJ(table->obj);
+ DEBUG_PRINT(" %d %d\n", table->instance, table->pin);
+ if (instance != -1 && instance != table->instance) {
+ continue;
+ }
+ if (pin == table->obj) {
+ return table;
+ }
+ }
+ mp_raise_ValueError_varg(translate("%q pin invalid"), name);
+}
+
+void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self,
+ const mcu_pin_obj_t * clock, const mcu_pin_obj_t * command,
+ uint8_t num_data, mcu_pin_obj_t ** data, uint32_t frequency) {
+ /*
+SD breakout as assembled ("*" = minimum viable set)
+
+PURPLE 9 DAT2 SDA
+BLUE 1 DAT3 SCL
+GREEN 2 CMD * D32
+YELLOW 3 VSS1
+RED 4 VDD * 3.3V
+BROWN 5 CLK * BROWN
+BLACK 6 VSS2 * GND
+WHITE 7 DAT0 * D8
+GREY 8 DAT1 D29
+
+DAT0..3 PB18..21 (D8 D29 D20 D21) WHITE GREY PURPLE BLUE
+CMD PA20 PCC_D? (D33) GREEN
+CLK PA21 PCC_D? (D32) BROWN
+
+*/
+
+ pin_function_t *functions[6] = {};
+ functions[0] = find_pin_function(sdio_cmd, command, -1, MP_QSTR_command);
+ int instance = functions[0]->instance;
+ functions[1] = find_pin_function(sdio_ck, clock, instance, MP_QSTR_clock);
+ functions[2] = find_pin_function(sdio_dat0, data[0], instance, MP_QSTR_data0);
+ if(num_data == 4) {
+ functions[3] = find_pin_function(sdio_dat1, data[1], instance, MP_QSTR_data1);
+ functions[4] = find_pin_function(sdio_dat2, data[2], instance, MP_QSTR_data2);
+ functions[5] = find_pin_function(sdio_dat3, data[3], instance, MP_QSTR_data3);
+ }
+
+ // We've verified all pins, now set their special functions
+ self->command_pin = common_hal_mcu_pin_number(functions[0]->obj);
+ self->clock_pin = common_hal_mcu_pin_number(functions[1]->obj);
+
+ for(int i=0; i<num_data; i++) {
+ pin_function_t *function = functions[2+i];
+ if (function) {
+ self->data_pins[i] = common_hal_mcu_pin_number(function->obj);
+ } else {
+ self->data_pins[i] = COMMON_HAL_MCU_NO_PIN;
+ }
+ }
+
+ for(size_t i=0; i<MP_ARRAY_SIZE(functions); i++) {
+ if (!functions[i]->obj) {
+ break;
+ }
+
+ gpio_set_pin_direction(functions[i]->pin, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(functions[i]->pin, false);
+ // Enable pullups on all pins except CLK and DAT3
+ gpio_set_pin_pull_mode(functions[i]->pin,
+ (i == 1 || i == 5) ? GPIO_PULL_OFF : GPIO_PULL_UP);
+ gpio_set_pin_function(functions[i]->pin, GPIO_PIN_FUNCTION_SDIO);
+
+ common_hal_never_reset_pin(functions[i]->obj);
+ }
+
+ self->num_data = num_data;
+ self->frequency = frequency;
+
+ if(instance == 0) {
+ hri_mclk_set_AHBMASK_SDHC0_bit(MCLK);
+ hri_gclk_write_PCHCTRL_reg(GCLK, SDHC0_GCLK_ID, CONF_GCLK_SDHC0_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
+ hri_gclk_write_PCHCTRL_reg(GCLK, SDHC0_GCLK_ID_SLOW, CONF_GCLK_SDHC0_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
+ } else {
+#ifdef SDHC1_GCLK_ID
+ hri_mclk_set_AHBMASK_SDHC1_bit(MCLK);
+ hri_gclk_write_PCHCTRL_reg(GCLK, SDHC1_GCLK_ID, CONF_GCLK_SDHC1_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
+ hri_gclk_write_PCHCTRL_reg(GCLK, SDHC1_GCLK_ID_SLOW, CONF_GCLK_SDHC1_SLOW_SRC | (1 << GCLK_PCHCTRL_CHEN_Pos));
+#endif
+ }
+
+ DEBUG_PRINT("instance %d @%p\n", instance, sdhc_insts[instance]);
+ mci_sync_init(&self->IO_BUS, sdhc_insts[instance]);
+ sd_mmc_init(&self->IO_BUS, NULL, NULL);
+
+ sd_mmc_err_t result = SD_MMC_INIT_ONGOING;
+
+ for (int i=0; result == SD_MMC_INIT_ONGOING && i<100; i++) {
+ result = sd_mmc_check(0);
+ DEBUG_PRINT("sd_mmc_check(0) -> %d\n", result);
+ }
+
+ if (result != SD_MMC_OK) {
+ mp_raise_OSError_msg_varg(translate("%q failure: %d"), MP_QSTR_sd_mmc_check, (int)result);
+ }
+ // sd_mmc_get_capacity() is in KiB, but our "capacity" is in 512-byte blocks
+ self->capacity = sd_mmc_get_capacity(0) * 2;
+
+ DEBUG_PRINT("capacity=%u\n", self->capacity);
+}
+
+uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t *self) {
+ return self->capacity;
+}
+
+uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t *self) {
+ return self->frequency; // self->frequency;
+}
+
+uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t *self) {
+ return self->num_data; // self->width;
+}
+
+STATIC void check_for_deinit(sdioio_sdcard_obj_t *self) {
+}
+
+STATIC void check_whole_block(mp_buffer_info_t *bufinfo) {
+ if (bufinfo->len % 512) {
+ mp_raise_ValueError(translate("Buffer length must be a multiple of 512"));
+ }
+}
+
+STATIC void wait_write_complete(sdioio_sdcard_obj_t *self) {
+ if (self->state_programming) {
+ sd_mmc_wait_end_of_write_blocks(0);
+ self->state_programming = 0;
+ }
+}
+
+STATIC void debug_print_state(sdioio_sdcard_obj_t *self, const char *what, sd_mmc_err_t r) {
+#if DEBUG_SDIO
+ DEBUG_PRINT("%s: %d\n", what, r);
+#endif
+}
+
+int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
+ check_for_deinit(self);
+ check_whole_block(bufinfo);
+ wait_write_complete(self);
+ self->state_programming = true;
+ sd_mmc_err_t r = sd_mmc_init_write_blocks(0, start_block, bufinfo->len / 512);
+ if (r != SD_MMC_OK) {
+ debug_print_state(self, "sd_mmc_init_write_blocks", r);
+ return -EIO;
+ }
+ r = sd_mmc_start_write_blocks(bufinfo->buf, bufinfo->len / 512);
+ if (r != SD_MMC_OK) {
+ debug_print_state(self, "sd_mmc_start_write_blocks", r);
+ return -EIO;
+ }
+ // debug_print_state(self, "after writeblocks OK");
+ return 0;
+}
+
+int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t *self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
+ check_for_deinit(self);
+ check_whole_block(bufinfo);
+ wait_write_complete(self);
+ sd_mmc_err_t r = sd_mmc_init_read_blocks(0, start_block, bufinfo->len / 512);
+ if (r != SD_MMC_OK) {
+ debug_print_state(self, "sd_mmc_init_read_blocks", r);
+ return -EIO;
+ }
+ r = sd_mmc_start_read_blocks(bufinfo->buf, bufinfo->len / 512);
+ if (r != SD_MMC_OK) {
+ debug_print_state(self, "sd_mmc_start_read_blocks", r);
+ return -EIO;
+ }
+ sd_mmc_wait_end_of_write_blocks(0);
+ return 0;
+}
+
+bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t frequency, uint8_t bits) {
+ check_for_deinit(self);
+ return true;
+}
+
+bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self) {
+ return self->command_pin == COMMON_HAL_MCU_NO_PIN;
+}
+
+void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) {
+ reset_pin_number(self->command_pin);
+ reset_pin_number(self->clock_pin);
+ reset_pin_number(self->data_pins[0]);
+ reset_pin_number(self->data_pins[1]);
+ reset_pin_number(self->data_pins[2]);
+ reset_pin_number(self->data_pins[3]);
+
+ self->command_pin = COMMON_HAL_MCU_NO_PIN;
+ self->clock_pin = COMMON_HAL_MCU_NO_PIN;
+ self->data_pins[0] = COMMON_HAL_MCU_NO_PIN;
+ self->data_pins[1] = COMMON_HAL_MCU_NO_PIN;
+ self->data_pins[2] = COMMON_HAL_MCU_NO_PIN;
+ self->data_pins[3] = COMMON_HAL_MCU_NO_PIN;
+}
+
+void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) {
+}
diff --git a/ports/atmel-samd/common-hal/sdioio/SDCard.h b/ports/atmel-samd/common-hal/sdioio/SDCard.h
new file mode 100644
index 000000000..2baba38f0
--- /dev/null
+++ b/ports/atmel-samd/common-hal/sdioio/SDCard.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "hal_mci_sync.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ struct mci_sync_desc IO_BUS;
+ uint32_t frequency;
+ uint32_t capacity;
+ uint8_t num_data:3, state_programming:1, has_lock:1;
+ uint8_t command_pin;
+ uint8_t clock_pin;
+ uint8_t data_pins[4];
+} sdioio_sdcard_obj_t;
diff --git a/ports/atmel-samd/common-hal/sdioio/__init__.c b/ports/atmel-samd/common-hal/sdioio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/atmel-samd/common-hal/sdioio/__init__.c
diff --git a/ports/atmel-samd/common-hal/sdioio/__init__.h b/ports/atmel-samd/common-hal/sdioio/__init__.h
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/atmel-samd/common-hal/sdioio/__init__.h
diff --git a/ports/atmel-samd/fatfs_port.c b/ports/atmel-samd/fatfs_port.c
index c4ce18c2a..c65a73a42 100644
--- a/ports/atmel-samd/fatfs_port.c
+++ b/ports/atmel-samd/fatfs_port.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h
index 354097ce4..2a2428d67 100644
--- a/ports/atmel-samd/mpconfigport.h
+++ b/ports/atmel-samd/mpconfigport.h
@@ -109,7 +109,15 @@
#endif
#ifndef CIRCUITPY_DEFAULT_STACK_SIZE
-#define CIRCUITPY_DEFAULT_STACK_SIZE 4096
+#define CIRCUITPY_DEFAULT_STACK_SIZE 3584
+#endif
+
+#ifndef SAMD21_BOD33_LEVEL
+// Set brownout detection to ~2.7V. Default from factory is 1.7V,
+// which is too low for proper operation of external SPI flash chips
+// (they are 2.7-3.6V).
+#define SAMD21_BOD33_LEVEL (39)
+// 2.77V with hysteresis off. Table 37.20 in datasheet.
#endif
// Smallest unit of flash that can be erased.
@@ -129,6 +137,14 @@
#define CIRCUITPY_DEFAULT_STACK_SIZE (24*1024)
#endif
+#ifndef SAMD5x_E5x_BOD33_LEVEL
+// Set brownout detection to ~2.7V. Default from factory is 1.7V,
+// which is too low for proper operation of external SPI flash chips
+// (they are 2.7-3.6V).
+#define SAMD5x_E5x_BOD33_LEVEL (200)
+// 2.7V: 1.5V + LEVEL * 6mV.
+#endif
+
// Smallest unit of flash that can be erased.
#define FLASH_ERASE_SIZE NVMCTRL_BLOCK_SIZE
diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk
index 92d47b186..e4cf9ca83 100644
--- a/ports/atmel-samd/mpconfigport.mk
+++ b/ports/atmel-samd/mpconfigport.mk
@@ -37,6 +37,8 @@ ifndef CIRCUITPY_TOUCHIO_USE_NATIVE
CIRCUITPY_TOUCHIO_USE_NATIVE = 1
endif
+CIRCUITPY_SDCARDIO ?= 0
+
# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
USB_MSC_EP_NUM_OUT = 1
@@ -52,8 +54,7 @@ CIRCUITPY_TOUCHIO_USE_NATIVE = 0
# The ifndef's allow overriding in mpconfigboard.mk.
ifndef CIRCUITPY_NETWORK
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
+CIRCUITPY_NETWORK = 0
endif
ifndef CIRCUITPY_PS2IO
diff --git a/ports/atmel-samd/mphalport.h b/ports/atmel-samd/mphalport.h
index f11971749..adc65ade5 100644
--- a/ports/atmel-samd/mphalport.h
+++ b/ports/atmel-samd/mphalport.h
@@ -37,8 +37,8 @@
#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32())
// Number of bytes in receive buffer
-volatile uint8_t usb_rx_count;
-volatile bool mp_cdc_enabled;
+extern volatile uint8_t usb_rx_count;
+extern volatile bool mp_cdc_enabled;
int receive_usb(void);
diff --git a/ports/atmel-samd/sd_mmc/conf_sd_mmc.h b/ports/atmel-samd/sd_mmc/conf_sd_mmc.h
new file mode 100644
index 000000000..735dd3783
--- /dev/null
+++ b/ports/atmel-samd/sd_mmc/conf_sd_mmc.h
@@ -0,0 +1,79 @@
+/* Auto-generated config file conf_sd_mmc.h */
+#ifndef CONF_SD_MMC_H
+#define CONF_SD_MMC_H
+
+// <<< Use Configuration Wizard in Context Menu >>>
+
+// <q> Enable the SDIO support
+// <id> conf_sdio_support
+#ifndef CONF_SDIO_SUPPORT
+#define CONF_SDIO_SUPPORT 0
+#endif
+
+// <q> Enable the MMC card support
+// <id> conf_mmc_support
+#ifndef CONF_MMC_SUPPORT
+#define CONF_MMC_SUPPORT 0
+#endif
+
+// <q> Enable the OS support
+// <id> conf_sd_mmc_os_support
+#ifndef CONF_OS_SUPPORT
+#define CONF_OS_SUPPORT 0
+#endif
+
+// Detection (card/write protect) timeout (ms/ticks)
+// conf_sd_mmc_debounce
+#ifndef CONF_SD_MMC_DEBOUNCE
+#define CONF_SD_MMC_DEBOUNCE 1000
+#endif
+
+#ifndef CONF_SD_MMC_MEM_CNT
+#define CONF_SD_MMC_MEM_CNT 1
+#endif
+
+// <e> SD/MMC Slot 0
+// <id> conf_sd_mmc_0_enable
+#ifndef CONF_SD_MMC_0_ENABLE
+#define CONF_SD_MMC_0_ENABLE 1
+#endif
+
+// <e> Card Detect (CD) 0 Enable
+// <id> conf_sd_mmc_0_cd_detect_en
+#ifndef CONF_SD_MMC_0_CD_DETECT_EN
+#define CONF_SD_MMC_0_CD_DETECT_EN 0
+#endif
+
+// <o> Card Detect (CD) detection level
+// <1=> High
+// <0=> Low
+// <id> conf_sd_mmc_0_cd_detect_value
+#ifndef CONF_SD_MMC_0_CD_DETECT_VALUE
+#define CONF_SD_MMC_0_CD_DETECT_VALUE 0
+#endif
+// </e>
+
+// <e> Write Protect (WP) 0 Enable
+// <id> conf_sd_mmc_0_wp_detect_en
+#ifndef CONF_SD_MMC_0_WP_DETECT_EN
+#define CONF_SD_MMC_0_WP_DETECT_EN 0
+#endif
+
+// <o> Write Protect (WP) detection level
+// <1=> High
+// <0=> Low
+// <id> conf_sd_mmc_0_wp_detect_value
+#ifndef CONF_SD_MMC_0_WP_DETECT_VALUE
+#define CONF_SD_MMC_0_WP_DETECT_VALUE 1
+#endif
+// </e>
+
+// </e>
+
+#ifndef CONF_MCI_OS_SUPPORT
+#define CONF_MCI_OS_SUPPORT 0
+#endif
+
+// <<< end of configuration section >>>
+
+#endif // CONF_SD_MMC_H
diff --git a/ports/atmel-samd/sd_mmc/sd_mmc.c b/ports/atmel-samd/sd_mmc/sd_mmc.c
new file mode 100644
index 000000000..5ea9d830e
--- /dev/null
+++ b/ports/atmel-samd/sd_mmc/sd_mmc.c
@@ -0,0 +1,1671 @@
+/**
+ * \file
+ *
+ * \brief Common SD/MMC stack
+ *
+ * Copyright (c) 2016-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#include <string.h>
+
+#include "conf_sd_mmc.h"
+
+#include "sd_mmc_protocol.h"
+#include "sd_mmc.h"
+
+#if CONF_OS_SUPPORT
+#include <hal_rtos.h>
+#endif
+#include <hal_gpio.h>
+#include <utils.h>
+#include <utils_assert.h>
+#include <utils_repeat_macro.h>
+
+#define TPASTE2(a, b) a##b
+#define ATPASTE2(a, b) TPASTE2(a, b)
+
+/**
+ * \ingroup sd_mmc_stack
+ * \defgroup sd_mmc_stack_internal Implementation of SD/MMC/SDIO Stack
+ * @{
+ */
+
+#ifndef CONF_SD_MMC_MEM_CNT
+#define CONF_SD_MMC_MEM_CNT 0
+#endif
+
+/* Macros to switch SD MMC stack to the correct driver (MCI or SPI) */
+#if (CONF_SD_MMC_MEM_CNT != 0)
+#if CONF_MCI_OS_SUPPORT
+#include "hal_mci_os.h"
+#else
+#include "hal_mci_sync.h"
+#endif
+#define driver mci
+#else
+#error No MCI or HSMCI interfaces are defined for SD MMC stack. \
+ CONF_SD_MMC_MEM_CNT must be added in board.h file.
+#endif
+
+#if CONF_MCI_OS_SUPPORT
+#define driver_select_device ATPASTE2(driver, _os_select_device)
+#define driver_deselect_device ATPASTE2(driver, _os_deselect_device)
+#define driver_get_bus_width ATPASTE2(driver, _os_get_bus_width)
+#define driver_is_high_speed_capable ATPASTE2(driver, _os_is_high_speed_capable)
+#define driver_send_clock ATPASTE2(driver, _os_send_init_sequence)
+#define driver_send_cmd ATPASTE2(driver, _os_send_cmd)
+#define driver_get_response ATPASTE2(driver, _os_get_response)
+#define driver_get_response_128 ATPASTE2(driver, _os_get_response_128)
+#define driver_adtc_start ATPASTE2(driver, _os_adtc_start)
+#define driver_adtc_stop ATPASTE2(driver, _os_send_cmd)
+#define driver_read_word ATPASTE2(driver, _os_read_bytes)
+#define driver_write_word ATPASTE2(driver, _os_write_bytes)
+#define driver_start_read_blocks ATPASTE2(driver, _os_start_read_blocks)
+#define driver_wait_end_of_read_blocks ATPASTE2(driver, _os_wait_end_of_read_blocks)
+#define driver_start_write_blocks ATPASTE2(driver, _os_start_write_blocks)
+#define driver_wait_end_of_write_blocks ATPASTE2(driver, _os_wait_end_of_write_blocks)
+#else
+#define driver_select_device ATPASTE2(driver, _sync_select_device)
+#define driver_deselect_device ATPASTE2(driver, _sync_deselect_device)
+#define driver_get_bus_width ATPASTE2(driver, _sync_get_bus_width)
+#define driver_is_high_speed_capable ATPASTE2(driver, _sync_is_high_speed_capable)
+#define driver_send_clock ATPASTE2(driver, _sync_send_clock)
+#define driver_send_cmd ATPASTE2(driver, _sync_send_cmd)
+#define driver_get_response ATPASTE2(driver, _sync_get_response)
+#define driver_get_response_128 ATPASTE2(driver, _sync_get_response_128)
+#define driver_adtc_start ATPASTE2(driver, _sync_adtc_start)
+#define driver_adtc_stop ATPASTE2(driver, _sync_send_cmd)
+#define driver_read_word ATPASTE2(driver, _sync_read_word)
+#define driver_write_word ATPASTE2(driver, _sync_write_word)
+#define driver_start_read_blocks ATPASTE2(driver, _sync_start_read_blocks)
+#define driver_wait_end_of_read_blocks ATPASTE2(driver, _sync_wait_end_of_read_blocks)
+#define driver_start_write_blocks ATPASTE2(driver, _sync_start_write_blocks)
+#define driver_wait_end_of_write_blocks ATPASTE2(driver, _sync_wait_end_of_write_blocks)
+#endif
+
+#if (CONF_SDIO_SUPPORT == 1)
+#define IS_SDIO() (sd_mmc_card->type & CARD_TYPE_SDIO)
+#else
+#define IS_SDIO() false
+#endif
+
+/** This SD MMC stack supports only the high voltage */
+#define SD_MMC_VOLTAGE_SUPPORT \
+ (OCR_VDD_27_28 | OCR_VDD_28_29 | OCR_VDD_29_30 | OCR_VDD_30_31 | OCR_VDD_31_32 | OCR_VDD_32_33)
+
+/** SD/MMC card states */
+enum card_state {
+ SD_MMC_CARD_STATE_READY = 0, /**< Ready to use */
+ SD_MMC_CARD_STATE_DEBOUNCE = 1, /**< Debounce on going */
+ SD_MMC_CARD_STATE_INIT = 2, /**< Initialization on going */
+ SD_MMC_CARD_STATE_UNUSABLE = 3, /**< Unusable card */
+ SD_MMC_CARD_STATE_NO_CARD = 4 /**< No SD/MMC card inserted */
+};
+
+/** SD/MMC card information structure */
+struct sd_mmc_card {
+ uint32_t clock; /**< Card access clock */
+ uint32_t capacity; /**< Card capacity in KBytes */
+ uint16_t rca; /**< Relative card address */
+ enum card_state state; /**< Card state */
+ card_type_t type; /**< Card type */
+ card_version_t version; /**< Card version */
+ uint8_t bus_width; /**< Number of DATA lin on bus (MCI only) */
+ uint8_t csd[CSD_REG_BSIZE]; /**< CSD register */
+ uint8_t high_speed; /**< High speed card (1) */
+};
+
+/** Card detect pin */
+static sd_mmc_detect_t *_cd;
+/** Write protect pin */
+static sd_mmc_detect_t *_wp;
+
+/** SD/MMC card list */
+/** Note: Initialize card detect pin fields if present */
+static struct sd_mmc_card sd_mmc_cards[CONF_SD_MMC_MEM_CNT];
+
+/** HAL driver instance */
+static void *sd_mmc_hal;
+/** Index of current slot configurated */
+static uint8_t sd_mmc_slot_sel;
+/** Pointer on current slot configurated */
+static struct sd_mmc_card *sd_mmc_card;
+/** Number of block to read or write on the current transfer */
+static uint16_t sd_mmc_nb_block_to_tranfer = 0;
+/** Number of block remaining to read or write on the current transfer */
+static uint16_t sd_mmc_nb_block_remaining = 0;
+
+/** SD/MMC transfer rate unit codes (10K) list */
+const uint32_t sd_mmc_trans_units[7] = {10, 100, 1000, 10000, 0, 0, 0};
+/** SD transfer multiplier factor codes (1/10) list */
+const uint32_t sd_trans_multipliers[16] = {0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80};
+/** MMC transfer multiplier factor codes (1/10) list */
+const uint32_t mmc_trans_multipliers[16] = {0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80};
+
+/** \name MMC, SD and SDIO commands process */
+/** @{ */
+#if CONF_MMC_SUPPORT
+static bool mmc_mci_op_cond(void);
+static bool mmc_cmd6_set_bus_width(uint8_t bus_width);
+static bool mmc_cmd6_set_high_speed(void);
+static bool mmc_cmd8(uint8_t *b_authorize_high_speed);
+static void mmc_decode_csd(void);
+#endif
+static bool sd_mci_op_cond(uint8_t v2);
+static bool sdio_op_cond(void);
+static bool sdio_get_max_speed(void);
+static bool sdio_cmd52_set_bus_width(void);
+static bool sdio_cmd52_set_high_speed(void);
+static bool sd_cm6_set_high_speed(void);
+static bool sd_cmd8(uint8_t *v2);
+static bool sd_mmc_cmd9_mci(void);
+static void sd_decode_csd(void);
+static bool sd_mmc_cmd13(void);
+#if (CONF_SDIO_SUPPORT == 1)
+static bool sdio_cmd52(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t rd_after_wr, uint8_t *io_data);
+static bool sdio_cmd53(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t inc_addr, uint32_t size,
+ bool access_block);
+#endif
+static bool sd_acmd6(void);
+static bool sd_acmd51(void);
+/** @} */
+
+/** \name Internal function to process the initialization and install */
+/** @{ */
+static sd_mmc_err_t sd_mmc_select_slot(uint8_t slot);
+static void sd_mmc_configure_slot(void);
+static void sd_mmc_deselect_slot(void);
+static bool sd_mmc_mci_card_init(void);
+#if CONF_MMC_SUPPORT
+static bool sd_mmc_mci_install_mmc(void);
+#endif
+/** @} */
+
+/** \name Internal functions to manage a large timeout after a card insertion */
+/** @{ */
+#if CONF_OS_SUPPORT
+#define SD_MMC_START_TIMEOUT() os_sleep(CONF_SD_MMC_DEBOUNCE)
+#else
+#define SD_MMC_START_TIMEOUT()
+#endif
+#define SD_MMC_IS_TIMEOUT() true
+#define SD_MMC_STOP_TIMEOUT()
+/** @} */
+
+#if CONF_MMC_SUPPORT
+/**
+ * \brief Sends operation condition command and read OCR (MCI only)
+ * - CMD1 sends operation condition command
+ * - CMD1 reads OCR
+ *
+ * \return true if success, otherwise false
+ */
+static bool mmc_mci_op_cond(void)
+{
+ uint32_t retry, resp;
+
+ /*
+ * Timeout 1s = 400KHz / ((6+6)*8) cylces = 4200 retry
+ * 6 = cmd byte size
+ * 6 = response byte size
+ */
+ retry = 4200;
+ do {
+ if (!driver_send_cmd(sd_mmc_hal, MMC_MCI_CMD1_SEND_OP_COND, SD_MMC_VOLTAGE_SUPPORT | OCR_ACCESS_MODE_SECTOR)) {
+ return false;
+ }
+ /* Check busy flag */
+ resp = driver_get_response(sd_mmc_hal);
+ if (resp & OCR_POWER_UP_BUSY) {
+ /* Check OCR value */
+ if ((resp & OCR_ACCESS_MODE_MASK) == OCR_ACCESS_MODE_SECTOR) {
+ sd_mmc_card->type |= CARD_TYPE_HC;
+ }
+ break;
+ }
+ if (retry-- == 0) {
+ return false;
+ }
+ } while (1);
+ return true;
+}
+#endif
+
+/**
+ * \brief Ask to all cards to send their operations conditions (MCI only).
+ * - ACMD41 sends operation condition command.
+ * - ACMD41 reads OCR
+ *
+ * \param v2 Shall be 1 if it is a SD card V2
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_mci_op_cond(uint8_t v2)
+{
+ uint32_t arg, retry, resp;
+
+ /*
+ * Timeout 1s = 400KHz / ((6+6+6+6)*8) cylces = 2100 retry
+ * 6 = cmd byte size
+ * 6 = response byte size
+ * 6 = cmd byte size
+ * 6 = response byte size
+ */
+ retry = 2100;
+ do {
+ /* CMD55 - Indicate to the card that the next command is an
+ * application specific command rather than a standard command.*/
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, 0)) {
+ return false;
+ }
+
+ /* (ACMD41) Sends host OCR register */
+ arg = SD_MMC_VOLTAGE_SUPPORT;
+ if (v2) {
+ arg |= SD_ACMD41_HCS;
+ }
+ /* Check response */
+ if (!driver_send_cmd(sd_mmc_hal, SD_MCI_ACMD41_SD_SEND_OP_COND, arg)) {
+ return false;
+ }
+ resp = driver_get_response(sd_mmc_hal);
+ if (resp & OCR_POWER_UP_BUSY) {
+ /* Card is ready */
+ if ((resp & OCR_CCS) != 0) {
+ sd_mmc_card->type |= CARD_TYPE_HC;
+ }
+ break;
+ }
+ if (retry-- == 0) {
+ return false;
+ }
+ } while (1);
+ return true;
+}
+
+#if (CONF_SDIO_SUPPORT == 1)
+/**
+ * \brief Try to get the SDIO card's operating condition
+ * - CMD5 to read OCR NF field
+ * - CMD5 to wait OCR power up busy
+ * - CMD5 to read OCR MP field
+ * sd_mmc_card->type is updated
+ *
+ * \return true if success, otherwise false
+ */
+static bool sdio_op_cond(void)
+{
+ uint32_t resp;
+
+ /* CMD5 - SDIO send operation condition (OCR) command. */
+ if (!driver_send_cmd(sd_mmc_hal, SDIO_CMD5_SEND_OP_COND, 0)) {
+ return true; /* No error but card type not updated */
+ }
+ resp = driver_get_response(sd_mmc_hal);
+ if ((resp & OCR_SDIO_NF) == 0) {
+ return true; /* No error but card type not updated */
+ }
+
+ /*
+ * Wait card ready
+ * Timeout 1s = 400KHz / ((6+4)*8) cylces = 5000 retry
+ * 6 = cmd byte size
+ * 4(SPI) 6(MCI) = response byte size
+ */
+ uint32_t cmd5_retry = 5000;
+ while (1) {
+ /* CMD5 - SDIO send operation condition (OCR) command.*/
+ if (!driver_send_cmd(sd_mmc_hal, SDIO_CMD5_SEND_OP_COND, resp & SD_MMC_VOLTAGE_SUPPORT)) {
+ return false;
+ }
+ resp = driver_get_response(sd_mmc_hal);
+ if ((resp & OCR_POWER_UP_BUSY) == OCR_POWER_UP_BUSY) {
+ break;
+ }
+ if (cmd5_retry-- == 0) {
+ return false;
+ }
+ }
+ /* Update card type at the end of busy */
+ if ((resp & OCR_SDIO_MP) > 0) {
+ sd_mmc_card->type = CARD_TYPE_SD_COMBO;
+ } else {
+ sd_mmc_card->type = CARD_TYPE_SDIO;
+ }
+ return true; /* No error and card type updated with SDIO type */
+}
+
+/**
+ * \brief Get SDIO max transfer speed in Hz.
+ * - CMD53 reads CIS area address in CCCR area.
+ * - Nx CMD53 search Fun0 tuple in CIS area
+ * - CMD53 reads TPLFE_MAX_TRAN_SPEED in Fun0 tuple
+ * - Compute maximum speed of SDIO
+ * and update sd_mmc_card->clock
+ *
+ * \return true if success, otherwise false
+ */
+static bool sdio_get_max_speed(void)
+{
+ uint32_t addr_new, addr_old;
+ uint8_t buf[6];
+ uint32_t unit;
+ uint32_t mul;
+ uint8_t tplfe_max_tran_speed, i;
+ uint8_t addr_cis[4];
+
+ /* Read CIS area address in CCCR area */
+ addr_old = SDIO_CCCR_CIS_PTR;
+ for (i = 0; i < 4; i++) {
+ sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_old, 0, &addr_cis[i]);
+ addr_old++;
+ }
+ addr_old = addr_cis[0] + (addr_cis[1] << 8) + (addr_cis[2] << 16) + (addr_cis[3] << 24);
+ addr_new = addr_old;
+
+ while (1) {
+ /* Read a sample of CIA area */
+ for (i = 0; i < 3; i++) {
+ sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_new, 0, &buf[i]);
+ addr_new++;
+ }
+ if (buf[0] == SDIO_CISTPL_END) {
+ return false; /* Tuple error */
+ }
+ if (buf[0] == SDIO_CISTPL_FUNCE && buf[2] == 0x00) {
+ break; /* Fun0 tuple found */
+ }
+ if (buf[1] == 0) {
+ return false; /* Tuple error */
+ }
+ /* Next address */
+ addr_new += buf[1] - 1;
+ if (addr_new > (addr_old + 256)) {
+ return false; /* Outoff CIS area */
+ }
+ }
+
+ /* Read all Fun0 tuple fields: fn0_blk_siz & max_tran_speed */
+ addr_new -= 3;
+ for (i = 0; i < 6; i++) {
+ sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, addr_new, 0, &buf[i]);
+ addr_new++;
+ }
+
+ tplfe_max_tran_speed = buf[5];
+ if (tplfe_max_tran_speed > 0x32) {
+ /* Error on SDIO register, the high speed is not activated
+ * and the clock can not be more than 25MHz.
+ * This error is present on specific SDIO card
+ * (H&D wireless card - HDG104 WiFi SIP).
+ */
+ tplfe_max_tran_speed = 0x32; /* 25Mhz */
+ }
+
+ /* Decode transfer speed in Hz.*/
+ unit = sd_mmc_trans_units[tplfe_max_tran_speed & 0x7];
+ mul = sd_trans_multipliers[(tplfe_max_tran_speed >> 3) & 0xF];
+ sd_mmc_card->clock = unit * mul * 1000;
+ /**
+ * Note: A combo card shall be a Full-Speed SDIO card
+ * which supports upto 25MHz.
+ * A SDIO card alone can be:
+ * - a Low-Speed SDIO card which supports 400Khz minimum
+ * - a Full-Speed SDIO card which supports upto 25MHz
+ */
+ return true;
+}
+
+/**
+ * \brief CMD52 for SDIO - Switches the bus width mode to 4
+ *
+ * \note sd_mmc_card->bus_width is updated.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sdio_cmd52_set_bus_width(void)
+{
+ /**
+ * A SD memory card always supports bus 4bit
+ * A SD COMBO card always supports bus 4bit
+ * A SDIO Full-Speed alone always supports 4bit
+ * A SDIO Low-Speed alone can supports 4bit (Optional)
+ */
+ uint8_t u8_value;
+
+ /* Check 4bit support in 4BLS of "Card Capability" register */
+ if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, SDIO_CCCR_CAP, 0, &u8_value)) {
+ return false;
+ }
+ if ((u8_value & SDIO_CAP_4BLS) != SDIO_CAP_4BLS) {
+ /* No supported, it is not a protocol error */
+ return true;
+ }
+ /* HS mode possible, then enable */
+ u8_value = SDIO_BUSWIDTH_4B;
+ if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_BUS_CTRL, 1, &u8_value)) {
+ return false;
+ }
+ sd_mmc_card->bus_width = 4;
+ return true;
+}
+
+/**
+ * \brief CMD52 for SDIO - Enable the high speed mode
+ *
+ * \note sd_mmc_card->high_speed is updated.
+ * \note sd_mmc_card->clock is updated.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sdio_cmd52_set_high_speed(void)
+{
+ uint8_t u8_value;
+
+ /* Check CIA.HS */
+ if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, SDIO_CIA, SDIO_CCCR_HS, 0, &u8_value)) {
+ return false;
+ }
+ if ((u8_value & SDIO_SHS) != SDIO_SHS) {
+ /* No supported, it is not a protocol error */
+ return true;
+ }
+ /* HS mode possible, then enable */
+ u8_value = SDIO_EHS;
+ if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_HS, 1, &u8_value)) {
+ return false;
+ }
+ sd_mmc_card->high_speed = 1;
+ sd_mmc_card->clock *= 2;
+ return true;
+}
+
+#else
+static bool sdio_op_cond(void)
+{
+ return true; /* No error but card type not updated */
+}
+static bool sdio_get_max_speed(void)
+{
+ return false;
+}
+static bool sdio_cmd52_set_bus_width(void)
+{
+ return false;
+}
+static bool sdio_cmd52_set_high_speed(void)
+{
+ return false;
+}
+#endif
+
+/**
+ * \brief CMD6 for SD - Switch card in high speed mode
+ *
+ * \note CMD6 for SD is valid under the "trans" state.
+ * \note sd_mmc_card->high_speed is updated.
+ * \note sd_mmc_card->clock is updated.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_cm6_set_high_speed(void)
+{
+ uint8_t switch_status[SD_SW_STATUS_BSIZE] = {0};
+
+ if (!driver_adtc_start(sd_mmc_hal,
+ SD_CMD6_SWITCH_FUNC,
+ SD_CMD6_MODE_SWITCH | SD_CMD6_GRP6_NO_INFLUENCE | SD_CMD6_GRP5_NO_INFLUENCE
+ | SD_CMD6_GRP4_NO_INFLUENCE | SD_CMD6_GRP3_NO_INFLUENCE | SD_CMD6_GRP2_DEFAULT
+ | SD_CMD6_GRP1_HIGH_SPEED,
+ SD_SW_STATUS_BSIZE,
+ 1,
+ true)) {
+ return false;
+ }
+ if (!driver_start_read_blocks(sd_mmc_hal, switch_status, 1)) {
+ return false;
+ }
+ if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) {
+ return false;
+ }
+
+ if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) {
+ return false;
+ }
+ if (SD_SW_STATUS_FUN_GRP1_RC(switch_status) == SD_SW_STATUS_FUN_GRP_RC_ERROR) {
+ /* No supported, it is not a protocol error */
+ return true;
+ }
+ if (SD_SW_STATUS_FUN_GRP1_BUSY(switch_status)) {
+ return false;
+ }
+ /* CMD6 function switching period is within 8 clocks
+ * after the end bit of status data.*/
+ driver_send_clock(sd_mmc_hal);
+ sd_mmc_card->high_speed = 1;
+ sd_mmc_card->clock *= 2;
+ return true;
+}
+
+#if CONF_MMC_SUPPORT
+
+/**
+ * \brief CMD6 for MMC - Switches the bus width mode
+ *
+ * \note CMD6 is valid under the "trans" state.
+ * \note sd_mmc_card->bus_width is updated.
+ *
+ * \param bus_width Bus width to set
+ *
+ * \return true if success, otherwise false
+ */
+static bool mmc_cmd6_set_bus_width(uint8_t bus_width)
+{
+ uint32_t arg;
+
+ switch (bus_width) {
+ case 8:
+ arg = MMC_CMD6_ACCESS_SET_BITS | MMC_CMD6_INDEX_BUS_WIDTH | MMC_CMD6_VALUE_BUS_WIDTH_8BIT;
+ break;
+ case 4:
+ arg = MMC_CMD6_ACCESS_SET_BITS | MMC_CMD6_INDEX_BUS_WIDTH | MMC_CMD6_VALUE_BUS_WIDTH_4BIT;
+ break;
+ default:
+ arg = MMC_CMD6_ACCESS_SET_BITS | MMC_CMD6_INDEX_BUS_WIDTH | MMC_CMD6_VALUE_BUS_WIDTH_1BIT;
+ break;
+ }
+ if (!driver_send_cmd(sd_mmc_hal, MMC_CMD6_SWITCH, arg)) {
+ return false;
+ }
+ if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) {
+ /* No supported, it is not a protocol error */
+ return false;
+ }
+ sd_mmc_card->bus_width = bus_width;
+ return true;
+}
+
+/**
+ * \brief CMD6 for MMC - Switches in high speed mode
+ *
+ * \note CMD6 is valid under the "trans" state.
+ * \note sd_mmc_card->high_speed is updated.
+ * \note sd_mmc_card->clock is updated.
+ *
+ * \return true if success, otherwise false
+ */
+static bool mmc_cmd6_set_high_speed(void)
+{
+ if (!driver_send_cmd(sd_mmc_hal,
+ MMC_CMD6_SWITCH,
+ MMC_CMD6_ACCESS_WRITE_BYTE | MMC_CMD6_INDEX_HS_TIMING | MMC_CMD6_VALUE_HS_TIMING_ENABLE)) {
+ return false;
+ }
+ if (driver_get_response(sd_mmc_hal) & CARD_STATUS_SWITCH_ERROR) {
+ /* No supported, it is not a protocol error */
+ return false;
+ }
+ sd_mmc_card->high_speed = 1;
+ sd_mmc_card->clock = 52000000lu;
+ return true;
+}
+#endif
+
+/**
+ * \brief CMD8 for SD card - Send Interface Condition Command.
+ *
+ * \note
+ * Send SD Memory Card interface condition, which includes host supply
+ * voltage information and asks the card whether card supports voltage.
+ * Should be performed at initialization time to detect the card type.
+ *
+ * \param v2 Pointer to v2 flag to update
+ *
+ * \return true if success, otherwise false
+ * with a update of \ref sd_mmc_err.
+ */
+static bool sd_cmd8(uint8_t *v2)
+{
+ uint32_t resp;
+
+ *v2 = 0;
+ /* Test for SD version 2 */
+ if (!driver_send_cmd(sd_mmc_hal, SD_CMD8_SEND_IF_COND, SD_CMD8_PATTERN | SD_CMD8_HIGH_VOLTAGE)) {
+ return true; /* It is not a V2 */
+ }
+ /* Check R7 response */
+ resp = driver_get_response(sd_mmc_hal);
+ if (resp == 0xFFFFFFFF) {
+ /* No compliance R7 value */
+ return true; /* It is not a V2 */
+ }
+ if ((resp & (SD_CMD8_MASK_PATTERN | SD_CMD8_MASK_VOLTAGE)) != (SD_CMD8_PATTERN | SD_CMD8_HIGH_VOLTAGE)) {
+ return false;
+ }
+ *v2 = 1;
+ return true;
+}
+
+#if CONF_MMC_SUPPORT
+/**
+ * \brief CMD8 - The card sends its EXT_CSD register as a block of data.
+ *
+ * \param b_authorize_high_speed Pointer to update with the high speed
+ * support information
+ *
+ * \return true if success, otherwise false
+ */
+static bool mmc_cmd8(uint8_t *b_authorize_high_speed)
+{
+ uint16_t i;
+ uint32_t ext_csd;
+ uint32_t sec_count;
+
+ if (!driver_adtc_start(sd_mmc_hal, MMC_CMD8_SEND_EXT_CSD, 0, EXT_CSD_BSIZE, 1, false)) {
+ return false;
+ }
+ /* Read and decode Extended Extended CSD
+ * Note: The read access is done in byte to avoid a buffer
+ * of EXT_CSD_BSIZE Byte in stack.*/
+
+ /* Read card type */
+ for (i = 0; i < (EXT_CSD_CARD_TYPE_INDEX + 4) / 4; i++) {
+ if (!driver_read_word(sd_mmc_hal, &ext_csd)) {
+ return false;
+ }
+ }
+ *b_authorize_high_speed = (ext_csd >> ((EXT_CSD_CARD_TYPE_INDEX % 4) * 8)) & MMC_CTYPE_52MHZ;
+
+ if (MMC_CSD_C_SIZE(sd_mmc_card->csd) == 0xFFF) {
+ /* For high capacity SD/MMC card,
+ * memory capacity = SEC_COUNT * 512 byte */
+ for (; i < (EXT_CSD_SEC_COUNT_INDEX + 4) / 4; i++) {
+ if (!driver_read_word(sd_mmc_hal, &sec_count)) {
+ return false;
+ }
+ }
+ sd_mmc_card->capacity = sec_count / 2;
+ }
+ for (; i < EXT_CSD_BSIZE / 4; i++) {
+ if (!driver_read_word(sd_mmc_hal, &sec_count)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+#endif
+
+/**
+ * \brief CMD9: Addressed card sends its card-specific
+ * data (CSD) on the CMD line mci.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_mmc_cmd9_mci(void)
+{
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD9_SEND_CSD, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ driver_get_response_128(sd_mmc_hal, sd_mmc_card->csd);
+ return true;
+}
+
+#if CONF_MMC_SUPPORT
+/**
+ * \brief Decodes MMC CSD register
+ */
+static void mmc_decode_csd(void)
+{
+ uint32_t unit;
+ uint32_t mul;
+ uint32_t tran_speed;
+
+ /* Get MMC System Specification version supported by the card */
+ switch (MMC_CSD_SPEC_VERS(sd_mmc_card->csd)) {
+ default:
+ case 0:
+ sd_mmc_card->version = CARD_VER_MMC_1_2;
+ break;
+
+ case 1:
+ sd_mmc_card->version = CARD_VER_MMC_1_4;
+ break;
+
+ case 2:
+ sd_mmc_card->version = CARD_VER_MMC_2_2;
+ break;
+
+ case 3:
+ sd_mmc_card->version = CARD_VER_MMC_3;
+ break;
+
+ case 4:
+ sd_mmc_card->version = CARD_VER_MMC_4;
+ break;
+ }
+
+ /* Get MMC memory max transfer speed in Hz.*/
+ tran_speed = CSD_TRAN_SPEED(sd_mmc_card->csd);
+ unit = sd_mmc_trans_units[tran_speed & 0x7];
+ mul = mmc_trans_multipliers[(tran_speed >> 3) & 0xF];
+ sd_mmc_card->clock = unit * mul * 1000;
+
+ /*
+ * Get card capacity.
+ * ----------------------------------------------------
+ * For normal SD/MMC card:
+ * memory capacity = BLOCKNR * BLOCK_LEN
+ * Where
+ * BLOCKNR = (C_SIZE+1) * MULT
+ * MULT = 2 ^ (C_SIZE_MULT+2) (C_SIZE_MULT < 8)
+ * BLOCK_LEN = 2 ^ READ_BL_LEN (READ_BL_LEN < 12)
+ * ----------------------------------------------------
+ * For high capacity SD/MMC card:
+ * memory capacity = SEC_COUNT * 512 byte
+ */
+ if (MMC_CSD_C_SIZE(sd_mmc_card->csd) != 0xFFF) {
+ uint32_t blocknr
+ = ((MMC_CSD_C_SIZE(sd_mmc_card->csd) + 1) * (1 << (MMC_CSD_C_SIZE_MULT(sd_mmc_card->csd) + 2)));
+ sd_mmc_card->capacity = blocknr * (1 << MMC_CSD_READ_BL_LEN(sd_mmc_card->csd)) / 1024;
+ }
+}
+#endif
+
+/**
+ * \brief Decodes SD CSD register
+ */
+static void sd_decode_csd(void)
+{
+ uint32_t unit;
+ uint32_t mul;
+ uint32_t tran_speed;
+
+ /* Get SD memory maximum transfer speed in Hz. */
+ tran_speed = CSD_TRAN_SPEED(sd_mmc_card->csd);
+ unit = sd_mmc_trans_units[tran_speed & 0x7];
+ mul = sd_trans_multipliers[(tran_speed >> 3) & 0xF];
+ sd_mmc_card->clock = unit * mul * 1000;
+
+ /*
+ * Get card capacity.
+ * ----------------------------------------------------
+ * For normal SD/MMC card:
+ * memory capacity = BLOCKNR * BLOCK_LEN
+ * Where
+ * BLOCKNR = (C_SIZE+1) * MULT
+ * MULT = 2 ^ (C_SIZE_MULT+2) (C_SIZE_MULT < 8)
+ * BLOCK_LEN = 2 ^ READ_BL_LEN (READ_BL_LEN < 12)
+ * ----------------------------------------------------
+ * For high capacity SD card:
+ * memory capacity = (C_SIZE+1) * 512K byte
+ */
+ if (CSD_STRUCTURE_VERSION(sd_mmc_card->csd) >= SD_CSD_VER_2_0) {
+ sd_mmc_card->capacity = (SD_CSD_2_0_C_SIZE(sd_mmc_card->csd) + 1) * 512;
+ } else {
+ uint32_t blocknr
+ = ((SD_CSD_1_0_C_SIZE(sd_mmc_card->csd) + 1) * (1 << (SD_CSD_1_0_C_SIZE_MULT(sd_mmc_card->csd) + 2)));
+ sd_mmc_card->capacity = blocknr * (1 << SD_CSD_1_0_READ_BL_LEN(sd_mmc_card->csd)) / 1024;
+ }
+}
+
+/**
+ * \brief CMD13 - Addressed card sends its status register.
+ * This function waits the clear of the busy flag
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_mmc_cmd13(void)
+{
+ uint32_t nec_timeout;
+
+ /* Wait for data ready status.
+ * Nec timing: 0 to unlimited
+ * However a timeout is used.
+ * 200 000 * 8 cycles
+ */
+ nec_timeout = 200000;
+ do {
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD13_SEND_STATUS, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ /* Check busy flag */
+ if (driver_get_response(sd_mmc_hal) & CARD_STATUS_READY_FOR_DATA) {
+ break;
+ }
+ if (nec_timeout-- == 0) {
+ return false;
+ }
+ } while (1);
+
+ return true;
+}
+
+#if (CONF_SDIO_SUPPORT == 1)
+/**
+ * \brief CMD52 - SDIO IO_RW_DIRECT command
+ *
+ * \param rw_flag Direction, 1:write, 0:read.
+ * \param func_nb Number of the function.
+ * \param rd_after_wr Read after Write flag.
+ * \param reg_addr register address.
+ * \param io_data Pointer to input argument and response buffer.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sdio_cmd52(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t rd_after_wr, uint8_t *io_data)
+{
+ ASSERT(io_data != NULL);
+ if (!driver_send_cmd(sd_mmc_hal,
+ SDIO_CMD52_IO_RW_DIRECT,
+ ((uint32_t)*io_data << SDIO_CMD52_WR_DATA) | ((uint32_t)rw_flag << SDIO_CMD52_RW_FLAG)
+ | ((uint32_t)func_nb << SDIO_CMD52_FUNCTION_NUM)
+ | ((uint32_t)rd_after_wr << SDIO_CMD52_RAW_FLAG)
+ | ((uint32_t)reg_addr << SDIO_CMD52_REG_ADRR))) {
+ return false;
+ }
+ *io_data = driver_get_response(sd_mmc_hal) & 0xFF;
+ return true;
+}
+
+/**
+ * \brief CMD53 - SDIO IO_RW_EXTENDED command
+ * This implementation support only the SDIO multi-byte transfer mode which is
+ * similar to the single block transfer on memory.
+ * Note: The SDIO block transfer mode is optional for SDIO card.
+ *
+ * \param rw_flag Direction, 1:write, 0:read.
+ * \param func_nb Number of the function.
+ * \param reg_addr Register address.
+ * \param inc_addr 1:Incrementing address, 0: fixed.
+ * \param size Transfer data size.
+ * \param access_block true, if the block access (DMA) is used
+ *
+ * \return true if success, otherwise false
+ */
+static bool sdio_cmd53(uint8_t rw_flag, uint8_t func_nb, uint32_t reg_addr, uint8_t inc_addr, uint32_t size,
+ bool access_block)
+{
+ ASSERT(size != 0);
+ ASSERT(size <= 512);
+
+ return driver_adtc_start(
+ sd_mmc_hal,
+ (rw_flag == SDIO_CMD53_READ_FLAG) ? SDIO_CMD53_IO_R_BYTE_EXTENDED : SDIO_CMD53_IO_W_BYTE_EXTENDED,
+ ((size % 512) << SDIO_CMD53_COUNT) | ((uint32_t)reg_addr << SDIO_CMD53_REG_ADDR)
+ | ((uint32_t)inc_addr << SDIO_CMD53_OP_CODE) | ((uint32_t)0 << SDIO_CMD53_BLOCK_MODE)
+ | ((uint32_t)func_nb << SDIO_CMD53_FUNCTION_NUM) | ((uint32_t)rw_flag << SDIO_CMD53_RW_FLAG),
+ size,
+ 1,
+ access_block);
+}
+#endif
+
+/**
+ * \brief ACMD6 - Define the data bus width to 4 bits bus
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_acmd6(void)
+{
+ /* CMD55 - Indicate to the card that the next command is an
+ * application specific command rather than a standard command.*/
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ /* 10b = 4 bits bus */
+ if (!driver_send_cmd(sd_mmc_hal, SD_ACMD6_SET_BUS_WIDTH, 0x2)) {
+ return false;
+ }
+ sd_mmc_card->bus_width = 4;
+ return true;
+}
+
+/**
+ * \brief ACMD51 - Read the SD Configuration Register.
+ *
+ * \note
+ * SD Card Configuration Register (SCR) provides information on the SD Memory
+ * Card's special features that were configured into the given card. The size
+ * of SCR register is 64 bits.
+ *
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_acmd51(void)
+{
+ uint8_t scr[SD_SCR_REG_BSIZE];
+
+ /* CMD55 - Indicate to the card that the next command is an
+ * application specific command rather than a standard command.*/
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD55_APP_CMD, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ if (!driver_adtc_start(sd_mmc_hal, SD_ACMD51_SEND_SCR, 0, SD_SCR_REG_BSIZE, 1, true)) {
+ return false;
+ }
+ if (!driver_start_read_blocks(sd_mmc_hal, scr, 1)) {
+ return false;
+ }
+ if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) {
+ return false;
+ }
+
+ /* Get SD Memory Card - Spec. Version */
+ switch (SD_SCR_SD_SPEC(scr)) {
+ case SD_SCR_SD_SPEC_1_0_01:
+ sd_mmc_card->version = CARD_VER_SD_1_0;
+ break;
+
+ case SD_SCR_SD_SPEC_1_10:
+ sd_mmc_card->version = CARD_VER_SD_1_10;
+ break;
+
+ case SD_SCR_SD_SPEC_2_00:
+ if (SD_SCR_SD_SPEC3(scr) == SD_SCR_SD_SPEC_3_00) {
+ sd_mmc_card->version = CARD_VER_SD_3_0;
+ } else {
+ sd_mmc_card->version = CARD_VER_SD_2_0;
+ }
+ break;
+
+ default:
+ sd_mmc_card->version = CARD_VER_SD_1_0;
+ break;
+ }
+ return true;
+}
+
+/**
+ * \brief Select a card slot and initialize the associated driver
+ *
+ * \param slot Card slot number
+ *
+ * \retval SD_MMC_ERR_SLOT Wrong slot number
+ * \retval SD_MMC_ERR_NO_CARD No card present on slot
+ * \retval SD_MMC_ERR_UNUSABLE Unusable card
+ * \retval SD_MMC_INIT_ONGOING Card initialization requested
+ * \retval SD_MMC_OK Card present
+ */
+static sd_mmc_err_t sd_mmc_select_slot(uint8_t slot)
+{
+ if (slot >= CONF_SD_MMC_MEM_CNT) {
+ return SD_MMC_ERR_SLOT;
+ }
+
+ if (_cd && _cd[slot].pin != -1) {
+ /** Card Detect pins */
+ if (gpio_get_pin_level(_cd[slot].pin) != _cd[slot].val) {
+ if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_DEBOUNCE) {
+ SD_MMC_STOP_TIMEOUT();
+ }
+ sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD;
+ return SD_MMC_ERR_NO_CARD;
+ }
+ if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_NO_CARD) {
+ /* A card plug on going, but this is not initialized */
+ sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_DEBOUNCE;
+ /* Debounce + Power On Setup */
+ SD_MMC_START_TIMEOUT();
+ return SD_MMC_ERR_NO_CARD;
+ }
+ if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_DEBOUNCE) {
+ if (!SD_MMC_IS_TIMEOUT()) {
+ /* Debounce on going */
+ return SD_MMC_ERR_NO_CARD;
+ }
+ /* Card is not initialized */
+ sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_INIT;
+ /* Set 1-bit bus width and low clock for initialization */
+ sd_mmc_cards[slot].clock = SDMMC_CLOCK_INIT;
+ sd_mmc_cards[slot].bus_width = 1;
+ sd_mmc_cards[slot].high_speed = 0;
+ }
+ if (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_UNUSABLE) {
+ return SD_MMC_ERR_UNUSABLE;
+ }
+ } else {
+ /* No pin card detection, then always try to install it */
+ if ((sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_NO_CARD)
+ || (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_UNUSABLE)) {
+ /* Card is not initialized */
+ sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_INIT;
+ /* Set 1-bit bus width and low clock for initialization */
+ sd_mmc_cards[slot].clock = SDMMC_CLOCK_INIT;
+ sd_mmc_cards[slot].bus_width = 1;
+ sd_mmc_cards[slot].high_speed = 0;
+ }
+ }
+
+ ASSERT(!(sd_mmc_slot_sel != slot && sd_mmc_nb_block_remaining != 0));
+
+ /* Initialize interface */
+ sd_mmc_slot_sel = slot;
+ sd_mmc_card = &sd_mmc_cards[slot];
+ sd_mmc_configure_slot();
+ return (sd_mmc_cards[slot].state == SD_MMC_CARD_STATE_INIT) ? SD_MMC_INIT_ONGOING : SD_MMC_OK;
+}
+
+/**
+ * \brief Configures the driver with the selected card configuration
+ */
+static void sd_mmc_configure_slot(void)
+{
+ driver_select_device(
+ sd_mmc_hal, sd_mmc_slot_sel, sd_mmc_card->clock, sd_mmc_card->bus_width, sd_mmc_card->high_speed);
+}
+
+/**
+ * \brief Deselect the current card slot
+ */
+static void sd_mmc_deselect_slot(void)
+{
+ if (sd_mmc_slot_sel < CONF_SD_MMC_MEM_CNT) {
+ driver_deselect_device(sd_mmc_hal, sd_mmc_slot_sel);
+ }
+}
+
+/**
+ * \brief Initialize the SD card in MCI mode.
+ *
+ * \note
+ * This function runs the initialization procedure and the identification
+ * process, then it sets the SD/MMC card in transfer state.
+ * At last, it will automaticly enable maximum bus width and transfer speed.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_mmc_mci_card_init(void)
+{
+ uint8_t v2 = 0;
+#if (CONF_SDIO_SUPPORT == 1)
+ uint8_t data = 0x08;
+#endif
+
+ /* In first, try to install SD/SDIO card */
+ sd_mmc_card->type = CARD_TYPE_SD;
+ sd_mmc_card->version = CARD_VER_UNKNOWN;
+ sd_mmc_card->rca = 0;
+
+ /* Card need of 74 cycles clock minimum to start */
+ driver_send_clock(sd_mmc_hal);
+
+#if (CONF_SDIO_SUPPORT == 1)
+ /* CMD52 Reset SDIO */
+ sdio_cmd52(SDIO_CMD52_WRITE_FLAG, SDIO_CIA, SDIO_CCCR_IOA, 0, &data);
+#endif
+
+ /* CMD0 - Reset all cards to idle state.*/
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD0_GO_IDLE_STATE, 0)) {
+ return false;
+ }
+ if (!sd_cmd8(&v2)) {
+ return false;
+ }
+ /* Try to get the SDIO card's operating condition */
+ if (!sdio_op_cond()) {
+ return false;
+ }
+
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ /* Try to get the SD card's operating condition */
+ if (!sd_mci_op_cond(v2)) {
+ /* It is not a SD card */
+#if CONF_MMC_SUPPORT
+ sd_mmc_card->type = CARD_TYPE_MMC;
+ return sd_mmc_mci_install_mmc();
+#else
+ sd_mmc_card->type = CARD_TYPE_UNKNOWN;
+ return false;
+#endif
+ }
+ }
+
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ /* SD MEMORY, Put the Card in Identify Mode
+ * Note: The CID is not used in this stack */
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD2_ALL_SEND_CID, 0)) {
+ return false;
+ }
+ }
+ /* Ask the card to publish a new relative address (RCA).*/
+ if (!driver_send_cmd(sd_mmc_hal, SD_CMD3_SEND_RELATIVE_ADDR, 0)) {
+ return false;
+ }
+ sd_mmc_card->rca = (driver_get_response(sd_mmc_hal) >> 16) & 0xFFFF;
+
+ /* SD MEMORY, Get the Card-Specific Data */
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ if (!sd_mmc_cmd9_mci()) {
+ return false;
+ }
+ sd_decode_csd();
+ }
+ /* Select the and put it into Transfer Mode */
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD7_SELECT_CARD_CMD, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ /* SD MEMORY, Read the SCR to get card version */
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ if (!sd_acmd51()) {
+ return false;
+ }
+ }
+ if (IS_SDIO()) {
+ if (!sdio_get_max_speed()) {
+ return false;
+ }
+ }
+ if ((4 <= driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel))) {
+ /* TRY to enable 4-bit mode */
+ if (IS_SDIO()) {
+ if (!sdio_cmd52_set_bus_width()) {
+ return false;
+ }
+ }
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ if (!sd_acmd6()) {
+ return false;
+ }
+ }
+ /* Switch to selected bus mode */
+ sd_mmc_configure_slot();
+ }
+ if (driver_is_high_speed_capable(sd_mmc_hal)) {
+ /* TRY to enable High-Speed Mode */
+ if (IS_SDIO()) {
+ if (!sdio_cmd52_set_high_speed()) {
+ return false;
+ }
+ }
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ if (sd_mmc_card->version > CARD_VER_SD_1_0) {
+ if (!sd_cm6_set_high_speed()) {
+ return false;
+ }
+ }
+ }
+ /* Valid new configuration */
+ sd_mmc_configure_slot();
+ }
+ /* SD MEMORY, Set default block size */
+ if (sd_mmc_card->type & CARD_TYPE_SD) {
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD16_SET_BLOCKLEN, SD_MMC_BLOCK_SIZE)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+#if CONF_MMC_SUPPORT
+/**
+ * \brief Initialize the MMC card in MCI mode.
+ *
+ * \note
+ * This function runs the initialization procedure and the identification
+ * process, then it sets the SD/MMC card in transfer state.
+ * At last, it will automaticly enable maximum bus width and transfer speed.
+ *
+ * \return true if success, otherwise false
+ */
+static bool sd_mmc_mci_install_mmc(void)
+{
+ uint8_t b_authorize_high_speed;
+
+ /* CMD0 - Reset all cards to idle state. */
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_MCI_CMD0_GO_IDLE_STATE, 0)) {
+ return false;
+ }
+
+ if (!mmc_mci_op_cond()) {
+ return false;
+ }
+
+ /* Put the Card in Identify Mode
+ * Note: The CID is not used in this stack*/
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD2_ALL_SEND_CID, 0)) {
+ return false;
+ }
+ /* Assign relative address to the card.*/
+ sd_mmc_card->rca = 1;
+ if (!driver_send_cmd(sd_mmc_hal, MMC_CMD3_SET_RELATIVE_ADDR, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ /* Get the Card-Specific Data */
+ if (!sd_mmc_cmd9_mci()) {
+ return false;
+ }
+ mmc_decode_csd();
+ /* Select the and put it into Transfer Mode */
+ if (!driver_send_cmd(sd_mmc_hal, SDMMC_CMD7_SELECT_CARD_CMD, (uint32_t)sd_mmc_card->rca << 16)) {
+ return false;
+ }
+ if (sd_mmc_card->version >= CARD_VER_MMC_4) {
+ /* For MMC 4.0 Higher version
+ * Get EXT_CSD */
+ if (!mmc_cmd8(&b_authorize_high_speed)) {
+ return false;
+ }
+ if (4 <= driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel)) {
+ /* Enable more bus width */
+ if (!mmc_cmd6_set_bus_width(driver_get_bus_width(sd_mmc_hal, sd_mmc_slot_sel))) {
+ return false;
+ }
+ /* Reinitialize the slot with the bus width */
+ sd_mmc_configure_slot();
+ }
+ if (driver_is_high_speed_capable(sd_mmc_hal) && b_authorize_high_speed) {
+ /* Enable HS */
+ if (!mmc_cmd6_set_high_speed()) {
+ return false;
+ }
+ /* Reinitialize the slot with the new speed */
+ sd_mmc_configure_slot();
+ }
+ } else {
+ /* Reinitialize the slot with the new speed */
+ sd_mmc_configure_slot();
+ }
+
+ uint8_t retry = 10;
+ while (retry--) {
+ /* Retry is a WORKAROUND for no compliance card (Atmel Internal ref. MMC19):
+ * These cards seem not ready immediatly
+ * after the end of busy of mmc_cmd6_set_high_speed()*/
+
+ /* Set default block size */
+ if (driver_send_cmd(sd_mmc_hal, SDMMC_CMD16_SET_BLOCKLEN, SD_MMC_BLOCK_SIZE)) {
+ return true;
+ }
+ }
+ return false;
+}
+#endif
+
+/*--------------------- PUBLIC FUNCTIONS ----------------------------*/
+
+void sd_mmc_init(void *hal, sd_mmc_detect_t *card_detects, sd_mmc_detect_t *wp_detects)
+{
+ /* GPIO will be used to detect card and write protect.
+ * The related clocks and pinmux must be configurated in good
+ * condition. */
+
+ for (uint8_t slot = 0; slot < CONF_SD_MMC_MEM_CNT; slot++) {
+ sd_mmc_cards[slot].state = SD_MMC_CARD_STATE_NO_CARD;
+ }
+ sd_mmc_slot_sel = 0xFF; /* No slot configurated */
+ sd_mmc_hal = hal;
+ _cd = card_detects;
+ _wp = wp_detects;
+}
+
+uint8_t sd_mmc_nb_slot(void)
+{
+ return CONF_SD_MMC_MEM_CNT;
+}
+
+sd_mmc_err_t sd_mmc_check(uint8_t slot)
+{
+ sd_mmc_err_t sd_mmc_err;
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_INIT_ONGOING) {
+ sd_mmc_deselect_slot();
+ return sd_mmc_err;
+ }
+
+ /* Initialization of the card requested */
+ if (sd_mmc_mci_card_init()) {
+ sd_mmc_card->state = SD_MMC_CARD_STATE_READY;
+ sd_mmc_deselect_slot();
+ /* To notify that the card has been just initialized
+ * It is necessary for USB Device MSC */
+ return SD_MMC_INIT_ONGOING;
+ }
+ sd_mmc_card->state = SD_MMC_CARD_STATE_UNUSABLE;
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_UNUSABLE;
+}
+
+card_type_t sd_mmc_get_type(uint8_t slot)
+{
+ if (SD_MMC_OK != sd_mmc_select_slot(slot)) {
+ return CARD_TYPE_UNKNOWN;
+ }
+ sd_mmc_deselect_slot();
+ return sd_mmc_card->type;
+}
+
+card_version_t sd_mmc_get_version(uint8_t slot)
+{
+ if (SD_MMC_OK != sd_mmc_select_slot(slot)) {
+ return CARD_VER_UNKNOWN;
+ }
+ sd_mmc_deselect_slot();
+ return sd_mmc_card->version;
+}
+
+uint32_t sd_mmc_get_capacity(uint8_t slot)
+{
+ if (SD_MMC_OK != sd_mmc_select_slot(slot)) {
+ return 0;
+ }
+ sd_mmc_deselect_slot();
+ return sd_mmc_card->capacity;
+}
+
+bool sd_mmc_is_write_protected(uint8_t slot)
+{
+ /* No detection, always writable */
+ if (!_wp || _wp[slot].pin == -1) {
+ return false;
+ }
+ /* Write Protect Detect */
+ if (gpio_get_pin_level(_wp[slot].pin) == _wp[slot].val) {
+ return true;
+ }
+ return false;
+}
+
+sd_mmc_err_t sd_mmc_init_read_blocks(uint8_t slot, uint32_t start, uint16_t nb_block)
+{
+ sd_mmc_err_t sd_mmc_err;
+ uint32_t cmd, arg, resp;
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_OK) {
+ return sd_mmc_err;
+ }
+
+ /* Wait for data ready status */
+ if (!sd_mmc_cmd13()) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ if (nb_block > 1) {
+ cmd = SDMMC_CMD18_READ_MULTIPLE_BLOCK;
+ } else {
+ cmd = SDMMC_CMD17_READ_SINGLE_BLOCK;
+ }
+ /*
+ * SDSC Card (CCS=0) uses byte unit address,
+ * SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit).
+ */
+ if (sd_mmc_card->type & CARD_TYPE_HC) {
+ arg = start;
+ } else {
+ arg = (start * SD_MMC_BLOCK_SIZE);
+ }
+
+ if (!driver_adtc_start(sd_mmc_hal, cmd, arg, SD_MMC_BLOCK_SIZE, nb_block, true)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ /* Check response */
+ resp = driver_get_response(sd_mmc_hal);
+ if (resp & CARD_STATUS_ERR_RD_WR) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ sd_mmc_nb_block_remaining = nb_block;
+ sd_mmc_nb_block_to_tranfer = nb_block;
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sd_mmc_start_read_blocks(void *dest, uint16_t nb_block)
+{
+ ASSERT(sd_mmc_nb_block_remaining >= nb_block);
+
+ if (!driver_start_read_blocks(sd_mmc_hal, dest, nb_block)) {
+ sd_mmc_nb_block_remaining = 0;
+ return SD_MMC_ERR_COMM;
+ }
+ sd_mmc_nb_block_remaining -= nb_block;
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sd_mmc_wait_end_of_read_blocks(bool abort)
+{
+ if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) {
+ return SD_MMC_ERR_COMM;
+ }
+ if (abort) {
+ sd_mmc_nb_block_remaining = 0;
+ } else if (sd_mmc_nb_block_remaining) {
+ return SD_MMC_OK;
+ }
+
+ /* All blocks are transfered then stop read operation */
+ if (sd_mmc_nb_block_to_tranfer == 1) {
+ /* Single block transfer, then nothing to do */
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+ }
+ /* WORKAROUND for no compliance card (Atmel Internal ref. !MMC7 !SD19):
+ * The errors on this command must be ignored
+ * and one retry can be necessary in SPI mode for no compliance card.*/
+ if (!driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0)) {
+ driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0);
+ }
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sd_mmc_init_write_blocks(uint8_t slot, uint32_t start, uint16_t nb_block)
+{
+ sd_mmc_err_t sd_mmc_err;
+ uint32_t cmd, arg, resp;
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_OK) {
+ return sd_mmc_err;
+ }
+ if (sd_mmc_is_write_protected(slot)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_WP;
+ }
+
+ if (nb_block > 1) {
+ cmd = SDMMC_CMD25_WRITE_MULTIPLE_BLOCK;
+ } else {
+ cmd = SDMMC_CMD24_WRITE_BLOCK;
+ }
+ /*
+ * SDSC Card (CCS=0) uses byte unit address,
+ * SDHC and SDXC Cards (CCS=1) use block unit address (512 Bytes unit).
+ */
+ if (sd_mmc_card->type & CARD_TYPE_HC) {
+ arg = start;
+ } else {
+ arg = (start * SD_MMC_BLOCK_SIZE);
+ }
+ if (!driver_adtc_start(sd_mmc_hal, cmd, arg, SD_MMC_BLOCK_SIZE, nb_block, true)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ /* Check response */
+ resp = driver_get_response(sd_mmc_hal);
+ if (resp & CARD_STATUS_ERR_RD_WR) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ sd_mmc_nb_block_remaining = nb_block;
+ sd_mmc_nb_block_to_tranfer = nb_block;
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sd_mmc_start_write_blocks(const void *src, uint16_t nb_block)
+{
+ ASSERT(sd_mmc_nb_block_remaining >= nb_block);
+ if (!driver_start_write_blocks(sd_mmc_hal, src, nb_block)) {
+ sd_mmc_nb_block_remaining = 0;
+ return SD_MMC_ERR_COMM;
+ }
+ sd_mmc_nb_block_remaining -= nb_block;
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sd_mmc_wait_end_of_write_blocks(bool abort)
+{
+ if (!driver_wait_end_of_write_blocks(sd_mmc_hal)) {
+ return SD_MMC_ERR_COMM;
+ }
+ if (abort) {
+ sd_mmc_nb_block_remaining = 0;
+ } else if (sd_mmc_nb_block_remaining) {
+ return SD_MMC_OK;
+ }
+
+ /* All blocks are transfered then stop write operation */
+ if (sd_mmc_nb_block_to_tranfer == 1) {
+ /* Single block transfer, then nothing to do */
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+ }
+
+ /* Note: SPI multiblock writes terminate using a special
+ * token, not a STOP_TRANSMISSION request.*/
+ if (!driver_adtc_stop(sd_mmc_hal, SDMMC_CMD12_STOP_TRANSMISSION, 0)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+}
+
+#if (CONF_SDIO_SUPPORT == 1)
+sd_mmc_err_t sdio_read_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t *dest)
+{
+ sd_mmc_err_t sd_mmc_err;
+
+ if (dest == NULL) {
+ return SD_MMC_ERR_PARAM;
+ }
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_OK) {
+ return sd_mmc_err;
+ }
+
+ if (!sdio_cmd52(SDIO_CMD52_READ_FLAG, func_num, addr, 0, dest)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sdio_write_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t data)
+{
+ sd_mmc_err_t sd_mmc_err;
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_OK) {
+ return sd_mmc_err;
+ }
+
+ if (!sdio_cmd52(SDIO_CMD52_WRITE_FLAG, func_num, addr, 0, &data)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sdio_read_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *dest,
+ uint16_t size)
+{
+ sd_mmc_err_t sd_mmc_err;
+
+ if ((size == 0) || (size > 512)) {
+ return SD_MMC_ERR_PARAM;
+ }
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_OK) {
+ return sd_mmc_err;
+ }
+
+ if (!sdio_cmd53(SDIO_CMD53_READ_FLAG, func_num, addr, inc_addr, size, true)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ if (!driver_start_read_blocks(sd_mmc_hal, dest, 1)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ if (!driver_wait_end_of_read_blocks(sd_mmc_hal)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+}
+
+sd_mmc_err_t sdio_write_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *src,
+ uint16_t size)
+{
+ sd_mmc_err_t sd_mmc_err;
+
+ if ((size == 0) || (size > 512)) {
+ return SD_MMC_ERR_PARAM;
+ }
+
+ sd_mmc_err = sd_mmc_select_slot(slot);
+ if (sd_mmc_err != SD_MMC_OK) {
+ return sd_mmc_err;
+ }
+
+ if (!sdio_cmd53(SDIO_CMD53_WRITE_FLAG, func_num, addr, inc_addr, size, true)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ if (!driver_start_write_blocks(sd_mmc_hal, src, 1)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+ if (!driver_wait_end_of_write_blocks(sd_mmc_hal)) {
+ sd_mmc_deselect_slot();
+ return SD_MMC_ERR_COMM;
+ }
+
+ sd_mmc_deselect_slot();
+ return SD_MMC_OK;
+}
+#endif
+
+/** @} */
diff --git a/ports/atmel-samd/sd_mmc/sd_mmc.h b/ports/atmel-samd/sd_mmc/sd_mmc.h
new file mode 100644
index 000000000..1437e5efd
--- /dev/null
+++ b/ports/atmel-samd/sd_mmc/sd_mmc.h
@@ -0,0 +1,310 @@
+/**
+ * \file
+ *
+ * \brief Common SD/MMC stack header file
+ *
+ * Copyright (c) 2012-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#ifndef SD_MMC_H_INCLUDED
+#define SD_MMC_H_INCLUDED
+
+#include "compiler.h"
+#include "conf_sd_mmc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \ingroup common_memory
+ * \defgroup sd_mmc_stack_group SD/MMC/SDIO common stack
+ *
+ * SD/MMC/SDIO basic APIs used by SD/MMC/SDIO memory
+ * APIs (\ref sd_mmc_stack_mem_group).
+ * Also, it can be used by application which use the SDIO card
+ * or specific application which does not need of File System.
+ *
+ * For usual application which use the SD/MMC card in
+ * memory mode with a file system, please refer to
+ * \ref sd_mmc_stack_mem_group.
+ * @{
+ */
+
+typedef uint8_t sd_mmc_err_t; /**< Type of return error code */
+
+/** \name Return error codes */
+/** @{ */
+#define SD_MMC_OK 0 /**< No error */
+#define SD_MMC_INIT_ONGOING 1 /**< Card not initialized */
+#define SD_MMC_ERR_NO_CARD 2 /**< No SD/MMC card inserted */
+#define SD_MMC_ERR_UNUSABLE 3 /**< Unusable card */
+#define SD_MMC_ERR_SLOT 4 /**< Slot unknow */
+#define SD_MMC_ERR_COMM 5 /**< General communication error */
+#define SD_MMC_ERR_PARAM 6 /**< Illeage input parameter */
+#define SD_MMC_ERR_WP 7 /**< Card write protected */
+/** @} */
+
+typedef uint8_t card_type_t; /**< Type of card type */
+
+/** \name Card Types */
+/** @{ */
+#define CARD_TYPE_UNKNOWN (0) /**< Unknown type card */
+#define CARD_TYPE_SD (1 << 0) /**< SD card */
+#define CARD_TYPE_MMC (1 << 1) /**< MMC card */
+#define CARD_TYPE_SDIO (1 << 2) /**< SDIO card */
+#define CARD_TYPE_HC (1 << 3) /**< High capacity card */
+/** SD combo card (io + memory) */
+#define CARD_TYPE_SD_COMBO (CARD_TYPE_SD | CARD_TYPE_SDIO)
+/** @} */
+
+typedef uint8_t card_version_t; /**< Type of card version */
+
+/** \name Card Versions */
+/** @{ */
+#define CARD_VER_UNKNOWN (0) /**< Unknown card version */
+#define CARD_VER_SD_1_0 (0x10) /**< SD version 1.0 and 1.01 */
+#define CARD_VER_SD_1_10 (0x1A) /**< SD version 1.10 */
+#define CARD_VER_SD_2_0 (0X20) /**< SD version 2.00 */
+#define CARD_VER_SD_3_0 (0X30) /**< SD version 3.0X */
+#define CARD_VER_MMC_1_2 (0x12) /**< MMC version 1.2 */
+#define CARD_VER_MMC_1_4 (0x14) /**< MMC version 1.4 */
+#define CARD_VER_MMC_2_2 (0x22) /**< MMC version 2.2 */
+#define CARD_VER_MMC_3 (0x30) /**< MMC version 3 */
+#define CARD_VER_MMC_4 (0x40) /**< MMC version 4 */
+/** @} */
+
+/** Card detect setting */
+typedef struct sd_mmc_detect {
+ int16_t pin; /**< Detection pin, -1 if no such pin */
+ uint16_t val; /**< Detection value */
+} sd_mmc_detect_t;
+
+/** This SD MMC stack uses the maximum block size autorized (512 bytes) */
+#define SD_MMC_BLOCK_SIZE 512
+
+/**
+ * \brief Initialize the SD/MMC stack and low level driver required
+ * \param[in] hal Pointer to HAL instance
+ * \param[in] card_detects Pointer to list of card detect settings,
+ * list size should be \ref CONF_SD_MMC_MEM_CNT
+ * \param[in] wp_detects Pointer to list of write protect detect settings
+ * list size should be \ref CONF_SD_MMC_MEM_CNT
+ */
+void sd_mmc_init(void *hal, sd_mmc_detect_t *card_detects, sd_mmc_detect_t *wp_detects);
+
+/** \brief Return the number of slot available
+ *
+ * \return Number of card slot available
+ */
+uint8_t sd_mmc_nb_slot(void);
+
+/** \brief Performs a card checks
+ *
+ * \param[in] slot Card slot to use
+ *
+ * \retval SD_MMC_OK Card ready
+ * \retval SD_MMC_INIT_ONGOING Initialization on going
+ * \retval SD_MMC_ERR_NO_CARD Card not present in slot
+ * \retval Other value for error cases, see \ref sd_mmc_err_t
+ */
+sd_mmc_err_t sd_mmc_check(uint8_t slot);
+
+/** \brief Get the card type
+ *
+ * \param[in] slot Card slot
+ *
+ * \return Card type (\ref card_type_t)
+ */
+card_type_t sd_mmc_get_type(uint8_t slot);
+
+/** \brief Get the card version
+ *
+ * \param[in] slot Card slot
+ *
+ * \return Card version (\ref card_version_t)
+ */
+card_version_t sd_mmc_get_version(uint8_t slot);
+
+/** \brief Get the memory capacity
+ *
+ * \param[in] slot Card slot
+ *
+ * \return Capacity (unit KB)
+ */
+uint32_t sd_mmc_get_capacity(uint8_t slot);
+
+/** \brief Get the card write protection status
+ *
+ * \param[in] slot Card slot
+ *
+ * \return true, if write portected
+ */
+bool sd_mmc_is_write_protected(uint8_t slot);
+
+/**
+ * \brief Initialize the read blocks of data from the card.
+ *
+ * \param[in] slot Card slot to use
+ * \param[in] start Start block number to to read.
+ * \param[in] nb_block Total number of blocks to be read.
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sd_mmc_init_read_blocks(uint8_t slot, uint32_t start, uint16_t nb_block);
+
+/**
+ * \brief Start the read blocks of data from the card.
+ *
+ * \param[out] dest Pointer to read buffer.
+ * \param[in] nb_block Number of blocks to be read.
+ *
+ * \return return SD_MMC_OK if started,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sd_mmc_start_read_blocks(void *dest, uint16_t nb_block);
+
+/**
+ * \brief Wait the end of read blocks of data from the card.
+ *
+ * \param[in] abort Abort reading process initialized by
+ * \ref sd_mmc_init_read_blocks() after the reading issued by
+ * \ref sd_mmc_start_read_blocks() is done
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sd_mmc_wait_end_of_read_blocks(bool abort);
+
+/**
+ * \brief Initialize the write blocks of data
+ *
+ * \param[in] slot Card slot to use
+ * \param[in] start Start block number to be written.
+ * \param[in] nb_block Total number of blocks to be written.
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sd_mmc_init_write_blocks(uint8_t slot, uint32_t start, uint16_t nb_block);
+
+/**
+ * \brief Start the write blocks of data
+ *
+ * \param[in] src Pointer to write buffer.
+ * \param[in] nb_block Number of blocks to be written.
+ *
+ * \return return SD_MMC_OK if started,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sd_mmc_start_write_blocks(const void *src, uint16_t nb_block);
+
+/**
+ * \brief Wait the end of write blocks of data
+ *
+ * \param[in] abort Abort writing process initialized by
+ * \ref sd_mmc_init_write_blocks() after the writing issued by
+ * \ref sd_mmc_start_write_blocks() is done
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sd_mmc_wait_end_of_write_blocks(bool abort);
+
+#if (CONF_SDIO_SUPPORT == 1)
+/**
+ * \brief Read one byte from SDIO using RW_DIRECT command.
+ *
+ * \param[in] slot Card slot to use
+ * \param[in] func_num Function number.
+ * \param[in] addr Register address to read from.
+ * \param[out] dest Pointer to read buffer.
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sdio_read_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t *dest);
+/**
+ * \brief Write one byte to SDIO using RW_DIRECT command.
+ *
+ * \param[in] slot Card slot to use
+ * \param[in] func_num Function number.
+ * \param[in] addr Register address to read from.
+ * \param[in] data Data to be written.
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sdio_write_direct(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t data);
+
+/**
+ * \brief Read bytes from SDIO using RW_EXTENDED command.
+ *
+ * \param[in] slot Card slot to use
+ * \param[in] func_num Function number.
+ * \param[in] addr First register address to read from.
+ * \param[in] inc_addr 0 - The data address is fixed.
+ * 1 - The data address increase automatically.
+ * \param[out] dest Pointer to read buffer.
+ * \param[in] size Number of bytes to read (1 ~ 512).
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sdio_read_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *dest,
+ uint16_t size);
+
+/**
+ * \brief Write bytes to SDIO using RW_EXTENDED command.
+ *
+ * \param[in] slot Card slot to use
+ * \param[in] func_num Function number.
+ * \param[in] addr First register address to write to.
+ * \param[in] inc_addr 0 - The data address is fixed.
+ * 1 - The data address increase automatically.
+ * \param[in] src Pointer to write buffer.
+ * \param[in] size Number of bytes to read (1 ~ 512).
+ *
+ * \return return SD_MMC_OK if success,
+ * otherwise return an error code (\ref sd_mmc_err_t).
+ */
+sd_mmc_err_t sdio_write_extended(uint8_t slot, uint8_t func_num, uint32_t addr, uint8_t inc_addr, uint8_t *src,
+ uint16_t size);
+#endif /* SDIO_SUPPORT_ENABLE */
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SD_MMC_H_INCLUDED */
diff --git a/ports/atmel-samd/sd_mmc/sd_mmc_protocol.h b/ports/atmel-samd/sd_mmc/sd_mmc_protocol.h
new file mode 100644
index 000000000..0516e4fd1
--- /dev/null
+++ b/ports/atmel-samd/sd_mmc/sd_mmc_protocol.h
@@ -0,0 +1,1001 @@
+/**
+ * \file
+ *
+ * \brief SD/MMC protocol definitions.
+ *
+ * Copyright (c) 2014-2018 Microchip Technology Inc. and its subsidiaries.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * Subject to your compliance with these terms, you may use Microchip
+ * software and any derivatives exclusively with Microchip products.
+ * It is your responsibility to comply with third party license terms applicable
+ * to your use of third party software (including open source software) that
+ * may accompany Microchip software.
+ *
+ * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
+ * WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
+ * INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
+ * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
+ * LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
+ * LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
+ * SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
+ * POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
+ * ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
+ * RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
+ * THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="https://www.microchip.com/support/">Microchip Support</a>
+ */
+
+#ifndef SD_MMC_PROTOCOL_H_INCLUDED
+#define SD_MMC_PROTOCOL_H_INCLUDED
+
+#include "compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \addtogroup sd_mmc_protocol SD/MMC Protocol Definition
+ * \ingroup sd_mmc_stack_group
+ * @{
+ */
+
+// SD/MMC/SDIO default clock frequency for initialization (400KHz)
+#define SDMMC_CLOCK_INIT 400000
+
+/**
+ * \name Macros for command definition
+ *
+ * Commands types:
+ * - broadcast commands (bc), no response
+ * - broadcast commands with response (bcr) (Note: No open drain on SD card)
+ * - addressed (point-to-point) commands (ac), no data transfer on DAT lines
+ * - addressed (point-to-point) data transfer commands (adtc), data transfer
+ * on DAT lines
+ *
+ * Specific MMC norms:
+ * CMD1, CMD2 & CMD3 are processed in the open-drain mode.
+ * The CMD line is driven with push-pull drivers.
+ *
+ * Specific SD norms:
+ * There is no open drain mode in SD memory card.
+ *
+ ***************************************
+ * Responses types:
+ *
+ * R1, R3, R4 & R5 use a 48 bits response protected by a 7bit CRC checksum
+ * - R1 receiv data not specified
+ * - R3 receiv OCR
+ * - R4, R5 RCA management (MMC only)
+ * - R6, R7 RCA management (SD only)
+ *
+ * R1b assert the BUSY signal and respond with R1.
+ * If the busy signal is asserted, it is done two clock cycles (Nsr time)
+ * after the end bit of the command. The DAT0 line is driven low.
+ * DAT1-DAT7 lines are driven by the card though their values are not relevant.
+ *
+ * R2 use a 136 bits response protected by a 7bit CRC checksum
+ * The content is CID or CSD
+ *
+ * Specific MMC norms:
+ * - R4 (Fast I/O) return RCA
+ * - R5 (interrupt request) return RCA null
+ *
+ * Specific SD norms:
+ * - R6 (Published RCA) return RCA
+ * - R7 (Card interface condition) return RCA null
+ *
+ * @{
+ */
+
+//! Value to define a SD/MMC/SDIO command
+typedef uint32_t sdmmc_cmd_def_t;
+
+//! \name Flags used to define a SD/MMC/SDIO command
+//! @{
+#define SDMMC_CMD_GET_INDEX(cmd) (cmd & 0x3F)
+//! Have response (MCI only)
+#define SDMMC_RESP_PRESENT (1lu << 8)
+//! 8 bit response (SPI only)
+#define SDMMC_RESP_8 (1lu << 9)
+//! 32 bit response (SPI only)
+#define SDMMC_RESP_32 (1lu << 10)
+//! 136 bit response (MCI only)
+#define SDMMC_RESP_136 (1lu << 11)
+//! Expect valid crc (MCI only)
+#define SDMMC_RESP_CRC (1lu << 12)
+//! Card may send busy
+#define SDMMC_RESP_BUSY (1lu << 13)
+// Open drain for a braodcast command (bc)
+// or to enter in inactive state (MCI only)
+#define SDMMC_CMD_OPENDRAIN (1lu << 14)
+//! To signal a data write operation
+#define SDMMC_CMD_WRITE (1lu << 15)
+//! To signal a SDIO tranfer in multi byte mode
+#define SDMMC_CMD_SDIO_BYTE (1lu << 16)
+//! To signal a SDIO tranfer in block mode
+#define SDMMC_CMD_SDIO_BLOCK (1lu << 17)
+//! To signal a data transfer in stream mode
+#define SDMMC_CMD_STREAM (1lu << 18)
+//! To signal a data transfer in single block mode
+#define SDMMC_CMD_SINGLE_BLOCK (1lu << 19)
+//! To signal a data transfer in multi block mode
+#define SDMMC_CMD_MULTI_BLOCK (1lu << 20)
+//! @}
+
+//! \name Set of flags to define a reponse type
+//! @{
+#define SDMMC_CMD_NO_RESP (0)
+#define SDMMC_CMD_R1 (SDMMC_RESP_PRESENT | SDMMC_RESP_CRC)
+#define SDMMC_CMD_R1B (SDMMC_RESP_PRESENT | SDMMC_RESP_CRC | SDMMC_RESP_BUSY)
+#define SDMMC_CMD_R2 (SDMMC_RESP_PRESENT | SDMMC_RESP_8 | SDMMC_RESP_136 | SDMMC_RESP_CRC)
+#define SDMMC_CMD_R3 (SDMMC_RESP_PRESENT | SDMMC_RESP_32)
+#define SDMMC_CMD_R4 (SDMMC_RESP_PRESENT | SDMMC_RESP_32)
+#define SDMMC_CMD_R5 (SDMMC_RESP_PRESENT | SDMMC_RESP_8 | SDMMC_RESP_CRC)
+#define SDMMC_CMD_R6 (SDMMC_RESP_PRESENT | SDMMC_RESP_CRC)
+#define SDMMC_CMD_R7 (SDMMC_RESP_PRESENT | SDMMC_RESP_32 | SDMMC_RESP_CRC)
+//! @}
+
+//! \name SD/MMC/SDIO command definitions
+//! SDMMC_CMDx are include in SD and MMC norms
+//! MMC_CMDx are include in MMC norms only
+//! SD_CMDx are include in SD norms only
+//! SDIO_CMDx are include in SDIO norms only
+//! @{
+
+/*
+ * --- Basic commands and read-stream command (class 0 and class 1) ---
+ */
+
+/** Cmd0(bc): Reset all cards to idle state */
+#define SDMMC_SPI_CMD0_GO_IDLE_STATE (0 | SDMMC_CMD_R1)
+#define SDMMC_MCI_CMD0_GO_IDLE_STATE (0 | SDMMC_CMD_NO_RESP | SDMMC_CMD_OPENDRAIN)
+/** MMC Cmd1(bcr, R3): Ask the card to send its Operating Conditions */
+#define MMC_SPI_CMD1_SEND_OP_COND (1 | SDMMC_CMD_R1)
+#define MMC_MCI_CMD1_SEND_OP_COND (1 | SDMMC_CMD_R3 | SDMMC_CMD_OPENDRAIN)
+/** Cmd2(bcr, R2): Ask the card to send its CID number (stuff but arg 0 used) */
+#define SDMMC_CMD2_ALL_SEND_CID (2 | SDMMC_CMD_R2 | SDMMC_CMD_OPENDRAIN)
+/** SD Cmd3(bcr, R6): Ask the card to publish a new relative address (RCA) */
+#define SD_CMD3_SEND_RELATIVE_ADDR (3 | SDMMC_CMD_R6 | SDMMC_CMD_OPENDRAIN)
+/** MMC Cmd3(ac, R1): Assigns relative address to the card */
+#define MMC_CMD3_SET_RELATIVE_ADDR (3 | SDMMC_CMD_R1)
+/** Cmd4(bc): Program the DSR of all cards (MCI only) */
+#define SDMMC_CMD4_SET_DSR (4 | SDMMC_CMD_NO_RESP)
+/** MMC Cmd5(ac, R1b): Toggle the card between Sleep state and Standby state. */
+#define MMC_CMD5_SLEEP_AWAKE (5 | SDMMC_CMD_R1B)
+/** Cmd7(ac, R1/R1b): Select/Deselect card
+ * For SD: R1b only from the selected card.
+ * For MMC: R1 while selecting from Stand-By State to Transfer State;
+ * R1b while selecting from Disconnected State to Programming State.
+ */
+#define SDMMC_CMD7_SELECT_CARD_CMD (7 | SDMMC_CMD_R1B)
+#define SDMMC_CMD7_DESELECT_CARD_CMD (7 | SDMMC_CMD_R1)
+/** MMC Cmd8(adtc, R1): Send EXT_CSD register as a block of data */
+#define MMC_CMD8_SEND_EXT_CSD (8 | SDMMC_CMD_R1 | SDMMC_CMD_SINGLE_BLOCK)
+/** SD Cmd8(bcr, R7) : Send SD Memory Card interface condition */
+#define SD_CMD8_SEND_IF_COND (8 | SDMMC_CMD_R7 | SDMMC_CMD_OPENDRAIN)
+/** Cmd9 SPI (R1): Addressed card sends its card-specific data (CSD) */
+#define SDMMC_SPI_CMD9_SEND_CSD (9 | SDMMC_CMD_R1 | SDMMC_CMD_SINGLE_BLOCK)
+/** Cmd9 MCI (ac, R2): Addressed card sends its card-specific data (CSD) */
+#define SDMMC_MCI_CMD9_SEND_CSD (9 | SDMMC_CMD_R2)
+/** Cmd10(ac, R2): Addressed card sends its card identification (CID) */
+#define SDMMC_CMD10_SEND_CID (10 | SDMMC_CMD_R2)
+/**
+ * MMC Cmd11(adtc, R1): Read data stream from the card, starting at the given
+ * address, until a STOP_TRANSMISSION follows.
+ */
+#define MMC_CMD11_READ_DAT_UNTIL_STOP (11 | SDMMC_CMD_R1)
+/* SD Cmd11 MCI (ac, R1): Voltage switching */
+#define SD_CMD11_READ_DAT_UNTIL_STOP (11 | SDMMC_CMD_R1)
+/** Cmd12(ac, R1b): Force the card to stop transmission */
+#define SDMMC_CMD12_STOP_TRANSMISSION (12 | SDMMC_CMD_R1B)
+/** Cmd13(R2): Addressed card sends its status register. */
+#define SDMMC_SPI_CMD13_SEND_STATUS (13 | SDMMC_CMD_R2)
+/** Cmd13(ac, R1): Addressed card sends its status register. */
+#define SDMMC_MCI_CMD13_SEND_STATUS (13 | SDMMC_CMD_R1)
+/** MMC Cmd14(adtc, R1): Read the reversed bus testing data pattern from a card. */
+#define MMC_CMD14_BUSTEST_R (14 | SDMMC_CMD_R1)
+/** Cmd15(ac): Send an addressed card into the Inactive State. */
+// Note: It is a ac cmd, but it must be send like bc cmd to open drain
+#define SDMMC_CMD15_GO_INACTIVE_STATE (15 | SDMMC_CMD_NO_RESP | SDMMC_CMD_OPENDRAIN)
+/** MMC Cmd19(adtc, R1): Send the bus test data pattern */
+#define MMC_CMD19_BUSTEST_W (19 | SDMMC_CMD_R1)
+/** Cmd58(R3): Reads the OCR register of a card */
+#define SDMMC_SPI_CMD58_READ_OCR (58 | SDMMC_CMD_R3)
+/** Cmd59(R1): Turns the CRC option on or off */
+#define SDMMC_SPI_CMD59_CRC_ON_OFF (59 | SDMMC_CMD_R1)
+
+/*
+ * --- Block-oriented read commands (class 2) ---
+ */
+/** Cmd16(ac, R1): Set the block length (in bytes) */
+#define SDMMC_CMD16_SET_BLOCKLEN (16 | SDMMC_CMD_R1)
+/** Cmd17(adtc, R1): Read single block */
+#define SDMMC_CMD17_READ_SINGLE_BLOCK (17 | SDMMC_CMD_R1 | SDMMC_CMD_SINGLE_BLOCK)
+/** Cmd18(adtc, R1): Read multiple block */
+#define SDMMC_CMD18_READ_MULTIPLE_BLOCK (18 | SDMMC_CMD_R1 | SDMMC_CMD_MULTI_BLOCK)
+
+/*
+ * --- Sequential write commands (class 3) ---
+ */
+
+/**
+ * MMC Cmd20(adtc, R1): Write a data stream from the host, starting at the
+ * given address, until a STOP_TRANSMISSION follows.
+ */
+#define MMC_CMD20_WRITE_DAT_UNTIL_STOP (20 | SDMMC_CMD_R1)
+
+/*
+ * --- Block-oriented write commands (class 4) ---
+ */
+/** MMC Cmd23(ac, R1): Set block count */
+#define MMC_CMD23_SET_BLOCK_COUNT (23 | SDMMC_CMD_R1)
+/** Cmd24(adtc, R1): Write block */
+#define SDMMC_CMD24_WRITE_BLOCK (24 | SDMMC_CMD_R1 | SDMMC_CMD_WRITE | SDMMC_CMD_SINGLE_BLOCK)
+/** Cmd25(adtc, R1): Write multiple block */
+#define SDMMC_CMD25_WRITE_MULTIPLE_BLOCK (25 | SDMMC_CMD_R1 | SDMMC_CMD_WRITE | SDMMC_CMD_MULTI_BLOCK)
+/** MMC Cmd26(adtc, R1): Programming of the card identification register. */
+#define MMC_CMD26_PROGRAM_CID (26 | SDMMC_CMD_R1)
+/** Cmd27(adtc, R1): Programming of the programmable bits of the CSD. */
+#define SDMMC_CMD27_PROGRAM_CSD (27 | SDMMC_CMD_R1)
+
+/*
+ * --- Erase commands (class 5) ---
+ */
+/** SD Cmd32(ac, R1): */
+#define SD_CMD32_ERASE_WR_BLK_START (32 | SDMMC_CMD_R1)
+/** SD Cmd33(ac, R1): */
+#define SD_CMD33_ERASE_WR_BLK_END (33 | SDMMC_CMD_R1)
+/** MMC Cmd35(ac, R1): */
+#define MMC_CMD35_ERASE_GROUP_START (35 | SDMMC_CMD_R1)
+/** MMC Cmd36(ac, R1): */
+#define MMC_CMD36_ERASE_GROUP_END (36 | SDMMC_CMD_R1)
+/** Cmd38(ac, R1B): */
+#define SDMMC_CMD38_ERASE (38 | SDMMC_CMD_R1B)
+
+/*
+ * --- Block Oriented Write Protection Commands (class 6) ---
+ */
+/** Cmd28(ac, R1b): Set write protection */
+#define SDMMC_CMD28_SET_WRITE_PROT (28 | SDMMC_CMD_R1B)
+/** Cmd29(ac, R1b): Clr write protection */
+#define SDMMC_CMD29_CLR_WRITE_PROT (29 | SDMMC_CMD_R1B)
+/** Cmd30(adtc, R1b): Send write protection */
+#define SDMMC_CMD30_SEND_WRITE_PROT (30 | SDMMC_CMD_R1)
+
+/*
+ * --- Lock Card (class 7) ---
+ */
+/** Cmd42(adtc, R1): Used to set/reset the password or lock/unlock the card. */
+#define SDMMC_CMD42_LOCK_UNLOCK (42 | SDMMC_CMD_R1)
+
+/*
+ * --- Application-specific commands (class 8) ---
+ */
+/**
+ * Cmd55(ac, R1): Indicate to the card that the next command is an application
+ * specific command rather than a standard command.
+ */
+#define SDMMC_CMD55_APP_CMD (55 | SDMMC_CMD_R1)
+/**
+ * Cmd 56(adtc, R1): Used either to transfer a data block to the card or to get
+ * a data block from the card for general purpose/application specific commands.
+ */
+#define SDMMC_CMD56_GEN_CMD (56 | SDMMC_CMD_R1)
+
+/**
+ * MMC Cmd6(ac, R1b) : Switche the mode of operation of the selected card
+ * or modifies the EXT_CSD registers.
+ */
+#define MMC_CMD6_SWITCH (6 | SDMMC_CMD_R1B)
+/**
+ * SD Cmd6(adtc, R1) : Check switchable function (mode 0)
+ * and switch card function (mode 1).
+ */
+#define SD_CMD6_SWITCH_FUNC (6 | SDMMC_CMD_R1 | SDMMC_CMD_SINGLE_BLOCK)
+/** ACMD6(ac, R1): Define the data bus width */
+#define SD_ACMD6_SET_BUS_WIDTH (6 | SDMMC_CMD_R1)
+/** ACMD13(adtc, R1): Send the SD Status. */
+#define SD_ACMD13_SD_STATUS (13 | SDMMC_CMD_R1)
+/**
+ * ACMD22(adtc, R1): Send the number of the written (with-out errors) write
+ * blocks.
+ */
+#define SD_ACMD22_SEND_NUM_WR_BLOCKS (22 | SDMMC_CMD_R1)
+/**
+ * ACMD23(ac, R1): Set the number of write blocks to be pre-erased before
+ * writing
+ */
+#define SD_ACMD23_SET_WR_BLK_ERASE_COUNT (23 | SDMMC_CMD_R1)
+/**
+ * ACMD41(bcr, R3): Send host capacity support information (HCS) and asks the
+ * accessed card to send its operating condition register (OCR) content
+ * in the response
+ */
+#define SD_MCI_ACMD41_SD_SEND_OP_COND (41 | SDMMC_CMD_R3 | SDMMC_CMD_OPENDRAIN)
+/**
+ * ACMD41(R1): Send host capacity support information (HCS) and activates the
+ * card's initilization process
+ */
+#define SD_SPI_ACMD41_SD_SEND_OP_COND (41 | SDMMC_CMD_R1)
+/**
+ * ACMD42(ac, R1): Connect[1]/Disconnect[0] the 50 KOhm pull-up resistor on
+ * CD/DAT3 (pin 1) of the card.
+ */
+#define SD_ACMD42_SET_CLR_CARD_DETECT (42 | SDMMC_CMD_R1)
+/** ACMD51(adtc, R1): Read the SD Configuration Register (SCR). */
+#define SD_ACMD51_SEND_SCR (51 | SDMMC_CMD_R1 | SDMMC_CMD_SINGLE_BLOCK)
+
+/*
+ * --- I/O mode commands (class 9) ---
+ */
+/** MMC Cmd39(ac, R4): Used to write and read 8 bit (register) data fields. */
+#define MMC_CMD39_FAST_IO (39 | SDMMC_CMD_R4)
+/** MMC Cmd40(bcr, R5): Set the system into interrupt mode */
+#define MMC_CMD40_GO_IRQ_STATE (40 | SDMMC_CMD_R5 | SDMMC_CMD_OPENDRAIN)
+/** SDIO Cmd5(R4): Send operation condition */
+#define SDIO_CMD5_SEND_OP_COND (5 | SDMMC_CMD_R4 | SDMMC_CMD_OPENDRAIN)
+/** SDIO CMD52(R5): Direct IO read/write */
+#define SDIO_CMD52_IO_RW_DIRECT (52 | SDMMC_CMD_R5)
+/** SDIO CMD53(R5): Extended IO read/write */
+#define SDIO_CMD53_IO_R_BYTE_EXTENDED (53 | SDMMC_CMD_R5 | SDMMC_CMD_SDIO_BYTE)
+#define SDIO_CMD53_IO_W_BYTE_EXTENDED (53 | SDMMC_CMD_R5 | SDMMC_CMD_SDIO_BYTE | SDMMC_CMD_WRITE)
+#define SDIO_CMD53_IO_R_BLOCK_EXTENDED (53 | SDMMC_CMD_R5 | SDMMC_CMD_SDIO_BLOCK)
+#define SDIO_CMD53_IO_W_BLOCK_EXTENDED (53 | SDMMC_CMD_R5 | SDMMC_CMD_SDIO_BLOCK | SDMMC_CMD_WRITE)
+//! @}
+//! @}
+
+//! \name Macros for command argument definition
+//! @{
+
+//! \name MMC CMD6 argument structure
+//! @{
+//! [31:26] Set to 0
+//! [25:24] Access
+#define MMC_CMD6_ACCESS_COMMAND_SET (0lu << 24)
+#define MMC_CMD6_ACCESS_SET_BITS (1lu << 24)
+#define MMC_CMD6_ACCESS_CLEAR_BITS (2lu << 24)
+#define MMC_CMD6_ACCESS_WRITE_BYTE (3lu << 24)
+//! [23:16] Index for Mode Segment
+#define MMC_CMD6_INDEX_CMD_SET (EXT_CSD_CMD_SET_INDEX << 16)
+#define MMC_CMD6_INDEX_CMD_SET_REV (EXT_CSD_CMD_SET_REV_INDEX << 16)
+#define MMC_CMD6_INDEX_POWER_CLASS (EXT_CSD_POWER_CLASS_INDEX << 16)
+#define MMC_CMD6_INDEX_HS_TIMING (EXT_CSD_HS_TIMING_INDEX << 16)
+#define MMC_CMD6_INDEX_BUS_WIDTH (EXT_CSD_BUS_WIDTH_INDEX << 16)
+#define MMC_CMD6_INDEX_ERASED_MEM_CONT (EXT_CSD_ERASED_MEM_CONT_INDEX << 16)
+#define MMC_CMD6_INDEX_BOOT_CONFIG (EXT_CSD_BOOT_CONFIG_INDEX << 16)
+#define MMC_CMD6_INDEX_BOOT_BUS_WIDTH (EXT_CSD_BOOT_BUS_WIDTH_INDEX << 16)
+#define MMC_CMD6_INDEX_ERASE_GROUP_DEF (EXT_CSD_ERASE_GROUP_DEF_INDEX << 16)
+//! [15:8] Value
+#define MMC_CMD6_VALUE_BUS_WIDTH_1BIT (0x0lu << 8)
+#define MMC_CMD6_VALUE_BUS_WIDTH_4BIT (0x1lu << 8)
+#define MMC_CMD6_VALUE_BUS_WIDTH_8BIT (0x2lu << 8)
+#define MMC_CMD6_VALUE_HS_TIMING_ENABLE (0x1lu << 8)
+#define MMC_CMD6_VALUE_HS_TIMING_DISABLE (0x0lu << 8)
+//! [7:3] Set to 0
+//! [2:0] Cmd Set
+//! @}
+
+//! \name SD CMD6 argument structure
+//! @{
+//! CMD6 arg[ 3: 0] function group 1, access mode
+#define SD_CMD6_GRP1_HIGH_SPEED (0x1lu << 0)
+#define SD_CMD6_GRP1_DEFAULT (0x0lu << 0)
+//! CMD6 arg[ 7: 4] function group 2, command system
+#define SD_CMD6_GRP2_NO_INFLUENCE (0xFlu << 4)
+#define SD_CMD6_GRP2_DEFAULT (0x0lu << 4)
+//! CMD6 arg[11: 8] function group 3, 0xF or 0x0
+#define SD_CMD6_GRP3_NO_INFLUENCE (0xFlu << 8)
+#define SD_CMD6_GRP3_DEFAULT (0x0lu << 8)
+//! CMD6 arg[15:12] function group 4, 0xF or 0x0
+#define SD_CMD6_GRP4_NO_INFLUENCE (0xFlu << 12)
+#define SD_CMD6_GRP4_DEFAULT (0x0lu << 12)
+//! CMD6 arg[19:16] function group 5, 0xF or 0x0
+#define SD_CMD6_GRP5_NO_INFLUENCE (0xFlu << 16)
+#define SD_CMD6_GRP5_DEFAULT (0x0lu << 16)
+//! CMD6 arg[23:20] function group 6, 0xF or 0x0
+#define SD_CMD6_GRP6_NO_INFLUENCE (0xFlu << 20)
+#define SD_CMD6_GRP6_DEFAULT (0x0lu << 20)
+//! CMD6 arg[30:24] reserved 0
+//! CMD6 arg[31 ] Mode, 0: Check, 1: Switch
+#define SD_CMD6_MODE_CHECK (0lu << 31)
+#define SD_CMD6_MODE_SWITCH (1lu << 31)
+//! @}
+
+//! \name SD CMD8 argument structure
+//! @{
+#define SD_CMD8_PATTERN 0xAA
+#define SD_CMD8_MASK_PATTERN 0xFF
+#define SD_CMD8_HIGH_VOLTAGE 0x100
+#define SD_CMD8_MASK_VOLTAGE 0xF00
+//! @}
+
+//! \name SD ACMD41 arguments
+//! @{
+#define SD_ACMD41_HCS (1lu << 30) //!< (SD) Host Capacity Support
+ //! @}
+//! @}
+
+//! \name SDIO definitions
+//! @{
+
+//! \name SDIO state (in R5)
+//! @{
+#define SDIO_R5_COM_CRC_ERROR (1lu << 15) /**< CRC check error */
+#define SDIO_R5_ILLEGAL_COMMAND (1lu << 14) /**< Illegal command */
+#define SDIO_R5_STATE (3lu << 12) /**< SDIO R5 state mask */
+#define SDIO_R5_STATE_DIS (0lu << 12) /**< Disabled */
+#define SDIO_R5_STATE_CMD (1lu << 12) /**< DAT lines free */
+#define SDIO_R5_STATE_TRN (2lu << 12) /**< Transfer */
+#define SDIO_R5_STATE_RFU (3lu << 12) /**< Reserved */
+#define SDIO_R5_ERROR (1lu << 11) /**< General error */
+#define SDIO_R5_FUNC_NUM (1lu << 9) /**< Invalid function number */
+#define SDIO_R5_OUT_OF_RANGE (1lu << 8) /**< Argument out of range */
+#define SDIO_R5_STATUS_ERR (SDIO_R5_ERROR | SDIO_R5_FUNC_NUM | SDIO_R5_OUT_OF_RANGE) //!< Errro status bits mask
+ //! @}
+
+//! \name SDIO state (in R6)
+//! @{
+/** The CRC check of the previous command failed. */
+#define SDIO_R6_COM_CRC_ERROR (1lu << 15)
+/** Command not legal for the card state. */
+#define SDIO_R6_ILLEGAL_COMMAND (1lu << 14)
+/** A general or an unknown error occurred during the operation. */
+#define SDIO_R6_ERROR (1lu << 13)
+/** Status bits mask for SDIO R6 */
+#define SDIO_STATUS_R6 (SDIO_R6_COM_CRC_ERROR | SDIO_R6_ILLEGAL_COMMAND | SDIO_R6_ERROR)
+//! @}
+
+//! \name SDIO CMD52 argument bit offset
+//! @{
+//! CMD52 arg[ 7: 0] Write data or stuff bits
+#define SDIO_CMD52_WR_DATA 0
+//! CMD52 arg[ 8] Reserved
+#define SDIO_CMD52_STUFF0 8
+//! CMD52 arg[25: 9] Register address
+#define SDIO_CMD52_REG_ADRR 9
+//! CMD52 arg[ 26] Reserved
+#define SDIO_CMD52_STUFF1 26
+//! CMD52 arg[ 27] Read after Write flag
+#define SDIO_CMD52_RAW_FLAG 27
+//! CMD52 arg[30:28] Number of the function
+#define SDIO_CMD52_FUNCTION_NUM 28
+//! CMD52 arg[ 31] Direction, 1:write, 0:read.
+#define SDIO_CMD52_RW_FLAG 31
+#define SDIO_CMD52_READ_FLAG 0
+#define SDIO_CMD52_WRITE_FLAG 1
+//! @}
+
+//! \name SDIO CMD53 argument structure
+//! @{
+/**
+ * [ 8: 0] Byte mode: number of bytes to transfer,
+ * 0 cause 512 bytes transfer.
+ * Block mode: number of blocks to transfer,
+ * 0 set count to infinite.
+ */
+#define SDIO_CMD53_COUNT 0
+//! CMD53 arg[25: 9] Start Address I/O register
+#define SDIO_CMD53_REG_ADDR 9
+//! CMD53 arg[ 26] 1:Incrementing address, 0: fixed
+#define SDIO_CMD53_OP_CODE 26
+//! CMD53 arg[ 27] (Optional) 1:block mode
+#define SDIO_CMD53_BLOCK_MODE 27
+//! CMD53 arg[30:28] Number of the function
+#define SDIO_CMD53_FUNCTION_NUM 28
+//! CMD53 arg[ 31] Direction, 1:WR, 0:RD
+#define SDIO_CMD53_RW_FLAG 31
+#define SDIO_CMD53_READ_FLAG 0
+#define SDIO_CMD53_WRITE_FLAG 1
+//! @}
+
+//! \name SDIO Functions
+//! @{
+#define SDIO_CIA 0 /**< SDIO Function 0 (CIA) */
+#define SDIO_FN0 0 /**< SDIO Function 0 */
+#define SDIO_FN1 1 /**< SDIO Function 1 */
+#define SDIO_FN2 2 /**< SDIO Function 2 */
+#define SDIO_FN3 3 /**< SDIO Function 3 */
+#define SDIO_FN4 4 /**< SDIO Function 4 */
+#define SDIO_FN5 5 /**< SDIO Function 5 */
+#define SDIO_FN6 6 /**< SDIO Function 6 */
+#define SDIO_FN7 7 /**< SDIO Function 7 */
+ //! @}
+
+//! \name SDIO Card Common Control Registers (CCCR)
+//! @{
+#define SDIO_CCCR_SDIO_REV 0x00 /**< CCCR/SDIO revision (RO) */
+#define SDIO_CCCR_REV (0xFlu << 0) /**< CCCR/FBR Version */
+#define SDIO_CCCR_REV_1_00 (0x0lu << 0) /**< CCCR/FBR Version 1.00 */
+#define SDIO_CCCR_REV_1_10 (0x1lu << 0) /**< CCCR/FBR Version 1.10 */
+#define SDIO_CCCR_REV_2_00 (0x2lu << 0) /**< CCCR/FBR Version 2.00 */
+#define SDIO_CCCR_REV_3_00 (0x3lu << 0) /**< CCCR/FBR Version 3.00 */
+#define SDIO_SDIO_REV (0xFlu << 4) /**< SDIO Spec */
+#define SDIO_SDIO_REV_1_00 (0x0lu << 4) /**< SDIO Spec 1.00 */
+#define SDIO_SDIO_REV_1_10 (0x1lu << 4) /**< SDIO Spec 1.10 */
+#define SDIO_SDIO_REV_1_20 (0x2lu << 4) /**< SDIO Spec 1.20(unreleased) */
+#define SDIO_SDIO_REV_2_00 (0x3lu << 4) /**< SDIO Spec Version 2.00 */
+#define SDIO_SDIO_REV_3_00 (0x4lu << 4) /**< SDIO Spec Version 3.00 */
+#define SDIO_CCCR_SD_REV 0x01 /**< SD Spec Revision (RO) */
+#define SDIO_SD_REV (0xFlu << 0) /**< SD Physical Spec */
+#define SDIO_SD_REV_1_01 (0x0lu << 0) /**< SD 1.01 (Mar 2000) */
+#define SDIO_SD_REV_1_10 (0x1lu << 0) /**< SD 1.10 (Oct 2004) */
+#define SDIO_SD_REV_2_00 (0x2lu << 0) /**< SD 2.00 (May 2006) */
+#define SDIO_SD_REV_3_00 (0x3lu << 0) /**< SD 3.00 */
+#define SDIO_CCCR_IOE 0x02 /**< I/O Enable (R/W) */
+#define SDIO_IOE (0xFElu << 1) /**< Functions Enable/Disable */
+#define SDIO_IOE_FN1 (0x1lu << 1) /**< Function 1 Enable/Disable */
+#define SDIO_IOE_FN2 (0x1lu << 2) /**< Function 2 Enable/Disable */
+#define SDIO_IOE_FN3 (0x1lu << 3) /**< Function 3 Enable/Disable */
+#define SDIO_IOE_FN4 (0x1lu << 4) /**< Function 4 Enable/Disable */
+#define SDIO_IOE_FN5 (0x1lu << 5) /**< Function 5 Enable/Disable */
+#define SDIO_IOE_FN6 (0x1lu << 6) /**< Function 6 Enable/Disable */
+#define SDIO_IOE_FN7 (0x1lu << 7) /**< Function 7 Enable/Disable */
+#define SDIO_CCCR_IOR 0x03 /**< I/O Ready (RO) */
+#define SDIO_IOR (0xFElu << 1) /**< Functions ready */
+#define SDIO_IOR_FN1 (0x1lu << 1) /**< Function 1 ready */
+#define SDIO_IOR_FN2 (0x1lu << 2) /**< Function 2 ready */
+#define SDIO_IOR_FN3 (0x1lu << 3) /**< Function 3 ready */
+#define SDIO_IOR_FN4 (0x1lu << 4) /**< Function 4 ready */
+#define SDIO_IOR_FN5 (0x1lu << 5) /**< Function 5 ready */
+#define SDIO_IOR_FN6 (0x1lu << 6) /**< Function 6 ready */
+#define SDIO_IOR_FN7 (0x1lu << 7) /**< Function 7 ready */
+#define SDIO_CCCR_IEN 0x04 /**< Int Enable */
+#define SDIO_IENM (0x1lu << 0) /**< Int Enable Master (R/W) */
+#define SDIO_IEN (0xFElu << 1) /**< Functions Int Enable */
+#define SDIO_IEN_FN1 (0x1lu << 1) /**< Function 1 Int Enable */
+#define SDIO_IEN_FN2 (0x1lu << 2) /**< Function 2 Int Enable */
+#define SDIO_IEN_FN3 (0x1lu << 3) /**< Function 3 Int Enable */
+#define SDIO_IEN_FN4 (0x1lu << 4) /**< Function 4 Int Enable */
+#define SDIO_IEN_FN5 (0x1lu << 5) /**< Function 5 Int Enable */
+#define SDIO_IEN_FN6 (0x1lu << 6) /**< Function 6 Int Enable */
+#define SDIO_IEN_FN7 (0x1lu << 7) /**< Function 7 Int Enable */
+#define SDIO_CCCR_INT 0x05 /**< Int Pending */
+#define SDIO_INT (0xFElu << 1) /**< Functions Int pending */
+#define SDIO_INT_FN1 (0x1lu << 1) /**< Function 1 Int pending */
+#define SDIO_INT_FN2 (0x1lu << 2) /**< Function 2 Int pending */
+#define SDIO_INT_FN3 (0x1lu << 3) /**< Function 3 Int pending */
+#define SDIO_INT_FN4 (0x1lu << 4) /**< Function 4 Int pending */
+#define SDIO_INT_FN5 (0x1lu << 5) /**< Function 5 Int pending */
+#define SDIO_INT_FN6 (0x1lu << 6) /**< Function 6 Int pending */
+#define SDIO_INT_FN7 (0x1lu << 7) /**< Function 7 Int pending */
+#define SDIO_CCCR_IOA 0x06 /**< I/O Abort */
+#define SDIO_AS (0x7lu << 0) /**< Abort Select In Order (WO) */
+#define SDIO_AS_FN1 (0x1lu << 0) /**< Abort function 1 IO */
+#define SDIO_AS_FN2 (0x2lu << 0) /**< Abort function 2 IO */
+#define SDIO_AS_FN3 (0x3lu << 0) /**< Abort function 3 IO */
+#define SDIO_AS_FN4 (0x4lu << 0) /**< Abort function 4 IO */
+#define SDIO_AS_FN5 (0x5lu << 0) /**< Abort function 5 IO */
+#define SDIO_AS_FN6 (0x6lu << 0) /**< Abort function 6 IO */
+#define SDIO_AS_FN7 (0x7lu << 0) /**< Abort function 7 IO */
+#define SDIO_RES (0x1lu << 3) /**< IO CARD RESET (WO) */
+#define SDIO_CCCR_BUS_CTRL 0x07 /**< Bus Interface Control */
+#define SDIO_BUSWIDTH (0x3lu << 0) /**< Data bus width (R/W) */
+#define SDIO_BUSWIDTH_1B (0x0lu << 0) /**< 1-bit data bus */
+#define SDIO_BUSWIDTH_4B (0x2lu << 0) /**< 4-bit data bus */
+/** Enable Continuous SPI interrupt (R/W) */
+#define SDIO_BUS_ECSI (0x1lu << 5)
+/** Support Continuous SPI interrupt (RO) */
+#define SDIO_BUS_SCSI (0x1lu << 6)
+/** Connect(0)/Disconnect(1) pull-up on CD/DAT[3] (R/W) */
+#define SDIO_BUS_CD_DISABLE (0x1lu << 7)
+#define SDIO_CCCR_CAP 0x08 /**< Card Capability */
+/** Support Direct Commands during data transfer (RO) */
+#define SDIO_CAP_SDC (0x1lu << 0)
+/** Support Multi-Block (RO) */
+#define SDIO_CAP_SMB (0x1lu << 1)
+/** Support Read Wait (RO) */
+#define SDIO_CAP_SRW (0x1lu << 2)
+/** Support Suspend/Resume (RO) */
+#define SDIO_CAP_SBS (0x1lu << 3)
+/** Support interrupt between blocks of data in 4-bit SD mode (RO) */
+#define SDIO_CAP_S4MI (0x1lu << 4)
+/** Enable interrupt between blocks of data in 4-bit SD mode (R/W) */
+#define SDIO_CAP_E4MI (0x1lu << 5)
+/** Low-Speed Card (RO) */
+#define SDIO_CAP_LSC (0x1lu << 6)
+/** 4-bit support for Low-Speed Card (RO) */
+#define SDIO_CAP_4BLS (0x1lu << 7)
+/** Pointer to CIS (3B, LSB first) */
+#define SDIO_CCCR_CIS_PTR 0x09
+/** Bus Suspend */
+#define SDIO_CCCR_BUS_SUSPEND 0x0C
+/** Bus Status (transfer on DAT[x] lines) (RO) */
+#define SDIO_BS (0x1lu << 0)
+/** Bus Release Request/Status (R/W) */
+#define SDIO_BR (0x1lu << 1)
+#define SDIO_CCCR_FUN_SEL 0x0D /**< Function select */
+#define SDIO_DF (0x1lu << 7) /**< Resume Data Flag (RO) */
+#define SDIO_FS (0xFlu << 0) /**< Select Function (R/W) */
+#define SDIO_FS_CIA (0x0lu << 0) /**< Select CIA (function 0) */
+#define SDIO_FS_FN1 (0x1lu << 0) /**< Select Function 1 */
+#define SDIO_FS_FN2 (0x2lu << 0) /**< Select Function 2 */
+#define SDIO_FS_FN3 (0x3lu << 0) /**< Select Function 3 */
+#define SDIO_FS_FN4 (0x4lu << 0) /**< Select Function 4 */
+#define SDIO_FS_FN5 (0x5lu << 0) /**< Select Function 5 */
+#define SDIO_FS_FN6 (0x6lu << 0) /**< Select Function 6 */
+#define SDIO_FS_FN7 (0x7lu << 0) /**< Select Function 7 */
+#define SDIO_FS_MEM (0x8lu << 0) /**< Select memory in combo card */
+#define SDIO_CCCR_EXEC 0x0E /**< Exec Flags (RO) */
+#define SDIO_EXM (0x1lu << 0) /**< Executing status of memory */
+#define SDIO_EX (0xFElu << 1) /**< Executing functions status */
+#define SDIO_EX_FN1 (0x1lu << 1) /**< Executing status of func 1 */
+#define SDIO_EX_FN2 (0x1lu << 2) /**< Executing status of func 2 */
+#define SDIO_EX_FN3 (0x1lu << 3) /**< Executing status of func 3 */
+#define SDIO_EX_FN4 (0x1lu << 4) /**< Executing status of func 4 */
+#define SDIO_EX_FN5 (0x1lu << 5) /**< Executing status of func 5 */
+#define SDIO_EX_FN6 (0x1lu << 6) /**< Executing status of func 6 */
+#define SDIO_EX_FN7 (0x1lu << 7) /**< Executing status of func 7 */
+#define SDIO_CCCR_READY 0x0F /**< Ready Flags (RO) */
+#define SDIO_RFM (0x1lu << 0) /**< Ready Flag for memory */
+#define SDIO_RF (0xFElu) /**< Ready Flag for functions */
+#define SDIO_RF_FN1 (0x1lu << 1) /**< Ready Flag for function 1 */
+#define SDIO_RF_FN2 (0x1lu << 2) /**< Ready Flag for function 2 */
+#define SDIO_RF_FN3 (0x1lu << 3) /**< Ready Flag for function 3 */
+#define SDIO_RF_FN4 (0x1lu << 4) /**< Ready Flag for function 4 */
+#define SDIO_RF_FN5 (0x1lu << 5) /**< Ready Flag for function 5 */
+#define SDIO_RF_FN6 (0x1lu << 6) /**< Ready Flag for function 6 */
+#define SDIO_RF_FN7 (0x1lu << 7) /**< Ready Flag for function 7 */
+#define SDIO_CCCR_FN0_BLKSIZ 0x10 /**< FN0 Block Size (2B, LSB first) (R/W) */
+#define SDIO_CCCR_POWER 0x12 /**< Power Control */
+#define SDIO_SMPC (0x1lu << 0) /**< Support Master Power Control*/
+#define SDIO_EMPC (0x1lu << 1) /**< Enable Master Power Control */
+#define SDIO_CCCR_HS 0x13 /**< High-Speed */
+#define SDIO_SHS (0x1lu << 0) /**< Support High-Speed (RO) */
+#define SDIO_EHS (0x1lu << 1) /**< Enable High-Speed (R/W) */
+ //! @}
+
+//! \name SDIO Function Basic Registers (FBR)
+//! @{
+#define SDIO_FBR_ADDR(fn, x) (0x100 * (fn) + (x))
+#define SDIO_FBR_CSA_IF 0x0 /**< CSA and function interface code (RO) */
+#define SDIO_IFC (0xFUL << 0) /**< Standard SDIO Fun Interface Code */
+#define SDIO_IFC_NO_IF (0x0UL << 0) /**< No SDIO standard interface */
+#define SDIO_IFC_UART (0x1UL << 0) /**< UART */
+#define SDIO_IFC_TA_BT (0x2UL << 0) /**< Type-A Bluetooth */
+#define SDIO_IFC_TB_BT (0x3UL << 0) /**< Type-B Bluetooth */
+#define SDIO_IFC_GPS (0x4UL << 0) /**< GPS */
+#define SDIO_IFC_CAMERA (0x5UL << 0) /**< Camera */
+#define SDIO_IFC_PHS (0x6UL << 0) /**< PHS */
+#define SDIO_IFC_WLAN (0x7UL << 0) /**< WLAN */
+#define SDIO_IFC_ATA (0x8UL << 0) /**< Embedded SDIO-ATA */
+#define SDIO_IFC_EXT (0xFUL << 0) /**< Check EXT interface code */
+#define SDIO_SCSA (0x1UL << 6) /**< Function supports Code Storage Area (CSA) */
+#define SDIO_FBR_CSA (0x1UL << 7) /**< Function CSA enable */
+#define SDIO_FBR_EXT_IF 0x1 /**< Extended function interface code (RO) */
+#define SDIO_FBR_PWR 0x2 /**< function power control */
+#define SDIO_SPS (0x1UL << 0) /**< function support power selection (RO) */
+#define SDIO_EPS (0x1UL << 1) /**< Low Current Mode/High Current Mode (R/W) */
+#define SDIO_FBR_CIS_PTR 0x9 /**< Address pointer to function CIS (3B, LSB first) (RO) */
+#define SDIO_FBR_CSA_PTR 0xC /**< Address pointer to CSA (3B, LSB first) (R/W) */
+#define SDIO_FBR_CSA_DATA 0xF /**< Read/Write fifo to CSA (R/W) */
+#define SDIO_FBR_BLK_SIZ 0x10 /**< Block size (2B, LSB first) (R/W) */
+ //! @}
+
+//! \name SDIO Card Metaformat
+//! @{
+/** Null tuple (PCMCIA 3.1.9) */
+#define SDIO_CISTPL_NULL 0x00
+/** Device tuple (PCMCIA 3.2.2) */
+#define SDIO_CISTPL_DEVICE 0x01
+/** Checksum control (PCMCIA 3.1.1) */
+#define SDIO_CISTPL_CHECKSUM 0x10
+/** Level 1 version (PCMCIA 3.2.10) */
+#define SDIO_CISTPL_VERS_1 0x15
+/** Alternate Language String (PCMCIA 3.2.1) */
+#define SDIO_CISTPL_ALTSTR 0x16
+/** Manufacturer Identification String (PCMCIA 3.2.9) */
+#define SDIO_CISTPL_MANFID 0x20
+/** Function Identification (PCMCIA 3.2.7) */
+#define SDIO_CISTPL_FUNCID 0x21
+/** Function Extensions (PCMCIA 3.2.6) */
+#define SDIO_CISTPL_FUNCE 0x22
+/** Additional information for SDIO (PCMCIA 6.1.2) */
+#define SDIO_CISTPL_SDIO_STD 0x91
+/** Reserved for future SDIO (PCMCIA 6.1.3) */
+#define SDIO_CISTPL_SDIO_EXT 0x92
+/** The End-of-chain Tuple (PCMCIA 3.1.2) */
+#define SDIO_CISTPL_END 0xFF
+//! @}
+
+//! @}
+
+//! \name CSD, OCR, SCR, Switch status, extend CSD definitions
+//! @{
+
+/**
+ * \brief Macro function to extract a bits field from a large SD MMC register
+ * Used by : CSD, SCR, Switch status
+ */
+static inline uint32_t SDMMC_UNSTUFF_BITS(uint8_t *reg, uint16_t reg_size, uint16_t pos, uint8_t size)
+{
+ uint32_t value;
+ value = reg[((reg_size - pos + 7) / 8) - 1] >> (pos % 8);
+ if (((pos % 8) + size) > 8) {
+ value |= (uint32_t)reg[((reg_size - pos + 7) / 8) - 2] << (8 - (pos % 8));
+ }
+ if (((pos % 8) + size) > 16) {
+ value |= (uint32_t)reg[((reg_size - pos + 7) / 8) - 3] << (16 - (pos % 8));
+ }
+ if (((pos % 8) + size) > 24) {
+ value |= (uint32_t)reg[((reg_size - pos + 7) / 8) - 3] << (24 - (pos % 8));
+ }
+ value &= ((uint32_t)1 << size) - 1;
+ return value;
+}
+
+ //! \name CSD Fields
+ //! @{
+#define CSD_REG_BIT_SIZE 128 //!< 128 bits
+#define CSD_REG_BSIZE (CSD_REG_BIT_SIZE / 8) //!< 16 bytes
+#define CSD_STRUCTURE(csd, pos, size) SDMMC_UNSTUFF_BITS(csd, CSD_REG_BIT_SIZE, pos, size)
+#define CSD_STRUCTURE_VERSION(csd) CSD_STRUCTURE(csd, 126, 2)
+#define SD_CSD_VER_1_0 0
+#define SD_CSD_VER_2_0 1
+#define MMC_CSD_VER_1_0 0
+#define MMC_CSD_VER_1_1 1
+#define MMC_CSD_VER_1_2 2
+#define CSD_TRAN_SPEED(csd) CSD_STRUCTURE(csd, 96, 8)
+#define SD_CSD_1_0_C_SIZE(csd) CSD_STRUCTURE(csd, 62, 12)
+#define SD_CSD_1_0_C_SIZE_MULT(csd) CSD_STRUCTURE(csd, 47, 3)
+#define SD_CSD_1_0_READ_BL_LEN(csd) CSD_STRUCTURE(csd, 80, 4)
+#define SD_CSD_2_0_C_SIZE(csd) CSD_STRUCTURE(csd, 48, 22)
+#define MMC_CSD_C_SIZE(csd) CSD_STRUCTURE(csd, 62, 12)
+#define MMC_CSD_C_SIZE_MULT(csd) CSD_STRUCTURE(csd, 47, 3)
+#define MMC_CSD_READ_BL_LEN(csd) CSD_STRUCTURE(csd, 80, 4)
+#define MMC_CSD_SPEC_VERS(csd) CSD_STRUCTURE(csd, 122, 4)
+ //! @}
+
+ //! \name OCR Register Fields
+ //! @{
+#define OCR_REG_BSIZE (32 / 8) /**< 32 bits, 4 bytes */
+#define OCR_VDD_170_195 (1lu << 7)
+#define OCR_VDD_20_21 (1lu << 8)
+#define OCR_VDD_21_22 (1lu << 9)
+#define OCR_VDD_22_23 (1lu << 10)
+#define OCR_VDD_23_24 (1lu << 11)
+#define OCR_VDD_24_25 (1lu << 12)
+#define OCR_VDD_25_26 (1lu << 13)
+#define OCR_VDD_26_27 (1lu << 14)
+#define OCR_VDD_27_28 (1lu << 15)
+#define OCR_VDD_28_29 (1lu << 16)
+#define OCR_VDD_29_30 (1lu << 17)
+#define OCR_VDD_30_31 (1lu << 18)
+#define OCR_VDD_31_32 (1lu << 19)
+#define OCR_VDD_32_33 (1lu << 20)
+#define OCR_VDD_33_34 (1lu << 21)
+#define OCR_VDD_34_35 (1lu << 22)
+#define OCR_VDD_35_36 (1lu << 23)
+#define OCR_SDIO_S18R (1lu << 24) /**< Switching to 1.8V Accepted */
+#define OCR_SDIO_MP (1lu << 27) /**< Memory Present */
+#define OCR_SDIO_NF (7lu << 28) /**< Number of I/O Functions */
+#define OCR_ACCESS_MODE_MASK (3lu << 29) /**< (MMC) Access mode mask */
+#define OCR_ACCESS_MODE_BYTE (0lu << 29) /**< (MMC) Byte access mode */
+#define OCR_ACCESS_MODE_SECTOR (2lu << 29) /**< (MMC) Sector access mode */
+#define OCR_CCS (1lu << 30) /**< (SD) Card Capacity Status */
+#define OCR_POWER_UP_BUSY (1lu << 31) /**< Card power up status bit */
+ //! @}
+
+ //! \name SD SCR Register Fields
+ //! @{
+#define SD_SCR_REG_BIT_SIZE 64 //!< 64 bits
+#define SD_SCR_REG_BSIZE (SD_SCR_REG_BIT_SIZE / 8) //!< 8 bytes
+#define SD_SCR_STRUCTURE(scr, pos, size) SDMMC_UNSTUFF_BITS(scr, SD_SCR_REG_BIT_SIZE, pos, size)
+#define SD_SCR_SCR_STRUCTURE(scr) SD_SCR_STRUCTURE(scr, 60, 4)
+#define SD_SCR_SCR_STRUCTURE_1_0 0
+#define SD_SCR_SD_SPEC(scr) SD_SCR_STRUCTURE(scr, 56, 4)
+#define SD_SCR_SD_SPEC_1_0_01 0
+#define SD_SCR_SD_SPEC_1_10 1
+#define SD_SCR_SD_SPEC_2_00 2
+#define SD_SCR_DATA_STATUS_AFTER_ERASE(scr) SD_SCR_STRUCTURE(scr, 55, 1)
+#define SD_SCR_SD_SECURITY(scr) SD_SCR_STRUCTURE(scr, 52, 3)
+#define SD_SCR_SD_SECURITY_NO 0
+#define SD_SCR_SD_SECURITY_NOTUSED 1
+#define SD_SCR_SD_SECURITY_1_01 2
+#define SD_SCR_SD_SECURITY_2_00 3
+#define SD_SCR_SD_SECURITY_3_00 4
+#define SD_SCR_SD_BUS_WIDTHS(scr) SD_SCR_STRUCTURE(scr, 48, 4)
+#define SD_SCR_SD_BUS_WIDTH_1BITS (1lu << 0)
+#define SD_SCR_SD_BUS_WIDTH_4BITS (1lu << 2)
+#define SD_SCR_SD_SPEC3(scr) SD_SCR_STRUCTURE(scr, 47, 1)
+#define SD_SCR_SD_SPEC_3_00 1
+#define SD_SCR_SD_EX_SECURITY(scr) SD_SCR_STRUCTURE(scr, 43, 4)
+#define SD_SCR_SD_CMD_SUPPORT(scr) SD_SCR_STRUCTURE(scr, 32, 2)
+ //! @}
+
+ //! \name SD Switch Status Fields
+ //! @{
+#define SD_SW_STATUS_BIT_SIZE 512 //!< 512 bits
+#define SD_SW_STATUS_BSIZE (SD_SW_STATUS_BIT_SIZE / 8) //!< 64 bytes
+#define SD_SW_STATUS_STRUCTURE(sd_sw_status, pos, size) \
+ SDMMC_UNSTUFF_BITS(sd_sw_status, SD_SW_STATUS_BIT_SIZE, pos, size)
+#define SD_SW_STATUS_MAX_CURRENT_CONSUMPTION(status) SD_SW_STATUS_STRUCTURE(status, 496, 16)
+#define SD_SW_STATUS_FUN_GRP6_INFO(status) SD_SW_STATUS_STRUCTURE(status, 480, 16)
+#define SD_SW_STATUS_FUN_GRP5_INFO(status) SD_SW_STATUS_STRUCTURE(status, 464, 16)
+#define SD_SW_STATUS_FUN_GRP4_INFO(status) SD_SW_STATUS_STRUCTURE(status, 448, 16)
+#define SD_SW_STATUS_FUN_GRP3_INFO(status) SD_SW_STATUS_STRUCTURE(status, 432, 16)
+#define SD_SW_STATUS_FUN_GRP2_INFO(status) SD_SW_STATUS_STRUCTURE(status, 416, 16)
+#define SD_SW_STATUS_FUN_GRP1_INFO(status) SD_SW_STATUS_STRUCTURE(status, 400, 16)
+#define SD_SW_STATUS_FUN_GRP6_RC(status) SD_SW_STATUS_STRUCTURE(status, 396, 4)
+#define SD_SW_STATUS_FUN_GRP5_RC(status) SD_SW_STATUS_STRUCTURE(status, 392, 4)
+#define SD_SW_STATUS_FUN_GRP4_RC(status) SD_SW_STATUS_STRUCTURE(status, 388, 4)
+#define SD_SW_STATUS_FUN_GRP3_RC(status) SD_SW_STATUS_STRUCTURE(status, 384, 4)
+#define SD_SW_STATUS_FUN_GRP2_RC(status) SD_SW_STATUS_STRUCTURE(status, 380, 4)
+#define SD_SW_STATUS_FUN_GRP1_RC(status) SD_SW_STATUS_STRUCTURE(status, 376, 4)
+#define SD_SW_STATUS_FUN_GRP_RC_ERROR 0xFU
+#define SD_SW_STATUS_DATA_STRUCT_VER(status) SD_SW_STATUS_STRUCTURE(status, 368, 8)
+#define SD_SW_STATUS_FUN_GRP6_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 352, 16)
+#define SD_SW_STATUS_FUN_GRP5_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 336, 16)
+#define SD_SW_STATUS_FUN_GRP4_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 320, 16)
+#define SD_SW_STATUS_FUN_GRP3_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 304, 16)
+#define SD_SW_STATUS_FUN_GRP2_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 288, 16)
+#define SD_SW_STATUS_FUN_GRP1_BUSY(status) SD_SW_STATUS_STRUCTURE(status, 272, 16)
+ //! @}
+
+ //! \name Card Status Fields
+ //! @{
+#define CARD_STATUS_APP_CMD (1lu << 5)
+#define CARD_STATUS_SWITCH_ERROR (1lu << 7)
+#define CARD_STATUS_READY_FOR_DATA (1lu << 8)
+#define CARD_STATUS_STATE_IDLE (0lu << 9)
+#define CARD_STATUS_STATE_READY (1lu << 9)
+#define CARD_STATUS_STATE_IDENT (2lu << 9)
+#define CARD_STATUS_STATE_STBY (3lu << 9)
+#define CARD_STATUS_STATE_TRAN (4lu << 9)
+#define CARD_STATUS_STATE_DATA (5lu << 9)
+#define CARD_STATUS_STATE_RCV (6lu << 9)
+#define CARD_STATUS_STATE_PRG (7lu << 9)
+#define CARD_STATUS_STATE_DIS (8lu << 9)
+#define CARD_STATUS_STATE (0xFlu << 9)
+#define CARD_STATUS_ERASE_RESET (1lu << 13)
+#define CARD_STATUS_WP_ERASE_SKIP (1lu << 15)
+#define CARD_STATUS_CIDCSD_OVERWRITE (1lu << 16)
+#define CARD_STATUS_OVERRUN (1lu << 17)
+#define CARD_STATUS_UNERRUN (1lu << 18)
+#define CARD_STATUS_ERROR (1lu << 19)
+#define CARD_STATUS_CC_ERROR (1lu << 20)
+#define CARD_STATUS_CARD_ECC_FAILED (1lu << 21)
+#define CARD_STATUS_ILLEGAL_COMMAND (1lu << 22)
+#define CARD_STATUS_COM_CRC_ERROR (1lu << 23)
+#define CARD_STATUS_UNLOCK_FAILED (1lu << 24)
+#define CARD_STATUS_CARD_IS_LOCKED (1lu << 25)
+#define CARD_STATUS_WP_VIOLATION (1lu << 26)
+#define CARD_STATUS_ERASE_PARAM (1lu << 27)
+#define CARD_STATUS_ERASE_SEQ_ERROR (1lu << 28)
+#define CARD_STATUS_BLOCK_LEN_ERROR (1lu << 29)
+#define CARD_STATUS_ADDRESS_MISALIGN (1lu << 30)
+#define CARD_STATUS_ADDR_OUT_OF_RANGE (1lu << 31)
+
+#define CARD_STATUS_ERR_RD_WR \
+ (CARD_STATUS_ADDR_OUT_OF_RANGE | CARD_STATUS_ADDRESS_MISALIGN | CARD_STATUS_BLOCK_LEN_ERROR \
+ | CARD_STATUS_WP_VIOLATION | CARD_STATUS_ILLEGAL_COMMAND | CARD_STATUS_CC_ERROR | CARD_STATUS_ERROR)
+ //! @}
+
+ //! \name SD Status Field
+ //! @{
+#define SD_STATUS_BSIZE (512 / 8) /**< 512 bits, 64bytes */
+ //! @}
+
+ //! \name MMC Extended CSD Register Field
+ //! @{
+#define EXT_CSD_BSIZE 512 /**< 512 bytes. */
+/* Below belongs to Properties Segment */
+#define EXT_CSD_S_CMD_SET_INDEX 504lu
+#define EXT_CSD_BOOT_INFO_INDEX 228lu
+#define EXT_CSD_BOOT_SIZE_MULTI_INDEX 226lu
+#define EXT_CSD_ACC_SIZE_INDEX 225lu
+#define EXT_CSD_HC_ERASE_GRP_SIZE_INDEX 224lu
+#define EXT_CSD_ERASE_TIMEOUT_MULT_INDEX 223lu
+#define EXT_CSD_REL_WR_SEC_C_INDEX 222lu
+#define EXT_CSD_HC_WP_GRP_SIZE_INDEX 221lu
+#define EXT_CSD_S_C_VCC_INDEX 220lu
+#define EXT_CSD_S_C_VCCQ_INDEX 219lu
+#define EXT_CSD_S_A_TIMEOUT_INDEX 217lu
+#define EXT_CSD_SEC_COUNT_INDEX 212lu
+#define EXT_CSD_MIN_PERF_W_8_52_INDEX 210lu
+#define EXT_CSD_MIN_PERF_R_8_52_INDEX 209lu
+#define EXT_CSD_MIN_PERF_W_8_26_4_52_INDEX 208lu
+#define EXT_CSD_MIN_PERF_R_8_26_4_52_INDEX 207lu
+#define EXT_CSD_MIN_PERF_W_4_26_INDEX 206lu
+#define EXT_CSD_MIN_PERF_R_4_26_INDEX 205lu
+#define EXT_CSD_PWR_CL_26_360_INDEX 203lu
+#define EXT_CSD_PWR_CL_52_360_INDEX 202lu
+#define EXT_CSD_PWR_CL_26_195_INDEX 201lu
+#define EXT_CSD_PWR_CL_52_195_INDEX 200lu
+#define EXT_CSD_CARD_TYPE_INDEX 196lu
+/* MMC card type */
+#define MMC_CTYPE_26MHZ 0x1
+#define MMC_CTYPE_52MHZ 0x2
+#define EXT_CSD_CSD_STRUCTURE_INDEX 194lu
+#define EXT_CSD_EXT_CSD_REV_INDEX 192lu
+
+/* Below belongs to Mode Segment */
+#define EXT_CSD_CMD_SET_INDEX 191lu
+#define EXT_CSD_CMD_SET_REV_INDEX 189lu
+#define EXT_CSD_POWER_CLASS_INDEX 187lu
+#define EXT_CSD_HS_TIMING_INDEX 185lu
+#define EXT_CSD_BUS_WIDTH_INDEX 183lu
+#define EXT_CSD_ERASED_MEM_CONT_INDEX 181lu
+#define EXT_CSD_BOOT_CONFIG_INDEX 179lu
+#define EXT_CSD_BOOT_BUS_WIDTH_INDEX 177lu
+#define EXT_CSD_ERASE_GROUP_DEF_INDEX 175lu
+ //! @}
+//! @}
+
+//! \name Definition for SPI mode only
+//! @{
+
+//! SPI commands start with a start bit "0" and a transmit bit "1"
+#define SPI_CMD_ENCODE(x) (0x40 | (x & 0x3F))
+
+//! \name Register R1 definition for SPI mode
+//! The R1 register is always send after a command.
+//! @{
+#define R1_SPI_IDLE (1lu << 0)
+#define R1_SPI_ERASE_RESET (1lu << 1)
+#define R1_SPI_ILLEGAL_COMMAND (1lu << 2)
+#define R1_SPI_COM_CRC (1lu << 3)
+#define R1_SPI_ERASE_SEQ (1lu << 4)
+#define R1_SPI_ADDRESS (1lu << 5)
+#define R1_SPI_PARAMETER (1lu << 6)
+// R1 bit 7 is always zero, reuse this bit for error
+#define R1_SPI_ERROR (1lu << 7)
+//! @}
+
+//! \name Register R2 definition for SPI mode
+//! The R2 register can be send after R1 register.
+//! @{
+#define R2_SPI_CARD_LOCKED (1lu << 0)
+#define R2_SPI_WP_ERASE_SKIP (1lu << 1)
+#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
+#define R2_SPI_ERROR (1lu << 2)
+#define R2_SPI_CC_ERROR (1lu << 3)
+#define R2_SPI_CARD_ECC_ERROR (1lu << 4)
+#define R2_SPI_WP_VIOLATION (1lu << 5)
+#define R2_SPI_ERASE_PARAM (1lu << 6)
+#define R2_SPI_OUT_OF_RANGE (1lu << 7)
+#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
+//! @}
+
+//! \name Control Tokens in SPI Mode
+//! @{
+//! \name Tokens used for a read operation
+//! @{
+#define SPI_TOKEN_SINGLE_MULTI_READ 0xFE
+#define SPI_TOKEN_DATA_ERROR_VALID(token) (((token)&0xF0) == 0)
+#define SPI_TOKEN_DATA_ERROR_ERRORS (0x0F)
+#define SPI_TOKEN_DATA_ERROR_ERROR (1lu << 0)
+#define SPI_TOKEN_DATA_ERROR_CC_ERROR (1lu << 1)
+#define SPI_TOKEN_DATA_ERROR_ECC_ERROR (1lu << 2)
+#define SPI_TOKEN_DATA_ERROR_OUT_RANGE (1lu << 3)
+ //! @}
+ //! \name Tokens used for a write operation
+ //! @{
+#define SPI_TOKEN_SINGLE_WRITE 0xFE
+#define SPI_TOKEN_MULTI_WRITE 0xFC
+#define SPI_TOKEN_STOP_TRAN 0xFD
+#define SPI_TOKEN_DATA_RESP_VALID(token) ((((token) & (1 << 4)) == 0) && (((token) & (1 << 0)) == 1))
+#define SPI_TOKEN_DATA_RESP_CODE(token) ((token)&0x1E)
+#define SPI_TOKEN_DATA_RESP_ACCEPTED (2lu << 1)
+#define SPI_TOKEN_DATA_RESP_CRC_ERR (5lu << 1)
+#define SPI_TOKEN_DATA_RESP_WRITE_ERR (6lu << 1)
+ //! @}
+ //! @}
+ //! @}
+
+ //! @} end of sd_mmc_protocol
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SD_MMC_PROTOCOL_H_INCLUDED */
diff --git a/ports/atmel-samd/supervisor/internal_flash.c b/ports/atmel-samd/supervisor/internal_flash.c
index 091959c4e..ecb59f836 100644
--- a/ports/atmel-samd/supervisor/internal_flash.c
+++ b/ports/atmel-samd/supervisor/internal_flash.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/atmel-samd/supervisor/internal_flash.h b/ports/atmel-samd/supervisor/internal_flash.h
index df8b495cc..1199e3b9c 100644
--- a/ports/atmel-samd/supervisor/internal_flash.h
+++ b/ports/atmel-samd/supervisor/internal_flash.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c
index 48bd3211b..591a85853 100644
--- a/ports/atmel-samd/supervisor/port.c
+++ b/ports/atmel-samd/supervisor/port.c
@@ -91,6 +91,23 @@
#if CIRCUITPY_PEW
#include "common-hal/_pew/PewPew.h"
#endif
+volatile bool hold_interrupt = false;
+#ifdef SAMD21
+void rtc_start_pulsein(void) {
+ rtc_set_continuous();
+ hold_interrupt = true;
+}
+
+void rtc_end_pulsein(void) {
+ hold_interrupt = false;
+}
+
+void rtc_set_continuous(void) {
+ while (RTC->MODE0.STATUS.bit.SYNCBUSY);
+ RTC->MODE0.READREQ.reg = RTC_READREQ_RREQ | RTC_READREQ_RCONT | 0x0010;
+ while (RTC->MODE0.STATUS.bit.SYNCBUSY);
+}
+#endif
extern volatile bool mp_msc_enabled;
@@ -189,11 +206,10 @@ static void rtc_init(void) {
safe_mode_t port_init(void) {
#if defined(SAMD21)
- // Set brownout detection to ~2.7V. Default from factory is 1.7V,
- // which is too low for proper operation of external SPI flash chips (they are 2.7-3.6V).
+ // Set brownout detection.
// Disable while changing level.
SYSCTRL->BOD33.bit.ENABLE = 0;
- SYSCTRL->BOD33.bit.LEVEL = 39; // 2.77V with hysteresis off. Table 37.20 in datasheet.
+ SYSCTRL->BOD33.bit.LEVEL = SAMD21_BOD33_LEVEL;
SYSCTRL->BOD33.bit.ENABLE = 1;
#ifdef ENABLE_MICRO_TRACE_BUFFER
@@ -208,11 +224,10 @@ safe_mode_t port_init(void) {
#endif
#if defined(SAM_D5X_E5X)
- // Set brownout detection to ~2.7V. Default from factory is 1.7V,
- // which is too low for proper operation of external SPI flash chips (they are 2.7-3.6V).
+ // Set brownout detection.
// Disable while changing level.
SUPC->BOD33.bit.ENABLE = 0;
- SUPC->BOD33.bit.LEVEL = 200; // 2.7V: 1.5V + LEVEL * 6mV.
+ SUPC->BOD33.bit.LEVEL = SAMD5x_E5x_BOD33_LEVEL;
SUPC->BOD33.bit.ENABLE = 1;
// MPU (Memory Protection Unit) setup.
@@ -307,9 +322,11 @@ void reset_port(void) {
audioout_reset();
#endif
#if CIRCUITPY_AUDIOBUSIO
- i2sout_reset();
//pdmin_reset();
#endif
+#if CIRCUITPY_AUDIOBUSIO_I2SOUT
+ i2sout_reset();
+#endif
#if CIRCUITPY_TOUCHIO && CIRCUITPY_TOUCHIO_USE_NATIVE
touchin_reset();
@@ -489,6 +506,11 @@ void port_interrupt_after_ticks(uint32_t ticks) {
// We'll interrupt sooner with an overflow.
return;
}
+#ifdef SAMD21
+ if (hold_interrupt) {
+ return;
+ }
+#endif
RTC->MODE0.COMP[0].reg = current_ticks + (ticks << 4);
RTC->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0;
RTC->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0;
@@ -503,7 +525,7 @@ void port_sleep_until_interrupt(void) {
}
#endif
common_hal_mcu_disable_interrupts();
- if (!tud_task_event_ready()) {
+ if (!tud_task_event_ready() && !hold_interrupt) {
__DSB();
__WFI();
}
diff --git a/ports/atmel-samd/supervisor/usb.c b/ports/atmel-samd/supervisor/usb.c
index 650ed6a39..ea940f898 100644
--- a/ports/atmel-samd/supervisor/usb.c
+++ b/ports/atmel-samd/supervisor/usb.c
@@ -29,6 +29,8 @@
#include "hpl/gclk/hpl_gclk_base.h"
#include "hal_gpio.h"
#include "lib/tinyusb/src/device/usbd.h"
+#include "supervisor/background_callback.h"
+#include "supervisor/usb.h"
void init_usb_hardware(void) {
#ifdef SAMD21
@@ -61,24 +63,24 @@ void init_usb_hardware(void) {
#ifdef SAMD21
void USB_Handler(void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
#endif
#ifdef SAM_D5X_E5X
void USB_0_Handler (void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
void USB_1_Handler (void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
void USB_2_Handler (void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
void USB_3_Handler (void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
#endif
diff --git a/ports/atmel-samd/tools/gen_pin_name_table.py b/ports/atmel-samd/tools/gen_pin_name_table.py
index ded64e5f6..4e25c39fd 100644
--- a/ports/atmel-samd/tools/gen_pin_name_table.py
+++ b/ports/atmel-samd/tools/gen_pin_name_table.py
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/cxd56/Makefile b/ports/cxd56/Makefile
index 507d76331..bb3958af4 100644
--- a/ports/cxd56/Makefile
+++ b/ports/cxd56/Makefile
@@ -62,6 +62,13 @@ SPRESENSE_SDK = spresense-exported-sdk
FIRMWARE = $(SPRESENSE_SDK)/firmware
+BOOTLOADER_FILES += \
+ $(FIRMWARE)/AESM.espk \
+ $(FIRMWARE)/dnnrt-mp.espk \
+ $(FIRMWARE)/gnssfw.espk \
+ $(FIRMWARE)/loader.espk \
+ $(FIRMWARE)/sysutil.spk \
+
# Platforms are: Linux, Darwin, MSYS, CYGWIN
PLATFORM := $(firstword $(subst _, ,$(shell uname -s 2>/dev/null)))
@@ -91,8 +98,7 @@ INC += \
-I$(SPRESENSE_SDK)/nuttx/arch \
-I$(SPRESENSE_SDK)/nuttx/arch/chip \
-I$(SPRESENSE_SDK)/nuttx/arch/os \
- -I$(SPRESENSE_SDK)/sdk/bsp/include \
- -I$(SPRESENSE_SDK)/sdk/bsp/include/sdk \
+ -I$(SPRESENSE_SDK)/sdk/include \
CFLAGS += \
$(INC) \
@@ -101,7 +107,6 @@ CFLAGS += \
-Dmain=spresense_main \
-D_estack=__stack \
-c \
- -Os \
-pipe \
-std=gnu11 \
-mcpu=cortex-m4 \
@@ -117,6 +122,12 @@ CFLAGS += \
-fdata-sections \
-Wall \
+OPTIMIZATION_FLAGS ?= -O2
+
+# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS)
+
+
LIBM = "${shell "$(CC)" $(CFLAGS) -print-file-name=libm.a}"
LIBGCC = "${shell "$(CC)" $(CFLAGS) -print-libgcc-file-name}"
@@ -125,7 +136,7 @@ LDFLAGS = \
--entry=__start \
-nostartfiles \
-nodefaultlibs \
- -T$(SPRESENSE_SDK)/nuttx/build/ramconfig.ld \
+ -T$(SPRESENSE_SDK)/nuttx/scripts/ramconfig.ld \
--gc-sections \
-Map=$(BUILD)/output.map \
-o $(BUILD)/firmware.elf \
@@ -133,14 +144,14 @@ LDFLAGS = \
-u spresense_main \
-u board_timerhook \
$(BUILD)/libmpy.a \
- $(SPRESENSE_SDK)/sdk/libs/libapps.a \
- $(SPRESENSE_SDK)/sdk/libs/libsdk.a \
+ $(SPRESENSE_SDK)/nuttx/libs/libapps.a \
+ $(SPRESENSE_SDK)/nuttx/libs/libnuttx.a \
$(LIBM) \
$(LIBGCC) \
--end-group \
-L$(BUILD) \
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_CXD56 -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=512 $(CFLAGS_MOD)
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_CXD56 -DCFG_TUD_MIDI_RX_BUFSIZE=512 -DCFG_TUD_CDC_RX_BUFSIZE=512 -DCFG_TUD_MIDI_TX_BUFSIZE=512 -DCFG_TUD_CDC_TX_BUFSIZE=512 -DCFG_TUD_MSC_BUFSIZE=512 $(CFLAGS_MOD)
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
$(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \
@@ -213,11 +224,11 @@ $(BUILD)/firmware.spk: $(BUILD)/firmware.elf $(MKSPK)
flash: $(BUILD)/firmware.spk
$(ECHO) "Writing $< to the board"
- $(SPRESENSE_SDK)/sdk/tools/flash.sh -c $(SERIAL) $(BUILD)/firmware.spk
+ tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $(BUILD)/firmware.spk
flash-bootloader: $(SPRESENSE_SDK) $(FIRMWARE)
$(ECHO) "Writing loader to the board"
- $(SPRESENSE_SDK)/sdk/tools/flash.sh -l $(FIRMWARE) -c $(SERIAL)
+ tools/flash_writer.py -s -c $(SERIAL) -d -b 115200 -n $(BOOTLOADER_FILES)
include $(TOP)/py/mkrules.mk
diff --git a/ports/cxd56/README.md b/ports/cxd56/README.md
index ec284e742..7fa439aac 100644
--- a/ports/cxd56/README.md
+++ b/ports/cxd56/README.md
@@ -16,7 +16,7 @@ Board features:
* Spresense is powered by Sony's CXD5602 microcontroller (ARM® Cortex®-M4F × 6
cores), with a clock speed of 156 MHz.
-Currently, Spresense port does not support GNSS, Audio and Multicore.
+Currently, Spresense port does not support Audio and Multicore.
Refer to [developer.sony.com/develop/spresense/](https://developer.sony.com/develop/spresense/)
for further information about this board.
@@ -75,7 +75,7 @@ Bootloader information:
* You have to accept the End User License Agreement to be able to download and use the Spresense bootloader binary.
-Download the spresense binaries zip archive from: [Spresense firmware v1-4-000](https://developer.sony.com/file/download/download-spresense-firmware-v1-4-000)
+Download the spresense binaries zip archive from: [Spresense firmware v2-0-000](https://developer.sony.com/file/download/download-spresense-firmware-v2-0-000)
Extract spresense binaries in your PC to ports/spresense/spresense-exported-sdk/firmware/
diff --git a/ports/cxd56/background.c b/ports/cxd56/background.c
index af0957bd0..6de6d7275 100644
--- a/ports/cxd56/background.c
+++ b/ports/cxd56/background.c
@@ -30,28 +30,6 @@
#include "supervisor/filesystem.h"
#include "supervisor/shared/stack.h"
-static bool running_background_tasks = false;
-
-void background_tasks_reset(void) {
- running_background_tasks = false;
-}
-
-void run_background_tasks(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
-
- assert_heap_ok();
- running_background_tasks = true;
-
-#if CIRCUITPY_BLEIO
- bleio_background();
-#endif
-
- usb_background();
- filesystem_background();
-
- running_background_tasks = false;
- assert_heap_ok();
-}
+void port_background_task(void) {}
+void port_start_background_task(void) {}
+void port_finish_background_task(void) {}
diff --git a/ports/cxd56/background.h b/ports/cxd56/background.h
index a38e3faed..5f76e6442 100644
--- a/ports/cxd56/background.h
+++ b/ports/cxd56/background.h
@@ -27,7 +27,4 @@
#ifndef MICROPY_INCLUDED_CXD56_BACKGROUND_H
#define MICROPY_INCLUDED_CXD56_BACKGROUND_H
-void background_tasks_reset(void);
-void run_background_tasks(void);
-
#endif // MICROPY_INCLUDED_CXD56_BACKGROUND_H
diff --git a/ports/cxd56/boards/spresense/pins.c b/ports/cxd56/boards/spresense/pins.c
index fcc854590..5028d9155 100644
--- a/ports/cxd56/boards/spresense/pins.c
+++ b/ports/cxd56/boards/spresense/pins.c
@@ -24,8 +24,21 @@
* THE SOFTWARE.
*/
+#include "py/objtuple.h"
+
#include "shared-bindings/board/__init__.h"
+STATIC const mp_rom_obj_tuple_t sdio_data_tuple = {
+ {&mp_type_tuple},
+ 4,
+ {
+ MP_ROM_PTR(&pin_SDIO_DATA0),
+ MP_ROM_PTR(&pin_SDIO_DATA1),
+ MP_ROM_PTR(&pin_SDIO_DATA2),
+ MP_ROM_PTR(&pin_SDIO_DATA3),
+ }
+};
+
STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_UART2_RXD) },
{ MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_UART2_TXD) },
@@ -76,5 +89,8 @@ STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_CLOCK), MP_ROM_PTR(&pin_SDIO_CLK) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_COMMAND), MP_ROM_PTR(&pin_SDIO_CMD) },
+ { MP_ROM_QSTR(MP_QSTR_SDIO_DATA), MP_ROM_PTR(&sdio_data_tuple) },
};
MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/cxd56/common-hal/busio/SPI.c b/ports/cxd56/common-hal/busio/SPI.c
index 718a8ff16..2d365d482 100644
--- a/ports/cxd56/common-hal/busio/SPI.c
+++ b/ports/cxd56/common-hal/busio/SPI.c
@@ -130,7 +130,7 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len,
return true;
}
-bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
SPI_EXCHANGE(self->spi_dev, data_out, data_in, len);
return true;
diff --git a/ports/cxd56/common-hal/busio/UART.c b/ports/cxd56/common-hal/busio/UART.c
index e455b0568..52d2afc0c 100644
--- a/ports/cxd56/common-hal/busio/UART.c
+++ b/ports/cxd56/common-hal/busio/UART.c
@@ -56,7 +56,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
- uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
bool sigint_enabled) {
struct termios tio;
@@ -69,7 +69,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
mp_raise_ValueError(translate("Could not initialize UART"));
}
- if (parity != PARITY_NONE) {
+ if (parity != BUSIO_UART_PARITY_NONE) {
mp_raise_ValueError(translate("Could not initialize UART"));
}
diff --git a/ports/cxd56/common-hal/microcontroller/Pin.c b/ports/cxd56/common-hal/microcontroller/Pin.c
index 23377197c..7aba1ad54 100644
--- a/ports/cxd56/common-hal/microcontroller/Pin.c
+++ b/ports/cxd56/common-hal/microcontroller/Pin.c
@@ -72,6 +72,12 @@ const mcu_pin_obj_t pin_I2S1_BCK = PIN(PIN_I2S1_BCK, false);
const mcu_pin_obj_t pin_I2S1_LRCK = PIN(PIN_I2S1_LRCK, false);
const mcu_pin_obj_t pin_I2S1_DATA_IN = PIN(PIN_I2S1_DATA_IN, false);
const mcu_pin_obj_t pin_I2S1_DATA_OUT = PIN(PIN_I2S1_DATA_OUT, false);
+const mcu_pin_obj_t pin_SDIO_CLK = PIN(PIN_SDIO_CLK, false);
+const mcu_pin_obj_t pin_SDIO_CMD = PIN(PIN_SDIO_CMD, false);
+const mcu_pin_obj_t pin_SDIO_DATA0 = PIN(PIN_SDIO_DATA0, false);
+const mcu_pin_obj_t pin_SDIO_DATA1 = PIN(PIN_SDIO_DATA1, false);
+const mcu_pin_obj_t pin_SDIO_DATA2 = PIN(PIN_SDIO_DATA2, false);
+const mcu_pin_obj_t pin_SDIO_DATA3 = PIN(PIN_SDIO_DATA3, false);
const mcu_pin_obj_t pin_LPADC0 = PIN(0, true);
const mcu_pin_obj_t pin_LPADC1 = PIN(1, true);
const mcu_pin_obj_t pin_LPADC2 = PIN(2, true);
diff --git a/ports/cxd56/common-hal/microcontroller/Pin.h b/ports/cxd56/common-hal/microcontroller/Pin.h
index fe6524edb..6759a2dca 100644
--- a/ports/cxd56/common-hal/microcontroller/Pin.h
+++ b/ports/cxd56/common-hal/microcontroller/Pin.h
@@ -77,6 +77,12 @@ extern const mcu_pin_obj_t pin_I2S1_BCK;
extern const mcu_pin_obj_t pin_I2S1_LRCK;
extern const mcu_pin_obj_t pin_I2S1_DATA_IN;
extern const mcu_pin_obj_t pin_I2S1_DATA_OUT;
+extern const mcu_pin_obj_t pin_SDIO_CLK;
+extern const mcu_pin_obj_t pin_SDIO_CMD;
+extern const mcu_pin_obj_t pin_SDIO_DATA0;
+extern const mcu_pin_obj_t pin_SDIO_DATA1;
+extern const mcu_pin_obj_t pin_SDIO_DATA2;
+extern const mcu_pin_obj_t pin_SDIO_DATA3;
extern const mcu_pin_obj_t pin_LPADC0;
extern const mcu_pin_obj_t pin_LPADC1;
extern const mcu_pin_obj_t pin_LPADC2;
diff --git a/ports/cxd56/common-hal/pulseio/PWMOut.h b/ports/cxd56/common-hal/pulseio/PWMOut.h
index 57fc4181f..694acc4e0 100644
--- a/ports/cxd56/common-hal/pulseio/PWMOut.h
+++ b/ports/cxd56/common-hal/pulseio/PWMOut.h
@@ -27,7 +27,7 @@
#ifndef MICROPY_INCLUDED_CXD56_COMMON_HAL_PULSEIO_PWMOUT_H
#define MICROPY_INCLUDED_CXD56_COMMON_HAL_PULSEIO_PWMOUT_H
-#include <nuttx/drivers/pwm.h>
+#include <nuttx/timers/pwm.h>
#include "common-hal/microcontroller/Pin.h"
diff --git a/ports/cxd56/common-hal/sdioio/SDCard.c b/ports/cxd56/common-hal/sdioio/SDCard.c
new file mode 100644
index 000000000..cf7de422c
--- /dev/null
+++ b/ports/cxd56/common-hal/sdioio/SDCard.c
@@ -0,0 +1,141 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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 <fcntl.h>
+#include <unistd.h>
+#include <arch/chip/pin.h>
+
+#include "py/mperrno.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/sdioio/SDCard.h"
+#include "shared-bindings/util.h"
+
+#define DATA_PINS_NUM 4
+
+void common_hal_sdioio_sdcard_construct(sdioio_sdcard_obj_t *self,
+ const mcu_pin_obj_t *clock, const mcu_pin_obj_t *command,
+ uint8_t num_data, mcu_pin_obj_t **data, uint32_t frequency) {
+ struct geometry geo;
+
+ if (clock->number != PIN_SDIO_CLK || command->number != PIN_SDIO_CMD) {
+ mp_raise_ValueError(translate("Invalid pins"));
+ }
+
+ uint8_t data_pins_num = 0;
+ for (uint8_t i = 0; i < DATA_PINS_NUM; i++) {
+ if (data[i]->number != PIN_SDIO_DATA0 || data[i]->number != PIN_SDIO_DATA1 ||
+ data[i]->number != PIN_SDIO_DATA2 || data[i]->number != PIN_SDIO_DATA3) {
+ data_pins_num++;
+ }
+ }
+
+ if (data_pins_num != DATA_PINS_NUM) {
+ mp_raise_ValueError(translate("Invalid pins"));
+ }
+
+ if (open_blockdriver("/dev/mmcsd0", 0, &self->inode) < 0) {
+ mp_raise_ValueError(translate("Could not initialize SDCard"));
+ }
+
+ self->inode->u.i_bops->geometry(self->inode, &geo);
+
+ claim_pin(clock);
+ claim_pin(command);
+ self->clock_pin = clock;
+ self->command_pin = command;
+ for (uint8_t i = 0; i < DATA_PINS_NUM; i++) {
+ claim_pin(data[i]);
+ self->data_pins[i] = data[i];
+ }
+
+ self->count = geo.geo_nsectors;
+ self->frequency = frequency;
+ self->width = num_data;
+}
+
+void common_hal_sdioio_sdcard_deinit(sdioio_sdcard_obj_t *self) {
+ close_blockdriver(self->inode);
+ self->inode = NULL;
+
+ reset_pin_number(self->clock_pin->number);
+ reset_pin_number(self->command_pin->number);
+ for (uint8_t i = 0; i < DATA_PINS_NUM; i++) {
+ reset_pin_number(self->data_pins[i]->number);
+ }
+}
+
+bool common_hal_sdioio_sdcard_deinited(sdioio_sdcard_obj_t *self) {
+ return self->inode == NULL;
+}
+
+bool common_hal_sdioio_sdcard_configure(sdioio_sdcard_obj_t *self, uint32_t baudrate, uint8_t width) {
+ return true;
+}
+
+uint32_t common_hal_sdioio_sdcard_get_frequency(sdioio_sdcard_obj_t* self) {
+ return self->frequency;
+}
+
+uint8_t common_hal_sdioio_sdcard_get_width(sdioio_sdcard_obj_t* self) {
+ return self->width;
+}
+
+uint32_t common_hal_sdioio_sdcard_get_count(sdioio_sdcard_obj_t* self) {
+ return self->count;
+}
+
+STATIC void check_whole_block(mp_buffer_info_t *bufinfo) {
+ if (bufinfo->len % 512) {
+ mp_raise_ValueError(translate("Buffer length must be a multiple of 512"));
+ }
+}
+
+int common_hal_sdioio_sdcard_readblocks(sdioio_sdcard_obj_t* self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
+ if (common_hal_sdioio_sdcard_deinited(self)) {
+ raise_deinited_error();
+ }
+ check_whole_block(bufinfo);
+
+ return self->inode->u.i_bops->read(self->inode, bufinfo->buf, start_block, bufinfo->len / 512);
+}
+
+int common_hal_sdioio_sdcard_writeblocks(sdioio_sdcard_obj_t* self, uint32_t start_block, mp_buffer_info_t *bufinfo) {
+ if (common_hal_sdioio_sdcard_deinited(self)) {
+ raise_deinited_error();
+ }
+ check_whole_block(bufinfo);
+
+ return self->inode->u.i_bops->write(self->inode, bufinfo->buf, start_block, bufinfo->len / 512);;
+}
+
+void common_hal_sdioio_sdcard_never_reset(sdioio_sdcard_obj_t *self) {
+ never_reset_pin_number(self->clock_pin->number);
+ never_reset_pin_number(self->command_pin->number);
+ for (uint8_t i = 0; i < DATA_PINS_NUM; i++) {
+ never_reset_pin_number(self->data_pins[i]->number);
+ }
+}
diff --git a/ports/cxd56/common-hal/sdioio/SDCard.h b/ports/cxd56/common-hal/sdioio/SDCard.h
new file mode 100644
index 000000000..cbdcd4706
--- /dev/null
+++ b/ports/cxd56/common-hal/sdioio/SDCard.h
@@ -0,0 +1,47 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright 2020 Sony Semiconductor Solutions Corporation
+ *
+ * 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_CXD56_SDIOIO_SDCARD_H
+#define MICROPY_INCLUDED_CXD56_SDIOIO_SDCARD_H
+
+#include <nuttx/fs/fs.h>
+
+#include "py/obj.h"
+
+#include "common-hal/microcontroller/Pin.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ struct inode* inode;
+ uint32_t frequency;
+ uint32_t count;
+ uint8_t width;
+ const mcu_pin_obj_t *command_pin;
+ const mcu_pin_obj_t *clock_pin;
+ const mcu_pin_obj_t *data_pins[4];
+} sdioio_sdcard_obj_t;
+
+#endif // MICROPY_INCLUDED_CXD56_SDIOIO_SDCARD_H
diff --git a/ports/cxd56/common-hal/sdioio/__init__.c b/ports/cxd56/common-hal/sdioio/__init__.c
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/cxd56/common-hal/sdioio/__init__.c
diff --git a/ports/cxd56/configs/circuitpython/defconfig b/ports/cxd56/configs/circuitpython/defconfig
new file mode 100644
index 000000000..268f7a68e
--- /dev/null
+++ b/ports/cxd56/configs/circuitpython/defconfig
@@ -0,0 +1,171 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_ARCH_LEDS is not set
+# CONFIG_CXD56_I2C0_SCUSEQ is not set
+# CONFIG_CXD56_SFC is not set
+# CONFIG_CXD56_SPI3_SCUSEQ is not set
+# CONFIG_MMCSD_MMCSUPPORT is not set
+# CONFIG_MMCSD_SPI is not set
+# CONFIG_MTD_SMART_WEAR_LEVEL is not set
+# CONFIG_NET_IPv4 is not set
+# CONFIG_NXFONTS_PACKEDMSFIRST is not set
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="spresense"
+CONFIG_ARCH_BOARD_SPRESENSE=y
+CONFIG_ARCH_CHIP="cxd56xx"
+CONFIG_ARCH_CHIP_CXD56XX=y
+CONFIG_ARCH_INTERRUPTSTACK=2048
+CONFIG_ARCH_MATH_H=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARMV7M_USEBASEPRI=y
+CONFIG_ASMP=y
+CONFIG_AUDIO=y
+CONFIG_AUDIOUTILS_DSP_MOUNTPT="/mnt/sd0/BIN"
+CONFIG_AUDIOUTILS_MANAGER=y
+CONFIG_AUDIOUTILS_PLAYER=y
+CONFIG_AUDIOUTILS_PLAYLIST=y
+CONFIG_AUDIOUTILS_RECORDER=y
+CONFIG_BOARDCTL_IOCTL=y
+CONFIG_BOARDCTL_POWEROFF=y
+CONFIG_BOARDCTL_RESET=y
+CONFIG_BOARDCTL_UNIQUEID=y
+CONFIG_BOARDCTL_UNIQUEID_SIZE=5
+CONFIG_BOARDCTL_USBDEVCTRL=y
+CONFIG_BOARD_CRASHDUMP=y
+CONFIG_BOARD_LATE_INITIALIZE=y
+CONFIG_BOARD_LOOPSPERMSEC=5434
+CONFIG_BOOT_RUNFROMISRAM=y
+CONFIG_BUILTIN=y
+CONFIG_CLOCK_MONOTONIC=y
+CONFIG_CXD56_ADC=y
+CONFIG_CXD56_AUDIO=y
+CONFIG_CXD56_BINARY=y
+CONFIG_CXD56_CHARGER=y
+CONFIG_CXD56_CISIF=y
+CONFIG_CXD56_GAUGE=y
+CONFIG_CXD56_GNSS=y
+CONFIG_CXD56_HPADC0=y
+CONFIG_CXD56_HPADC1=y
+CONFIG_CXD56_I2C0=y
+CONFIG_CXD56_I2C2=y
+CONFIG_CXD56_I2C=y
+CONFIG_CXD56_I2C_DRIVER=y
+CONFIG_CXD56_IMAGEPROC=y
+CONFIG_CXD56_LPADC=y
+CONFIG_CXD56_PWM0=y
+CONFIG_CXD56_PWM1=y
+CONFIG_CXD56_PWM2=y
+CONFIG_CXD56_PWM3=y
+CONFIG_CXD56_PWM=y
+CONFIG_CXD56_SDIO=y
+CONFIG_CXD56_SPI3=y
+CONFIG_CXD56_SPI5=y
+CONFIG_CXD56_SPI=y
+CONFIG_CXD56_UART2=y
+CONFIG_DEBUG_FULLOPT=y
+CONFIG_DEBUG_SYMBOLS=y
+CONFIG_DNN_RT=y
+CONFIG_DNN_RT_MP=y
+CONFIG_DRIVERS_VIDEO=y
+CONFIG_EXTERNALS_CMSIS=y
+CONFIG_FAT_LCNAMES=y
+CONFIG_FAT_LFN=y
+CONFIG_FAT_MAXFNAME=64
+CONFIG_FS_FAT=y
+CONFIG_FS_PROCFS=y
+CONFIG_FS_PROCFS_REGISTER=y
+CONFIG_FS_ROMFS=y
+CONFIG_FS_SMARTFS=y
+CONFIG_HAVE_CXX=y
+CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_LCD=y
+CONFIG_LCD_NOGETRUN=y
+CONFIG_LIBC_FLOATINGPOINT=y
+CONFIG_LIBC_IPv4_ADDRCONV=y
+CONFIG_LIBC_IPv6_ADDRCONV=y
+CONFIG_LIB_KBDCODEC=y
+CONFIG_MAX_WDOGPARMS=2
+CONFIG_MEMUTILS=y
+CONFIG_MMCSD=y
+CONFIG_MMCSD_SDIO=y
+CONFIG_MTD=y
+CONFIG_MTD_BYTE_WRITE=y
+CONFIG_MTD_SMART=y
+CONFIG_MTD_SMART_ENABLE_CRC=y
+CONFIG_MTD_SMART_FSCK=y
+CONFIG_MTD_SMART_SECTOR_SIZE=4096
+CONFIG_NAME_MAX=64
+CONFIG_NET=y
+CONFIG_NETDEVICES=y
+CONFIG_NETDEV_LATEINIT=y
+CONFIG_NET_SOCKOPTS=y
+CONFIG_NET_TCP_NO_STACK=y
+CONFIG_NET_UDP_NO_STACK=y
+CONFIG_NET_USRSOCK=y
+CONFIG_NET_USRSOCK_TCP=y
+CONFIG_NET_USRSOCK_UDP=y
+CONFIG_NFILE_STREAMS=8
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_DISABLE_LOSMART=y
+CONFIG_NSH_LINELEN=160
+CONFIG_NSH_MAXARGUMENTS=14
+CONFIG_NSH_READLINE=y
+CONFIG_PIPES=y
+CONFIG_PREALLOC_MQ_MSGS=4
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_PREALLOC_WDOGS=16
+CONFIG_PWM=y
+CONFIG_RAM_SIZE=1572864
+CONFIG_RAM_START=0x0d000000
+CONFIG_READLINE_CMD_HISTORY=y
+CONFIG_READLINE_CMD_HISTORY_LINELEN=160
+CONFIG_READLINE_TABCOMPLETION=y
+CONFIG_RR_INTERVAL=200
+CONFIG_RTC=y
+CONFIG_RTC_ALARM=y
+CONFIG_RTC_DRIVER=y
+CONFIG_RTC_FREQUENCY=32768
+CONFIG_RTC_HIRES=y
+CONFIG_SCHED_CHILD_STATUS=y
+CONFIG_SCHED_HAVE_PARENT=y
+CONFIG_SCHED_HPWORK=y
+CONFIG_SCHED_LPNTHREADS=3
+CONFIG_SCHED_LPWORK=y
+CONFIG_SCHED_WAITPID=y
+CONFIG_SDCLONE_DISABLE=y
+CONFIG_SDIO_MUXBUS=y
+CONFIG_SDK_AUDIO=y
+CONFIG_SERIAL_TERMIOS=y
+CONFIG_SMARTFS_ALIGNED_ACCESS=y
+CONFIG_SMARTFS_MAXNAMLEN=30
+CONFIG_SMARTFS_MULTI_ROOT_DIRS=y
+CONFIG_SPECIFIC_DRIVERS=y
+CONFIG_SPI=y
+CONFIG_SPRESENSE_EXTENSION=y
+CONFIG_START_DAY=6
+CONFIG_START_MONTH=12
+CONFIG_START_YEAR=2011
+CONFIG_SYSTEMTICK_HOOK=y
+CONFIG_SYSTEM_CLE=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_SYSTEM_NSH_CXXINITIALIZE=y
+CONFIG_UART1_RXBUFSIZE=1024
+CONFIG_UART1_SERIAL_CONSOLE=y
+CONFIG_UART1_TXBUFSIZE=1024
+CONFIG_UART2_IFLOWCONTROL=y
+CONFIG_UART2_OFLOWCONTROL=y
+CONFIG_USBDEV=y
+CONFIG_USBDEV_DMA=y
+CONFIG_USBDEV_DUALSPEED=y
+CONFIG_USEC_PER_TICK=1000
+CONFIG_USERMAIN_STACKSIZE=1064960
+CONFIG_USER_ENTRYPOINT="spresense_main"
+CONFIG_VIDEO_ISX012=y
+CONFIG_VIDEO_STREAM=y
diff --git a/ports/cxd56/mkspk/elf32.h b/ports/cxd56/mkspk/elf32.h
new file mode 100644
index 000000000..94a9c81ba
--- /dev/null
+++ b/ports/cxd56/mkspk/elf32.h
@@ -0,0 +1,175 @@
+/****************************************************************************
+ * include/elf32.h
+ *
+ * Copyright (C) 2012 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Reference: System V Application Binary Interface, Edition 4.1, March 18,
+ * 1997, The Santa Cruz Operation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_ELF32_H
+#define __INCLUDE_ELF32_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define EI_NIDENT 16 /* Size of e_ident[] */
+
+#define ELF32_ST_BIND(i) ((i) >> 4)
+#define ELF32_ST_TYPE(i) ((i) & 0xf)
+#define ELF32_ST_INFO(b,t) (((b) << 4) | ((t) & 0xf))
+
+/* Definitions for Elf32_Rel*::r_info */
+
+#define ELF32_R_SYM(i) ((i) >> 8)
+#define ELF32_R_TYPE(i) ((i) & 0xff)
+#define ELF32_R_INFO(s,t) (((s)<< 8) | ((t) & 0xff))
+
+#define ELF_R_SYM(i) ELF32_R_SYM(i)
+
+/****************************************************************************
+ * Public Type Definitions
+ ****************************************************************************/
+
+/* Figure 4.2: 32-Bit Data Types */
+
+typedef uint32_t Elf32_Addr; /* Unsigned program address */
+typedef uint16_t Elf32_Half; /* Unsigned medium integer */
+typedef uint32_t Elf32_Off; /* Unsigned file offset */
+typedef int32_t Elf32_Sword; /* Signed large integer */
+typedef uint32_t Elf32_Word; /* Unsigned large integer */
+
+/* Figure 4-3: ELF Header */
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT];
+ Elf32_Half e_type;
+ Elf32_Half e_machine;
+ Elf32_Word e_version;
+ Elf32_Addr e_entry;
+ Elf32_Off e_phoff;
+ Elf32_Off e_shoff;
+ Elf32_Word e_flags;
+ Elf32_Half e_ehsize;
+ Elf32_Half e_phentsize;
+ Elf32_Half e_phnum;
+ Elf32_Half e_shentsize;
+ Elf32_Half e_shnum;
+ Elf32_Half e_shstrndx;
+} Elf32_Ehdr;
+
+/* Figure 4-8: Section Header */
+
+typedef struct
+{
+ Elf32_Word sh_name;
+ Elf32_Word sh_type;
+ Elf32_Word sh_flags;
+ Elf32_Addr sh_addr;
+ Elf32_Off sh_offset;
+ Elf32_Word sh_size;
+ Elf32_Word sh_link;
+ Elf32_Word sh_info;
+ Elf32_Word sh_addralign;
+ Elf32_Word sh_entsize;
+} Elf32_Shdr;
+
+/* Figure 4-15: Symbol Table Entry */
+
+typedef struct
+{
+ Elf32_Word st_name;
+ Elf32_Addr st_value;
+ Elf32_Word st_size;
+ unsigned char st_info;
+ unsigned char st_other;
+ Elf32_Half st_shndx;
+} Elf32_Sym;
+
+/* Figure 4-19: Relocation Entries */
+
+typedef struct
+{
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+} Elf32_Rel;
+
+typedef struct
+{
+ Elf32_Addr r_offset;
+ Elf32_Word r_info;
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+/* Figure 5-1: Program Header */
+
+typedef struct
+{
+ Elf32_Word p_type;
+ Elf32_Off p_offset;
+ Elf32_Addr p_vaddr;
+ Elf32_Addr p_paddr;
+ Elf32_Word p_filesz;
+ Elf32_Word p_memsz;
+ Elf32_Word p_flags;
+ Elf32_Word p_align;
+} Elf32_Phdr;
+
+/* Figure 5-9: Dynamic Structure */
+
+typedef struct
+{
+ Elf32_Sword d_tag;
+ union
+ {
+ Elf32_Word d_val;
+ Elf32_Addr d_ptr;
+ } d_un;
+} Elf32_Dyn;
+
+typedef Elf32_Addr Elf_Addr;
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Rel Elf_Rel;
+typedef Elf32_Rela Elf_Rela;
+typedef Elf32_Sym Elf_Sym;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Word Elf_Word;
+
+#endif /* __INCLUDE_ELF32_H */
diff --git a/ports/cxd56/mkspk/mkspk.h b/ports/cxd56/mkspk/mkspk.h
index 5a67bb3dd..5c1b979c0 100644
--- a/ports/cxd56/mkspk/mkspk.h
+++ b/ports/cxd56/mkspk/mkspk.h
@@ -36,12 +36,22 @@
****************************************************************************/
#include "clefia.h"
-#include "elf.h"
+#include "elf32.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+#define EI_MAG0 0 /* File identification */
+#define EI_MAG1 1
+#define EI_MAG2 2
+#define EI_MAG3 3
+
+#define SHT_SYMTAB 2
+#define SHT_STRTAB 3
+
+#define PT_LOAD 1
+
#define alignup(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define swap(a, b) { (a) ^= (b); (b) ^= (a); (a) ^= (b); }
diff --git a/ports/cxd56/mpconfigport.mk b/ports/cxd56/mpconfigport.mk
index 23f60f8a7..914e0b37d 100644
--- a/ports/cxd56/mpconfigport.mk
+++ b/ports/cxd56/mpconfigport.mk
@@ -1,5 +1,5 @@
USB_SERIAL_NUMBER_LENGTH = 10
-USB_MSC_MAX_PACKET_SIZE = 512
+USB_HIGHSPEED = 1
USB_RENUMBER_ENDPOINTS = 0
USB_CDC_EP_NUM_NOTIFICATION = 3
USB_CDC_EP_NUM_DATA_OUT = 2
@@ -7,6 +7,8 @@ USB_CDC_EP_NUM_DATA_IN = 1
USB_MSC_EP_NUM_OUT = 5
USB_MSC_EP_NUM_IN = 4
+MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
+
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_AUDIOIO = 0
CIRCUITPY_COUNTIO = 0
@@ -18,6 +20,7 @@ CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_NEOPIXEL_WRITE = 0
CIRCUITPY_NVM = 0
CIRCUITPY_ROTARYIO = 0
+CIRCUITPY_SDIOIO = 1
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_USB_HID = 0
CIRCUITPY_USB_MIDI = 0
diff --git a/ports/cxd56/tools/flash_writer.py b/ports/cxd56/tools/flash_writer.py
new file mode 100755
index 000000000..840f10c32
--- /dev/null
+++ b/ports/cxd56/tools/flash_writer.py
@@ -0,0 +1,580 @@
+#! /usr/bin/env python3
+
+# Copyright (C) 2018 Sony Semiconductor Solutions Corp.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name NuttX nor the names of its contributors may be
+# used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+import time
+import sys
+import os
+import struct
+import glob
+import fnmatch
+import errno
+import telnetlib
+import argparse
+import shutil
+import subprocess
+import re
+import xmodem
+
+import_serial_module = True
+
+# When SDK release, plase set SDK_RELEASE as True.
+SDK_RELEASE = False
+
+if SDK_RELEASE :
+ PRINT_RAW_COMMAND = False
+ REBOOT_AT_END = True
+else :
+ PRINT_RAW_COMMAND = True
+ REBOOT_AT_END = True
+
+try:
+ import serial
+except:
+ import_serial_module = False
+
+# supported environment various
+# CXD56_PORT
+# CXD56_TELNETSRV_PORT
+# CXD56_TELNETSRV_IP
+
+PROTOCOL_SERIAL = 0
+PROTOCOL_TELNET = 1
+
+MAX_DOT_COUNT = 70
+
+# configure parameters and default value
+class ConfigArgs:
+ PROTOCOL_TYPE = None
+ SERIAL_PORT = "COM1"
+ SERVER_PORT = 4569
+ SERVER_IP = "localhost"
+ EOL = bytes([10])
+ WAIT_RESET = True
+ AUTO_RESET = False
+ DTR_RESET = False
+ XMODEM_BAUD = 0
+ NO_SET_BOOTABLE = False
+ PACKAGE_NAME = []
+ FILE_NAME = []
+ ERASE_NAME = []
+ PKGSYS_NAME = []
+ PKGAPP_NAME = []
+ PKGUPD_NAME = []
+
+ROM_MSG = [b"Welcome to nash"]
+XMDM_MSG = "Waiting for XMODEM (CRC or 1K) transfer. Ctrl-X to cancel."
+
+class ConfigArgsLoader():
+ def __init__(self):
+ self.parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
+ self.parser.add_argument("package_name", help="the name of the package to install", nargs='*')
+ self.parser.add_argument("-f", "--file", dest="file_name", help="save file", action='append')
+ self.parser.add_argument("-e", "--erase", dest="erase_name", help="erase file", action='append')
+
+ self.parser.add_argument("-S", "--sys", dest="pkgsys_name", help="the name of the system package to install", action='append')
+ self.parser.add_argument("-A", "--app", dest="pkgapp_name", help="the name of the application package to install", action='append')
+ self.parser.add_argument("-U", "--upd", dest="pkgupd_name", help="the name of the updater package to install", action='append')
+
+ self.parser.add_argument("-a", "--auto-reset", dest="auto_reset",
+ action="store_true", default=None,
+ help="try to auto reset develop board if possible")
+ self.parser.add_argument("-d", "--dtr-reset", dest="dtr_reset",
+ action="store_true", default=None,
+ help="try to auto reset develop board if possible")
+ self.parser.add_argument("-n", "--no-set-bootable", dest="no_set_bootable",
+ action="store_true", default=None,
+ help="not to set bootable")
+
+ group = self.parser.add_argument_group()
+ group.add_argument("-i", "--server-ip", dest="server_ip",
+ help="the ip address connected to the telnet server")
+ group.add_argument("-p", "--server-port", dest="server_port", type=int,
+ help="the port connected to the telnet server")
+
+ group = self.parser.add_argument_group()
+ group.add_argument("-c", "--serial-port", dest="serial_port", help="the serial port")
+ group.add_argument("-b", "--xmodem-baudrate", dest="xmodem_baud", help="Use the faster baudrate in xmodem")
+
+ mutually_group = self.parser.add_mutually_exclusive_group()
+ mutually_group.add_argument("-t", "--telnet-protocol", dest="telnet_protocol",
+ action="store_true", default=None,
+ help="use the telnet protocol for binary transmission")
+ mutually_group.add_argument("-s", "--serial-protocol", dest="serial_protocol",
+ action="store_true", default=None,
+ help="use the serial port for binary transmission, default options")
+
+ mutually_group2 = self.parser.add_mutually_exclusive_group()
+ mutually_group2.add_argument("-F", "--force-wait-reset", dest="wait_reset",
+ action="store_true", default=None,
+ help="force wait for pressing RESET button")
+ mutually_group2.add_argument("-N", "--no-wait-reset", dest="wait_reset",
+ action="store_false", default=None,
+ help="if possible, skip to wait for pressing RESET button")
+
+ def update_config(self):
+ args = self.parser.parse_args()
+
+ ConfigArgs.PACKAGE_NAME = args.package_name
+ ConfigArgs.FILE_NAME = args.file_name
+ ConfigArgs.ERASE_NAME = args.erase_name
+ ConfigArgs.PKGSYS_NAME = args.pkgsys_name
+ ConfigArgs.PKGAPP_NAME = args.pkgapp_name
+ ConfigArgs.PKGUPD_NAME = args.pkgupd_name
+
+ # Get serial port or telnet server ip etc
+ if args.serial_protocol == True:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
+ elif args.telnet_protocol == True:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
+
+ if ConfigArgs.PROTOCOL_TYPE == None:
+ proto = os.environ.get("CXD56_PROTOCOL")
+ if proto is not None:
+ if 's' in proto:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
+ elif 't' in proto:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
+
+ if ConfigArgs.PROTOCOL_TYPE == None:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_SERIAL
+
+ if ConfigArgs.PROTOCOL_TYPE == PROTOCOL_SERIAL:
+ if args.serial_port is not None:
+ ConfigArgs.SERIAL_PORT = args.serial_port
+ else:
+ # Get serial port from the environment
+ port = os.environ.get("CXD56_PORT")
+ if port is not None:
+ ConfigArgs.SERIAL_PORT = port
+ else:
+ print("CXD56_PORT is not set, Use " + ConfigArgs.SERIAL_PORT + ".")
+ else:
+ ConfigArgs.PROTOCOL_TYPE = PROTOCOL_TELNET
+ if args.server_port is not None:
+ ConfigArgs.SERVER_PORT = args.server_port
+ else:
+ port = os.environ.get("CXD56_TELNETSRV_PORT")
+ if port is not None:
+ ConfigArgs.SERVER_PORT = port
+ else:
+ print("CXD56_TELNETSRV_PORT is not set, Use " + str(ConfigArgs.SERVER_PORT) + ".")
+ if args.server_ip is not None:
+ ConfigArgs.SERVER_IP = args.server_ip
+ else:
+ ip = os.environ.get("CXD56_TELNETSRV_IP")
+ if ip is not None:
+ ConfigArgs.SERVER_IP = ip
+ else:
+ print("CXD56_TELNETSRV_IP is not set, Use " + ConfigArgs.SERVER_IP + ".")
+
+ if args.xmodem_baud is not None:
+ ConfigArgs.XMODEM_BAUD = args.xmodem_baud
+
+ if args.auto_reset is not None:
+ ConfigArgs.AUTO_RESET = args.auto_reset
+
+ if args.dtr_reset is not None:
+ ConfigArgs.DTR_RESET = args.dtr_reset
+
+ if args.no_set_bootable is not None:
+ ConfigArgs.NO_SET_BOOTABLE = args.no_set_bootable
+
+ if args.wait_reset is not None:
+ ConfigArgs.WAIT_RESET = args.wait_reset
+
+class TelnetDev:
+ def __init__(self):
+ srv_ipaddr = ConfigArgs.SERVER_IP
+ srv_port = ConfigArgs.SERVER_PORT
+ self.recvbuf = b'';
+ try:
+ self.telnet = telnetlib.Telnet(host=srv_ipaddr, port=srv_port, timeout=10)
+ # There is a ack to be sent after connecting to the telnet server.
+ self.telnet.write(b"\xff")
+ except Exception as e:
+ print("Cannot connect to the server %s:%d" % (srv_ipaddr, srv_port))
+ sys.exit(e.args[0])
+
+ def readline(self, size=None):
+ res = b''
+ ch = b''
+ while ch != ConfigArgs.EOL:
+ ch = self.getc_raw(1, timeout=0.1)
+ if ch == b'':
+ return res
+ res += ch
+ return res
+
+ def getc_raw(self, size, timeout=1):
+ res = b''
+ tm = time.monotonic()
+ while size > 0:
+ while self.recvbuf == b'':
+ self.recvbuf = self.telnet.read_eager()
+ if self.recvbuf == b'':
+ if (time.monotonic() - tm) > timeout:
+ return res
+ time.sleep(0.1)
+ res += self.recvbuf[0:1]
+ self.recvbuf = self.recvbuf[1:]
+ size -= 1
+ return res
+
+ def write(self, buffer):
+ self.telnet.write(buffer)
+
+ def discard_inputs(self, timeout=1.0):
+ while True:
+ ch = self.getc_raw(1, timeout=timeout)
+ if ch == b'':
+ break
+
+ def getc(self, size, timeout=1):
+ c = self.getc_raw(size, timeout)
+ return c
+
+ def putc(self, buffer, timeout=1):
+ self.telnet.write(buffer)
+ self.show_progress(len(buffer))
+
+ def reboot(self):
+ # no-op
+ pass
+
+ def set_file_size(self, filesize):
+ self.bytes_transfered = 0
+ self.filesize = filesize
+ self.count = 0
+
+ def show_progress(self, sendsize):
+ if PRINT_RAW_COMMAND:
+ if self.count < MAX_DOT_COUNT:
+ self.bytes_transfered = self.bytes_transfered + sendsize
+ cur_count = int(self.bytes_transfered * MAX_DOT_COUNT / self.filesize)
+ if MAX_DOT_COUNT < cur_count:
+ cur_count = MAX_DOT_COUNT
+ for idx in range(cur_count - self.count):
+ print('#',end='')
+ sys.stdout.flush()
+ self.count = cur_count
+ if self.count == MAX_DOT_COUNT:
+ print("\n")
+
+class SerialDev:
+ def __init__(self):
+ if import_serial_module is False:
+ print("Cannot import serial module, maybe it's not install yet.")
+ print("\n", end="")
+ print("Please install python-setuptool by Cygwin installer.")
+ print("After that use easy_intall command to install serial module")
+ print(" $ cd tool/")
+ print(" $ python3 -m easy_install pyserial-2.7.tar.gz")
+ quit()
+ else:
+ port = ConfigArgs.SERIAL_PORT
+ try:
+ self.serial = serial.Serial(port, baudrate=115200,
+ parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE,
+ bytesize=serial.EIGHTBITS, timeout=0.1)
+ except Exception as e:
+ print("Cannot open port : " + port)
+ sys.exit(e.args[0])
+
+ def readline(self, size=None):
+ return self.serial.readline(size)
+
+ def write(self, buffer):
+ self.serial.write(buffer)
+ self.serial.flush()
+
+ def discard_inputs(self, timeout=1.0):
+ time.sleep(timeout)
+ self.serial.flushInput()
+
+ def getc(self, size, timeout=1):
+ self.serial.timeout = timeout
+ c = self.serial.read(size)
+ self.serial.timeout = 0.1
+ return c
+
+ def putc(self, buffer, timeout=1):
+ self.serial.timeout = timeout
+ self.serial.write(buffer)
+ self.serial.flush()
+ self.serial.timeout = 0.1
+ self.show_progress(len(buffer))
+
+ # Note: windows platform dependent code
+ def putc_win(self, buffer, timeout=1):
+ self.serial.write(buffer)
+ self.show_progress(len(buffer))
+ while True:
+ if self.serial.out_waiting == 0:
+ break
+
+ def setBaudrate(self, baudrate):
+# self.serial.setBaudrate(baudrate)
+ self.serial.baudrate = baudrate
+
+ def reboot(self):
+ # Target Reset by DTR
+ self.serial.setDTR(False)
+ self.serial.setDTR(True)
+ self.serial.setDTR(False)
+
+ def set_file_size(self, filesize):
+ self.bytes_transfered = 0
+ self.filesize = filesize
+ self.count = 0
+
+ def show_progress(self, sendsize):
+ if PRINT_RAW_COMMAND:
+ if self.count < MAX_DOT_COUNT:
+ self.bytes_transfered = self.bytes_transfered + sendsize
+ cur_count = int(self.bytes_transfered * MAX_DOT_COUNT / self.filesize)
+ if MAX_DOT_COUNT < cur_count:
+ cur_count = MAX_DOT_COUNT
+ for idx in range(cur_count - self.count):
+ print('#',end='')
+ sys.stdout.flush()
+ self.count = cur_count
+ if self.count == MAX_DOT_COUNT:
+ print("\n")
+
+class FlashWriter:
+ def __init__(self, protocol_sel=PROTOCOL_SERIAL):
+ if protocol_sel == PROTOCOL_TELNET:
+ self.serial = TelnetDev()
+ else:
+ self.serial = SerialDev()
+
+ def cancel_autoboot(self) :
+ boot_msg = ''
+ self.serial.reboot() # Target reboot before send 'r'
+ while boot_msg == '' :
+ rx = self.serial.readline().strip()
+ self.serial.write(b"r") # Send "r" key to avoid auto boot
+ for msg in ROM_MSG :
+ if msg in rx :
+ boot_msg = msg
+ break
+ while True :
+ rx = self.serial.readline().decode(errors="replace").strip()
+ if "updater" in rx :
+ # Workaround : Sometime first character is dropped.
+ # Send line feed as air shot before actual command.
+ self.serial.write(b"\n") # Send line feed
+ self.serial.discard_inputs()# Clear input buffer to sync
+ return boot_msg.decode(errors="ignore")
+
+ def recv(self):
+ rx = self.serial.readline()
+ if PRINT_RAW_COMMAND :
+ serial_line = rx.decode(errors="replace")
+ if serial_line.strip() != "" and not serial_line.startswith(XMDM_MSG):
+ print(serial_line, end="")
+ return rx
+
+ def wait(self, string):
+ while True:
+ rx = self.recv()
+ if string.encode() in rx:
+ time.sleep(0.1)
+ break
+
+ def wait_for_prompt(self):
+ prompt_pat = re.compile(b"updater")
+ while True:
+ rx = self.recv()
+ if prompt_pat.search(rx):
+ time.sleep(0.1)
+ break
+
+ def send(self, string):
+ self.serial.write(str(string).encode() + b"\n")
+ rx = self.serial.readline()
+ if PRINT_RAW_COMMAND :
+ print(rx.decode(errors="replace"), end="")
+
+ def read_output(self, prompt_text) :
+ output = []
+ while True :
+ rx = self.serial.readline()
+ if prompt_text.encode() in rx :
+ time.sleep(0.1)
+ break
+ if rx != "" :
+ output.append(rx.decode(errors="ignore").rstrip())
+ return output
+
+ def install_files(self, files, command) :
+ if ConfigArgs.XMODEM_BAUD:
+ command += " -b " + ConfigArgs.XMODEM_BAUD
+ if os.name == 'nt':
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc_win, 'xmodem1k')
+ else:
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc, 'xmodem1k')
+ for file in files:
+ with open(file, "rb") as bin :
+ self.send(command)
+ print("Install " + file)
+ self.wait(XMDM_MSG)
+ print("|0%" +
+ "-" * (int(MAX_DOT_COUNT / 2) - 6) +
+ "50%" +
+ "-" * (MAX_DOT_COUNT - int(MAX_DOT_COUNT / 2) - 5) +
+ "100%|")
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(ConfigArgs.XMODEM_BAUD)
+ self.serial.discard_inputs() # Clear input buffer to sync
+ self.serial.set_file_size(os.path.getsize(file))
+ modem.send(bin)
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(115200)
+ self.wait_for_prompt()
+
+ def save_files(self, files) :
+ if ConfigArgs.XMODEM_BAUD:
+ command = "save_file -b " + ConfigArgs.XMODEM_BAUD + " -x "
+ else:
+ command = "save_file -x "
+ if os.name == 'nt':
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc_win, 'xmodem1k')
+ else:
+ modem = xmodem.XMODEM(self.serial.getc, self.serial.putc, 'xmodem1k')
+ for file in files:
+ with open(file, "rb") as bin :
+ self.send(command + os.path.basename(file))
+ print("Save " + file)
+ self.wait(XMDM_MSG)
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(ConfigArgs.XMODEM_BAUD)
+ self.serial.discard_inputs() # Clear input buffer to sync
+ self.serial.set_file_size(os.path.getsize(file))
+ modem.send(bin)
+ if ConfigArgs.XMODEM_BAUD:
+ self.serial.setBaudrate(115200)
+ self.wait_for_prompt()
+ self.send("chmod d+rw " + os.path.basename(file))
+ self.wait_for_prompt()
+
+ def delete_files(self, files) :
+ for file in files :
+ self.delete_binary(file)
+
+ def delete_binary(self, bin_name) :
+ self.send("rm " + bin_name)
+ self.wait_for_prompt()
+
+def main():
+ try:
+ config_loader = ConfigArgsLoader()
+ config_loader.update_config()
+ except:
+ return errno.EINVAL
+
+ # Wait to reset the board
+ writer = FlashWriter(ConfigArgs.PROTOCOL_TYPE)
+
+ do_wait_reset = True
+ if ConfigArgs.AUTO_RESET:
+ if subprocess.call("cd " + sys.path[0] + "; ./reset_board.sh", shell=True) == 0:
+ print("auto reset board sucess!!")
+ do_wait_reset = False
+ bootrom_msg = writer.cancel_autoboot()
+
+ if ConfigArgs.DTR_RESET:
+ do_wait_reset = False
+ bootrom_msg = writer.cancel_autoboot()
+
+ if ConfigArgs.WAIT_RESET == False and do_wait_reset == True:
+ rx = writer.recv()
+ time.sleep(1)
+ for i in range(3):
+ writer.send("")
+ rx = writer.recv()
+ if "updater".encode() in rx:
+ # No need to wait for reset
+ do_wait_reset = False
+ break
+ time.sleep(1)
+
+ if do_wait_reset:
+ # Wait to reset the board
+ print('Please press RESET button on target board')
+ sys.stdout.flush()
+ bootrom_msg = writer.cancel_autoboot()
+
+ # Remove files
+ if ConfigArgs.ERASE_NAME :
+ print(">>> Remove exisiting files ...")
+ writer.delete_files(ConfigArgs.ERASE_NAME)
+
+ # Install files
+ if ConfigArgs.PACKAGE_NAME or ConfigArgs.PKGSYS_NAME or ConfigArgs.PKGAPP_NAME or ConfigArgs.PKGUPD_NAME:
+ print(">>> Install files ...")
+ if ConfigArgs.PACKAGE_NAME :
+ writer.install_files(ConfigArgs.PACKAGE_NAME, "install")
+ if ConfigArgs.PKGSYS_NAME :
+ writer.install_files(ConfigArgs.PKGSYS_NAME, "install")
+ if ConfigArgs.PKGAPP_NAME :
+ writer.install_files(ConfigArgs.PKGAPP_NAME, "install")
+ if ConfigArgs.PKGUPD_NAME :
+ writer.install_files(ConfigArgs.PKGUPD_NAME, "install -k updater.key")
+
+ # Save files
+ if ConfigArgs.FILE_NAME :
+ print(">>> Save files ...")
+ writer.save_files(ConfigArgs.FILE_NAME)
+
+ # Set auto boot
+ if not ConfigArgs.NO_SET_BOOTABLE:
+ print(">>> Save Configuration to FlashROM ...")
+ writer.send("set bootable M0P")
+ writer.wait_for_prompt()
+
+ # Sync all cached data to flash
+ writer.send("sync")
+ writer.wait_for_prompt()
+
+ if REBOOT_AT_END :
+ print("Restarting the board ...")
+ writer.send("reboot")
+
+ return 0
+
+if __name__ == "__main__":
+ try:
+ sys.exit(main())
+ except KeyboardInterrupt:
+ print("Canceled by keyboard interrupt.")
+ pass
diff --git a/ports/cxd56/tools/xmodem.py b/ports/cxd56/tools/xmodem.py
new file mode 100644
index 000000000..c93430056
--- /dev/null
+++ b/ports/cxd56/tools/xmodem.py
@@ -0,0 +1,590 @@
+'''
+===============================
+ XMODEM file transfer protocol
+===============================
+
+.. $Id$
+
+This is a literal implementation of XMODEM.TXT_, XMODEM1K.TXT_ and
+XMODMCRC.TXT_, support for YMODEM and ZMODEM is pending. YMODEM should
+be fairly easy to implement as it is a hack on top of the XMODEM
+protocol using sequence bytes ``0x00`` for sending file names (and some
+meta data).
+
+.. _XMODEM.TXT: doc/XMODEM.TXT
+.. _XMODEM1K.TXT: doc/XMODEM1K.TXT
+.. _XMODMCRC.TXT: doc/XMODMCRC.TXT
+
+Data flow example including error recovery
+==========================================
+
+Here is a sample of the data flow, sending a 3-block message.
+It includes the two most common line hits - a garbaged block,
+and an ``ACK`` reply getting garbaged. ``CRC`` or ``CSUM`` represents
+the checksum bytes.
+
+XMODEM 128 byte blocks
+----------------------
+
+::
+
+ SENDER RECEIVER
+
+ <-- NAK
+ SOH 01 FE Data[128] CSUM -->
+ <-- ACK
+ SOH 02 FD Data[128] CSUM -->
+ <-- ACK
+ SOH 03 FC Data[128] CSUM -->
+ <-- ACK
+ SOH 04 FB Data[128] CSUM -->
+ <-- ACK
+ SOH 05 FA Data[100] CPMEOF[28] CSUM -->
+ <-- ACK
+ EOT -->
+ <-- ACK
+
+XMODEM-1k blocks, CRC mode
+--------------------------
+
+::
+
+ SENDER RECEIVER
+
+ <-- C
+ STX 01 FE Data[1024] CRC CRC -->
+ <-- ACK
+ STX 02 FD Data[1024] CRC CRC -->
+ <-- ACK
+ STX 03 FC Data[1000] CPMEOF[24] CRC CRC -->
+ <-- ACK
+ EOT -->
+ <-- ACK
+
+Mixed 1024 and 128 byte Blocks
+------------------------------
+
+::
+
+ SENDER RECEIVER
+
+ <-- C
+ STX 01 FE Data[1024] CRC CRC -->
+ <-- ACK
+ STX 02 FD Data[1024] CRC CRC -->
+ <-- ACK
+ SOH 03 FC Data[128] CRC CRC -->
+ <-- ACK
+ SOH 04 FB Data[100] CPMEOF[28] CRC CRC -->
+ <-- ACK
+ EOT -->
+ <-- ACK
+
+YMODEM Batch Transmission Session (1 file)
+------------------------------------------
+
+::
+
+ SENDER RECEIVER
+ <-- C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC -->
+ <-- ACK
+ <-- C
+ SOH 01 FE Data[128] CRC CRC -->
+ <-- ACK
+ SOH 02 FC Data[128] CRC CRC -->
+ <-- ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC -->
+ <-- ACK
+ EOT -->
+ <-- NAK
+ EOT -->
+ <-- ACK
+ <-- C
+ SOH 00 FF NUL[128] CRC CRC -->
+ <-- ACK
+
+
+'''
+
+__author__ = 'Wijnand Modderman <maze@pyth0n.org>'
+__copyright__ = ['Copyright (c) 2010 Wijnand Modderman',
+ 'Copyright (c) 1981 Chuck Forsberg']
+__license__ = 'MIT'
+__version__ = '0.3.2'
+
+import logging
+import time
+import sys
+from functools import partial
+import collections
+
+# Loggerr
+log = logging.getLogger('xmodem')
+
+# Protocol bytes
+SOH = bytes([0x01])
+STX = bytes([0x02])
+EOT = bytes([0x04])
+ACK = bytes([0x06])
+DLE = bytes([0x10])
+NAK = bytes([0x15])
+CAN = bytes([0x18])
+CRC = bytes([0x43]) # C
+
+
+class XMODEM(object):
+ '''
+ XMODEM Protocol handler, expects an object to read from and an object to
+ write to.
+
+ >>> def getc(size, timeout=1):
+ ... return data or None
+ ...
+ >>> def putc(data, timeout=1):
+ ... return size or None
+ ...
+ >>> modem = XMODEM(getc, putc)
+
+
+ :param getc: Function to retreive bytes from a stream
+ :type getc: callable
+ :param putc: Function to transmit bytes to a stream
+ :type putc: callable
+ :param mode: XMODEM protocol mode
+ :type mode: string
+ :param pad: Padding character to make the packets match the packet size
+ :type pad: char
+
+ '''
+
+ # crctab calculated by Mark G. Mendel, Network Systems Corporation
+ crctable = [
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
+ ]
+
+ def __init__(self, getc, putc, mode='xmodem', pad=b'\x1a'):
+ self.getc = getc
+ self.putc = putc
+ self.mode = mode
+ self.pad = pad
+
+ def abort(self, count=2, timeout=60):
+ '''
+ Send an abort sequence using CAN bytes.
+ '''
+ for counter in range(0, count):
+ self.putc(CAN, timeout)
+
+ def send(self, stream, retry=32, timeout=360, quiet=0, callback=None):
+ '''
+ Send a stream via the XMODEM protocol.
+
+ >>> stream = file('/etc/issue', 'rb')
+ >>> print modem.send(stream)
+ True
+
+ Returns ``True`` upon succesful transmission or ``False`` in case of
+ failure.
+
+ :param stream: The stream object to send data from.
+ :type stream: stream (file, etc.)
+ :param retry: The maximum number of times to try to resend a failed
+ packet before failing.
+ :type retry: int
+ :param timeout: The number of seconds to wait for a response before
+ timing out.
+ :type timeout: int
+ :param quiet: If 0, it prints info to stderr. If 1, it does not print any info.
+ :type quiet: int
+ :param callback: Reference to a callback function that has the
+ following signature. This is useful for
+ getting status updates while a xmodem
+ transfer is underway.
+ Expected callback signature:
+ def callback(total_packets, success_count, error_count)
+ :type callback: callable
+ '''
+
+ # initialize protocol
+ try:
+ packet_size = dict(
+ xmodem = 128,
+ xmodem1k = 1024,
+ )[self.mode]
+ except AttributeError:
+ raise ValueError("An invalid mode was supplied")
+
+ error_count = 0
+ crc_mode = 0
+ cancel = 0
+ while True:
+ char = self.getc(1)
+ if char:
+ if char == NAK:
+ crc_mode = 0
+ break
+ elif char == CRC:
+ crc_mode = 1
+ break
+ elif char == CAN:
+ if not quiet:
+ print('received CAN', file=sys.stderr)
+ if cancel:
+ return False
+ else:
+ cancel = 1
+ else:
+ log.error('send ERROR expected NAK/CRC, got %s' % \
+ (ord(char),))
+
+ error_count += 1
+ if error_count >= retry:
+ self.abort(timeout=timeout)
+ return False
+
+ # send data
+ error_count = 0
+ success_count = 0
+ total_packets = 0
+ sequence = 1
+ while True:
+ data = stream.read(packet_size)
+ if not data:
+ log.info('sending EOT')
+ # end of stream
+ break
+ total_packets += 1
+ data = data.ljust(packet_size, self.pad)
+ if crc_mode:
+ crc = self.calc_crc(data)
+ else:
+ crc = self.calc_checksum(data)
+
+ # emit packet
+ while True:
+ if packet_size == 128:
+ self.putc(SOH)
+ else: # packet_size == 1024
+ self.putc(STX)
+ self.putc(bytes([sequence]))
+ self.putc(bytes([0xff - sequence]))
+ self.putc(data)
+ if crc_mode:
+ self.putc(bytes([crc >> 8]))
+ self.putc(bytes([crc & 0xff]))
+ else:
+ self.putc(bytes([crc]))
+
+ char = self.getc(1, timeout)
+ if char == ACK:
+ success_count += 1
+ if isinstance(callback, collections.Callable):
+ callback(total_packets, success_count, error_count)
+ break
+ if char == NAK:
+ error_count += 1
+ if isinstance(callback, collections.Callable):
+ callback(total_packets, success_count, error_count)
+ if error_count >= retry:
+ # excessive amounts of retransmissions requested,
+ # abort transfer
+ self.abort(timeout=timeout)
+ log.warning('excessive NAKs, transfer aborted')
+ return False
+
+ # return to loop and resend
+ continue
+ else:
+ log.error('Not ACK, Not NAK')
+ error_count += 1
+ if isinstance(callback, collections.Callable):
+ callback(total_packets, success_count, error_count)
+ if error_count >= retry:
+ # excessive amounts of retransmissions requested,
+ # abort transfer
+ self.abort(timeout=timeout)
+ log.warning('excessive protocol errors, transfer aborted')
+ return False
+
+ # return to loop and resend
+ continue
+
+ # protocol error
+ self.abort(timeout=timeout)
+ log.error('protocol error')
+ return False
+
+ # keep track of sequence
+ sequence = (sequence + 1) % 0x100
+
+ while True:
+ # end of transmission
+ self.putc(EOT)
+
+ #An ACK should be returned
+ char = self.getc(1, timeout)
+ if char == ACK:
+ break
+ else:
+ error_count += 1
+ if error_count >= retry:
+ self.abort(timeout=timeout)
+ log.warning('EOT was not ACKd, transfer aborted')
+ return False
+
+ return True
+
+ def recv(self, stream, crc_mode=1, retry=16, timeout=60, delay=1, quiet=0):
+ '''
+ Receive a stream via the XMODEM protocol.
+
+ >>> stream = file('/etc/issue', 'wb')
+ >>> print modem.recv(stream)
+ 2342
+
+ Returns the number of bytes received on success or ``None`` in case of
+ failure.
+ '''
+
+ # initiate protocol
+ error_count = 0
+ char = 0
+ cancel = 0
+ while True:
+ # first try CRC mode, if this fails,
+ # fall back to checksum mode
+ if error_count >= retry:
+ self.abort(timeout=timeout)
+ return None
+ elif crc_mode and error_count < (retry / 2):
+ if not self.putc(CRC):
+ time.sleep(delay)
+ error_count += 1
+ else:
+ crc_mode = 0
+ if not self.putc(NAK):
+ time.sleep(delay)
+ error_count += 1
+
+ char = self.getc(1, timeout)
+ if not char:
+ error_count += 1
+ continue
+ elif char == SOH:
+ #crc_mode = 0
+ break
+ elif char == STX:
+ break
+ elif char == CAN:
+ if cancel:
+ return None
+ else:
+ cancel = 1
+ else:
+ error_count += 1
+
+ # read data
+ error_count = 0
+ income_size = 0
+ packet_size = 128
+ sequence = 1
+ cancel = 0
+ while True:
+ while True:
+ if char == SOH:
+ packet_size = 128
+ break
+ elif char == STX:
+ packet_size = 1024
+ break
+ elif char == EOT:
+ # We received an EOT, so send an ACK and return the received
+ # data length
+ self.putc(ACK)
+ return income_size
+ elif char == CAN:
+ # cancel at two consecutive cancels
+ if cancel:
+ return None
+ else:
+ cancel = 1
+ else:
+ if not quiet:
+ print('recv ERROR expected SOH/EOT, got', ord(char), file=sys.stderr)
+ error_count += 1
+ if error_count >= retry:
+ self.abort()
+ return None
+ # read sequence
+ error_count = 0
+ cancel = 0
+ seq1 = ord(self.getc(1))
+ seq2 = 0xff - ord(self.getc(1))
+ if seq1 == sequence and seq2 == sequence:
+ # sequence is ok, read packet
+ # packet_size + checksum
+ data = self.getc(packet_size + 1 + crc_mode, timeout)
+ if crc_mode:
+ csum = (ord(data[-2]) << 8) + ord(data[-1])
+ data = data[:-2]
+ log.debug('CRC (%04x <> %04x)' % \
+ (csum, self.calc_crc(data)))
+ valid = csum == self.calc_crc(data)
+ else:
+ csum = data[-1]
+ data = data[:-1]
+ log.debug('checksum (checksum(%02x <> %02x)' % \
+ (ord(csum), self.calc_checksum(data)))
+ valid = ord(csum) == self.calc_checksum(data)
+
+ # valid data, append chunk
+ if valid:
+ income_size += len(data)
+ stream.write(data)
+ self.putc(ACK)
+ sequence = (sequence + 1) % 0x100
+ char = self.getc(1, timeout)
+ continue
+ else:
+ # consume data
+ self.getc(packet_size + 1 + crc_mode)
+ self.debug('expecting sequence %d, got %d/%d' % \
+ (sequence, seq1, seq2))
+
+ # something went wrong, request retransmission
+ self.putc(NAK)
+
+ def calc_checksum(self, data, checksum=0):
+ '''
+ Calculate the checksum for a given block of data, can also be used to
+ update a checksum.
+
+ >>> csum = modem.calc_checksum('hello')
+ >>> csum = modem.calc_checksum('world', csum)
+ >>> hex(csum)
+ '0x3c'
+
+ '''
+ return (sum(map(ord, data)) + checksum) % 256
+
+ def calc_crc(self, data, crc=0):
+ '''
+ Calculate the Cyclic Redundancy Check for a given block of data, can
+ also be used to update a CRC.
+
+ >>> crc = modem.calc_crc('hello')
+ >>> crc = modem.calc_crc('world', crc)
+ >>> hex(crc)
+ '0xd5e3'
+
+ '''
+ for char in data:
+ crc = (crc << 8) ^ self.crctable[((crc >> 8) ^ int(char)) & 0xff]
+ return crc & 0xffff
+
+
+XMODEM1k = partial(XMODEM, mode='xmodem1k')
+
+
+def run():
+ import optparse
+ import subprocess
+
+ parser = optparse.OptionParser(usage='%prog [<options>] <send|recv> filename filename')
+ parser.add_option('-m', '--mode', default='xmodem',
+ help='XMODEM mode (xmodem, xmodem1k)')
+
+ options, args = parser.parse_args()
+ if len(args) != 3:
+ parser.error('invalid arguments')
+ return 1
+
+ elif args[0] not in ('send', 'recv'):
+ parser.error('invalid mode')
+ return 1
+
+ def _func(so, si):
+ import select
+ import subprocess
+
+ print('si', si)
+ print('so', so)
+
+ def getc(size, timeout=3):
+ w,t,f = select.select([so], [], [], timeout)
+ if w:
+ data = so.read(size)
+ else:
+ data = None
+
+ print('getc(', repr(data), ')')
+ return data
+
+ def putc(data, timeout=3):
+ w,t,f = select.select([], [si], [], timeout)
+ if t:
+ si.write(data)
+ si.flush()
+ size = len(data)
+ else:
+ size = None
+
+ print('putc(', repr(data), repr(size), ')')
+ return size
+
+ return getc, putc
+
+ def _pipe(*command):
+ pipe = subprocess.Popen(command,
+ stdout=subprocess.PIPE, stdin=subprocess.PIPE)
+ return pipe.stdout, pipe.stdin
+
+ if args[0] == 'recv':
+ import io
+ getc, putc = _func(*_pipe('sz', '--xmodem', args[2]))
+ stream = open(args[1], 'wb')
+ xmodem = XMODEM(getc, putc, mode=options.mode)
+ status = xmodem.recv(stream, retry=8)
+ stream.close()
+
+ elif args[0] == 'send':
+ getc, putc = _func(*_pipe('rz', '--xmodem', args[2]))
+ stream = open(args[1], 'rb')
+ xmodem = XMODEM(getc, putc, mode=options.mode)
+ status = xmodem.send(stream, retry=8)
+ stream.close()
+
+if __name__ == '__main__':
+ sys.exit(run())
diff --git a/ports/esp32s2/CMakeLists.txt b/ports/esp32s2/CMakeLists.txt
index c831e4846..716588cf2 100644
--- a/ports/esp32s2/CMakeLists.txt
+++ b/ports/esp32s2/CMakeLists.txt
@@ -1,6 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.13)
set(ENV{IDF_PATH} ${CMAKE_SOURCE_DIR}/esp-idf)
set(COMPONENTS esptool_py soc driver log main)
diff --git a/ports/esp32s2/Makefile b/ports/esp32s2/Makefile
index 5ad5c2f1d..55db73604 100644
--- a/ports/esp32s2/Makefile
+++ b/ports/esp32s2/Makefile
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -78,6 +78,7 @@ INC += -Iesp-idf/components/freertos/xtensa/include
INC += -Iesp-idf/components/esp32s2/include
INC += -Iesp-idf/components/xtensa/esp32s2/include
INC += -Iesp-idf/components/esp_common/include
+INC += -Iesp-idf/components/esp_ringbuf/include
INC += -Iesp-idf/components/esp_rom/include
INC += -Iesp-idf/components/xtensa/include
INC += -Iesp-idf/components/esp_timer/include
@@ -100,14 +101,19 @@ CFLAGS += -DSTACK_CANARY_VALUE=0xa5a5a5a5
#Debugging/Optimization
ifeq ($(DEBUG), 1)
CFLAGS += -ggdb
+ OPTIMIZATION_FLAGS ?= -Og
# You may want to enable these flags to make setting breakpoints easier.
# CFLAGS += -fno-inline -fno-ipa-sra
else
- CFLAGS += -Os -DNDEBUG -ggdb3
+ CFLAGS += -DNDEBUG -ggdb3
+ OPTIMIZATION_FLAGS ?= -O2
# TODO: Test with -flto
### CFLAGS += -flto
endif
+# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS)
+
CFLAGS += $(INC) -Werror -Wall -mlongcalls -std=gnu11 -Wl,--gc-sections $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
LDFLAGS = $(CFLAGS) -Wl,-nostdlib -Wl,-Map=$@.map -Wl,-cref
@@ -212,12 +218,12 @@ $(BUILD)/esp-idf:
# create the config headers
$(BUILD)/esp-idf/config/sdkconfig.h: boards/$(BOARD)/sdkconfig | $(BUILD)/esp-idf
- IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;boards/$(BOARD)/sdkconfig" -DCMAKE_TOOLCHAIN_FILE=$IDF_PATH/tools/cmake/toolchain-esp32s2.cmake -DIDF_TARGET=esp32s2 -GNinja
+ IDF_PATH=$(IDF_PATH) cmake -S . -B $(BUILD)/esp-idf -DSDKCONFIG=$(BUILD)/esp-idf/sdkconfig -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;boards/$(BOARD)/sdkconfig" -DCMAKE_TOOLCHAIN_FILE=$(IDF_PATH)/tools/cmake/toolchain-esp32s2.cmake -DIDF_TARGET=esp32s2 -GNinja
# build a lib
# Adding -d explain -j 1 -v to the ninja line will output debug info
-$(BUILD)/esp-idf/esp-idf/%.a: $(BUILD)/esp-idf/config/sdkconfig.h
- ninja -C $(BUILD)/esp-idf esp-idf/$*.a
+#$(BUILD)/esp-idf/esp-idf/%.a: $(BUILD)/esp-idf/config/sdkconfig.h
+# ninja -C $(BUILD)/esp-idf esp-idf/$*.a
$(BUILD)/esp-idf/esp-idf/esp32s2/esp32s2_out.ld: $(BUILD)/esp-idf/config/sdkconfig.h
ninja -C $(BUILD)/esp-idf esp-idf/esp32s2/esp32s2_out.ld
@@ -229,9 +235,6 @@ $(BUILD)/esp-idf/esp-idf/esp32s2/ld/esp32s2.project.ld: $(BUILD)/esp-idf/config/
$(BUILD)/esp-idf/partition_table/partition-table.bin: $(BUILD)/esp-idf/config/sdkconfig.h
IDF_PATH=$(IDF_PATH) ninja -C $(BUILD)/esp-idf partition_table/partition-table.bin
-$(BUILD)/esp-idf/bootloader/bootloader.bin: $(BUILD)/esp-idf/config/sdkconfig.h
- ninja -C $(BUILD)/esp-idf bootloader/bootloader.bin
-
# run menuconfig
menuconfig: $(BUILD)/esp-idf/config
ninja -C $(BUILD)/esp-idf menuconfig
@@ -257,11 +260,22 @@ ESP_AUTOGEN_LD = $(BUILD)/esp-idf/esp-idf/esp32s2/esp32s2_out.ld $(BUILD)/esp-id
FLASH_FLAGS = --flash_mode $(CIRCUITPY_ESP_FLASH_MODE) --flash_freq $(CIRCUITPY_ESP_FLASH_FREQ) --flash_size $(CIRCUITPY_ESP_FLASH_SIZE)
-all: $(BUILD)/firmware.bin
+all: $(BUILD)/firmware.bin $(BUILD)/firmware.uf2
+
+.PHONY: esp-idf-stamp
+esp-idf-stamp: $(BUILD)/esp-idf/config/sdkconfig.h
+ ninja -C $(BUILD)/esp-idf \
+ bootloader/bootloader.bin \
+ esp-idf/bootloader_support/libbootloader_support.a \
+ esp-idf/esp32s2/ld/esp32s2.project.ld \
+ esp-idf/esp_system/libesp_system.a \
+ esp-idf/freertos/libfreertos.a \
+ esp-idf/log/liblog.a \
+ esp-idf/xtensa/libxtensa.a
-$(BUILD)/firmware.elf: $(OBJ) | $(ESP_IDF_COMPONENTS_EXPANDED) $(ESP_AUTOGEN_LD)
+$(BUILD)/firmware.elf: $(OBJ) | esp-idf-stamp
$(STEPECHO) "LINK $@"
- $(Q)$(CC) -o $@ $(LDFLAGS) $^ $(ESP_IDF_COMPONENTS_EXPANDED) $(BINARY_BLOBS) build-$(BOARD)/esp-idf/esp-idf/newlib/libnewlib.a -u newlib_include_pthread_impl
+ $(Q)$(CC) -o $@ $(LDFLAGS) $^ $(ESP_IDF_COMPONENTS_EXPANDED) $(BINARY_BLOBS) build-$(BOARD)/esp-idf/esp-idf/newlib/libnewlib.a -u newlib_include_pthread_impl -Wl,--start-group $(LIBS) -Wl,--end-group
# $(Q)$(SIZE) $@ | $(PYTHON3) $(TOP)/tools/build_memory_info.py $(BUILD)/esp-idf/esp-idf/esp32s2/esp32s2_out.ld
$(BUILD)/circuitpython-firmware.bin: $(BUILD)/firmware.elf
@@ -270,11 +284,18 @@ $(BUILD)/circuitpython-firmware.bin: $(BUILD)/firmware.elf
# $(Q)$(OBJCOPY) -O binary $^ $@
# $(Q)$(OBJCOPY) -O binary -j .vectors -j .text -j .data $^ $@
-$(BUILD)/firmware.bin: $(BUILD)/esp-idf/partition_table/partition-table.bin $(BUILD)/esp-idf/bootloader/bootloader.bin $(BUILD)/circuitpython-firmware.bin
+$(BUILD)/firmware.bin: $(BUILD)/circuitpython-firmware.bin | esp-idf-stamp
$(Q)$(PYTHON) ../../tools/join_bins.py $@ 0x1000 $(BUILD)/esp-idf/bootloader/bootloader.bin 0x8000 $(BUILD)/esp-idf/partition_table/partition-table.bin 0x10000 $(BUILD)/circuitpython-firmware.bin
+$(BUILD)/firmware.uf2: $(BUILD)/circuitpython-firmware.bin
+ $(STEPECHO) "Create $@"
+ $(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -f 0xbfdd4eee -b 0x0000 -c -o $@ $^
+
flash: $(BUILD)/firmware.bin
- esptool.py --chip esp32s2 -p $(PORT) -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x0000 $^
+ esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x0000 $^
+
+flash-circuitpython-only: $(BUILD)/circuitpython-firmware.bin
+ esptool.py --chip esp32s2 -p $(PORT) --no-stub -b 460800 --before=default_reset --after=hard_reset write_flash $(FLASH_FLAGS) 0x10000 $^
include $(TOP)/py/mkrules.mk
diff --git a/ports/esp32s2/background.c b/ports/esp32s2/background.c
index 81ebf960f..40ce9ecfd 100644
--- a/ports/esp32s2/background.c
+++ b/ports/esp32s2/background.c
@@ -35,33 +35,12 @@
#include "shared-module/displayio/__init__.h"
#endif
-static bool running_background_tasks = false;
-void background_tasks_reset(void) {
- running_background_tasks = false;
+void port_background_task(void) {
+ // Zero delay in case FreeRTOS wants to switch to something else.
+ vTaskDelay(0);
}
-void run_background_tasks(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
+void port_start_background_task(void) {}
- // Delay for 1 tick so that we don't starve the idle task.
- // TODO: 1 tick is 10ms which is a long time! Can we delegate to idle for a minimal amount of
- // time?
- vTaskDelay(1);
- running_background_tasks = true;
- filesystem_background();
-
-#if CIRCUITPY_BLEIO
- bleio_background();
-#endif
-
- // #if CIRCUITPY_DISPLAYIO
- // displayio_background();
- // #endif
- running_background_tasks = false;
-
- assert_heap_ok();
-}
+void port_finish_background_task(void) {}
diff --git a/ports/esp32s2/background.h b/ports/esp32s2/background.h
index 0e1fb7a56..cb850d4e5 100644
--- a/ports/esp32s2/background.h
+++ b/ports/esp32s2/background.h
@@ -29,7 +29,4 @@
#include <stdbool.h>
-void background_tasks_reset(void);
-void run_background_tasks(void);
-
#endif // MICROPY_INCLUDED_ESP32S2_BACKGROUND_H
diff --git a/ports/esp32s2/boards/espressif_saola_1_wroom/board.c b/ports/esp32s2/boards/espressif_saola_1_wroom/board.c
index b7b2c4ef5..9f708874b 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wroom/board.c
+++ b/ports/esp32s2/boards/espressif_saola_1_wroom/board.c
@@ -30,12 +30,12 @@
void board_init(void) {
// USB
- never_reset_pin(&pin_GPIO19);
- never_reset_pin(&pin_GPIO20);
+ common_hal_never_reset_pin(&pin_GPIO19);
+ common_hal_never_reset_pin(&pin_GPIO20);
// Debug UART
- never_reset_pin(&pin_GPIO43);
- never_reset_pin(&pin_GPIO44);
+ common_hal_never_reset_pin(&pin_GPIO43);
+ common_hal_never_reset_pin(&pin_GPIO44);
}
bool board_requests_safe_mode(void) {
diff --git a/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk b/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk
index d9ad56886..6e7627265 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk
+++ b/ports/esp32s2/boards/espressif_saola_1_wroom/mpconfigboard.mk
@@ -11,8 +11,6 @@ LONGINT_IMPL = MPZ
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
CIRCUITPY_NEOPIXEL_WRITE = 0
-CIRCUITPY_DIGITALIO = 0
-CIRCUITPY_MICROCONTROLLER = 0
CIRCUITPY_ESP_FLASH_MODE=dio
CIRCUITPY_ESP_FLASH_FREQ=40m
diff --git a/ports/esp32s2/boards/espressif_saola_1_wrover/board.c b/ports/esp32s2/boards/espressif_saola_1_wrover/board.c
index b7b2c4ef5..9f708874b 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wrover/board.c
+++ b/ports/esp32s2/boards/espressif_saola_1_wrover/board.c
@@ -30,12 +30,12 @@
void board_init(void) {
// USB
- never_reset_pin(&pin_GPIO19);
- never_reset_pin(&pin_GPIO20);
+ common_hal_never_reset_pin(&pin_GPIO19);
+ common_hal_never_reset_pin(&pin_GPIO20);
// Debug UART
- never_reset_pin(&pin_GPIO43);
- never_reset_pin(&pin_GPIO44);
+ common_hal_never_reset_pin(&pin_GPIO43);
+ common_hal_never_reset_pin(&pin_GPIO44);
}
bool board_requests_safe_mode(void) {
diff --git a/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk b/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk
index 558b1144a..1437df7f4 100644
--- a/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk
+++ b/ports/esp32s2/boards/espressif_saola_1_wrover/mpconfigboard.mk
@@ -11,8 +11,6 @@ LONGINT_IMPL = MPZ
CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
CIRCUITPY_NEOPIXEL_WRITE = 0
-CIRCUITPY_DIGITALIO = 0
-CIRCUITPY_MICROCONTROLLER = 0
CIRCUITPY_ESP_FLASH_MODE=dio
CIRCUITPY_ESP_FLASH_FREQ=40m
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c b/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c
new file mode 100644
index 000000000..1dc30b5af
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/board.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+#include "mpconfigboard.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+void board_init(void) {
+ // USB
+ common_hal_never_reset_pin(&pin_GPIO19);
+ common_hal_never_reset_pin(&pin_GPIO20);
+
+ // Debug UART
+ common_hal_never_reset_pin(&pin_GPIO43);
+ common_hal_never_reset_pin(&pin_GPIO44);
+
+ // SPI Flash and RAM
+ common_hal_never_reset_pin(&pin_GPIO26);
+ common_hal_never_reset_pin(&pin_GPIO27);
+ common_hal_never_reset_pin(&pin_GPIO28);
+ common_hal_never_reset_pin(&pin_GPIO29);
+ common_hal_never_reset_pin(&pin_GPIO30);
+ common_hal_never_reset_pin(&pin_GPIO31);
+ common_hal_never_reset_pin(&pin_GPIO32);
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h
new file mode 100644
index 000000000..93fb0c573
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+ *
+ * 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.
+ */
+
+//Micropython setup
+
+#define MICROPY_HW_BOARD_NAME "FeatherS2"
+#define MICROPY_HW_MCU_NAME "ESP32S2"
+
+#define AUTORESET_DELAY_MS 500
+
+// Doesn't work with this on.
+// #define MICROPY_HW_APA102_MOSI (&pin_GPIO44)
+// #define MICROPY_HW_APA102_SCK (&pin_GPIO45)
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
new file mode 100644
index 000000000..ea3484d2f
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/mpconfigboard.mk
@@ -0,0 +1,21 @@
+USB_VID = 0x239A
+USB_PID = 0x80AC
+USB_PRODUCT = "FeatherS2"
+USB_MANUFACTURER = "UnexpectedMaker"
+USB_DEVICES = "CDC,MSC,HID"
+
+
+INTERNAL_FLASH_FILESYSTEM = 1
+LONGINT_IMPL = MPZ
+
+# The default queue depth of 16 overflows on release builds,
+# so increase it to 32.
+CFLAGS += -DCFG_TUD_TASK_QUEUE_SZ=32
+
+CIRCUITPY_NEOPIXEL_WRITE = 0
+
+CIRCUITPY_ESP_FLASH_MODE=qio
+CIRCUITPY_ESP_FLASH_FREQ=40m
+CIRCUITPY_ESP_FLASH_SIZE=16MB
+
+CIRCUITPY_BITBANG_APA102 = 1
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/pins.c b/ports/esp32s2/boards/unexpectedmaker_feathers2/pins.c
new file mode 100644
index 000000000..e8dd2edf6
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/pins.c
@@ -0,0 +1,57 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_GPIO17) },
+ { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_GPIO17) },
+
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_GPIO18) },
+ { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_GPIO18) },
+
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_GPIO14) },
+ { MP_ROM_QSTR(MP_QSTR_D16), MP_ROM_PTR(&pin_GPIO14) },
+
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_GPIO12) },
+ { MP_ROM_QSTR(MP_QSTR_D17), MP_ROM_PTR(&pin_GPIO12) },
+
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_GPIO6) },
+ { MP_ROM_QSTR(MP_QSTR_D18), MP_ROM_PTR(&pin_GPIO6) },
+
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_GPIO5) },
+ { MP_ROM_QSTR(MP_QSTR_D19), MP_ROM_PTR(&pin_GPIO5) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_GPIO36) },
+ { MP_ROM_QSTR(MP_QSTR_D25), MP_ROM_PTR(&pin_GPIO36) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_GPIO35) },
+ { MP_ROM_QSTR(MP_QSTR_D24), MP_ROM_PTR(&pin_GPIO35) },
+
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_GPIO37) },
+ { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_GPIO37) },
+
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_GPIO44) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_GPIO44) },
+
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_GPIO43) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_GPIO43) },
+
+ // Moving to 9 and 8
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_GPIO38) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_GPIO33) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_GPIO1) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_GPIO3) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_GPIO7) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_GPIO8) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_GPIO9) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_GPIO10) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_GPIO11) },
+
+ { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_GPIO44) }, // MTDO
+ { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_GPIO45) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pin_GPIO13) },
+
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig b/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ports/esp32s2/boards/unexpectedmaker_feathers2/sdkconfig
diff --git a/ports/esp32s2/common-hal/busio/I2C.c b/ports/esp32s2/common-hal/busio/I2C.c
new file mode 100644
index 000000000..57270372f
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/I2C.c
@@ -0,0 +1,228 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries LLC
+ *
+ * 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 "shared-bindings/busio/I2C.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+
+#include "driver/i2c.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "supervisor/shared/translate.h"
+
+typedef enum {
+ STATUS_FREE = 0,
+ STATUS_IN_USE,
+ STATUS_NEVER_RESET
+} i2c_status_t;
+
+static i2c_status_t i2c_status[I2C_NUM_MAX];
+
+void never_reset_i2c(i2c_port_t num) {
+ i2c_status[num] = STATUS_NEVER_RESET;
+}
+
+void i2c_reset(void) {
+ for (i2c_port_t num = 0; num < I2C_NUM_MAX; num++) {
+ if (i2c_status[num] == STATUS_IN_USE) {
+ i2c_driver_delete(num);
+ i2c_status[num] = STATUS_FREE;
+ }
+ }
+}
+
+void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
+ const mcu_pin_obj_t* scl, const mcu_pin_obj_t* sda, uint32_t frequency, uint32_t timeout) {
+ // Pins 45 and 46 are "strapping" pins that impact start up behavior. They usually need to
+ // be pulled-down so pulling them up for I2C is a bad idea. To make this hard, we don't
+ // support I2C on these pins.
+ //
+ // 46 is also input-only so it'll never work.
+ if (scl->number == 45 || scl->number == 46 || sda->number == 45 || sda->number == 46) {
+ mp_raise_ValueError(translate("Invalid pins"));
+ }
+
+#if CIRCUITPY_REQUIRE_I2C_PULLUPS
+ // Test that the pins are in a high state. (Hopefully indicating they are pulled up.)
+ gpio_set_direction(sda->number, GPIO_MODE_DEF_INPUT);
+ gpio_set_direction(scl->number, GPIO_MODE_DEF_INPUT);
+
+ gpio_pulldown_en(sda->number);
+ gpio_pulldown_en(scl->number);
+
+ common_hal_mcu_delay_us(10);
+
+ gpio_pulldown_dis(sda->number);
+ gpio_pulldown_dis(scl->number);
+
+ // We must pull up within 3us to achieve 400khz.
+ common_hal_mcu_delay_us(3);
+
+ if (gpio_get_level(sda->number) == 0 || gpio_get_level(scl->number) == 0) {
+ reset_pin_number(sda->number);
+ reset_pin_number(scl->number);
+ mp_raise_RuntimeError(translate("SDA or SCL needs a pull up"));
+ }
+#endif
+
+
+ if (xSemaphoreCreateBinaryStatic(&self->semaphore) != &self->semaphore) {
+ mp_raise_RuntimeError(translate("Unable to create lock"));
+ }
+ xSemaphoreGive(&self->semaphore);
+ self->sda_pin = sda;
+ self->scl_pin = scl;
+ self->i2c_num = I2C_NUM_MAX;
+ for (i2c_port_t num = 0; num < I2C_NUM_MAX; num++) {
+ if (i2c_status[num] == STATUS_FREE) {
+ self->i2c_num = num;
+ }
+ }
+ if (self->i2c_num == I2C_NUM_MAX) {
+ mp_raise_ValueError(translate("All I2C peripherals are in use"));
+ }
+ i2c_status[self->i2c_num] = STATUS_IN_USE;
+ i2c_config_t i2c_conf = {
+ .mode = I2C_MODE_MASTER,
+ .sda_io_num = self->sda_pin->number,
+ .scl_io_num = self->scl_pin->number,
+ .sda_pullup_en = GPIO_PULLUP_DISABLE, /*!< Internal GPIO pull mode for I2C sda signal*/
+ .scl_pullup_en = GPIO_PULLUP_DISABLE, /*!< Internal GPIO pull mode for I2C scl signal*/
+
+ .master = {
+ .clk_speed = frequency,
+ }
+ };
+ esp_err_t result = i2c_param_config(self->i2c_num, &i2c_conf);
+ if (result != ESP_OK) {
+ mp_raise_ValueError(translate("Invalid pins"));
+ }
+ result = i2c_driver_install(self->i2c_num,
+ I2C_MODE_MASTER,
+ 0,
+ 0,
+ 0);
+ if (result != ESP_OK) {
+ mp_raise_OSError(MP_EIO);
+ }
+
+ claim_pin(sda);
+ claim_pin(scl);
+}
+
+bool common_hal_busio_i2c_deinited(busio_i2c_obj_t *self) {
+ return self->sda_pin == NULL;
+}
+
+void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
+ if (common_hal_busio_i2c_deinited(self)) {
+ return;
+ }
+
+ i2c_driver_delete(self->i2c_num);
+ i2c_status[self->i2c_num] = STATUS_FREE;
+
+ common_hal_reset_pin(self->sda_pin);
+ common_hal_reset_pin(self->scl_pin);
+ self->sda_pin = NULL;
+ self->scl_pin = NULL;
+}
+
+bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, addr << 1, true);
+ i2c_master_stop(cmd);
+ esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 10);
+ i2c_cmd_link_delete(cmd);
+ return result == ESP_OK;
+}
+
+bool common_hal_busio_i2c_try_lock(busio_i2c_obj_t *self) {
+ if (self->has_lock) {
+ return false;
+ }
+ self->has_lock = xSemaphoreTake(&self->semaphore, 0) == pdTRUE;
+ return self->has_lock;
+}
+
+bool common_hal_busio_i2c_has_lock(busio_i2c_obj_t *self) {
+ return self->has_lock;
+}
+
+void common_hal_busio_i2c_unlock(busio_i2c_obj_t *self) {
+ xSemaphoreGive(&self->semaphore);
+ self->has_lock = false;
+}
+
+uint8_t common_hal_busio_i2c_write(busio_i2c_obj_t *self, uint16_t addr,
+ const uint8_t *data, size_t len, bool transmit_stop_bit) {
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, addr << 1, true);
+ i2c_master_write(cmd, (uint8_t*) data, len, true);
+ if (transmit_stop_bit) {
+ i2c_master_stop(cmd);
+ }
+ esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100 /* wait in ticks */);
+ i2c_cmd_link_delete(cmd);
+
+ if (result == ESP_OK) {
+ return 0;
+ } else if (result == ESP_FAIL) {
+ return MP_ENODEV;
+ }
+ return MP_EIO;
+}
+
+uint8_t common_hal_busio_i2c_read(busio_i2c_obj_t *self, uint16_t addr,
+ uint8_t *data, size_t len) {
+ i2c_cmd_handle_t cmd = i2c_cmd_link_create();
+ i2c_master_start(cmd);
+ i2c_master_write_byte(cmd, addr << 1 | 1, true); // | 1 to indicate read
+ if (len > 1) {
+ i2c_master_read(cmd, data, len - 1, 0);
+ }
+ i2c_master_read_byte(cmd, data + len - 1, 1);
+ i2c_master_stop(cmd);
+ esp_err_t result = i2c_master_cmd_begin(self->i2c_num, cmd, 100 /* wait in ticks */);
+ i2c_cmd_link_delete(cmd);
+
+ if (result == ESP_OK) {
+ return 0;
+ } else if (result == ESP_FAIL) {
+ return MP_ENODEV;
+ }
+ return MP_EIO;
+}
+
+void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
+ never_reset_i2c(self->i2c_num);
+
+ common_hal_never_reset_pin(self->scl_pin);
+ common_hal_never_reset_pin(self->sda_pin);
+}
diff --git a/ports/esp32s2/common-hal/busio/I2C.h b/ports/esp32s2/common-hal/busio/I2C.h
new file mode 100644
index 000000000..24a3fd495
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/I2C.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * 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_ESP32S2_COMMON_HAL_BUSIO_I2C_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_I2C_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "esp-idf/components/soc/include/hal/i2c_types.h"
+#include "FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ const mcu_pin_obj_t* scl_pin;
+ const mcu_pin_obj_t* sda_pin;
+ i2c_port_t i2c_num;
+ StaticSemaphore_t semaphore;
+ bool has_lock;
+} busio_i2c_obj_t;
+
+void i2c_reset(void);
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_I2C_H
diff --git a/ports/esp32s2/common-hal/busio/OneWire.h b/ports/esp32s2/common-hal/busio/OneWire.h
new file mode 100644
index 000000000..bb6a01419
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/OneWire.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft
+ *
+ * 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_ESP32S2_COMMON_HAL_BUSIO_ONEWIRE_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_ONEWIRE_H
+
+// Use bitbangio.
+#include "shared-module/busio/OneWire.h"
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_ONEWIRE_H
diff --git a/ports/esp32s2/common-hal/busio/SPI.c b/ports/esp32s2/common-hal/busio/SPI.c
new file mode 100644
index 000000000..a22075cd5
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/SPI.c
@@ -0,0 +1,358 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * 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 "shared-bindings/busio/SPI.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+
+#include "boards/board.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "supervisor/shared/rgb_led_status.h"
+
+static bool spi_never_reset[SOC_SPI_PERIPH_NUM];
+
+// Store one lock handle per device so that we can free it.
+static spi_bus_lock_dev_handle_t lock_dev_handle[SOC_SPI_PERIPH_NUM];
+static intr_handle_t intr_handle[SOC_SPI_PERIPH_NUM];
+
+void spi_reset(void) {
+ for (spi_host_device_t host_id = SPI2_HOST; host_id < SOC_SPI_PERIPH_NUM; host_id++) {
+ if (spi_never_reset[host_id]) {
+ continue;
+ }
+ bool in_use = false;
+ if (lock_dev_handle[host_id] != NULL) {
+ spi_bus_lock_unregister_dev(lock_dev_handle[host_id]);
+ lock_dev_handle[host_id] = NULL;
+ in_use = true;
+ }
+ if (intr_handle[host_id] != NULL) {
+ esp_intr_free(intr_handle[host_id]);
+ intr_handle[host_id] = NULL;
+ in_use = true;
+ }
+ if (in_use) {
+ spi_bus_free(host_id);
+ }
+ }
+}
+
+// This is copied in from the ESP-IDF because it is static.
+// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+static bool bus_uses_iomux_pins(spi_host_device_t host, const spi_bus_config_t* bus_config)
+{
+ if (bus_config->sclk_io_num>=0 &&
+ bus_config->sclk_io_num != spi_periph_signal[host].spiclk_iomux_pin) return false;
+ if (bus_config->quadwp_io_num>=0 &&
+ bus_config->quadwp_io_num != spi_periph_signal[host].spiwp_iomux_pin) return false;
+ if (bus_config->quadhd_io_num>=0 &&
+ bus_config->quadhd_io_num != spi_periph_signal[host].spihd_iomux_pin) return false;
+ if (bus_config->mosi_io_num >= 0 &&
+ bus_config->mosi_io_num != spi_periph_signal[host].spid_iomux_pin) return false;
+ if (bus_config->miso_io_num>=0 &&
+ bus_config->miso_io_num != spi_periph_signal[host].spiq_iomux_pin) return false;
+
+ return true;
+}
+
+// End copied code.
+
+static bool spi_bus_is_free(spi_host_device_t host_id) {
+ return spi_bus_get_attr(host_id) == NULL;
+}
+
+static void spi_interrupt_handler(void *arg) {
+ // busio_spi_obj_t *self = arg;
+}
+
+// The interrupt may get invoked by the bus lock.
+static void spi_bus_intr_enable(void *self)
+{
+ esp_intr_enable(((busio_spi_obj_t *)self)->interrupt);
+}
+
+// The interrupt is always disabled by the ISR itself, not exposed
+static void spi_bus_intr_disable(void *self)
+{
+ esp_intr_disable(((busio_spi_obj_t *)self)->interrupt);
+}
+
+void common_hal_busio_spi_construct(busio_spi_obj_t *self,
+ const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi,
+ const mcu_pin_obj_t * miso) {
+ spi_bus_config_t bus_config;
+ bus_config.mosi_io_num = mosi != NULL ? mosi->number : -1;
+ bus_config.miso_io_num = miso != NULL ? miso->number : -1;
+ bus_config.sclk_io_num = clock != NULL ? clock->number : -1;
+ bus_config.quadwp_io_num = -1;
+ bus_config.quadhd_io_num = -1;
+ bus_config.max_transfer_sz = 0; // Uses the default
+ bus_config.flags = SPICOMMON_BUSFLAG_MASTER | SPICOMMON_BUSFLAG_SCLK |
+ (mosi != NULL ? SPICOMMON_BUSFLAG_MOSI : 0) |
+ (miso != NULL ? SPICOMMON_BUSFLAG_MISO : 0);
+ bus_config.intr_flags = 0;
+
+ // RAM and Flash is often on SPI1 and is unsupported by the IDF so use it as
+ // a flag value.
+ spi_host_device_t host_id = SPI1_HOST;
+ self->connected_through_gpio = true;
+ // Try and save SPI2 for pins that are on the IOMUX
+ if (bus_uses_iomux_pins(SPI2_HOST, &bus_config) && spi_bus_is_free(SPI2_HOST)) {
+ host_id = SPI2_HOST;
+ self->connected_through_gpio = false;
+ } else if (spi_bus_is_free(SPI3_HOST)) {
+ host_id = SPI3_HOST;
+ } else if (spi_bus_is_free(SPI2_HOST)) {
+ host_id = SPI2_HOST;
+ }
+ if (host_id == SPI1_HOST) {
+ mp_raise_ValueError(translate("All SPI peripherals are in use"));
+ }
+
+ esp_err_t result = spi_bus_initialize(host_id, &bus_config, host_id /* dma channel */);
+ if (result == ESP_ERR_NO_MEM) {
+ mp_raise_msg(&mp_type_MemoryError, translate("ESP-IDF memory allocation failed"));
+ } else if (result == ESP_ERR_INVALID_ARG) {
+ mp_raise_ValueError(translate("Invalid pins"));
+ }
+
+ // After this point, we need to deinit to free IDF memory so fill out self's pins.
+ self->clock_pin = clock;
+ self->MOSI_pin = mosi;
+ self->MISO_pin = miso;
+ self->host_id = host_id;
+
+ spi_bus_lock_dev_config_t config = { .flags = 0 };
+ // The returned lock is stored in the bus lock but must be freed separately with
+ // spi_bus_lock_unregister_dev.
+ result = spi_bus_lock_register_dev(spi_bus_get_attr(host_id)->lock,
+ &config,
+ &self->lock);
+ if (result == ESP_ERR_NO_MEM) {
+ common_hal_busio_spi_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError, translate("ESP-IDF memory allocation failed"));
+ }
+ lock_dev_handle[host_id] = self->lock;
+
+ result = esp_intr_alloc(spicommon_irqsource_for_host(host_id),
+ bus_config.intr_flags | ESP_INTR_FLAG_INTRDISABLED,
+ spi_interrupt_handler, self, &self->interrupt);
+ if (result == ESP_ERR_NO_MEM) {
+ common_hal_busio_spi_deinit(self);
+ mp_raise_msg(&mp_type_MemoryError, translate("ESP-IDF memory allocation failed"));
+ }
+ intr_handle[host_id] = self->interrupt;
+ spi_bus_lock_set_bg_control(spi_bus_get_attr(host_id)->lock, spi_bus_intr_enable, spi_bus_intr_disable, self);
+
+ spi_hal_context_t* hal = &self->hal_context;
+
+ // spi_hal_init clears the given hal context so set everything after.
+ spi_hal_init(hal, host_id);
+ hal->dmadesc_tx = &self->tx_dma;
+ hal->dmadesc_rx = &self->rx_dma;
+ hal->dmadesc_n = 1;
+
+ // We don't use native CS.
+ // hal->cs_setup = 0;
+ // hal->cs_hold = 0;
+ // hal->cs_pin_id = 0;
+
+ hal->sio = 0;
+ hal->half_duplex = 0;
+ // hal->tx_lsbfirst = 0;
+ // hal->rx_lsbfirst = 0;
+ hal->dma_enabled = 1;
+ hal->no_compensate = 1;
+ // Ignore CS bits
+
+ // We don't use cmd, addr or dummy bits.
+ // hal->cmd = 0;
+ // hal->cmd_bits = 0;
+ // hal->addr_bits = 0;
+ // hal->dummy_bits = 0;
+ // hal->addr = 0;
+
+ hal->io_mode = SPI_LL_IO_MODE_NORMAL;
+
+ common_hal_busio_spi_configure(self, 250000, 0, 0, 8);
+}
+
+void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) {
+ spi_never_reset[self->host_id] = true;
+
+ common_hal_never_reset_pin(self->clock_pin);
+ common_hal_never_reset_pin(self->MOSI_pin);
+ common_hal_never_reset_pin(self->MISO_pin);
+}
+
+bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) {
+ return self->clock_pin == NULL;
+}
+
+void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
+ if (common_hal_busio_spi_deinited(self)) {
+ return;
+ }
+ spi_never_reset[self->host_id] = false;
+ if (self->lock != NULL) {
+ spi_bus_lock_unregister_dev(self->lock);
+ lock_dev_handle[self->host_id] = NULL;
+ }
+ if (self->interrupt != NULL) {
+ esp_intr_free(self->interrupt);
+ intr_handle[self->host_id] = NULL;
+ }
+ spi_bus_free(self->host_id);
+
+ common_hal_reset_pin(self->clock_pin);
+ common_hal_reset_pin(self->MOSI_pin);
+ common_hal_reset_pin(self->MISO_pin);
+ self->clock_pin = NULL;
+}
+
+bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
+ uint32_t baudrate, uint8_t polarity, uint8_t phase, uint8_t bits) {
+ if (baudrate == self->target_frequency &&
+ polarity == self->polarity &&
+ phase == self->phase &&
+ bits == self->bits) {
+ return true;
+ }
+ self->hal_context.mode = polarity << 1 | phase;
+ self->polarity = polarity;
+ self->phase = phase;
+ self->bits = bits;
+ self->target_frequency = baudrate;
+ self->hal_context.timing_conf = &self->timing_conf;
+ esp_err_t result = spi_hal_get_clock_conf(&self->hal_context,
+ self->target_frequency,
+ 128 /* duty_cycle */,
+ self->connected_through_gpio,
+ 0 /* input_delay_ns */,
+ &self->real_frequency,
+ &self->timing_conf);
+ if (result != ESP_OK) {
+ return false;
+ }
+
+ spi_hal_setup_device(&self->hal_context);
+ return true;
+}
+
+bool common_hal_busio_spi_try_lock(busio_spi_obj_t *self) {
+ // If our lock has already been taken then return false because someone else
+ // may already grabbed it in our call stack.
+ if (self->has_lock) {
+ return false;
+ }
+ // Wait to grab the lock from another task.
+ esp_err_t result = spi_bus_lock_acquire_start(self->lock, portMAX_DELAY);
+ self->has_lock = result == ESP_OK;
+ return self->has_lock;
+}
+
+bool common_hal_busio_spi_has_lock(busio_spi_obj_t *self) {
+ return self->has_lock;
+}
+
+void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
+ spi_bus_lock_acquire_end(self->lock);
+ self->has_lock = false;
+}
+
+bool common_hal_busio_spi_write(busio_spi_obj_t *self,
+ const uint8_t *data, size_t len) {
+ return common_hal_busio_spi_transfer(self, data, NULL, len);
+}
+
+bool common_hal_busio_spi_read(busio_spi_obj_t *self,
+ uint8_t *data, size_t len, uint8_t write_value) {
+ return common_hal_busio_spi_transfer(self, NULL, data, len);
+}
+
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
+ if (len == 0) {
+ return true;
+ }
+
+ spi_hal_context_t* hal = &self->hal_context;
+ hal->send_buffer = NULL;
+ hal->rcv_buffer = NULL;
+ // Reset timing_conf in case we've moved since the last time we used it.
+ hal->timing_conf = &self->timing_conf;
+ // This rounds up.
+ size_t dma_count = (len + LLDESC_MAX_NUM_PER_DESC - 1) / LLDESC_MAX_NUM_PER_DESC;
+ for (size_t i = 0; i < dma_count; i++) {
+ size_t offset = LLDESC_MAX_NUM_PER_DESC * i;
+ size_t dma_len = len - offset;
+ if (dma_len > LLDESC_MAX_NUM_PER_DESC) {
+ dma_len = LLDESC_MAX_NUM_PER_DESC;
+ }
+ hal->tx_bitlen = dma_len * self->bits;
+ hal->rx_bitlen = dma_len * self->bits;
+ if (data_out != NULL) {
+ hal->send_buffer = (uint8_t*) data_out + offset;
+ }
+ if (data_in != NULL) {
+ hal->rcv_buffer = data_in + offset;
+ }
+
+ spi_hal_setup_trans(hal);
+ spi_hal_prepare_data(hal);
+ spi_hal_user_start(hal);
+ // TODO: Switch to waiting on a lock that is given by an interrupt.
+ while (!spi_hal_usr_is_done(hal)) {
+ RUN_BACKGROUND_TASKS;
+ }
+ spi_hal_fetch_result(hal);
+ }
+
+ return true;
+}
+
+uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self) {
+ return self->real_frequency;
+}
+
+uint8_t common_hal_busio_spi_get_phase(busio_spi_obj_t* self) {
+ return self->phase;
+}
+
+uint8_t common_hal_busio_spi_get_polarity(busio_spi_obj_t* self) {
+ return self->polarity;
+}
diff --git a/ports/esp32s2/common-hal/busio/SPI.h b/ports/esp32s2/common-hal/busio/SPI.h
new file mode 100644
index 000000000..6d8203831
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/SPI.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * 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_ESP32S2_COMMON_HAL_BUSIO_SPI_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_SPI_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "esp-idf/components/driver/include/driver/spi_common_internal.h"
+#include "esp-idf/components/soc/include/hal/spi_hal.h"
+#include "esp-idf/components/soc/include/hal/spi_types.h"
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ const mcu_pin_obj_t* clock_pin;
+ const mcu_pin_obj_t* MOSI_pin;
+ const mcu_pin_obj_t* MISO_pin;
+ spi_host_device_t host_id;
+ spi_bus_lock_dev_handle_t lock;
+ spi_hal_context_t hal_context;
+ spi_hal_timing_conf_t timing_conf;
+ intr_handle_t interrupt;
+ // IDF allocates these in DMA accessible memory so they may need to move when
+ // we use external RAM for CircuitPython.
+ lldesc_t tx_dma;
+ lldesc_t rx_dma;
+ uint32_t target_frequency;
+ int32_t real_frequency;
+ uint8_t polarity;
+ uint8_t phase;
+ uint8_t bits;
+ bool has_lock;
+ bool connected_through_gpio;
+} busio_spi_obj_t;
+
+void spi_reset(void);
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_SPI_H
diff --git a/ports/esp32s2/common-hal/busio/UART.c b/ports/esp32s2/common-hal/busio/UART.c
new file mode 100644
index 000000000..b0162adba
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/UART.c
@@ -0,0 +1,348 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Scott Shawcroft for Adafruit Industries LLC
+ *
+ * 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 "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/busio/UART.h"
+
+#include "driver/uart.h"
+
+#include "mpconfigport.h"
+#include "lib/utils/interrupt_char.h"
+#include "py/gc.h"
+#include "py/mperrno.h"
+#include "py/runtime.h"
+#include "py/stream.h"
+#include "supervisor/shared/translate.h"
+#include "supervisor/shared/tick.h"
+
+void uart_reset(void) {
+ for (uart_port_t num = 0; num < UART_NUM_MAX; num++) {
+ // Ignore the UART used by the IDF.
+ #ifdef CONFIG_CONSOLE_UART_NUM
+ if (num == CONFIG_CONSOLE_UART_NUM) {
+ continue;
+ }
+ #endif
+ if (uart_is_driver_installed(num)) {
+ uart_driver_delete(num);
+ }
+ }
+}
+
+void common_hal_busio_uart_construct(busio_uart_obj_t *self,
+ const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
+ const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
+ const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
+ mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
+ bool sigint_enabled) {
+
+ if (bits > 8) {
+ mp_raise_NotImplementedError(translate("bytes > 8 bits not supported"));
+ }
+
+ bool have_tx = tx != NULL;
+ bool have_rx = rx != NULL;
+ bool have_rts = rts != NULL;
+ bool have_cts = cts != NULL;
+ bool have_rs485_dir = rs485_dir != NULL;
+ if (!have_tx && !have_rx) {
+ mp_raise_ValueError(translate("tx and rx cannot both be None"));
+ }
+
+ // Filter for sane settings for RS485
+ if (have_rs485_dir) {
+ if (have_rts || have_cts) {
+ mp_raise_ValueError(translate("Cannot specify RTS or CTS in RS485 mode"));
+ }
+ } else if (rs485_invert) {
+ mp_raise_ValueError(translate("RS485 inversion specified when not in RS485 mode"));
+ }
+
+ self->timeout_ms = timeout * 1000;
+
+ self->uart_num = UART_NUM_MAX;
+ for (uart_port_t num = 0; num < UART_NUM_MAX; num++) {
+ if (!uart_is_driver_installed(num)) {
+ self->uart_num = num;
+ }
+ }
+ if (self->uart_num == UART_NUM_MAX) {
+ mp_raise_ValueError(translate("All UART peripherals are in use"));
+ }
+
+ uart_mode_t mode = UART_MODE_UART;
+ uart_hw_flowcontrol_t flow_control = UART_HW_FLOWCTRL_DISABLE;
+ if (have_rs485_dir) {
+ mode = UART_MODE_RS485_HALF_DUPLEX;
+ if (!rs485_invert) {
+ uart_set_line_inverse(self->uart_num, UART_SIGNAL_DTR_INV);
+ }
+ } else if (have_rts && have_cts) {
+ flow_control = UART_HW_FLOWCTRL_CTS_RTS;
+ } else if (have_rts) {
+ flow_control = UART_HW_FLOWCTRL_RTS;
+ } else if (have_rts) {
+ flow_control = UART_HW_FLOWCTRL_CTS;
+ }
+
+ if (receiver_buffer_size <= UART_FIFO_LEN) {
+ receiver_buffer_size = UART_FIFO_LEN + 8;
+ }
+
+ uint8_t rx_threshold = UART_FIFO_LEN - 8;
+ // Install the driver before we change the settings.
+ if (uart_driver_install(self->uart_num, receiver_buffer_size, 0, 0, NULL, 0) != ESP_OK ||
+ uart_set_mode(self->uart_num, mode) != ESP_OK) {
+ mp_raise_ValueError(translate("Could not initialize UART"));
+ }
+ uart_set_hw_flow_ctrl(self->uart_num, flow_control, rx_threshold);
+
+ // Set baud rate
+ common_hal_busio_uart_set_baudrate(self, baudrate);
+
+ uart_word_length_t word_length = UART_DATA_8_BITS;
+ switch (bits) {
+ // Shared bindings prevents data < 7 bits.
+ // case 5:
+ // word_length = UART_DATA_5_BITS;
+ // break;
+ // case 6:
+ // word_length = UART_DATA_6_BITS;
+ // break;
+ case 7:
+ word_length = UART_DATA_7_BITS;
+ break;
+ case 8:
+ word_length = UART_DATA_8_BITS;
+ break;
+ default:
+ // Won't hit this because shared-bindings limits to 7-9 bits. We error on 9 above.
+ break;
+ }
+ uart_set_word_length(self->uart_num, word_length);
+
+ uart_parity_t parity_mode = UART_PARITY_DISABLE;
+ switch (parity) {
+ case BUSIO_UART_PARITY_NONE:
+ parity_mode = UART_PARITY_DISABLE;
+ break;
+ case BUSIO_UART_PARITY_EVEN:
+ parity_mode = UART_PARITY_EVEN;
+ break;
+ case BUSIO_UART_PARITY_ODD:
+ parity_mode = UART_PARITY_ODD;
+ break;
+ default:
+ // Won't reach here because the input is an enum that is completely handled.
+ break;
+ }
+ uart_set_parity(self->uart_num, parity_mode);
+
+ // Stop is 1 or 2 always.
+ uart_stop_bits_t stop_bits= UART_STOP_BITS_1;
+ if (stop == 2) {
+ stop_bits = UART_STOP_BITS_2;
+ }
+ uart_set_stop_bits(self->uart_num, stop_bits);
+
+ self->tx_pin = NULL;
+ self->rx_pin = NULL;
+ self->rts_pin = NULL;
+ self->cts_pin = NULL;
+ int tx_num = -1;
+ int rx_num = -1;
+ int rts_num = -1;
+ int cts_num = -1;
+ if (have_tx) {
+ claim_pin(tx);
+ self->tx_pin = tx;
+ tx_num = tx->number;
+ }
+
+ if (have_rx) {
+ claim_pin(rx);
+ self->rx_pin = rx;
+ rx_num = rx->number;
+ }
+
+ if (have_rts) {
+ claim_pin(rts);
+ self->rts_pin = rts;
+ rts_num = rts->number;
+ }
+
+ if (have_cts) {
+ claim_pin(cts);
+ self->cts_pin = cts;
+ cts_num = cts->number;
+ }
+
+ if (have_rs485_dir) {
+ claim_pin(rs485_dir);
+ // RTS is used for RS485 direction.
+ self->rts_pin = rs485_dir;
+ rts_num = rs485_dir->number;
+ }
+ if (uart_set_pin(self->uart_num, tx_num, rx_num, rts_num, cts_num) != ESP_OK) {
+ mp_raise_ValueError(translate("Invalid pins"));
+ }
+}
+
+bool common_hal_busio_uart_deinited(busio_uart_obj_t *self) {
+ return self->rx_pin == NULL && self->tx_pin == NULL;
+}
+
+void common_hal_busio_uart_deinit(busio_uart_obj_t *self) {
+ if (common_hal_busio_uart_deinited(self)) {
+ return;
+ }
+ uart_driver_delete(self->uart_num);
+
+ common_hal_reset_pin(self->rx_pin);
+ common_hal_reset_pin(self->tx_pin);
+ common_hal_reset_pin(self->rts_pin);
+ common_hal_reset_pin(self->cts_pin);
+ self->rx_pin = NULL;
+ self->tx_pin = NULL;
+ self->cts_pin = NULL;
+ self->rts_pin = NULL;
+}
+
+// Read characters.
+size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t len, int *errcode) {
+ if (self->rx_pin == NULL) {
+ mp_raise_ValueError(translate("No RX pin"));
+ }
+ if (len == 0) {
+ // Nothing to read.
+ return 0;
+ }
+
+ size_t total_read = 0;
+ uint64_t start_ticks = supervisor_ticks_ms64();
+
+ // Busy-wait until timeout or until we've read enough chars.
+ while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) {
+ // Read as many chars as we can right now, up to len.
+ size_t num_read = uart_read_bytes(self->uart_num, data, len, 0);
+ if (num_read < 0) {
+ break;
+ }
+
+ // Advance pointer in data buffer, and decrease how many chars left to read.
+ data += num_read;
+ len -= num_read;
+ total_read += num_read;
+ if (len == 0) {
+ // Don't need to read any more: data buf is full.
+ break;
+ }
+ if (num_read > 0) {
+ // Reset the timeout on every character read.
+ start_ticks = supervisor_ticks_ms64();
+ }
+ RUN_BACKGROUND_TASKS;
+ // Allow user to break out of a timeout with a KeyboardInterrupt.
+ if (mp_hal_is_interrupted()) {
+ break;
+ }
+ // If we are zero timeout, make sure we don't loop again (in the event
+ // we read in under 1ms)
+ if (self->timeout_ms == 0) {
+ break;
+ }
+ }
+
+ if (total_read == 0) {
+ *errcode = EAGAIN;
+ return MP_STREAM_ERROR;
+ }
+
+ return total_read;
+}
+
+// Write characters.
+size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data, size_t len, int *errcode) {
+ if (self->tx_pin == NULL) {
+ mp_raise_ValueError(translate("No TX pin"));
+ }
+
+ while (len > 0) {
+ int count = uart_tx_chars(self->uart_num, (const char*) data, len);
+ if (count < 0) {
+ *errcode = MP_EAGAIN;
+ return MP_STREAM_ERROR;
+ }
+ len -= count;
+ data += count;
+ RUN_BACKGROUND_TASKS;
+ }
+ while (uart_wait_tx_done(self->uart_num, 0) == ESP_ERR_TIMEOUT) {
+ RUN_BACKGROUND_TASKS;
+ }
+
+ return len;
+}
+
+uint32_t common_hal_busio_uart_get_baudrate(busio_uart_obj_t *self) {
+ uint32_t baudrate;
+ uart_get_baudrate(self->uart_num, &baudrate);
+ return baudrate;
+}
+
+void common_hal_busio_uart_set_baudrate(busio_uart_obj_t *self, uint32_t baudrate) {
+ if (baudrate > UART_BITRATE_MAX ||
+ uart_set_baudrate(self->uart_num, baudrate) != ESP_OK) {
+ mp_raise_ValueError(translate("Unsupported baudrate"));
+ }
+}
+
+mp_float_t common_hal_busio_uart_get_timeout(busio_uart_obj_t *self) {
+ return (mp_float_t) (self->timeout_ms / 1000.0f);
+}
+
+void common_hal_busio_uart_set_timeout(busio_uart_obj_t *self, mp_float_t timeout) {
+ self->timeout_ms = timeout * 1000;
+}
+
+uint32_t common_hal_busio_uart_rx_characters_available(busio_uart_obj_t *self) {
+ size_t count;
+ uart_get_buffered_data_len(self->uart_num, &count);
+ return count;
+}
+
+void common_hal_busio_uart_clear_rx_buffer(busio_uart_obj_t *self) {
+ uart_flush(self->uart_num);
+}
+
+// True if there are no characters still to be written.
+bool common_hal_busio_uart_ready_to_tx(busio_uart_obj_t *self) {
+ if (self->tx_pin == NULL) {
+ return false;
+ }
+ return uart_wait_tx_done(self->uart_num, 0) != ESP_ERR_TIMEOUT;
+}
diff --git a/ports/esp32s2/common-hal/busio/UART.h b/ports/esp32s2/common-hal/busio/UART.h
new file mode 100644
index 000000000..b3cc92966
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/UART.h
@@ -0,0 +1,49 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * 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_ESP32S2_COMMON_HAL_BUSIO_UART_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_UART_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "esp-idf/components/soc/include/hal/uart_types.h"
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ const mcu_pin_obj_t* rx_pin;
+ const mcu_pin_obj_t* tx_pin;
+ const mcu_pin_obj_t* rts_pin;
+ const mcu_pin_obj_t* cts_pin;
+ uart_port_t uart_num;
+ uint8_t character_bits;
+ bool rx_error;
+ uint32_t timeout_ms;
+} busio_uart_obj_t;
+
+void uart_reset(void);
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_BUSIO_UART_H
diff --git a/ports/esp32s2/common-hal/busio/__init__.c b/ports/esp32s2/common-hal/busio/__init__.c
new file mode 100644
index 000000000..41761b674
--- /dev/null
+++ b/ports/esp32s2/common-hal/busio/__init__.c
@@ -0,0 +1 @@
+// No busio module functions.
diff --git a/ports/esp32s2/common-hal/digitalio/DigitalInOut.c b/ports/esp32s2/common-hal/digitalio/DigitalInOut.c
index 7745a9c0a..fb3ee10ad 100644
--- a/ports/esp32s2/common-hal/digitalio/DigitalInOut.c
+++ b/ports/esp32s2/common-hal/digitalio/DigitalInOut.c
@@ -46,7 +46,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct(
}
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self) {
- return self->pin == mp_const_none;
+ return self->pin == NULL;
}
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self) {
@@ -55,7 +55,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self
}
reset_pin_number(self->pin->number);
- self->pin = mp_const_none;
+ self->pin = NULL;
}
void common_hal_digitalio_digitalinout_switch_to_input(
diff --git a/ports/esp32s2/common-hal/displayio/ParallelBus.c b/ports/esp32s2/common-hal/displayio/ParallelBus.c
new file mode 100644
index 000000000..314b72ff7
--- /dev/null
+++ b/ports/esp32s2/common-hal/displayio/ParallelBus.c
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * 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 "shared-bindings/displayio/ParallelBus.h"
+
+#include <stdint.h>
+
+#include "common-hal/microcontroller/Pin.h"
+#include "py/runtime.h"
+#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/microcontroller/__init__.h"
+
+void common_hal_displayio_parallelbus_construct(displayio_parallelbus_obj_t* self,
+ const mcu_pin_obj_t* data0, const mcu_pin_obj_t* command, const mcu_pin_obj_t* chip_select,
+ const mcu_pin_obj_t* write, const mcu_pin_obj_t* read, const mcu_pin_obj_t* reset) {
+
+ mp_raise_NotImplementedError(translate("ParallelBus not yet supported"));
+}
+
+void common_hal_displayio_parallelbus_deinit(displayio_parallelbus_obj_t* self) {
+
+}
+
+bool common_hal_displayio_parallelbus_reset(mp_obj_t obj) {
+ return false;
+}
+
+bool common_hal_displayio_parallelbus_bus_free(mp_obj_t obj) {
+ return false;
+}
+
+bool common_hal_displayio_parallelbus_begin_transaction(mp_obj_t obj) {
+
+ return false;
+}
+
+void common_hal_displayio_parallelbus_send(mp_obj_t obj, display_byte_type_t byte_type, display_chip_select_behavior_t chip_select, uint8_t *data, uint32_t data_length) {
+
+}
+
+void common_hal_displayio_parallelbus_end_transaction(mp_obj_t obj) {
+
+}
diff --git a/ports/esp32s2/common-hal/displayio/ParallelBus.h b/ports/esp32s2/common-hal/displayio/ParallelBus.h
new file mode 100644
index 000000000..cd636921d
--- /dev/null
+++ b/ports/esp32s2/common-hal/displayio/ParallelBus.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * 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_ESP32S2_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
+
+#include "common-hal/digitalio/DigitalInOut.h"
+
+typedef struct {
+ mp_obj_base_t base;
+} displayio_parallelbus_obj_t;
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_DISPLAYIO_PARALLELBUS_H
diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.c b/ports/esp32s2/common-hal/microcontroller/Pin.c
index 4c39eea16..5a059f0bb 100644
--- a/ports/esp32s2/common-hal/microcontroller/Pin.c
+++ b/ports/esp32s2/common-hal/microcontroller/Pin.c
@@ -35,11 +35,14 @@
STATIC uint32_t never_reset_pins[2];
STATIC uint32_t in_use[2];
+bool apa102_mosi_in_use;
+bool apa102_sck_in_use;
+
void never_reset_pin_number(gpio_num_t pin_number) {
never_reset_pins[pin_number / 32] |= 1 << pin_number % 32;
}
-void never_reset_pin(const mcu_pin_obj_t* pin) {
+void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) {
never_reset_pin_number(pin->number);
}
@@ -49,6 +52,10 @@ void reset_pin_number(gpio_num_t pin_number) {
in_use[pin_number / 32] &= ~(1 << pin_number % 32);
}
+void common_hal_reset_pin(const mcu_pin_obj_t* pin) {
+ reset_pin_number(pin->number);
+}
+
void reset_all_pins(void) {
for (uint8_t i = 0; i < GPIO_PIN_COUNT; i++) {
uint32_t iomux_address = GPIO_PIN_MUX_REG[i];
diff --git a/ports/esp32s2/common-hal/microcontroller/Pin.h b/ports/esp32s2/common-hal/microcontroller/Pin.h
index 6f47b1ed3..19985bda6 100644
--- a/ports/esp32s2/common-hal/microcontroller/Pin.h
+++ b/ports/esp32s2/common-hal/microcontroller/Pin.h
@@ -31,13 +31,16 @@
#include "peripherals/pins.h"
+extern bool apa102_mosi_in_use;
+extern bool apa102_sck_in_use;
+
void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer.
void reset_pin_number(gpio_num_t pin_number);
+void common_hal_reset_pin(const mcu_pin_obj_t* pin);
void claim_pin(const mcu_pin_obj_t* pin);
bool pin_number_is_free(gpio_num_t pin_number);
void never_reset_pin_number(gpio_num_t pin_number);
-void never_reset_pin(const mcu_pin_obj_t* pin);
#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_MICROCONTROLLER_PIN_H
diff --git a/ports/esp32s2/common-hal/microcontroller/Processor.c b/ports/esp32s2/common-hal/microcontroller/Processor.c
index 8eaf1a33d..39b85a18b 100644
--- a/ports/esp32s2/common-hal/microcontroller/Processor.c
+++ b/ports/esp32s2/common-hal/microcontroller/Processor.c
@@ -26,10 +26,14 @@
*/
#include <math.h>
+#include <string.h>
+
#include "common-hal/microcontroller/Processor.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
+#include "soc/efuse_reg.h"
+
float common_hal_mcu_processor_get_temperature(void) {
return NAN;
}
@@ -42,5 +46,23 @@ uint32_t common_hal_mcu_processor_get_frequency(void) {
return 0;
}
+STATIC uint8_t swap_nibbles(uint8_t v) {
+ return ((v << 4) | (v >> 4)) & 0xff;
+}
+
void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) {
+ memset(raw_id, 0, COMMON_HAL_MCU_PROCESSOR_UID_LENGTH);
+
+ uint8_t *ptr = &raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH-1];
+ // MAC address contains 48 bits (6 bytes), 32 in the low order word
+ uint32_t mac_address_part = REG_READ(EFUSE_RD_MAC_SPI_SYS_0_REG);
+ *ptr-- = swap_nibbles(mac_address_part & 0xff); mac_address_part >>= 8;
+ *ptr-- = swap_nibbles(mac_address_part & 0xff); mac_address_part >>= 8;
+ *ptr-- = swap_nibbles(mac_address_part & 0xff); mac_address_part >>= 8;
+ *ptr-- = swap_nibbles(mac_address_part & 0xff);
+
+ // and 16 in the high order word
+ mac_address_part = REG_READ(EFUSE_RD_MAC_SPI_SYS_1_REG);
+ *ptr-- = swap_nibbles(mac_address_part & 0xff); mac_address_part >>= 8;
+ *ptr-- = swap_nibbles(mac_address_part & 0xff);
}
diff --git a/ports/esp32s2/common-hal/microcontroller/Processor.h b/ports/esp32s2/common-hal/microcontroller/Processor.h
index a2ea261c8..f6636b333 100644
--- a/ports/esp32s2/common-hal/microcontroller/Processor.h
+++ b/ports/esp32s2/common-hal/microcontroller/Processor.h
@@ -27,7 +27,7 @@
#ifndef MICROPY_INCLUDED_LITEX_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
#define MICROPY_INCLUDED_LITEX_COMMON_HAL_MICROCONTROLLER_PROCESSOR_H
-#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 15
+#define COMMON_HAL_MCU_PROCESSOR_UID_LENGTH 6
#include "py/obj.h"
diff --git a/ports/esp32s2/common-hal/pulseio/PWMOut.c b/ports/esp32s2/common-hal/pulseio/PWMOut.c
new file mode 100644
index 000000000..c4f5e18dd
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/PWMOut.c
@@ -0,0 +1,198 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ * Uses code from Micropython, Copyright (c) 2013-2016 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 <math.h>
+
+#include "common-hal/pulseio/PWMOut.h"
+#include "shared-bindings/pulseio/PWMOut.h"
+#include "py/runtime.h"
+#include "driver/ledc.h"
+
+#define INDEX_EMPTY 0xFF
+
+STATIC uint32_t reserved_timer_freq[LEDC_TIMER_MAX];
+STATIC uint8_t reserved_channels[LEDC_CHANNEL_MAX];
+STATIC bool never_reset_tim[LEDC_TIMER_MAX];
+STATIC bool never_reset_chan[LEDC_CHANNEL_MAX];
+
+void pwmout_reset(void) {
+ for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++ ) {
+ ledc_stop(LEDC_LOW_SPEED_MODE, i, 0);
+ if (!never_reset_chan[i]) {
+ reserved_channels[i] = INDEX_EMPTY;
+ }
+ }
+ for (size_t i = 0; i < LEDC_TIMER_MAX; i++ ) {
+ ledc_timer_rst(LEDC_LOW_SPEED_MODE, i);
+ if (!never_reset_tim[i]) {
+ reserved_timer_freq[i] = 0;
+ }
+ }
+}
+
+pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
+ const mcu_pin_obj_t* pin,
+ uint16_t duty,
+ uint32_t frequency,
+ bool variable_frequency) {
+ // Calculate duty cycle
+ uint32_t duty_bits = 0;
+ uint32_t interval = LEDC_APB_CLK_HZ/frequency;
+ for (size_t i = 0; i < 32; i++) {
+ if(!(interval >> i)) {
+ duty_bits = i - 1;
+ break;
+ }
+ }
+ if (duty_bits < 1) {
+ mp_raise_ValueError(translate("Invalid frequency"));
+ } else if (duty_bits >= LEDC_TIMER_14_BIT) {
+ duty_bits = LEDC_TIMER_13_BIT;
+ }
+
+ // Find a viable timer
+ size_t timer_index = INDEX_EMPTY;
+ size_t channel_index = INDEX_EMPTY;
+ for (size_t i = 0; i < LEDC_TIMER_MAX; i++) {
+ if ((reserved_timer_freq[i] == frequency) && !variable_frequency) {
+ //prioritize matched frequencies so we don't needlessly take slots
+ timer_index = i;
+ break;
+ } else if (reserved_timer_freq[i] == 0) {
+ timer_index = i;
+ break;
+ }
+ }
+ if (timer_index == INDEX_EMPTY) {
+ // Running out of timers isn't pin related on ESP32S2 so we can't re-use error messages
+ mp_raise_ValueError(translate("No more timers available"));
+ }
+
+ // Find a viable channel
+ for (size_t i = 0; i < LEDC_CHANNEL_MAX; i++) {
+ if (reserved_channels[i] == INDEX_EMPTY) {
+ channel_index = i;
+ break;
+ }
+ }
+ if (channel_index == INDEX_EMPTY) {
+ mp_raise_ValueError(translate("No more channels available"));
+ }
+
+ // Run configuration
+ self->tim_handle.timer_num = timer_index;
+ self->tim_handle.duty_resolution = duty_bits;
+ self->tim_handle.freq_hz = frequency;
+ self->tim_handle.speed_mode = LEDC_LOW_SPEED_MODE;
+ self->tim_handle.clk_cfg = LEDC_AUTO_CLK;
+
+ if (ledc_timer_config(&(self->tim_handle)) != ESP_OK) {
+ mp_raise_ValueError(translate("Could not initialize timer"));
+ }
+
+ self->chan_handle.channel = channel_index;
+ self->chan_handle.duty = duty >> (16 - duty_bits);
+ self->chan_handle.gpio_num = pin->number;
+ self->chan_handle.speed_mode = LEDC_LOW_SPEED_MODE; // Only LS is allowed on ESP32-S2
+ self->chan_handle.hpoint = 0;
+ self->chan_handle.timer_sel = timer_index;
+
+ if (ledc_channel_config(&(self->chan_handle))) {
+ mp_raise_ValueError(translate("Could not initialize channel"));
+ }
+
+ // Make reservations
+ reserved_timer_freq[timer_index] = frequency;
+ reserved_channels[channel_index] = timer_index;
+
+ self->variable_frequency = variable_frequency;
+ self->pin_number = pin->number;
+ self->deinited = false;
+ self->duty_resolution = duty_bits;
+ claim_pin(pin);
+
+ // Set initial duty
+ common_hal_pulseio_pwmout_set_duty_cycle(self, duty);
+
+ return PWMOUT_OK;
+}
+
+void common_hal_pulseio_pwmout_never_reset(pulseio_pwmout_obj_t *self) {
+ never_reset_tim[self->tim_handle.timer_num] = true;
+ never_reset_chan[self->chan_handle.channel] = true;
+}
+
+void common_hal_pulseio_pwmout_reset_ok(pulseio_pwmout_obj_t *self) {
+ never_reset_tim[self->tim_handle.timer_num] = false;
+ never_reset_chan[self->chan_handle.channel] = false;
+}
+
+bool common_hal_pulseio_pwmout_deinited(pulseio_pwmout_obj_t* self) {
+ return self->deinited == true;
+}
+
+void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
+ if (common_hal_pulseio_pwmout_deinited(self)) {
+ return;
+ }
+ ledc_stop(LEDC_LOW_SPEED_MODE, self->chan_handle.channel, 0);
+ // Search if any other channel is using the timer
+ bool taken = false;
+ for (size_t i =0; i < LEDC_CHANNEL_MAX; i++) {
+ if (reserved_channels[i] == self->tim_handle.timer_num) {
+ taken = true;
+ }
+ }
+ // Variable frequency means there's only one channel on the timer
+ if (!taken || self->variable_frequency) {
+ ledc_timer_rst(LEDC_LOW_SPEED_MODE, self->tim_handle.timer_num);
+ reserved_timer_freq[self->tim_handle.timer_num] = 0;
+ }
+ reset_pin_number(self->pin_number);
+ reserved_channels[self->chan_handle.channel] = INDEX_EMPTY;
+ self->deinited = true;
+}
+
+void common_hal_pulseio_pwmout_set_duty_cycle(pulseio_pwmout_obj_t* self, uint16_t duty) {
+ ledc_set_duty(LEDC_LOW_SPEED_MODE, self->chan_handle.channel, duty >> (16 - self->duty_resolution));
+ ledc_update_duty(LEDC_LOW_SPEED_MODE, self->chan_handle.channel);
+}
+
+uint16_t common_hal_pulseio_pwmout_get_duty_cycle(pulseio_pwmout_obj_t* self) {
+ return ledc_get_duty(LEDC_LOW_SPEED_MODE, self->chan_handle.channel) << (16 - self->duty_resolution);
+}
+
+void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_t frequency) {
+ ledc_set_freq(LEDC_LOW_SPEED_MODE, self->tim_handle.timer_num, frequency);
+}
+
+uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
+ return ledc_get_freq(LEDC_LOW_SPEED_MODE, self->tim_handle.timer_num);
+}
+
+bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) {
+ return self->variable_frequency;
+}
diff --git a/ports/esp32s2/common-hal/pulseio/PWMOut.h b/ports/esp32s2/common-hal/pulseio/PWMOut.h
new file mode 100644
index 000000000..90a0c3ed9
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/PWMOut.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * 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_ESP32S2_COMMON_HAL_PULSEIO_PWMOUT_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PWMOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "driver/ledc.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ ledc_timer_config_t tim_handle;
+ ledc_channel_config_t chan_handle;
+ uint16_t pin_number;
+ uint8_t duty_resolution;
+ bool variable_frequency: 1;
+ bool deinited: 1;
+} pulseio_pwmout_obj_t;
+
+void pwmout_reset(void);
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PWMOUT_H
diff --git a/ports/esp32s2/common-hal/pulseio/PulseIn.c b/ports/esp32s2/common-hal/pulseio/PulseIn.c
new file mode 100644
index 000000000..65fc6631d
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/PulseIn.c
@@ -0,0 +1,75 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+ *
+ * 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 "common-hal/pulseio/PulseIn.h"
+#include "py/runtime.h"
+
+// STATIC void pulsein_handler(uint8_t num) {
+// }
+
+void pulsein_reset(void) {
+}
+
+void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
+ uint16_t maxlen, bool idle_state) {
+ mp_raise_NotImplementedError(translate("PulseIn not supported on this chip"));
+}
+
+bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
+ return false;
+}
+
+void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
+}
+
+void common_hal_pulseio_pulsein_pause(pulseio_pulsein_obj_t* self) {
+}
+
+void common_hal_pulseio_pulsein_resume(pulseio_pulsein_obj_t* self, uint16_t trigger_duration) {
+}
+
+void common_hal_pulseio_pulsein_clear(pulseio_pulsein_obj_t* self) {
+}
+
+uint16_t common_hal_pulseio_pulsein_get_item(pulseio_pulsein_obj_t* self, int16_t index) {
+ return false;
+}
+
+uint16_t common_hal_pulseio_pulsein_popleft(pulseio_pulsein_obj_t* self) {
+ return false;
+}
+
+uint16_t common_hal_pulseio_pulsein_get_maxlen(pulseio_pulsein_obj_t* self) {
+ return false;
+}
+
+bool common_hal_pulseio_pulsein_get_paused(pulseio_pulsein_obj_t* self) {
+ return false;
+}
+
+uint16_t common_hal_pulseio_pulsein_get_len(pulseio_pulsein_obj_t* self) {
+ return false;
+}
diff --git a/ports/esp32s2/common-hal/pulseio/PulseIn.h b/ports/esp32s2/common-hal/pulseio/PulseIn.h
new file mode 100644
index 000000000..b317c516c
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/PulseIn.h
@@ -0,0 +1,53 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * 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_ESP32S2_COMMON_HAL_PULSEIO_PULSEIN_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEIN_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+
+ const mcu_pin_obj_t* pin;
+ bool idle_state;
+ bool paused;
+ volatile bool first_edge;
+
+ uint16_t* buffer;
+ uint16_t maxlen;
+
+ volatile uint16_t start;
+ volatile uint16_t len;
+ volatile uint32_t last_overflow;
+ volatile uint16_t last_count;
+} pulseio_pulsein_obj_t;
+
+void pulsein_reset(void);
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEIN_H
diff --git a/ports/esp32s2/common-hal/pulseio/PulseOut.c b/ports/esp32s2/common-hal/pulseio/PulseOut.c
new file mode 100644
index 000000000..c448c578d
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/PulseOut.c
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * 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 "common-hal/pulseio/PulseOut.h"
+
+#include "shared-bindings/pulseio/PWMOut.h"
+#include "py/runtime.h"
+
+// STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
+// }
+
+// STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) {
+// }
+
+// STATIC void start_timer(void) {
+// }
+
+// STATIC void pulseout_event_handler(void) {
+// }
+
+void pulseout_reset() {
+}
+
+void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
+ const pulseio_pwmout_obj_t* carrier) {
+ mp_raise_NotImplementedError(translate("PulseOut not supported on this chip"));
+}
+
+bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) {
+ return false;
+}
+
+void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) {
+}
+
+void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pulses, uint16_t length) {
+}
diff --git a/ports/esp32s2/common-hal/pulseio/PulseOut.h b/ports/esp32s2/common-hal/pulseio/PulseOut.h
new file mode 100644
index 000000000..f465d0079
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/PulseOut.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+ *
+ * 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_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H
+#define MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/pulseio/PWMOut.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ pulseio_pwmout_obj_t *pwmout;
+} pulseio_pulseout_obj_t;
+
+void pulseout_reset(void);
+
+#endif // MICROPY_INCLUDED_ESP32S2_COMMON_HAL_PULSEIO_PULSEOUT_H
diff --git a/ports/esp32s2/common-hal/pulseio/__init__.c b/ports/esp32s2/common-hal/pulseio/__init__.c
new file mode 100644
index 000000000..2bee925bc
--- /dev/null
+++ b/ports/esp32s2/common-hal/pulseio/__init__.c
@@ -0,0 +1 @@
+// No pulseio module functions.
diff --git a/ports/esp32s2/fatfs_port.c b/ports/esp32s2/fatfs_port.c
index 13ac21fb1..8bdc047c1 100644
--- a/ports/esp32s2/fatfs_port.c
+++ b/ports/esp32s2/fatfs_port.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/esp32s2/modules/wroom.c b/ports/esp32s2/modules/wroom.c
index 16c586118..5e530701b 100644
--- a/ports/esp32s2/modules/wroom.c
+++ b/ports/esp32s2/modules/wroom.c
@@ -28,10 +28,10 @@
void never_reset_module_internal_pins(void) {
// SPI Flash
- never_reset_pin(&pin_GPIO27);
- never_reset_pin(&pin_GPIO28);
- never_reset_pin(&pin_GPIO29);
- never_reset_pin(&pin_GPIO30);
- never_reset_pin(&pin_GPIO31);
- never_reset_pin(&pin_GPIO32);
+ common_hal_never_reset_pin(&pin_GPIO27);
+ common_hal_never_reset_pin(&pin_GPIO28);
+ common_hal_never_reset_pin(&pin_GPIO29);
+ common_hal_never_reset_pin(&pin_GPIO30);
+ common_hal_never_reset_pin(&pin_GPIO31);
+ common_hal_never_reset_pin(&pin_GPIO32);
}
diff --git a/ports/esp32s2/modules/wrover.c b/ports/esp32s2/modules/wrover.c
index d589a8fd4..23fa7ee5c 100644
--- a/ports/esp32s2/modules/wrover.c
+++ b/ports/esp32s2/modules/wrover.c
@@ -28,11 +28,11 @@
void never_reset_module_internal_pins(void) {
// SPI Flash and RAM
- never_reset_pin(&pin_GPIO26);
- never_reset_pin(&pin_GPIO27);
- never_reset_pin(&pin_GPIO28);
- never_reset_pin(&pin_GPIO29);
- never_reset_pin(&pin_GPIO30);
- never_reset_pin(&pin_GPIO31);
- never_reset_pin(&pin_GPIO32);
+ common_hal_never_reset_pin(&pin_GPIO26);
+ common_hal_never_reset_pin(&pin_GPIO27);
+ common_hal_never_reset_pin(&pin_GPIO28);
+ common_hal_never_reset_pin(&pin_GPIO29);
+ common_hal_never_reset_pin(&pin_GPIO30);
+ common_hal_never_reset_pin(&pin_GPIO31);
+ common_hal_never_reset_pin(&pin_GPIO32);
}
diff --git a/ports/esp32s2/mpconfigport.mk b/ports/esp32s2/mpconfigport.mk
index ad2310539..c2d21e084 100644
--- a/ports/esp32s2/mpconfigport.mk
+++ b/ports/esp32s2/mpconfigport.mk
@@ -7,7 +7,7 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
INTERNAL_LIBM = 1
# Chip supplied serial number, in bytes
-USB_SERIAL_NUMBER_LENGTH = 30
+USB_SERIAL_NUMBER_LENGTH = 12
# Longints can be implemented as mpz, as longlong, or not
LONGINT_IMPL = MPZ
@@ -16,16 +16,16 @@ CIRCUITPY_FULL_BUILD = 0
CIRCUITPY_ANALOGIO = 0
CIRCUITPY_AUDIOBUSIO = 0
CIRCUITPY_AUDIOIO = 0
-CIRCUITPY_BITBANGIO = 0
+CIRCUITPY_BITBANGIO = 1
CIRCUITPY_BOARD = 1
CIRCUITPY_DIGITALIO = 1
-CIRCUITPY_BUSIO = 0
-CIRCUITPY_DISPLAYIO = 0
+CIRCUITPY_BUSIO = 1
+CIRCUITPY_DISPLAYIO = 1
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CPERIPHERAL = 0
CIRCUITPY_MICROCONTROLLER = 1
CIRCUITPY_NVM = 0
-CIRCUITPY_PULSEIO = 0
+CIRCUITPY_PULSEIO = 1
CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
CIRCUITPY_TOUCHIO = 0
diff --git a/ports/esp32s2/mphalport.c b/ports/esp32s2/mphalport.c
index da5258b0e..e1662a6ce 100644
--- a/ports/esp32s2/mphalport.c
+++ b/ports/esp32s2/mphalport.c
@@ -32,9 +32,10 @@
#include "py/gc.h"
#include "esp-idf/components/xtensa/include/esp_debug_helpers.h"
+#include "esp-idf/components/esp_rom/include/esp32s2/rom/ets_sys.h"
void mp_hal_delay_us(mp_uint_t delay) {
- mp_hal_delay_ms(delay / 1000);
+ ets_delay_us(delay);
}
// This is provided by the esp-idf/components/xtensa/esp32s2/libhal.a binary
diff --git a/ports/esp32s2/sdkconfig.defaults b/ports/esp32s2/sdkconfig.defaults
index 958e1852e..729ebac88 100644
--- a/ports/esp32s2/sdkconfig.defaults
+++ b/ports/esp32s2/sdkconfig.defaults
@@ -190,9 +190,9 @@ CONFIG_EFUSE_MAX_BLK_LEN=256
# ESP32S2-specific
#
# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_80 is not set
-CONFIG_ESP32S2_DEFAULT_CPU_FREQ_160=y
-# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240 is not set
-CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=160
+# CONFIG_ESP32S2_DEFAULT_CPU_FREQ_160 is not set
+CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y
+CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=240
#
# Memory protection
@@ -271,10 +271,7 @@ CONFIG_ESP_CONSOLE_UART_RX_GPIO=3
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
CONFIG_ESP_INT_WDT=y
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
-CONFIG_ESP_TASK_WDT=y
-# CONFIG_ESP_TASK_WDT_PANIC is not set
-CONFIG_ESP_TASK_WDT_TIMEOUT_S=5
-CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
+# CONFIG_ESP_TASK_WDT is not set
CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y
CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y
# end of Common ESP-related
@@ -528,6 +525,7 @@ CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
CONFIG_MBEDTLS_SSL_IN_CONTENT_LEN=16384
CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096
+# CONFIG_MBEDTLS_DYNAMIC_BUFFER is not set
# CONFIG_MBEDTLS_DEBUG is not set
#
@@ -547,8 +545,12 @@ CONFIG_MBEDTLS_AES_USE_INTERRUPT=y
CONFIG_MBEDTLS_HARDWARE_GCM=y
CONFIG_MBEDTLS_HARDWARE_MPI=y
CONFIG_MBEDTLS_HARDWARE_SHA=y
+# CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set
+# CONFIG_MBEDTLS_ATCA_HW_ECDSA_VERIFY is not set
CONFIG_MBEDTLS_HAVE_TIME=y
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
+CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y
+CONFIG_MBEDTLS_SHA512_C=y
CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
# CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set
# CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set
@@ -627,6 +629,10 @@ CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
+# CONFIG_MBEDTLS_POLY1305_C is not set
+# CONFIG_MBEDTLS_CHACHA20_C is not set
+# CONFIG_MBEDTLS_HKDF_C is not set
+# CONFIG_MBEDTLS_THREADING_C is not set
# CONFIG_MBEDTLS_SECURITY_RISKS is not set
# end of mbedTLS
@@ -705,6 +711,7 @@ CONFIG_WPA_MBEDTLS_CRYPTO=y
# CONFIG_WPA_DEBUG_PRINT is not set
# CONFIG_WPA_TESTING_OPTIONS is not set
# CONFIG_WPA_TLS_V12 is not set
+# CONFIG_WPA_WPS_WARS is not set
# end of Supplicant
# end of Component config
@@ -756,7 +763,7 @@ CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
CONFIG_ADC2_DISABLE_DAC=y
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
-CONFIG_MAIN_TASK_STACK_SIZE=3584
+CONFIG_MAIN_TASK_STACK_SIZE=8192
CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_CONSOLE_UART_DEFAULT=y
# CONFIG_CONSOLE_UART_CUSTOM is not set
@@ -767,10 +774,7 @@ CONFIG_CONSOLE_UART_RX_GPIO=3
CONFIG_CONSOLE_UART_BAUDRATE=115200
CONFIG_INT_WDT=y
CONFIG_INT_WDT_TIMEOUT_MS=300
-CONFIG_TASK_WDT=y
-# CONFIG_TASK_WDT_PANIC is not set
-CONFIG_TASK_WDT_TIMEOUT_S=5
-CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
+# CONFIG_TASK_WDT is not set
# CONFIG_EVENT_LOOP_PROFILING is not set
CONFIG_POST_EVENTS_FROM_ISR=y
CONFIG_POST_EVENTS_FROM_IRAM_ISR=y
diff --git a/ports/esp32s2/supervisor/internal_flash.c b/ports/esp32s2/supervisor/internal_flash.c
index a8d3fa485..26774efac 100644
--- a/ports/esp32s2/supervisor/internal_flash.c
+++ b/ports/esp32s2/supervisor/internal_flash.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -39,11 +39,6 @@
#include "esp-idf/components/spi_flash/include/esp_partition.h"
-#include "esp_log.h"
-
-
-static const char* TAG = "CircuitPython Internal Flash";
-
#include "supervisor/usb.h"
STATIC const esp_partition_t * _partition;
@@ -52,8 +47,6 @@ void supervisor_flash_init(void) {
_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
ESP_PARTITION_SUBTYPE_DATA_FAT,
NULL);
-
- ESP_EARLY_LOGW(TAG, "fatfs partition %p", _partition);
}
uint32_t supervisor_flash_get_block_size(void) {
@@ -74,11 +67,10 @@ STATIC uint8_t _cache[SECTOR_SIZE];
STATIC uint32_t _cache_lba;
mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) {
- esp_err_t ok = esp_partition_read(_partition,
- block * FILESYSTEM_BLOCK_SIZE,
- dest,
- num_blocks * FILESYSTEM_BLOCK_SIZE);
- ESP_EARLY_LOGW(TAG, "read %d", ok);
+ esp_partition_read(_partition,
+ block * FILESYSTEM_BLOCK_SIZE,
+ dest,
+ num_blocks * FILESYSTEM_BLOCK_SIZE);
return 0;
}
@@ -90,13 +82,11 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
uint32_t sector_offset = block_address / blocks_per_sector * SECTOR_SIZE;
uint8_t block_offset = block_address % blocks_per_sector;
- esp_err_t result;
if (_cache_lba != block_address) {
- result = esp_partition_read(_partition,
- sector_offset,
- _cache,
- SECTOR_SIZE);
- ESP_EARLY_LOGW(TAG, "flash read before write %d", result);
+ esp_partition_read(_partition,
+ sector_offset,
+ _cache,
+ SECTOR_SIZE);
_cache_lba = sector_offset;
}
for (uint8_t b = block_offset; b < blocks_per_sector; b++) {
@@ -109,11 +99,11 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
FILESYSTEM_BLOCK_SIZE);
block++;
}
- result = esp_partition_erase_range(_partition, sector_offset, SECTOR_SIZE);
- result = esp_partition_write(_partition,
- sector_offset,
- _cache,
- SECTOR_SIZE);
+ esp_partition_erase_range(_partition, sector_offset, SECTOR_SIZE);
+ esp_partition_write(_partition,
+ sector_offset,
+ _cache,
+ SECTOR_SIZE);
}
return 0; // success
diff --git a/ports/esp32s2/supervisor/internal_flash.h b/ports/esp32s2/supervisor/internal_flash.h
index e06ef2d16..02d519003 100644
--- a/ports/esp32s2/supervisor/internal_flash.h
+++ b/ports/esp32s2/supervisor/internal_flash.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/esp32s2/supervisor/port.c b/ports/esp32s2/supervisor/port.c
index 2437b4f34..e4767e514 100644
--- a/ports/esp32s2/supervisor/port.c
+++ b/ports/esp32s2/supervisor/port.c
@@ -35,13 +35,13 @@
#include "freertos/task.h"
#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/busio/I2C.h"
+#include "common-hal/busio/SPI.h"
+#include "common-hal/busio/UART.h"
+#include "common-hal/pulseio/PWMOut.h"
#include "supervisor/memory.h"
#include "supervisor/shared/tick.h"
-#include "esp_log.h"
-
-static const char* TAG = "CircuitPython";
-
STATIC esp_timer_handle_t _tick_timer;
void tick_timer_cb(void* arg) {
@@ -54,18 +54,25 @@ safe_mode_t port_init(void) {
args.arg = NULL;
args.dispatch_method = ESP_TIMER_TASK;
args.name = "CircuitPython Tick";
- esp_err_t result = esp_timer_create(&args, &_tick_timer);
- if (result != ESP_OK) {
- ESP_EARLY_LOGE(TAG, "Unable to create tick timer.");
- }
+ esp_timer_create(&args, &_tick_timer);
never_reset_module_internal_pins();
- ESP_EARLY_LOGW(TAG, "port init done");
return NO_SAFE_MODE;
}
void reset_port(void) {
-
reset_all_pins();
+
+ // A larger delay so the idle task can run and do any IDF cleanup needed.
+ vTaskDelay(4);
+
+#if CIRCUITPY_PULSEIO
+ pwmout_reset();
+#endif
+#if CIRCUITPY_BUSIO
+ i2c_reset();
+ spi_reset();
+ uart_reset();
+#endif
}
void reset_to_bootloader(void) {
@@ -98,12 +105,8 @@ uint32_t *port_stack_get_top(void) {
supervisor_allocation _fixed_stack;
supervisor_allocation* port_fixed_stack(void) {
-
- ESP_EARLY_LOGW(TAG, "port fixed stack");
_fixed_stack.ptr = port_stack_get_limit();
- ESP_EARLY_LOGW(TAG, "got limit %p", _fixed_stack.ptr);
_fixed_stack.length = (port_stack_get_top() - port_stack_get_limit()) * sizeof(uint32_t);
- ESP_EARLY_LOGW(TAG, "got length %d", _fixed_stack.length);
return &_fixed_stack;
}
@@ -128,10 +131,7 @@ uint64_t port_get_raw_ticks(uint8_t* subticks) {
// Enable 1/1024 second tick.
void port_enable_tick(void) {
- esp_err_t result = esp_timer_start_periodic(_tick_timer, 1000000 / 1024);
- if (result != ESP_OK) {
- ESP_EARLY_LOGE(TAG, "Unable to start tick timer.");
- }
+ esp_timer_start_periodic(_tick_timer, 1000000 / 1024);
}
// Disable 1/1024 second tick.
@@ -142,14 +142,12 @@ void port_disable_tick(void) {
TickType_t sleep_time_set;
TickType_t sleep_time_duration;
void port_interrupt_after_ticks(uint32_t ticks) {
- // ESP_EARLY_LOGW(TAG, "after ticks");
sleep_time_set = xTaskGetTickCount();
sleep_time_duration = ticks / portTICK_PERIOD_MS;
// esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
}
void port_sleep_until_interrupt(void) {
- // ESP_EARLY_LOGW(TAG, "sleep until");
// FreeRTOS delay here maybe.
// Light sleep shuts down BLE and wifi.
// esp_light_sleep_start()
@@ -163,8 +161,5 @@ void port_sleep_until_interrupt(void) {
// Wrap main in app_main that the IDF expects.
extern void main(void);
void app_main(void) {
- ESP_EARLY_LOGW(TAG, "Hello from CircuitPython");
- // ESP_LOGW(TAG, "Hello from CircuitPython");
-
main();
}
diff --git a/ports/litex/Makefile b/ports/litex/Makefile
index d75a4da28..612953daa 100644
--- a/ports/litex/Makefile
+++ b/ports/litex/Makefile
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2019 Scott Shawcroft for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -77,12 +77,17 @@ ifeq ($(DEBUG), 1)
CFLAGS += -ggdb
# You may want to enable these flags to make setting breakpoints easier.
CFLAGS += -fno-inline -fno-ipa-sra
+ OPTIMIZATION_FLAGS ?= -Og
else
- CFLAGS += -Os -DNDEBUG -ggdb3
+ CFLAGS += -DNDEBUG -ggdb3
+ OPTIMIZATION_FLAGS ?= -O2
# TODO: Test with -flto
### CFLAGS += -flto
endif
+# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS)
+
CFLAGS += $(INC) -Werror -Wall -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(C_DEFS) $(CFLAGS_MOD) $(COPT)
# TODO: check this
diff --git a/ports/litex/background.c b/ports/litex/background.c
index b1b765536..174d9588a 100644
--- a/ports/litex/background.c
+++ b/ports/litex/background.c
@@ -29,37 +29,6 @@
#include "supervisor/usb.h"
#include "supervisor/shared/stack.h"
-#if CIRCUITPY_DISPLAYIO
-#include "shared-module/displayio/__init__.h"
-#endif
-
-static bool running_background_tasks = false;
-
-void background_tasks_reset(void) {
- running_background_tasks = false;
-}
-
-void run_background_tasks(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
- running_background_tasks = true;
- filesystem_background();
-
-#if USB_AVAILABLE
- usb_background();
-#endif
-
-#if CIRCUITPY_BLEIO
- bleio_background();
-#endif
-
-#if CIRCUITPY_DISPLAYIO
- displayio_background();
-#endif
-
- running_background_tasks = false;
-
- assert_heap_ok();
-}
+void port_background_task(void) {}
+void port_start_background_task(void) {}
+void port_finish_background_task(void) {}
diff --git a/ports/litex/background.h b/ports/litex/background.h
index 09551c7fb..c80fbbe5c 100644
--- a/ports/litex/background.h
+++ b/ports/litex/background.h
@@ -27,9 +27,4 @@
#ifndef MICROPY_INCLUDED_LITEX_BACKGROUND_H
#define MICROPY_INCLUDED_LITEX_BACKGROUND_H
-#include <stdbool.h>
-
-void background_tasks_reset(void);
-void run_background_tasks(void);
-
#endif // MICROPY_INCLUDED_LITEX_BACKGROUND_H
diff --git a/ports/litex/common-hal/digitalio/DigitalInOut.c b/ports/litex/common-hal/digitalio/DigitalInOut.c
index 26f79f16d..53df637c4 100644
--- a/ports/litex/common-hal/digitalio/DigitalInOut.c
+++ b/ports/litex/common-hal/digitalio/DigitalInOut.c
@@ -46,7 +46,7 @@ digitalinout_result_t common_hal_digitalio_digitalinout_construct(
}
bool common_hal_digitalio_digitalinout_deinited(digitalio_digitalinout_obj_t *self) {
- return self->pin == mp_const_none;
+ return self->pin == NULL;
}
void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self) {
@@ -55,7 +55,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t *self
}
// reset_pin_number(0, self->pin->number);
- self->pin = mp_const_none;
+ self->pin = NULL;
}
void common_hal_digitalio_digitalinout_switch_to_input(
diff --git a/ports/litex/common-hal/microcontroller/Pin.c b/ports/litex/common-hal/microcontroller/Pin.c
index 632468f6d..38601e0d3 100644
--- a/ports/litex/common-hal/microcontroller/Pin.c
+++ b/ports/litex/common-hal/microcontroller/Pin.c
@@ -41,12 +41,19 @@ void reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
claimed_pins[pin_port] &= ~(1<<pin_number);
}
+void common_hal_reset_pin(const mcu_pin_obj_t* pin) {
+ reset_pin_number(0, pin->number);
+}
void claim_pin(const mcu_pin_obj_t* pin) {
// Set bit in claimed_pins bitmask.
claimed_pins[0] |= 1<<pin->number;
}
+void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) {
+ claim_pin(pin);
+}
+
bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) {
return !(claimed_pins[pin_port] & 1<<pin_number);
}
diff --git a/ports/litex/fatfs_port.c b/ports/litex/fatfs_port.c
index 13ac21fb1..8bdc047c1 100644
--- a/ports/litex/fatfs_port.c
+++ b/ports/litex/fatfs_port.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/litex/mpconfigport.mk b/ports/litex/mpconfigport.mk
index 311c87b5d..427e9ea84 100644
--- a/ports/litex/mpconfigport.mk
+++ b/ports/litex/mpconfigport.mk
@@ -18,6 +18,7 @@ CIRCUITPY_AUDIOIO = 0
CIRCUITPY_BITBANGIO = 0
CIRCUITPY_BOARD = 0
CIRCUITPY_BUSIO = 0
+CIRCUITPY_COUNTIO = 0
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CIRCUITPY_I2CPERIPHERAL = 0
@@ -25,7 +26,7 @@ CIRCUITPY_NVM = 0
CIRCUITPY_PULSEIO = 0
CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 0
-CIRCUITPY_COUNTIO = 0
+CIRCUITPY_SDCARDIO = 0
# Enable USB support
CIRCUITPY_USB_HID = 1
CIRCUITPY_USB_MIDI = 1
diff --git a/ports/litex/mphalport.c b/ports/litex/mphalport.c
index 84a546795..862f16393 100644
--- a/ports/litex/mphalport.c
+++ b/ports/litex/mphalport.c
@@ -31,6 +31,7 @@
#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/gc.h"
+#include "supervisor/usb.h"
#include "csr.h"
#include "generated/soc.h"
@@ -49,7 +50,7 @@ void isr(void) {
#ifdef CFG_TUSB_MCU
if (irqs & (1 << USB_INTERRUPT))
- tud_int_handler(0);
+ usb_irq_handler();
#endif
if (irqs & (1 << TIMER0_INTERRUPT))
SysTick_Handler();
diff --git a/ports/litex/supervisor/internal_flash.c b/ports/litex/supervisor/internal_flash.c
index cf777a8ac..9b1dea685 100644
--- a/ports/litex/supervisor/internal_flash.c
+++ b/ports/litex/supervisor/internal_flash.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/litex/supervisor/internal_flash.h b/ports/litex/supervisor/internal_flash.h
index 41a69e2ab..1498207d3 100644
--- a/ports/litex/supervisor/internal_flash.h
+++ b/ports/litex/supervisor/internal_flash.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/mimxrt10xx/Makefile b/ports/mimxrt10xx/Makefile
index 78cab0188..248798f63 100644
--- a/ports/mimxrt10xx/Makefile
+++ b/ports/mimxrt10xx/Makefile
@@ -2,8 +2,8 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2019 Dan Halbert for Adafruit Industries
-# Copyright (c) 2019 Artur Pacholec
+# SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2019 Artur Pacholec
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -78,7 +78,7 @@ INC += \
CFLAGS += -Os -DNDEBUG
# TinyUSB defines
-CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX -DCFG_TUD_MIDI_RX_BUFSIZE=128 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_MIDI_TX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024
+CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_MIMXRT10XX -DCFG_TUD_MIDI_RX_BUFSIZE=512 -DCFG_TUD_CDC_RX_BUFSIZE=512 -DCFG_TUD_MIDI_TX_BUFSIZE=512 -DCFG_TUD_CDC_TX_BUFSIZE=512 -DCFG_TUD_MSC_BUFSIZE=1024
#Debugging/Optimization
ifeq ($(DEBUG), 1)
@@ -105,9 +105,14 @@ CFLAGS += \
-DCPU_$(CHIP_VARIANT) \
-DDEBUG \
-DIMXRT10XX \
- -Os -g3 -Wno-unused-parameter \
+ -g3 -Wno-unused-parameter \
-ffunction-sections -fdata-sections -fstack-usage
+OPTIMIZATION_FLAGS ?= -O2
+
+# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS)
+
LD_FILES = $(wildcard boards/$(BOARD)/*.ld) $(addprefix linking/, flash/$(FLASH).ld chip_family/$(CHIP_FAMILY).ld common.ld)
LD_SCRIPT_FLAG := -Wl,-T,
diff --git a/ports/mimxrt10xx/background.c b/ports/mimxrt10xx/background.c
index 550009473..a8a613d41 100644
--- a/ports/mimxrt10xx/background.c
+++ b/ports/mimxrt10xx/background.c
@@ -24,64 +24,13 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#include "background.h"
-//#include "audio_dma.h"
-#include "supervisor/filesystem.h"
-#include "supervisor/shared/tick.h"
-#include "supervisor/usb.h"
+#include "supervisor/port.h"
-#include "py/runtime.h"
-#include "shared-module/network/__init__.h"
-#include "supervisor/linker.h"
-#include "supervisor/shared/stack.h"
-
-#ifdef CIRCUITPY_DISPLAYIO
-#include "shared-module/displayio/__init__.h"
-#endif
-
-volatile uint64_t last_finished_tick = 0;
-
-bool stack_ok_so_far = true;
-
-static bool running_background_tasks = false;
-
-void background_tasks_reset(void) {
- running_background_tasks = false;
-}
-
-void PLACE_IN_ITCM(run_background_tasks)(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
- assert_heap_ok();
- running_background_tasks = true;
-
-#if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
+void port_background_task(void) {
+ #if CIRCUITPY_AUDIOIO || CIRCUITPY_AUDIOBUSIO
audio_dma_background();
-#endif
-
-#if CIRCUITPY_BLEIO
- bleio_background();
-#endif
-
-#if CIRCUITPY_DISPLAYIO
- displayio_background();
-#endif
-
-#if CIRCUITPY_NETWORK
- network_module_background();
-#endif
-
- filesystem_background();
- usb_background();
- running_background_tasks = false;
- assert_heap_ok();
-
- last_finished_tick = supervisor_ticks_ms64();
-}
-
-bool background_tasks_ok(void) {
- return supervisor_ticks_ms64() - last_finished_tick < 1000;
+ #endif
}
+void port_start_background_task(void) {}
+void port_finish_background_task(void) {}
diff --git a/ports/mimxrt10xx/background.h b/ports/mimxrt10xx/background.h
index 52789d038..a3fe102ac 100644
--- a/ports/mimxrt10xx/background.h
+++ b/ports/mimxrt10xx/background.h
@@ -28,11 +28,4 @@
#ifndef MICROPY_INCLUDED_MIMXRT10XX_BACKGROUND_H
#define MICROPY_INCLUDED_MIMXRT10XX_BACKGROUND_H
-#include <stdbool.h>
-
-void background_tasks_reset(void);
-void run_background_tasks(void);
-void run_background_vm_tasks(void);
-bool background_tasks_ok(void);
-
#endif // MICROPY_INCLUDED_MIMXRT10XX_BACKGROUND_H
diff --git a/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c b/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c
index 3d072627a..6bdbeff7c 100644
--- a/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c
+++ b/ports/mimxrt10xx/common-hal/analogio/AnalogOut.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/mimxrt10xx/common-hal/board/__init__.c b/ports/mimxrt10xx/common-hal/board/__init__.c
index e86251480..4967e1a76 100644
--- a/ports/mimxrt10xx/common-hal/board/__init__.c
+++ b/ports/mimxrt10xx/common-hal/board/__init__.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/mimxrt10xx/common-hal/busio/SPI.c b/ports/mimxrt10xx/common-hal/busio/SPI.c
index c51aef4da..8fe1b799d 100644
--- a/ports/mimxrt10xx/common-hal/busio/SPI.c
+++ b/ports/mimxrt10xx/common-hal/busio/SPI.c
@@ -321,7 +321,7 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
return (status == kStatus_Success);
}
-bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
if (len == 0) {
return true;
}
@@ -332,7 +332,7 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
LPSPI_SetDummyData(self->spi, 0xFF);
lpspi_transfer_t xfer = { 0 };
- xfer.txData = data_out;
+ xfer.txData = (uint8_t *)data_out;
xfer.rxData = data_in;
xfer.dataSize = len;
diff --git a/ports/mimxrt10xx/common-hal/busio/UART.c b/ports/mimxrt10xx/common-hal/busio/UART.c
index 5ef347e59..db5582d15 100644
--- a/ports/mimxrt10xx/common-hal/busio/UART.c
+++ b/ports/mimxrt10xx/common-hal/busio/UART.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -85,7 +85,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
- uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
bool sigint_enabled) {
@@ -94,7 +94,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
self->timeout_ms = timeout * 1000;
// We are transmitting one direction if one pin is NULL and the other isn't.
- bool is_onedirection = (rx != NULL) != (tx != NULL);
+ bool is_onedirection = (rx == NULL) != (tx == NULL);
bool uart_taken = false;
const uint32_t rx_count = MP_ARRAY_SIZE(mcu_uart_rx_list);
diff --git a/ports/mimxrt10xx/common-hal/pulseio/PWMOut.c b/ports/mimxrt10xx/common-hal/pulseio/PWMOut.c
index c75b75316..50dd477ea 100644
--- a/ports/mimxrt10xx/common-hal/pulseio/PWMOut.c
+++ b/ports/mimxrt10xx/common-hal/pulseio/PWMOut.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c
index d8bf2017e..ec0290861 100644
--- a/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c
+++ b/ports/mimxrt10xx/common-hal/pulseio/PulseIn.c
@@ -64,7 +64,7 @@
// // last ms.
// current_us = 1000 - current_us;
// pulseio_pulsein_obj_t* self = get_eic_channel_data(channel);
-// if (!background_tasks_ok() || self->errored_too_fast) {
+// if (!supervisor_background_tasks_ok() || self->errored_too_fast) {
// self->errored_too_fast = true;
// common_hal_pulseio_pulsein_pause(self);
// return;
diff --git a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c b/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c
index a49cfa7af..ffa885688 100644
--- a/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c
+++ b/ports/mimxrt10xx/common-hal/pulseio/PulseOut.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/mimxrt10xx/fatfs_port.c b/ports/mimxrt10xx/fatfs_port.c
index c4ce18c2a..c65a73a42 100644
--- a/ports/mimxrt10xx/fatfs_port.c
+++ b/ports/mimxrt10xx/fatfs_port.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/mimxrt10xx/mpconfigport.mk b/ports/mimxrt10xx/mpconfigport.mk
index 12f34343b..b4cc9586a 100644
--- a/ports/mimxrt10xx/mpconfigport.mk
+++ b/ports/mimxrt10xx/mpconfigport.mk
@@ -15,7 +15,7 @@ endif
INTERNAL_LIBM = 1
USB_SERIAL_NUMBER_LENGTH = 32
-USB_MSC_MAX_PACKET_SIZE = 512
+USB_HIGHSPEED = 1
INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/mimxrt10xx/supervisor/internal_flash.c b/ports/mimxrt10xx/supervisor/internal_flash.c
index 9abd15e60..09f44cced 100644
--- a/ports/mimxrt10xx/supervisor/internal_flash.c
+++ b/ports/mimxrt10xx/supervisor/internal_flash.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/mimxrt10xx/supervisor/internal_flash.h b/ports/mimxrt10xx/supervisor/internal_flash.h
index dfbfe1d4b..daee66620 100644
--- a/ports/mimxrt10xx/supervisor/internal_flash.h
+++ b/ports/mimxrt10xx/supervisor/internal_flash.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/mimxrt10xx/supervisor/usb.c b/ports/mimxrt10xx/supervisor/usb.c
index 1bc7ea9b5..af259405a 100644
--- a/ports/mimxrt10xx/supervisor/usb.c
+++ b/ports/mimxrt10xx/supervisor/usb.c
@@ -27,6 +27,7 @@
#include "fsl_clock.h"
#include "tusb.h"
+#include "supervisor/usb.h"
void init_usb_hardware(void) {
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
@@ -56,5 +57,5 @@ void init_usb_hardware(void) {
}
void USB_OTG1_IRQHandler(void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile
index 5b81fa9a7..13a148df3 100755
--- a/ports/nrf/Makefile
+++ b/ports/nrf/Makefile
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2019 Dan Halbert for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -86,12 +86,16 @@ INC += -I../../supervisor/shared/usb
#Debugging/Optimization
ifeq ($(DEBUG), 1)
- CFLAGS += -ggdb3 -Og
+ CFLAGS += -ggdb3
+ OPTIMIZATION_FLAGS = -Og
else
- CFLAGS += -Os -DNDEBUG -ggdb3
+ OPTIMIZATION_FLAGS ?= -O2
+ CFLAGS += -DNDEBUG -ggdb3
CFLAGS += -flto -flto-partition=none
endif
+# option to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS)
CFLAGS += $(INC) -Wall -Werror -std=gnu11 -nostdlib -fshort-enums $(BASE_CFLAGS) $(CFLAGS_MOD) $(COPT)
diff --git a/ports/nrf/background.c b/ports/nrf/background.c
index faaf80b6c..10543ddb2 100644
--- a/ports/nrf/background.c
+++ b/ports/nrf/background.c
@@ -46,35 +46,14 @@
#include "common-hal/_bleio/bonding.h"
#endif
-static bool running_background_tasks = false;
+void port_start_background_task(void) {}
+void port_finish_background_task(void) {}
-void background_tasks_reset(void) {
- running_background_tasks = false;
-}
-
-void run_background_tasks(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
- running_background_tasks = true;
- filesystem_background();
- usb_background();
+void port_background_task(void) {
#if CIRCUITPY_AUDIOPWMIO
audiopwmout_background();
#endif
#if CIRCUITPY_AUDIOBUSIO
i2s_background();
#endif
-
-#if CIRCUITPY_BLEIO
- bleio_background();
-#endif
-
- #if CIRCUITPY_DISPLAYIO
- displayio_background();
- #endif
- running_background_tasks = false;
-
- assert_heap_ok();
}
diff --git a/ports/nrf/background.h b/ports/nrf/background.h
index d53681c0f..64a768cf9 100644
--- a/ports/nrf/background.h
+++ b/ports/nrf/background.h
@@ -27,9 +27,4 @@
#ifndef MICROPY_INCLUDED_NRF_BACKGROUND_H
#define MICROPY_INCLUDED_NRF_BACKGROUND_H
-#include <stdbool.h>
-
-void background_tasks_reset(void);
-void run_background_tasks(void);
-
#endif // MICROPY_INCLUDED_NRF_BACKGROUND_H
diff --git a/ports/nrf/boards/bless_dev_board_multi_sensor/board.c b/ports/nrf/boards/bless_dev_board_multi_sensor/board.c
new file mode 100644
index 000000000..71b9a0657
--- /dev/null
+++ b/ports/nrf/boards/bless_dev_board_multi_sensor/board.c
@@ -0,0 +1,12 @@
+#include "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.h b/ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.h
new file mode 100644
index 000000000..7fffd86cc
--- /dev/null
+++ b/ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.h
@@ -0,0 +1,17 @@
+#include "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "BLE-SS dev board Multi Sensor"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+#define MICROPY_HW_LED_STATUS (&pin_P0_07)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_26)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_24)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_13) /* n.c */
+#define DEFAULT_SPI_BUS_MOSI (&pin_P0_14) /* n.c */
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_15) /* n.c */
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_02) /* TP7 */
+#define DEFAULT_UART_BUS_TX (&pin_P0_03) /* TP6 */
+
+/* Note: Flash chip is not provided. */
diff --git a/ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.mk b/ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.mk
new file mode 100644
index 000000000..90b090850
--- /dev/null
+++ b/ports/nrf/boards/bless_dev_board_multi_sensor/mpconfigboard.mk
@@ -0,0 +1,8 @@
+USB_VID = 0x2786
+USB_PID = 0x9207
+USB_PRODUCT = "BLE-SS dev board Multi Sensor"
+USB_MANUFACTURER = "Switch Science, Inc."
+
+MCU_CHIP = nrf52840
+
+INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/nrf/boards/bless_dev_board_multi_sensor/pins.c b/ports/nrf/boards/bless_dev_board_multi_sensor/pins.c
new file mode 100644
index 000000000..c6010a8c3
--- /dev/null
+++ b/ports/nrf/boards/bless_dev_board_multi_sensor/pins.c
@@ -0,0 +1,45 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_02) }, // TP7
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P0_03) }, // TP6
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P0_04) }, // LED1
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P0_05) }, // U2-BMX055-INT1
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_06) }, // U2-BMX055-DRDYM
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_07) }, // LED2
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P0_08) }, // U4-HDC2010-DRDY/INT
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_09) }, // TP1
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_10) }, // U3-LPS22HB-INT_DRDY
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_12) }, // S2
+ { MP_ROM_QSTR(MP_QSTR_D23), MP_ROM_PTR(&pin_P0_23) }, // BZ1
+ { MP_ROM_QSTR(MP_QSTR_D28), MP_ROM_PTR(&pin_P0_28) }, // U2-BMX055-INT4
+ { MP_ROM_QSTR(MP_QSTR_D29), MP_ROM_PTR(&pin_P0_29) }, // U2-BMX055-INT3
+ { MP_ROM_QSTR(MP_QSTR_D30), MP_ROM_PTR(&pin_P0_30) }, // U2-BMX055-INT5
+ { MP_ROM_QSTR(MP_QSTR_D31), MP_ROM_PTR(&pin_P0_31) }, // S1
+
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_02) }, // A0/TP7
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_03) }, // A1/TP6
+
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_24) }, // 24 - SDA
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_26) }, // 26 - SCL
+
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_13) }, // 13 - MISO (n.c)
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_14) }, // 14 - MOSI (n.c)
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_15) }, // 15 - SCK (n.c)
+
+ { MP_ROM_QSTR(MP_QSTR_LED1), MP_ROM_PTR(&pin_P0_07) }, // 4 - LED1
+ { MP_ROM_QSTR(MP_QSTR_LED2), MP_ROM_PTR(&pin_P0_04) }, // 7 - LED2
+
+ { MP_ROM_QSTR(MP_QSTR_BUTTON1), MP_ROM_PTR(&pin_P0_31) }, // 31 - S1
+ { MP_ROM_QSTR(MP_QSTR_BUTTON2), MP_ROM_PTR(&pin_P0_12) }, // 12 - S2
+
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_02) }, // 2 - UART RX
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_03) }, // 3 - UART TX
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_QWIIC), MP_ROM_PTR(&board_i2c_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/ikigaisense_vita/board.c b/ports/nrf/boards/ikigaisense_vita/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/ikigaisense_vita/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h b/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h
new file mode 100644
index 000000000..14798aeee
--- /dev/null
+++ b/ports/nrf/boards/ikigaisense_vita/mpconfigboard.h
@@ -0,0 +1,20 @@
+#include "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "IkigaiSense Vita nRF52840"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+
+#define MICROPY_HW_LED_STATUS (&pin_P0_27)
+
+#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE (4096)
+
+#define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_08)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_04)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_24)
+#define DEFAULT_UART_BUS_TX (&pin_P0_22)
diff --git a/ports/nrf/boards/ikigaisense_vita/mpconfigboard.mk b/ports/nrf/boards/ikigaisense_vita/mpconfigboard.mk
new file mode 100644
index 000000000..28bdee952
--- /dev/null
+++ b/ports/nrf/boards/ikigaisense_vita/mpconfigboard.mk
@@ -0,0 +1,8 @@
+USB_VID = 0x239A
+USB_PID = 0x8094
+USB_PRODUCT = "IkigaiSense Vita nRF52840"
+USB_MANUFACTURER = "IkigaiSense Technologies LTD"
+
+MCU_CHIP = nrf52840
+
+INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/nrf/boards/ikigaisense_vita/pins.c b/ports/nrf/boards/ikigaisense_vita/pins.c
new file mode 100644
index 000000000..021f94f30
--- /dev/null
+++ b/ports/nrf/boards/ikigaisense_vita/pins.c
@@ -0,0 +1,36 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P1_15) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P1_13) },
+
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_22) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P0_17) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_22) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_04) },
+
+ { MP_ROM_QSTR(MP_QSTR_MAXTEMP_SCL), MP_ROM_PTR(&pin_P0_31) },
+ { MP_ROM_QSTR(MP_QSTR_MAXTEMP_SDA), MP_ROM_PTR(&pin_P0_30) },
+
+ { MP_ROM_QSTR(MP_QSTR_ACC_SCL), MP_ROM_PTR(&pin_P1_11) },
+ { MP_ROM_QSTR(MP_QSTR_ACC_SDA), MP_ROM_PTR(&pin_P1_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_ADDON_SCL), MP_ROM_PTR(&pin_P1_09) },
+ { MP_ROM_QSTR(MP_QSTR_ADDON_SDA), MP_ROM_PTR(&pin_P0_06) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_YELLOW_LED), MP_ROM_PTR(&pin_P0_27) },
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/README.md b/ports/nrf/boards/makerdiary_m60_keyboard/README.md
new file mode 100644
index 000000000..04486ba21
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_m60_keyboard/README.md
@@ -0,0 +1,4 @@
+# Makerdiary M60 Keyboard
+
+M60 is a USB & BLE, modular, hot-swappable, 60% keyboard powered by Python.
+Refer to https://makerdiary.com/m60 for more details.
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/board.c b/ports/nrf/boards/makerdiary_m60_keyboard/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_m60_keyboard/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h
new file mode 100644
index 000000000..086718089
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * 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 "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "Makerdiary M60 Keyboard"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+
+#define CP_RGB_STATUS_R (&pin_P0_30)
+#define CP_RGB_STATUS_G (&pin_P0_29)
+#define CP_RGB_STATUS_B (&pin_P0_31)
+
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 15)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(1, 12)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(1, 11)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(1, 13)
+
+#define BOARD_HAS_CRYSTAL 1
+
+// #define DEFAULT_UART_BUS_RX (&pin_P0_15)
+// #define DEFAULT_UART_BUS_TX (&pin_P0_16)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P1_06)
+#define DEFAULT_I2C_BUS_SDA (&pin_P1_05)
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk
new file mode 100644
index 000000000..fc630e5bb
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.mk
@@ -0,0 +1,12 @@
+USB_VID = 0x2886
+USB_PID = 0xf002
+USB_PRODUCT = "M60 Keyboard"
+USB_MANUFACTURER = "Makerdiary"
+
+MCU_CHIP = nrf52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "MX25R6435F"
+
+CIRCUITPY_ENABLE_MPY_NATIVE = 1
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/pins.c b/ports/nrf/boards/makerdiary_m60_keyboard/pins.c
new file mode 100644
index 000000000..63c3ad171
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_m60_keyboard/pins.c
@@ -0,0 +1,41 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "boards/board.h"
+#include "shared-module/displayio/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_R1), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_R2), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_R3), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_R4), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_R5), MP_ROM_PTR(&pin_P1_09) },
+ { MP_ROM_QSTR(MP_QSTR_R6), MP_ROM_PTR(&pin_P1_08) },
+ { MP_ROM_QSTR(MP_QSTR_R7), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_R8), MP_ROM_PTR(&pin_P0_11) },
+
+ { MP_ROM_QSTR(MP_QSTR_C1), MP_ROM_PTR(&pin_P0_19) },
+ { MP_ROM_QSTR(MP_QSTR_C2), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_C3), MP_ROM_PTR(&pin_P0_21) },
+ { MP_ROM_QSTR(MP_QSTR_C4), MP_ROM_PTR(&pin_P0_22) },
+ { MP_ROM_QSTR(MP_QSTR_C5), MP_ROM_PTR(&pin_P0_23) },
+ { MP_ROM_QSTR(MP_QSTR_C6), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_C7), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_C8), MP_ROM_PTR(&pin_P0_26) },
+
+ { MP_ROM_QSTR(MP_QSTR_TXD), MP_ROM_PTR(&pin_P0_16) },
+ { MP_ROM_QSTR(MP_QSTR_RXD), MP_ROM_PTR(&pin_P0_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P1_06) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P1_05) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_BTN), MP_ROM_PTR(&pin_P0_27) },
+
+// { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) }
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/README.md b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/README.md
new file mode 100644
index 000000000..b75385414
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/README.md
@@ -0,0 +1,8 @@
+# Makerdiary nRF52840 M.2 Developer Kit
+
+The devkit is a versatile IoT prototyping platform,
+including the nRF52840 M.2 Module and M.2 Dock. You can use the developer kit
+to prototype your IoT products and then scale to production faster using the
+nRF52840 M.2 Module combined with your custom PCB hardware.
+
+Refer to https://github.com/makerdiary/nrf52840-m2-devkit for more details.
diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/board.c b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/board.c
new file mode 100644
index 000000000..e7f946f4d
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/board.c
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2020 Yihui Xiong for Makerdiary
+ *
+ * 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 "boards/board.h"
+#include "mpconfigboard.h"
+
+#include "shared-bindings/busio/SPI.h"
+#include "shared-bindings/displayio/FourWire.h"
+#include "shared-module/displayio/__init__.h"
+#include "shared-module/displayio/mipi_constants.h"
+
+displayio_fourwire_obj_t board_display_obj;
+
+#define DELAY 0x80
+
+uint8_t display_init_sequence[] = {
+ 0x01, 0 | DELAY, 150, // SWRESET
+ 0x11, 0 | DELAY, 255, // SLPOUT
+ 0x36, 1, 0b10100000, // _MADCTL for rotation 0
+ 0x3a, 1, 0x55, // COLMOD - 16bit color
+ 0x21, 0 | DELAY, 10, // _INVON
+ 0x13, 0 | DELAY, 10, // _NORON
+ 0x29, 0 | DELAY, 255, // _DISPON
+};
+
+void board_init(void) {
+ busio_spi_obj_t* spi = &displays[0].fourwire_bus.inline_bus;
+ common_hal_busio_spi_construct(spi, &pin_P0_11, &pin_P0_12, NULL);
+ common_hal_busio_spi_never_reset(spi);
+
+ displayio_fourwire_obj_t* bus = &displays[0].fourwire_bus;
+ bus->base.type = &displayio_fourwire_type;
+ common_hal_displayio_fourwire_construct(bus,
+ spi,
+ &pin_P0_08, // TFT_DC Command or data
+ &pin_P0_06, // TFT_CS Chip select
+ &pin_P1_09, // TFT_RST Reset
+ 60000000, // Baudrate
+ 0, // Polarity
+ 0); // Phase
+
+ displayio_display_obj_t* display = &displays[0].display;
+ display->base.type = &displayio_display_type;
+ common_hal_displayio_display_construct(display,
+ bus,
+ 240, // Width (after rotation)
+ 240, // Height (after rotation)
+ 80, // column start
+ 0, // row start
+ 0, // rotation
+ 16, // Color depth
+ false, // Grayscale
+ false, // Pixels in a byte share a row. Only used for depth < 8
+ 1, // bytes per cell. Only valid for depths < 8
+ false, // reverse_pixels_in_byte. Only valid for depths < 8
+ true, // reverse_pixels_in_word
+ MIPI_COMMAND_SET_COLUMN_ADDRESS, // Set column command
+ MIPI_COMMAND_SET_PAGE_ADDRESS, // Set row command
+ MIPI_COMMAND_WRITE_MEMORY_START, // Write memory command
+ 37, // set vertical scroll command
+ display_init_sequence,
+ sizeof(display_init_sequence),
+ &pin_P0_20, // backlight pin
+ NO_BRIGHTNESS_COMMAND,
+ 1.0f, // brightness (ignored)
+ true, // auto_brightness
+ false, // single_byte_bounds
+ false, // data_as_commands
+ true, // auto_refresh
+ 60, // native_frames_per_second
+ true); // backlight_on_high
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+}
diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h
new file mode 100644
index 000000000..dab2ff042
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * 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 "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "Makerdiary nRF52840 M.2 Developer Kit"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+
+#define MICROPY_HW_LED_STATUS (&pin_P1_07)
+
+#define CP_RGB_STATUS_INVERTED_PWM
+#define CP_RGB_STATUS_R (&pin_P0_30)
+#define CP_RGB_STATUS_G (&pin_P0_29)
+#define CP_RGB_STATUS_B (&pin_P0_31)
+
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 15)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(1, 12)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(1, 11)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(1, 13)
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_15)
+#define DEFAULT_UART_BUS_TX (&pin_P0_16)
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P1_06)
+#define DEFAULT_I2C_BUS_SDA (&pin_P1_05)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_11)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P0_12)
+#define DEFAULT_SPI_BUS_MISO (&pin_P1_08)
diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk
new file mode 100644
index 000000000..4e6aebc8e
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/mpconfigboard.mk
@@ -0,0 +1,12 @@
+USB_VID = 0x2886
+USB_PID = 0xf001
+USB_PRODUCT = "nRF52840 M.2 Developer Kit"
+USB_MANUFACTURER = "Makerdiary"
+
+MCU_CHIP = nrf52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "MX25R6435F"
+
+CIRCUITPY_ENABLE_MPY_NATIVE = 1
diff --git a/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/pins.c b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/pins.c
new file mode 100644
index 000000000..cb3bda35a
--- /dev/null
+++ b/ports/nrf/boards/makerdiary_nrf52840_m2_devkit/pins.c
@@ -0,0 +1,110 @@
+#include "shared-bindings/board/__init__.h"
+
+#include "boards/board.h"
+#include "shared-module/displayio/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_AIN0), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_AIN1), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_AIN2), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_AIN3), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_AIN4), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_AIN5), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_AIN6), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_AIN7), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_VDIV), MP_ROM_PTR(&pin_P0_05) },
+
+ { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_P2), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_P3), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_P4), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_P5), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_P6), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_P7), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_P8), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_P9), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_P10), MP_ROM_PTR(&pin_P0_10) },
+ { MP_ROM_QSTR(MP_QSTR_P11), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_P12), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_P13), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_P14), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_P15), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_P16), MP_ROM_PTR(&pin_P0_16) },
+ { MP_ROM_QSTR(MP_QSTR_P17), MP_ROM_PTR(&pin_P0_17) },
+ { MP_ROM_QSTR(MP_QSTR_P18), MP_ROM_PTR(&pin_P0_18) },
+ { MP_ROM_QSTR(MP_QSTR_P19), MP_ROM_PTR(&pin_P0_19) },
+ { MP_ROM_QSTR(MP_QSTR_P20), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_P21), MP_ROM_PTR(&pin_P0_21) },
+ { MP_ROM_QSTR(MP_QSTR_P25), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_P26), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_P27), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_P28), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_P29), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_P30), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_P31), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_P1_0), MP_ROM_PTR(&pin_P1_00) },
+ { MP_ROM_QSTR(MP_QSTR_P1_1), MP_ROM_PTR(&pin_P1_01) },
+ { MP_ROM_QSTR(MP_QSTR_P1_2), MP_ROM_PTR(&pin_P1_02) },
+ { MP_ROM_QSTR(MP_QSTR_P1_3), MP_ROM_PTR(&pin_P1_03) },
+ { MP_ROM_QSTR(MP_QSTR_P1_4), MP_ROM_PTR(&pin_P1_04) },
+ { MP_ROM_QSTR(MP_QSTR_P1_5), MP_ROM_PTR(&pin_P1_05) },
+ { MP_ROM_QSTR(MP_QSTR_P1_6), MP_ROM_PTR(&pin_P1_06) },
+ { MP_ROM_QSTR(MP_QSTR_P1_7), MP_ROM_PTR(&pin_P1_07) },
+ { MP_ROM_QSTR(MP_QSTR_P1_8), MP_ROM_PTR(&pin_P1_08) },
+ { MP_ROM_QSTR(MP_QSTR_P1_9), MP_ROM_PTR(&pin_P1_09) },
+
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_P0_16) },
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_19) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_P0_21) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P0_22) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_23) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_P1_00) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P1_01) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P1_02) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P1_03) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P1_04) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_07) },
+ { MP_ROM_QSTR(MP_QSTR_D14), MP_ROM_PTR(&pin_P1_05) },
+ { MP_ROM_QSTR(MP_QSTR_D15), MP_ROM_PTR(&pin_P1_06) },
+
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_04) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P1_08) },
+
+ { MP_ROM_QSTR(MP_QSTR_LCD_DC), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_CS), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_BL), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_LCD_RST), MP_ROM_PTR(&pin_P1_09) },
+
+ { MP_ROM_QSTR(MP_QSTR_TXD), MP_ROM_PTR(&pin_P0_16) },
+ { MP_ROM_QSTR(MP_QSTR_RXD), MP_ROM_PTR(&pin_P0_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_USR_BTN), MP_ROM_PTR(&pin_P0_19) },
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_DISPLAY), MP_ROM_PTR(&displays[0].display)}
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/particle_argon/mpconfigboard.mk b/ports/nrf/boards/particle_argon/mpconfigboard.mk
index 2ca08b982..f8d3d2aca 100644
--- a/ports/nrf/boards/particle_argon/mpconfigboard.mk
+++ b/ports/nrf/boards/particle_argon/mpconfigboard.mk
@@ -8,7 +8,3 @@ MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25L3233F"
-
-# Support for the Ethernet FeatherWing
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
diff --git a/ports/nrf/boards/particle_boron/mpconfigboard.mk b/ports/nrf/boards/particle_boron/mpconfigboard.mk
index f03f43a7b..eada97a73 100644
--- a/ports/nrf/boards/particle_boron/mpconfigboard.mk
+++ b/ports/nrf/boards/particle_boron/mpconfigboard.mk
@@ -8,7 +8,3 @@ MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25L3233F"
-
-# Support for the Ethernet FeatherWing
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
diff --git a/ports/nrf/boards/particle_xenon/mpconfigboard.mk b/ports/nrf/boards/particle_xenon/mpconfigboard.mk
index 44309bbca..6062da378 100644
--- a/ports/nrf/boards/particle_xenon/mpconfigboard.mk
+++ b/ports/nrf/boards/particle_xenon/mpconfigboard.mk
@@ -8,7 +8,3 @@ MCU_CHIP = nrf52840
QSPI_FLASH_FILESYSTEM = 1
EXTERNAL_FLASH_DEVICE_COUNT = 1
EXTERNAL_FLASH_DEVICES = "MX25L3233F"
-
-# Support for the Ethernet FeatherWing
-CIRCUITPY_NETWORK = 1
-MICROPY_PY_WIZNET5K = 5500
diff --git a/ports/nrf/boards/pca10100/mpconfigboard.mk b/ports/nrf/boards/pca10100/mpconfigboard.mk
index 385870a65..e15bf3a67 100644
--- a/ports/nrf/boards/pca10100/mpconfigboard.mk
+++ b/ports/nrf/boards/pca10100/mpconfigboard.mk
@@ -21,6 +21,7 @@ CIRCUITPY_PIXELBUF = 0
CIRCUITPY_RGBMATRIX = 0
CIRCUITPY_ROTARYIO = 0
CIRCUITPY_RTC = 1
+CIRCUITPY_SDCARDIO = 0
CIRCUITPY_TOUCHIO = 0
CIRCUITPY_ULAB = 0
@@ -29,3 +30,6 @@ SUPEROPT_GC = 0
# These defines must be overridden before mpconfigboard.h is included, which is
# why they are passed on the command line.
CFLAGS += -DSPIM3_BUFFER_SIZE=0 -DSOFTDEVICE_RAM_SIZE='(32*1024)'
+
+# Override optimization to keep binary small
+OPTIMIZATION_FLAGS = -Os
diff --git a/ports/nrf/boards/raytac_mdbt50q-db-40/board.c b/ports/nrf/boards/raytac_mdbt50q-db-40/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/raytac_mdbt50q-db-40/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/raytac_mdbt50q-db-40/bootloader/6.0.0/pca10056_bootloader_6.0.0_s140.zip b/ports/nrf/boards/raytac_mdbt50q-db-40/bootloader/6.0.0/pca10056_bootloader_6.0.0_s140.zip
new file mode 100644
index 000000000..691f4a1ab
--- /dev/null
+++ b/ports/nrf/boards/raytac_mdbt50q-db-40/bootloader/6.0.0/pca10056_bootloader_6.0.0_s140.zip
Binary files differ
diff --git a/ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.h b/ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.h
new file mode 100644
index 000000000..93fdce3a0
--- /dev/null
+++ b/ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.h
@@ -0,0 +1,30 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ *
+ * 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.
+ */
+
+#define MICROPY_HW_BOARD_NAME "MDBT50Q-DB-40"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+
+#define MICROPY_HW_LED_STATUS (&pin_P0_13)
diff --git a/ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.mk b/ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.mk
new file mode 100644
index 000000000..f49618e77
--- /dev/null
+++ b/ports/nrf/boards/raytac_mdbt50q-db-40/mpconfigboard.mk
@@ -0,0 +1,8 @@
+USB_VID = 0x239A
+USB_PID = 0x80BC
+USB_PRODUCT = "MDBT50Q-DB-40"
+USB_MANUFACTURER = "Raytac Corporation"
+
+MCU_CHIP = nrf52840
+
+INTERNAL_FLASH_FILESYSTEM = 1
diff --git a/ports/nrf/boards/raytac_mdbt50q-db-40/pins.c b/ports/nrf/boards/raytac_mdbt50q-db-40/pins.c
new file mode 100644
index 000000000..426498cc2
--- /dev/null
+++ b/ports/nrf/boards/raytac_mdbt50q-db-40/pins.c
@@ -0,0 +1,80 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_P0_02), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_P0_03), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_P0_04), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_P0_05), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_P0_06), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_P0_07), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_P0_08), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_P0_09), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_P0_10), MP_ROM_PTR(&pin_P0_10) },
+ { MP_ROM_QSTR(MP_QSTR_P0_11), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_P0_12), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_P0_13), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_P0_14), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_P0_15), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_P0_16), MP_ROM_PTR(&pin_P0_16) },
+ { MP_ROM_QSTR(MP_QSTR_P0_17), MP_ROM_PTR(&pin_P0_17) },
+ { MP_ROM_QSTR(MP_QSTR_P0_18), MP_ROM_PTR(&pin_P0_18) },
+ { MP_ROM_QSTR(MP_QSTR_P0_19), MP_ROM_PTR(&pin_P0_19) },
+ { MP_ROM_QSTR(MP_QSTR_P0_20), MP_ROM_PTR(&pin_P0_20) },
+ { MP_ROM_QSTR(MP_QSTR_P0_21), MP_ROM_PTR(&pin_P0_21) },
+ { MP_ROM_QSTR(MP_QSTR_P0_22), MP_ROM_PTR(&pin_P0_22) },
+ { MP_ROM_QSTR(MP_QSTR_P0_23), MP_ROM_PTR(&pin_P0_23) },
+ { MP_ROM_QSTR(MP_QSTR_P0_24), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_P0_25), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_P0_26), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_P0_27), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_P0_28), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_P0_29), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_P0_30), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_P0_31), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_P1_00), MP_ROM_PTR(&pin_P1_00) },
+ { MP_ROM_QSTR(MP_QSTR_P1_01), MP_ROM_PTR(&pin_P1_01) },
+ { MP_ROM_QSTR(MP_QSTR_P1_02), MP_ROM_PTR(&pin_P1_02) },
+ { MP_ROM_QSTR(MP_QSTR_P1_03), MP_ROM_PTR(&pin_P1_03) },
+ { MP_ROM_QSTR(MP_QSTR_P1_04), MP_ROM_PTR(&pin_P1_04) },
+ { MP_ROM_QSTR(MP_QSTR_P1_05), MP_ROM_PTR(&pin_P1_05) },
+ { MP_ROM_QSTR(MP_QSTR_P1_06), MP_ROM_PTR(&pin_P1_06) },
+ { MP_ROM_QSTR(MP_QSTR_P1_07), MP_ROM_PTR(&pin_P1_07) },
+ { MP_ROM_QSTR(MP_QSTR_P1_08), MP_ROM_PTR(&pin_P1_08) },
+ { MP_ROM_QSTR(MP_QSTR_P1_09), MP_ROM_PTR(&pin_P1_09) },
+ { MP_ROM_QSTR(MP_QSTR_P1_10), MP_ROM_PTR(&pin_P1_10) },
+ { MP_ROM_QSTR(MP_QSTR_P1_11), MP_ROM_PTR(&pin_P1_11) },
+ { MP_ROM_QSTR(MP_QSTR_P1_12), MP_ROM_PTR(&pin_P1_12) },
+ { MP_ROM_QSTR(MP_QSTR_P1_13), MP_ROM_PTR(&pin_P1_13) },
+ { MP_ROM_QSTR(MP_QSTR_P1_14), MP_ROM_PTR(&pin_P1_14) },
+ { MP_ROM_QSTR(MP_QSTR_P1_15), MP_ROM_PTR(&pin_P1_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_AIN_0), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_1), MP_ROM_PTR(&pin_P0_03) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_2), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_3), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_4), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_5), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_6), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_AIN_7), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_NFC_1), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_NFC_2), MP_ROM_PTR(&pin_P0_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_PTR(&pin_P0_05) },
+
+ { MP_ROM_QSTR(MP_QSTR_LED_R), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_LED_G), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_LED_B), MP_ROM_PTR(&pin_P0_15) },
+ { MP_ROM_QSTR(MP_QSTR_LED_4), MP_ROM_PTR(&pin_P0_16) },
+
+ { MP_ROM_QSTR(MP_QSTR_SW1), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_SW2), MP_ROM_PTR(&pin_P0_12) },
+ { MP_ROM_QSTR(MP_QSTR_SW3), MP_ROM_PTR(&pin_P0_24) },
+ { MP_ROM_QSTR(MP_QSTR_SW4), MP_ROM_PTR(&pin_P0_25) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/boards/simmel/mpconfigboard.mk b/ports/nrf/boards/simmel/mpconfigboard.mk
index 2bca2492f..8dd284d57 100644
--- a/ports/nrf/boards/simmel/mpconfigboard.mk
+++ b/ports/nrf/boards/simmel/mpconfigboard.mk
@@ -32,3 +32,6 @@ CIRCUITPY_WATCHDOG = 1
# These defines must be overridden before mpconfigboard.h is included, which is
# why they are passed on the command line.
CFLAGS += -DSPIM3_BUFFER_SIZE=0 -DSOFTDEVICE_RAM_SIZE='(32*1024)' -DNRFX_SPIM3_ENABLED=0
+
+# Override optimization to keep binary small
+OPTIMIZATION_FLAGS = -Os
diff --git a/ports/nrf/boards/tinkeringtech_scoutmakes_azul/README.md b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/README.md
new file mode 100644
index 000000000..614daa72c
--- /dev/null
+++ b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/README.md
@@ -0,0 +1,25 @@
+# Setup
+
+The TinkeringTech ScoutMakes Azul is a bluetooth enabled, feather format, open source platform featuring the nRF52840 from Nordic Semiconductors. The design is based on the Adafruit nRF52840 feather express and uses the Raytac MDBT50Q-1MV2 module.
+
+Schematic, datasheet, pin mapping etc. can be found over [here](https://tinkeringtech.com/scoutmakes-azul).
+
+features:
+- ARM Cortex M4F (with HW floating point acceleration) running at 64MHz
+- Raytac MDBT50Q-1MV2 BLE module. FCC / IC / TELEC certified module
+- 1MB flash and 256KB SRAM
+- Native Open Source USB stack – pre-programmed with UF2 bootloader and CircuitPython
+- 128×32 OLED display
+- USB type-C
+- On/off power switch
+- Bluetooth Low Energy compatible 2.4GHz radio (Details available in the nRF52840 product specification)
+- BT5.1 & BT5 Bluetooth Specification Certified
+- Supports BT5 Long Range Feature
+- 1.7v to 3.3v operation with internal linear and DC/DC voltage regulators
+- 21 GPIO, 6 x 12-bit ADC pins, up to 12 PWM outputs (3 PWM modules with 4 outputs each)
+- Pin #3 red LED for general purpose blinking,
+- Programmable NeoPixel for colorful feedback
+- 4 mounting holes
+- Reset button
+- Works out of the box with Adafruit feather wings.
+- Open source design.
diff --git a/ports/nrf/boards/tinkeringtech_scoutmakes_azul/board.c b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/board.c
new file mode 100644
index 000000000..4421970ee
--- /dev/null
+++ b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/board.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ *
+ * 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 "boards/board.h"
+
+void board_init(void) {
+}
+
+bool board_requests_safe_mode(void) {
+ return false;
+}
+
+void reset_board(void) {
+
+}
diff --git a/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.h b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.h
new file mode 100644
index 000000000..2d6663394
--- /dev/null
+++ b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.h
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ *
+ * 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 "nrfx/hal/nrf_gpio.h"
+
+#define MICROPY_HW_BOARD_NAME "TinkeringTech ScoutMakes Azul"
+#define MICROPY_HW_MCU_NAME "nRF52840"
+
+#define MICROPY_HW_NEOPIXEL (&pin_P0_16)
+
+#define MICROPY_HW_LED_STATUS (&pin_P1_15)
+
+#if QSPI_FLASH_FILESYSTEM
+#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 17)
+#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 22)
+#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 23)
+#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 21)
+#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19)
+#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 20)
+#endif
+
+#if SPI_FLASH_FILESYSTEM
+#define SPI_FLASH_MOSI_PIN &pin_P0_17
+#define SPI_FLASH_MISO_PIN &pin_P0_22
+#define SPI_FLASH_SCK_PIN &pin_P0_19
+#define SPI_FLASH_CS_PIN &pin_P0_20
+#endif
+
+#define BOARD_HAS_CRYSTAL 1
+
+#define DEFAULT_I2C_BUS_SCL (&pin_P0_11)
+#define DEFAULT_I2C_BUS_SDA (&pin_P0_12)
+
+#define DEFAULT_SPI_BUS_SCK (&pin_P0_14)
+#define DEFAULT_SPI_BUS_MOSI (&pin_P0_13)
+#define DEFAULT_SPI_BUS_MISO (&pin_P0_15)
+
+#define DEFAULT_UART_BUS_RX (&pin_P0_24)
+#define DEFAULT_UART_BUS_TX (&pin_P0_25)
diff --git a/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk
new file mode 100644
index 000000000..e8bd636ad
--- /dev/null
+++ b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/mpconfigboard.mk
@@ -0,0 +1,10 @@
+USB_VID = 0x239A
+USB_PID = 0x80BE
+USB_PRODUCT = "TinkeringTech ScoutMakes Azul"
+USB_MANUFACTURER = "TinkeringTech LLC"
+
+MCU_CHIP = nrf52840
+
+QSPI_FLASH_FILESYSTEM = 1
+EXTERNAL_FLASH_DEVICE_COUNT = 1
+EXTERNAL_FLASH_DEVICES = "GD25Q16C"
diff --git a/ports/nrf/boards/tinkeringtech_scoutmakes_azul/pins.c b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/pins.c
new file mode 100644
index 000000000..ec2689ab4
--- /dev/null
+++ b/ports/nrf/boards/tinkeringtech_scoutmakes_azul/pins.c
@@ -0,0 +1,53 @@
+#include "shared-bindings/board/__init__.h"
+
+STATIC const mp_rom_map_elem_t board_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_P0_04) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_P0_05) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_P0_30) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_P0_28) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_P0_02) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_P0_03) },
+
+ { MP_ROM_QSTR(MP_QSTR_AREF), MP_ROM_PTR(&pin_P0_31) },
+
+ { MP_ROM_QSTR(MP_QSTR_VOLTAGE_MONITOR), MP_ROM_PTR(&pin_P0_29) },
+ { MP_ROM_QSTR(MP_QSTR_BATTERY), MP_ROM_PTR(&pin_P0_29) },
+
+ { MP_ROM_QSTR(MP_QSTR_SWITCH), MP_ROM_PTR(&pin_P1_02) },
+
+ { MP_ROM_QSTR(MP_QSTR_NFC1), MP_ROM_PTR(&pin_P0_09) },
+ { MP_ROM_QSTR(MP_QSTR_NFC2), MP_ROM_PTR(&pin_P0_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_P0_10) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_P1_08) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_P0_07) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_P0_26) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_P0_27) },
+ { MP_ROM_QSTR(MP_QSTR_D11), MP_ROM_PTR(&pin_P0_06) },
+ { MP_ROM_QSTR(MP_QSTR_D12), MP_ROM_PTR(&pin_P0_08) },
+ { MP_ROM_QSTR(MP_QSTR_D13), MP_ROM_PTR(&pin_P1_09) },
+
+ { MP_ROM_QSTR(MP_QSTR_NEOPIXEL), MP_ROM_PTR(&pin_P0_16) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_P0_14) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_P0_13) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_P0_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_P0_25) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_P0_24) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_P0_11) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_P0_12) },
+
+ { MP_ROM_QSTR(MP_QSTR_L), MP_ROM_PTR(&pin_P1_15) },
+ { MP_ROM_QSTR(MP_QSTR_RED_LED), MP_ROM_PTR(&pin_P1_15) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_P1_15) },
+
+ { MP_ROM_QSTR(MP_QSTR_BLUE_LED), MP_ROM_PTR(&pin_P1_10) },
+
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&board_uart_obj) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&board_spi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&board_i2c_obj) },
+};
+
+MP_DEFINE_CONST_DICT(board_module_globals, board_module_globals_table);
diff --git a/ports/nrf/common-hal/_bleio/__init__.c b/ports/nrf/common-hal/_bleio/__init__.c
index 9ac26aee3..8eea319b7 100644
--- a/ports/nrf/common-hal/_bleio/__init__.c
+++ b/ports/nrf/common-hal/_bleio/__init__.c
@@ -39,6 +39,7 @@
#include "supervisor/shared/bluetooth.h"
#include "common-hal/_bleio/__init__.h"
+#include "common-hal/_bleio/bonding.h"
void check_nrf_error(uint32_t err_code) {
if (err_code == NRF_SUCCESS) {
@@ -241,11 +242,10 @@ void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buff
}
-void common_hal_bleio_gc_collect(void) {
- bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
-}
-
void bleio_background(void) {
- supervisor_bluetooth_background();
bonding_background();
}
+
+void common_hal_bleio_gc_collect(void) {
+ bleio_adapter_gc_collect(&common_hal_bleio_adapter_obj);
+}
diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c
index 3f205e778..f27f0e267 100644
--- a/ports/nrf/common-hal/busio/SPI.c
+++ b/ports/nrf/common-hal/busio/SPI.c
@@ -271,13 +271,13 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len,
return true;
}
-bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, const uint8_t *data_out, uint8_t *data_in, size_t len) {
const bool is_spim3 = self->spim_peripheral->spim.p_reg == NRF_SPIM3;
- uint8_t *next_chunk_out = data_out;
+ const uint8_t *next_chunk_out = data_out;
uint8_t *next_chunk_in = data_in;
while (len > 0) {
- uint8_t *chunk_out = next_chunk_out;
+ const uint8_t *chunk_out = next_chunk_out;
size_t chunk_size = MIN(len, self->spim_peripheral->max_xfer_size);
if (is_spim3) {
// If SPIM3, copy into unused RAM block, and do DMA from there.
diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c
index 89f3c9f32..012ebc3b5 100644
--- a/ports/nrf/common-hal/busio/UART.c
+++ b/ports/nrf/common-hal/busio/UART.c
@@ -133,7 +133,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
- uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
bool sigint_enabled) {
@@ -162,7 +162,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
mp_raise_ValueError(translate("Invalid buffer size"));
}
- if ( parity == PARITY_ODD ) {
+ if ( parity == BUSIO_UART_PARITY_ODD ) {
mp_raise_ValueError(translate("Odd parity is not supported"));
}
@@ -176,7 +176,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
.interrupt_priority = 7,
.hal_cfg = {
.hwfc = NRF_UARTE_HWFC_DISABLED,
- .parity = (parity == PARITY_NONE) ? NRF_UARTE_PARITY_EXCLUDED : NRF_UARTE_PARITY_INCLUDED
+ .parity = (parity == BUSIO_UART_PARITY_NONE) ? NRF_UARTE_PARITY_EXCLUDED : NRF_UARTE_PARITY_INCLUDED
}
};
diff --git a/ports/nrf/common-hal/microcontroller/__init__.c b/ports/nrf/common-hal/microcontroller/__init__.c
index f5caf68ef..06aac9409 100644
--- a/ports/nrf/common-hal/microcontroller/__init__.c
+++ b/ports/nrf/common-hal/microcontroller/__init__.c
@@ -50,36 +50,34 @@ void common_hal_mcu_delay_us(uint32_t delay) {
static volatile uint32_t nesting_count = 0;
static uint8_t is_nested_critical_region;
-static uint8_t sd_is_enabled = false;
void common_hal_mcu_disable_interrupts() {
- sd_softdevice_is_enabled(&sd_is_enabled);
- if (sd_is_enabled) {
+ if (nesting_count == 0) {
+ // Unlike __disable_irq(), this should only be called the first time
+ // "is_nested_critical_region" is sd's equivalent of our nesting count
+ // so a nested call would store 0 in the global and make the later
+ // exit call not actually reenable interrupts
+ //
+ // This only disables interrupts of priority 2 through 7; levels 0, 1,
+ // and 4, are exclusive to softdevice and should never be used, so
+ // this limitation is not important.
sd_nvic_critical_region_enter(&is_nested_critical_region);
- } else {
- __disable_irq();
- __DMB();
- nesting_count++;
}
+ __DMB();
+ nesting_count++;
}
void common_hal_mcu_enable_interrupts() {
- // Don't check here if SD is enabled, because we'll crash if interrupts
- // were turned off and sd_softdevice_is_enabled is called.
- if (sd_is_enabled) {
- sd_nvic_critical_region_exit(is_nested_critical_region);
- } else {
- if (nesting_count == 0) {
- // This is very very bad because it means there was mismatched disable/enables so we
- // crash.
- reset_into_safe_mode(HARD_CRASH);
- }
- nesting_count--;
- if (nesting_count > 0) {
- return;
- }
- __DMB();
- __enable_irq();
+ if (nesting_count == 0) {
+ // This is very very bad because it means there was mismatched disable/enables so we
+ // crash.
+ reset_into_safe_mode(HARD_CRASH);
}
+ nesting_count--;
+ if (nesting_count > 0) {
+ return;
+ }
+ __DMB();
+ sd_nvic_critical_region_exit(is_nested_critical_region);
}
void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
diff --git a/ports/nrf/examples/ubluepy_temp.py b/ports/nrf/examples/ubluepy_temp.py
index 118407af5..405f77c4b 100644
--- a/ports/nrf/examples/ubluepy_temp.py
+++ b/ports/nrf/examples/ubluepy_temp.py
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2017 Glenn Ruben Bakke
+# SPDX-FileCopyrightText: Copyright (c) 2017 Glenn Ruben Bakke
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/nrf/fatfs_port.c b/ports/nrf/fatfs_port.c
index cb1bfa834..2b741f993 100644
--- a/ports/nrf/fatfs_port.c
+++ b/ports/nrf/fatfs_port.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/nrf/peripherals/nrf/nvm.c b/ports/nrf/peripherals/nrf/nvm.c
index dc50e2eef..ce47d73c7 100644
--- a/ports/nrf/peripherals/nrf/nvm.c
+++ b/ports/nrf/peripherals/nrf/nvm.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Nick Moore for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/nrf/peripherals/nrf/nvm.h b/ports/nrf/peripherals/nrf/nvm.h
index 8ba95773d..9e144d802 100644
--- a/ports/nrf/peripherals/nrf/nvm.h
+++ b/ports/nrf/peripherals/nrf/nvm.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019 Nick Moore for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/nrf/supervisor/internal_flash.c b/ports/nrf/supervisor/internal_flash.c
index 737bab203..93de0b2c4 100644
--- a/ports/nrf/supervisor/internal_flash.c
+++ b/ports/nrf/supervisor/internal_flash.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/nrf/supervisor/internal_flash.h b/ports/nrf/supervisor/internal_flash.h
index 024a53ebb..81da69021 100644
--- a/ports/nrf/supervisor/internal_flash.h
+++ b/ports/nrf/supervisor/internal_flash.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c
index aee2d63e1..e681e6825 100644
--- a/ports/nrf/supervisor/port.c
+++ b/ports/nrf/supervisor/port.c
@@ -313,12 +313,21 @@ void port_sleep_until_interrupt(void) {
// instruction will returned as long as an interrupt is
// available, even though the actual handler won't fire until
// we re-enable interrupts.
- common_hal_mcu_disable_interrupts();
+ //
+ // We do not use common_hal_mcu_disable_interrupts here because
+ // we truly require that interrupts be disabled, while
+ // common_hal_mcu_disable_interrupts actually just masks the
+ // interrupts that are not required to allow the softdevice to
+ // function (whether or not SD is enabled)
+ int nested = __get_PRIMASK();
+ __disable_irq();
if (!tud_task_event_ready()) {
__DSB();
__WFI();
}
- common_hal_mcu_enable_interrupts();
+ if (!nested) {
+ __enable_irq();
+ }
}
}
diff --git a/ports/nrf/supervisor/usb.c b/ports/nrf/supervisor/usb.c
index 3d2527faa..771e86ce0 100644
--- a/ports/nrf/supervisor/usb.c
+++ b/ports/nrf/supervisor/usb.c
@@ -30,6 +30,7 @@
#include "lib/utils/interrupt_char.h"
#include "lib/mp-readline/readline.h"
#include "lib/tinyusb/src/device/usbd.h"
+#include "supervisor/background_callback.h"
#ifdef SOFTDEVICE_PRESENT
#include "nrf_sdm.h"
@@ -42,7 +43,9 @@ extern void tusb_hal_nrf_power_event(uint32_t event);
void init_usb_hardware(void) {
- // 2 is max priority (0, 1 are reserved for SD)
+ // 2 is max priority (0, 1, and 4 are reserved for SD)
+ // 5 is max priority that still allows calling SD functions such as
+ // sd_softdevice_is_enabled
NVIC_SetPriority(USBD_IRQn, 2);
// USB power may already be ready at this time -> no event generated
@@ -89,5 +92,5 @@ void init_usb_hardware(void) {
}
void USBD_IRQHandler(void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
diff --git a/ports/stm/Makefile b/ports/stm/Makefile
index 08cb36ddf..dccc749ed 100755
--- a/ports/stm/Makefile
+++ b/ports/stm/Makefile
@@ -2,8 +2,8 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2019 Dan Halbert for Adafruit Industries
-# Copyright (c) 2019 Lucian Copeland for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2019 Dan Halbert for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2019 Lucian Copeland for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -81,16 +81,20 @@ INC += -I../../supervisor/shared/usb
#Debugging/Optimization
ifeq ($(DEBUG), 1)
- CFLAGS += -ggdb
+ CFLAGS += -ggdb3
# You may want to enable these flags to make setting breakpoints easier.
CFLAGS += -fno-inline -fno-ipa-sra
else
- CFLAGS += -Os -DNDEBUG
- CFLAGS += -ggdb
+ CFLAGS += -DNDEBUG
+ OPTIMIZATION_FLAGS ?= -O2
+ CFLAGS += -ggdb3
# TODO: Test with -flto
# CFLAGS += -flto
endif
+# to override compiler optimization level, set in boards/$(BOARD)/mpconfigboard.mk
+CFLAGS += $(OPTIMIZATION_FLAGS)
+
# MCU Series is defined by the HAL package and doesn't need to be specified here
C_DEFS = -D$(MCU_PACKAGE) -DUSE_HAL_DRIVER -DUSE_FULL_LL_DRIVER -D$(MCU_VARIANT)
@@ -207,6 +211,7 @@ SRC_C += \
mphalport.c \
boards/$(BOARD)/board.c \
boards/$(BOARD)/pins.c \
+ peripherals/timers.c \
peripherals/stm32$(MCU_SERIES_LOWER)/clocks.c \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/pins.c \
peripherals/stm32$(MCU_SERIES_LOWER)/$(MCU_VARIANT_LOWER)/gpio.c \
diff --git a/ports/stm/background.c b/ports/stm/background.c
index b1b765536..d83a0ccec 100644
--- a/ports/stm/background.c
+++ b/ports/stm/background.c
@@ -33,33 +33,6 @@
#include "shared-module/displayio/__init__.h"
#endif
-static bool running_background_tasks = false;
-
-void background_tasks_reset(void) {
- running_background_tasks = false;
-}
-
-void run_background_tasks(void) {
- // Don't call ourselves recursively.
- if (running_background_tasks) {
- return;
- }
- running_background_tasks = true;
- filesystem_background();
-
-#if USB_AVAILABLE
- usb_background();
-#endif
-
-#if CIRCUITPY_BLEIO
- bleio_background();
-#endif
-
-#if CIRCUITPY_DISPLAYIO
- displayio_background();
-#endif
-
- running_background_tasks = false;
-
- assert_heap_ok();
-}
+void port_background_task(void) {}
+void port_start_background_task(void) {}
+void port_finish_background_task(void) {}
diff --git a/ports/stm/background.h b/ports/stm/background.h
index 6225429f8..e57aa40dd 100644
--- a/ports/stm/background.h
+++ b/ports/stm/background.h
@@ -27,9 +27,4 @@
#ifndef MICROPY_INCLUDED_STM32_BACKGROUND_H
#define MICROPY_INCLUDED_STM32_BACKGROUND_H
-#include <stdbool.h>
-
-void background_tasks_reset(void);
-void run_background_tasks(void);
-
#endif // MICROPY_INCLUDED_STM32_BACKGROUND_H
diff --git a/ports/stm/boards/STM32F411_nvm.ld b/ports/stm/boards/STM32F411_nvm.ld
index 5ac3e52a6..b2134b259 100644
--- a/ports/stm/boards/STM32F411_nvm.ld
+++ b/ports/stm/boards/STM32F411_nvm.ld
@@ -6,10 +6,10 @@
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K /* entire flash */
- FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */
- FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 32K /* sectors 1,2 are 16K */
- FLASH_NVM (rwx) : ORIGIN = 0x0800C000, LENGTH = 16K /* sector 3 is 16K */
- FLASH_FIRMWARE (rx) : ORIGIN = 0x08010000, LENGTH = 448K /* sector 4 is 64K, sectors 5,6,7 are 128K */
+ FLASH_ISR (rx) : ORIGIN = 0x08000000, LENGTH = 16K /* sector 0 */
+ FLASH_FS (rx) : ORIGIN = 0x08004000, LENGTH = 48K /* sectors 1,2,3 are 16K */
+ FLASH_NVM (rwx) : ORIGIN = 0x08010000, LENGTH = 64K /* sector 4 is 64K */
+ FLASH_FIRMWARE (rx) : ORIGIN = 0x08020000, LENGTH = 384K /* sectors 5,6,7 are 128K */
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
}
diff --git a/ports/stm/boards/thunderpack/mpconfigboard.h b/ports/stm/boards/thunderpack/mpconfigboard.h
index 394fbfd84..c2649e255 100644
--- a/ports/stm/boards/thunderpack/mpconfigboard.h
+++ b/ports/stm/boards/thunderpack/mpconfigboard.h
@@ -28,16 +28,16 @@
// Non-volatile memory config
#define CIRCUITPY_INTERNAL_NVM_SIZE (0x4000)
-#define CIRCUITPY_INTERNAL_NVM_START_ADDR (0x0800C000)
-#define CIRCUITPY_INTERNAL_NVM_SECTOR FLASH_SECTOR_3
+#define CIRCUITPY_INTERNAL_NVM_START_ADDR (0x08010000)
+#define CIRCUITPY_INTERNAL_NVM_SECTOR FLASH_SECTOR_4
// Putting the entire flash sector in the NVM byte array buffer
// would take up too much RAM. This limits how much of the sector we use.
-#define NVM_BYTEARRAY_BUFFER_SIZE 512
+#define NVM_BYTEARRAY_BUFFER_SIZE 512
// Flash config
-#define FLASH_SIZE (0x80000)
-#define FLASH_PAGE_SIZE (0x4000)
+#define FLASH_SIZE (0x80000)
+#define FLASH_PAGE_SIZE (0x4000)
#define BOARD_FLASH_SIZE (FLASH_SIZE - CIRCUITPY_INTERNAL_NVM_SIZE- 0x2000 - 0xC000)
#define HSE_VALUE ((uint32_t)24000000U)
@@ -47,7 +47,7 @@
#define BOARD_HAS_LOW_SPEED_CRYSTAL (0)
// Status LEDs
-#define MICROPY_HW_LED_STATUS (&pin_PA02)
+#define MICROPY_HW_LED_STATUS (&pin_PA02)
-#define DEFAULT_I2C_BUS_SCL (&pin_PB06)
-#define DEFAULT_I2C_BUS_SDA (&pin_PB07)
+#define DEFAULT_I2C_BUS_SCL (&pin_PB06)
+#define DEFAULT_I2C_BUS_SDA (&pin_PB07)
diff --git a/ports/stm/common-hal/analogio/AnalogIn.c b/ports/stm/common-hal/analogio/AnalogIn.c
index 1d1b308b6..588d687ee 100644
--- a/ports/stm/common-hal/analogio/AnalogIn.c
+++ b/ports/stm/common-hal/analogio/AnalogIn.c
@@ -29,7 +29,7 @@
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
-#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Pin.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_ll_gpio.h"
@@ -57,7 +57,7 @@ void common_hal_analogio_analogin_construct(analogio_analogin_obj_t* self,
} else {
mp_raise_ValueError(translate("Invalid ADC Unit value"));
}
- claim_pin(pin);
+ common_hal_mcu_pin_claim(pin);
self->pin = pin;
}
diff --git a/ports/stm/common-hal/analogio/AnalogOut.c b/ports/stm/common-hal/analogio/AnalogOut.c
index 2ea969f50..69c1f3e04 100644
--- a/ports/stm/common-hal/analogio/AnalogOut.c
+++ b/ports/stm/common-hal/analogio/AnalogOut.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2019, Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -86,7 +86,7 @@ void common_hal_analogio_analogout_construct(analogio_analogout_obj_t* self,
dac_on[self->dac_index] = true;
self->pin = pin;
- claim_pin(pin);
+ common_hal_mcu_pin_claim(pin);
#endif
}
diff --git a/ports/stm/common-hal/busio/I2C.c b/ports/stm/common-hal/busio/I2C.c
index 6adcf5575..b05d28c85 100644
--- a/ports/stm/common-hal/busio/I2C.c
+++ b/ports/stm/common-hal/busio/I2C.c
@@ -32,7 +32,7 @@
#include "shared-bindings/microcontroller/__init__.h"
#include "supervisor/shared/translate.h"
-#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Pin.h"
// I2C timing specs for the H7 and F7
// Configured for maximum possible clock settings for the family
@@ -161,8 +161,8 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
if (HAL_I2C_Init(&(self->handle)) != HAL_OK) {
mp_raise_RuntimeError(translate("I2C Init Error"));
}
- claim_pin(sda);
- claim_pin(scl);
+ common_hal_mcu_pin_claim(sda);
+ common_hal_mcu_pin_claim(scl);
}
void common_hal_busio_i2c_never_reset(busio_i2c_obj_t *self) {
diff --git a/ports/stm/common-hal/busio/SPI.c b/ports/stm/common-hal/busio/SPI.c
index 65eeb8ebc..15c746b62 100644
--- a/ports/stm/common-hal/busio/SPI.c
+++ b/ports/stm/common-hal/busio/SPI.c
@@ -33,7 +33,7 @@
#include "shared-bindings/microcontroller/__init__.h"
#include "boards/board.h"
#include "supervisor/shared/translate.h"
-#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Pin.h"
// Note that any bugs introduced in this file can cause crashes at startup
// for chips using external SPI flash.
@@ -107,104 +107,78 @@ void spi_reset(void) {
spi_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
}
-void common_hal_busio_spi_construct(busio_spi_obj_t *self,
+STATIC const mcu_periph_obj_t *find_pin_function(const mcu_periph_obj_t *table, size_t sz, const mcu_pin_obj_t *pin, int periph_index) {
+ for(size_t i = 0; i<sz; i++, table++) {
+ if(periph_index == table->periph_index && pin == table->pin ) {
+ return table;
+ }
+ }
+ return NULL;
+}
+
+//match pins to SPI objects
+STATIC int check_pins(busio_spi_obj_t *self,
const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi,
const mcu_pin_obj_t * miso) {
-
- //match pins to SPI objects
- SPI_TypeDef * SPIx;
+ bool spi_taken = false;
uint8_t sck_len = MP_ARRAY_SIZE(mcu_spi_sck_list);
uint8_t mosi_len = MP_ARRAY_SIZE(mcu_spi_mosi_list);
uint8_t miso_len = MP_ARRAY_SIZE(mcu_spi_miso_list);
- bool spi_taken = false;
//SCK is not optional. MOSI and MISO are
+ if (!sck) {
+ mp_raise_ValueError(translate("Must provide SCK pin"));
+ }
+
+ if (!miso && !mosi) {
+ mp_raise_ValueError(translate("Must provide MISO or MOSI pin"));
+ }
+
+ // Loop over each possibility for SCK. Check whether MISO and/or MOSI can be used on the same peripheral
for (uint i = 0; i < sck_len; i++) {
- if (mcu_spi_sck_list[i].pin == sck) {
- //if both MOSI and MISO exist, loop search normally
- if ((mosi != NULL) && (miso != NULL)) {
- //MOSI
- for (uint j = 0; j < mosi_len; j++) {
- if (mcu_spi_mosi_list[j].pin == mosi) {
- //MISO
- for (uint k = 0; k < miso_len; k++) {
- if ((mcu_spi_miso_list[k].pin == miso) //everything needs the same index
- && (mcu_spi_sck_list[i].periph_index == mcu_spi_mosi_list[j].periph_index)
- && (mcu_spi_sck_list[i].periph_index == mcu_spi_miso_list[k].periph_index)) {
- //keep looking if the SPI is taken, edge case
- if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) {
- spi_taken = true;
- continue;
- }
- //store pins if not
- self->sck = &mcu_spi_sck_list[i];
- self->mosi = &mcu_spi_mosi_list[j];
- self->miso = &mcu_spi_miso_list[k];
- break;
- }
- }
- if (self->sck != NULL) {
- break; // Multi-level break to pick lowest peripheral
- }
- }
- }
- if (self->sck != NULL) {
- break;
- }
- // if just MISO, reduce search
- } else if (miso != NULL) {
- for (uint j = 0; j < miso_len; j++) {
- if ((mcu_spi_miso_list[j].pin == miso) //only SCK and MISO need the same index
- && (mcu_spi_sck_list[i].periph_index == mcu_spi_miso_list[j].periph_index)) {
- if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) {
- spi_taken = true;
- continue;
- }
- self->sck = &mcu_spi_sck_list[i];
- self->mosi = NULL;
- self->miso = &mcu_spi_miso_list[j];
- break;
- }
- }
- if (self->sck != NULL) {
- break;
- }
- // if just MOSI, reduce search
- } else if (mosi != NULL) {
- for (uint j = 0; j < mosi_len; j++) {
- if ((mcu_spi_mosi_list[j].pin == mosi) //only SCK and MOSI need the same index
- && (mcu_spi_sck_list[i].periph_index == mcu_spi_mosi_list[j].periph_index)) {
- if (reserved_spi[mcu_spi_sck_list[i].periph_index - 1]) {
- spi_taken = true;
- continue;
- }
- self->sck = &mcu_spi_sck_list[i];
- self->mosi = &mcu_spi_mosi_list[j];
- self->miso = NULL;
- break;
- }
- }
- if (self->sck != NULL) {
- break;
- }
- } else {
- //throw an error immediately
- mp_raise_ValueError(translate("Must provide MISO or MOSI pin"));
- }
+ const mcu_periph_obj_t *mcu_spi_sck = &mcu_spi_sck_list[i];
+ if (mcu_spi_sck->pin != sck) {
+ continue;
+ }
+
+ int periph_index = mcu_spi_sck->periph_index;
+
+ const mcu_periph_obj_t *mcu_spi_miso = NULL;
+ if (miso && !(mcu_spi_miso = find_pin_function(mcu_spi_miso_list, miso_len, miso, periph_index))) {
+ continue;
}
+
+ const mcu_periph_obj_t *mcu_spi_mosi = NULL;
+ if (mosi && !(mcu_spi_mosi = find_pin_function(mcu_spi_mosi_list, mosi_len, mosi, periph_index))) {
+ continue;
+ }
+
+ if (reserved_spi[periph_index-1]) {
+ spi_taken = true;
+ continue;
+ }
+
+ self->sck = mcu_spi_sck;
+ self->mosi = mcu_spi_mosi;
+ self->miso = mcu_spi_miso;
+
+ return periph_index;
}
- //handle typedef selection, errors
- if (self->sck != NULL && (self->mosi != NULL || self->miso != NULL)) {
- SPIx = mcu_spi_banks[self->sck->periph_index - 1];
+ if (spi_taken) {
+ mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
} else {
- if (spi_taken) {
- mp_raise_ValueError(translate("Hardware busy, try alternative pins"));
- } else {
- mp_raise_ValueError(translate("Invalid SPI pin selection"));
- }
+ mp_raise_ValueError(translate("Invalid SPI pin selection"));
}
+}
+
+void common_hal_busio_spi_construct(busio_spi_obj_t *self,
+ const mcu_pin_obj_t * sck, const mcu_pin_obj_t * mosi,
+ const mcu_pin_obj_t * miso) {
+
+ int periph_index = check_pins(self, sck, mosi, miso);
+ SPI_TypeDef * SPIx = mcu_spi_banks[periph_index - 1];
//Start GPIO for each pin
GPIO_InitTypeDef GPIO_InitStruct = {0};
@@ -259,12 +233,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
self->phase = 0;
self->bits = 8;
- claim_pin(sck);
+ common_hal_mcu_pin_claim(sck);
if (self->mosi != NULL) {
- claim_pin(mosi);
+ common_hal_mcu_pin_claim(mosi);
}
if (self->miso != NULL) {
- claim_pin(miso);
+ common_hal_mcu_pin_claim(miso);
}
}
@@ -380,12 +354,12 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
}
bool common_hal_busio_spi_transfer(busio_spi_obj_t *self,
- uint8_t *data_out, uint8_t *data_in, size_t len) {
+ const uint8_t *data_out, uint8_t *data_in, size_t len) {
if (self->miso == NULL || self->mosi == NULL) {
mp_raise_ValueError(translate("Missing MISO or MOSI Pin"));
}
HAL_StatusTypeDef result = HAL_SPI_TransmitReceive (&self->handle,
- data_out, data_in, (uint16_t)len,HAL_MAX_DELAY);
+ (uint8_t *) data_out, data_in, (uint16_t)len,HAL_MAX_DELAY);
return result == HAL_OK;
}
diff --git a/ports/stm/common-hal/busio/UART.c b/ports/stm/common-hal/busio/UART.c
index 86a932290..08dae7e42 100644
--- a/ports/stm/common-hal/busio/UART.c
+++ b/ports/stm/common-hal/busio/UART.c
@@ -25,6 +25,7 @@
*/
#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/busio/UART.h"
#include "mpconfigport.h"
@@ -79,7 +80,7 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
const mcu_pin_obj_t * tx, const mcu_pin_obj_t * rx,
const mcu_pin_obj_t * rts, const mcu_pin_obj_t * cts,
const mcu_pin_obj_t * rs485_dir, bool rs485_invert,
- uint32_t baudrate, uint8_t bits, uart_parity_t parity, uint8_t stop,
+ uint32_t baudrate, uint8_t bits, busio_uart_parity_t parity, uint8_t stop,
mp_float_t timeout, uint16_t receiver_buffer_size, byte* receiver_buffer,
bool sigint_enabled) {
@@ -201,8 +202,8 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
self->handle.Init.BaudRate = baudrate;
self->handle.Init.WordLength = (bits == 9) ? UART_WORDLENGTH_9B : UART_WORDLENGTH_8B;
self->handle.Init.StopBits = (stop > 1) ? UART_STOPBITS_2 : UART_STOPBITS_1;
- self->handle.Init.Parity = (parity == PARITY_ODD) ? UART_PARITY_ODD :
- (parity == PARITY_EVEN) ? UART_PARITY_EVEN :
+ self->handle.Init.Parity = (parity == BUSIO_UART_PARITY_ODD) ? UART_PARITY_ODD :
+ (parity == BUSIO_UART_PARITY_EVEN) ? UART_PARITY_EVEN :
UART_PARITY_NONE;
self->handle.Init.Mode = (self->tx != NULL && self->rx != NULL) ? UART_MODE_TX_RX :
(self->tx != NULL) ? UART_MODE_TX :
@@ -224,10 +225,10 @@ void common_hal_busio_uart_construct(busio_uart_obj_t *self,
mp_raise_ValueError(translate("UART Buffer allocation error"));
}
}
- claim_pin(rx);
+ common_hal_mcu_pin_claim(rx);
}
if (self->tx != NULL) {
- claim_pin(tx);
+ common_hal_mcu_pin_claim(tx);
}
self->baudrate = baudrate;
self->timeout_ms = timeout * 1000;
diff --git a/ports/stm/common-hal/digitalio/DigitalInOut.c b/ports/stm/common-hal/digitalio/DigitalInOut.c
index 1354e1a32..a676aeb15 100644
--- a/ports/stm/common-hal/digitalio/DigitalInOut.c
+++ b/ports/stm/common-hal/digitalio/DigitalInOut.c
@@ -26,6 +26,7 @@
*/
#include "shared-bindings/digitalio/DigitalInOut.h"
+#include "shared-bindings/microcontroller/Pin.h"
#include "py/runtime.h"
#include "supervisor/shared/translate.h"
@@ -46,7 +47,7 @@ void common_hal_digitalio_digitalinout_never_reset(
digitalinout_result_t common_hal_digitalio_digitalinout_construct(
digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) {
- claim_pin(pin);
+ common_hal_mcu_pin_claim(pin);
self->pin = pin;
GPIO_InitTypeDef GPIO_InitStruct = {0};
diff --git a/ports/stm/common-hal/microcontroller/Pin.c b/ports/stm/common-hal/microcontroller/Pin.c
index 3e3fc0522..9fbdedead 100644
--- a/ports/stm/common-hal/microcontroller/Pin.c
+++ b/ports/stm/common-hal/microcontroller/Pin.c
@@ -89,6 +89,8 @@ void reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number) {
never_reset_pins[pin_port] |= 1<<pin_number;
+ // Make sure never reset pins are also always claimed
+ claimed_pins[pin_port] |= 1<<pin_number;
}
void common_hal_never_reset_pin(const mcu_pin_obj_t* pin) {
@@ -99,15 +101,9 @@ void common_hal_reset_pin(const mcu_pin_obj_t* pin) {
reset_pin_number(pin->port, pin->number);
}
-void claim_pin(const mcu_pin_obj_t* pin) {
+void claim_pin(uint8_t pin_port, uint8_t pin_number) {
// Set bit in claimed_pins bitmask.
- claimed_pins[pin->port] |= 1<<pin->number;
-
- #ifdef MICROPY_HW_NEOPIXEL
- if (pin == MICROPY_HW_NEOPIXEL) {
- neopixel_in_use = true;
- }
- #endif
+ claimed_pins[pin_port] |= 1<<pin_number;
}
bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number) {
@@ -137,7 +133,12 @@ uint8_t common_hal_mcu_pin_number(const mcu_pin_obj_t* pin) {
}
void common_hal_mcu_pin_claim(const mcu_pin_obj_t* pin) {
- claim_pin(pin);
+ claim_pin(pin->port, pin->number);
+ #ifdef MICROPY_HW_NEOPIXEL
+ if (pin == MICROPY_HW_NEOPIXEL) {
+ neopixel_in_use = true;
+ }
+ #endif
}
void common_hal_mcu_pin_reset_number(uint8_t pin_no) {
diff --git a/ports/stm/common-hal/microcontroller/Pin.h b/ports/stm/common-hal/microcontroller/Pin.h
index d69ddfb1d..f461d3813 100644
--- a/ports/stm/common-hal/microcontroller/Pin.h
+++ b/ports/stm/common-hal/microcontroller/Pin.h
@@ -43,7 +43,7 @@ void reset_all_pins(void);
// reset_pin_number takes the pin number instead of the pointer so that objects don't
// need to store a full pointer.
void reset_pin_number(uint8_t pin_port, uint8_t pin_number);
-void claim_pin(const mcu_pin_obj_t* pin);
+void claim_pin(uint8_t pin_port, uint8_t pin_number);
bool pin_number_is_free(uint8_t pin_port, uint8_t pin_number);
void never_reset_pin_number(uint8_t pin_port, uint8_t pin_number);
GPIO_TypeDef * pin_port(uint8_t pin_port);
diff --git a/ports/stm/common-hal/pulseio/PWMOut.c b/ports/stm/common-hal/pulseio/PWMOut.c
index 304a1539c..ddbadaf4c 100644
--- a/ports/stm/common-hal/pulseio/PWMOut.c
+++ b/ports/stm/common-hal/pulseio/PWMOut.c
@@ -33,7 +33,9 @@
#include "shared-bindings/microcontroller/__init__.h"
#include STM32_HAL_H
-#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+#include "timers.h"
#define ALL_CLOCKS 0xFFFF
@@ -41,32 +43,6 @@ STATIC uint8_t reserved_tim[TIM_BANK_ARRAY_LEN];
STATIC uint32_t tim_frequencies[TIM_BANK_ARRAY_LEN];
STATIC bool never_reset_tim[TIM_BANK_ARRAY_LEN];
-STATIC void tim_clock_enable(uint16_t mask);
-STATIC void tim_clock_disable(uint16_t mask);
-
-// Get the frequency (in Hz) of the source clock for the given timer.
-// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set.
-// If the APB prescaler is 1, then the timer clock is equal to its respective
-// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its
-// respective APB clock. See DM00031020 Rev 4, page 115.
-STATIC uint32_t timer_get_source_freq(uint32_t tim_id) {
- uint32_t source, clk_div;
- if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
- // TIM{1,8,9,10,11} are on APB2
- source = HAL_RCC_GetPCLK2Freq();
- clk_div = RCC->CFGR & RCC_CFGR_PPRE2;
- } else {
- // TIM{2,3,4,5,6,7,12,13,14} are on APB1
- source = HAL_RCC_GetPCLK1Freq();
- clk_div = RCC->CFGR & RCC_CFGR_PPRE1;
- }
- if (clk_div != 0) {
- // APB prescaler for this timer is > 1
- source *= 2;
- }
- return source;
-}
-
STATIC uint32_t timer_get_internal_duty(uint16_t duty, uint32_t period) {
//duty cycle is duty/0xFFFF fraction x (number of pulses per period)
return (duty*period) / ((1 << 16) - 1);
@@ -97,7 +73,6 @@ void pwmout_reset(void) {
never_reset_mask |= 1 << i;
}
}
- tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
}
pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
@@ -107,6 +82,7 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
bool variable_frequency) {
TIM_TypeDef * TIMx;
uint8_t tim_num = MP_ARRAY_SIZE(mcu_tim_pin_list);
+ bool tim_taken_internal = false;
bool tim_chan_taken = false;
bool tim_taken_f_mismatch = false;
bool var_freq_mismatch = false;
@@ -119,8 +95,13 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
//if pin is same
if (l_tim->pin == pin) {
- //check if the timer has a channel active
+ //check if the timer has a channel active, or is reserved by main timer system
if (reserved_tim[l_tim_index] != 0) {
+ // Timer has already been reserved by an internal module
+ if (stm_peripherals_timer_is_reserved(mcu_tim_banks[l_tim_index])) {
+ tim_taken_internal = true;
+ continue; //keep looking
+ }
//is it the same channel? (or all channels reserved by a var-freq)
if (reserved_tim[l_tim_index] & 1 << (l_tim_channel)) {
tim_chan_taken = true;
@@ -155,9 +136,12 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
reserved_tim[self->tim->tim_index - 1] |= 1 << (self->tim->channel_index - 1);
}
tim_frequencies[self->tim->tim_index - 1] = frequency;
+ stm_peripherals_timer_reserve(TIMx);
} else { //no match found
if (tim_chan_taken) {
mp_raise_ValueError(translate("No more timers available on this pin."));
+ } else if (tim_taken_internal) {
+ mp_raise_ValueError(translate("Timer was reserved for internal use - declare PWM pins earlier in the program"));
} else if (tim_taken_f_mismatch) {
mp_raise_ValueError(translate("Frequency must match existing PWMOut using this timer"));
} else if (var_freq_mismatch) {
@@ -182,8 +166,8 @@ pwmout_result_t common_hal_pulseio_pwmout_construct(pulseio_pwmout_obj_t* self,
uint32_t prescaler = 0; //prescaler is 15 bit
uint32_t period = 0; //period is 16 bit
- timer_get_optimal_divisors(&period, &prescaler, frequency,
- timer_get_source_freq(self->tim->tim_index));
+ uint32_t source_freq = stm_peripherals_timer_get_source_freq(TIMx);
+ timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq);
//Timer init
self->handle.Instance = TIMx;
@@ -260,7 +244,7 @@ void common_hal_pulseio_pwmout_deinit(pulseio_pwmout_obj_t* self) {
//if reserved timer has no active channels, we can disable it
if (!reserved_tim[self->tim->tim_index - 1]) {
tim_frequencies[self->tim->tim_index - 1] = 0x00;
- tim_clock_disable(1 << (self->tim->tim_index - 1));
+ stm_peripherals_timer_free(self->handle.Instance);
}
}
@@ -282,8 +266,8 @@ void common_hal_pulseio_pwmout_set_frequency(pulseio_pwmout_obj_t* self, uint32_
uint32_t prescaler = 0;
uint32_t period = 0;
- timer_get_optimal_divisors(&period, &prescaler, frequency,
- timer_get_source_freq(self->tim->tim_index));
+ uint32_t source_freq = stm_peripherals_timer_get_source_freq(self->handle.Instance);
+ timer_get_optimal_divisors(&period, &prescaler, frequency, source_freq);
//shut down
HAL_TIM_PWM_Stop(&self->handle, self->channel);
@@ -318,131 +302,3 @@ uint32_t common_hal_pulseio_pwmout_get_frequency(pulseio_pwmout_obj_t* self) {
bool common_hal_pulseio_pwmout_get_variable_frequency(pulseio_pwmout_obj_t* self) {
return self->variable_frequency;
}
-
-STATIC void tim_clock_enable(uint16_t mask) {
- #ifdef TIM1
- if (mask & (1 << 0)) {
- __HAL_RCC_TIM1_CLK_ENABLE();
- }
- #endif
- #ifdef TIM2
- if (mask & (1 << 1)) {
- __HAL_RCC_TIM2_CLK_ENABLE();
- }
- #endif
- #ifdef TIM3
- if (mask & (1 << 2)) {
- __HAL_RCC_TIM3_CLK_ENABLE();
- }
- #endif
- #ifdef TIM4
- if (mask & (1 << 3)) {
- __HAL_RCC_TIM4_CLK_ENABLE();
- }
- #endif
- #ifdef TIM5
- if (mask & (1 << 4)) {
- __HAL_RCC_TIM5_CLK_ENABLE();
- }
- #endif
- //6 and 7 are reserved ADC timers
- #ifdef TIM8
- if (mask & (1 << 7)) {
- __HAL_RCC_TIM8_CLK_ENABLE();
- }
- #endif
- #ifdef TIM9
- if (mask & (1 << 8)) {
- __HAL_RCC_TIM9_CLK_ENABLE();
- }
- #endif
- #ifdef TIM10
- if (mask & (1 << 9)) {
- __HAL_RCC_TIM10_CLK_ENABLE();
- }
- #endif
- #ifdef TIM11
- if (mask & (1 << 10)) {
- __HAL_RCC_TIM11_CLK_ENABLE();
- }
- #endif
- #ifdef TIM12
- if (mask & (1 << 11)) {
- __HAL_RCC_TIM12_CLK_ENABLE();
- }
- #endif
- #ifdef TIM13
- if (mask & (1 << 12)) {
- __HAL_RCC_TIM13_CLK_ENABLE();
- }
- #endif
- #ifdef TIM14
- if (mask & (1 << 13)) {
- __HAL_RCC_TIM14_CLK_ENABLE();
- }
- #endif
-}
-
-STATIC void tim_clock_disable(uint16_t mask) {
- #ifdef TIM1
- if (mask & (1 << 0)) {
- __HAL_RCC_TIM1_CLK_DISABLE();
- }
- #endif
- #ifdef TIM2
- if (mask & (1 << 1)) {
- __HAL_RCC_TIM2_CLK_DISABLE();
- }
- #endif
- #ifdef TIM3
- if (mask & (1 << 2)) {
- __HAL_RCC_TIM3_CLK_DISABLE();
- }
- #endif
- #ifdef TIM4
- if (mask & (1 << 3)) {
- __HAL_RCC_TIM4_CLK_DISABLE();
- }
- #endif
- #ifdef TIM5
- if (mask & (1 << 4)) {
- __HAL_RCC_TIM5_CLK_DISABLE();
- }
- #endif
- //6 and 7 are reserved ADC timers
- #ifdef TIM8
- if (mask & (1 << 7)) {
- __HAL_RCC_TIM8_CLK_DISABLE();
- }
- #endif
- #ifdef TIM9
- if (mask & (1 << 8)) {
- __HAL_RCC_TIM9_CLK_DISABLE();
- }
- #endif
- #ifdef TIM10
- if (mask & (1 << 9)) {
- __HAL_RCC_TIM10_CLK_DISABLE();
- }
- #endif
- #ifdef TIM11
- if (mask & (1 << 10)) {
- __HAL_RCC_TIM11_CLK_DISABLE();
- }
- #endif
- #ifdef TIM12
- if (mask & (1 << 11)) {
- __HAL_RCC_TIM12_CLK_DISABLE();
- }
- #endif
- #ifdef TIM13
- if (mask & (1 << 12)) {
- __HAL_RCC_TIM13_CLK_DISABLE();
- }
- #endif
- #ifdef TIM14
- if (mask & (1 << 13)) {
- __HAL_RCC_TIM14_CLK_DISABLE();
- }
- #endif
-}
diff --git a/ports/stm/common-hal/pulseio/PulseIn.c b/ports/stm/common-hal/pulseio/PulseIn.c
index 9d82a18a0..4052c240f 100644
--- a/ports/stm/common-hal/pulseio/PulseIn.c
+++ b/ports/stm/common-hal/pulseio/PulseIn.c
@@ -31,40 +31,38 @@
#include "py/gc.h"
#include "py/runtime.h"
#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/pulseio/PulseIn.h"
+#include "timers.h"
#include STM32_HAL_H
#define STM32_GPIO_PORT_SIZE 16
-
static pulseio_pulsein_obj_t* _objs[STM32_GPIO_PORT_SIZE];
-STATIC TIM_HandleTypeDef t6_handle;
+STATIC TIM_HandleTypeDef tim_handle;
static uint32_t overflow_count = 0;
STATIC uint8_t refcount = 0;
static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num);
-void TIM6_IRQHandler(void)
+void pulsein_timer_event_handler(void)
{
// Detect TIM Update event
- if (__HAL_TIM_GET_FLAG(&t6_handle, TIM_FLAG_UPDATE) != RESET)
+ if (__HAL_TIM_GET_FLAG(&tim_handle, TIM_FLAG_UPDATE) != RESET)
{
- if (__HAL_TIM_GET_IT_SOURCE(&t6_handle, TIM_IT_UPDATE) != RESET)
+ if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET)
{
- __HAL_TIM_CLEAR_IT(&t6_handle, TIM_IT_UPDATE);
+ __HAL_TIM_CLEAR_IT(&tim_handle, TIM_IT_UPDATE);
overflow_count++;
}
}
}
-static void pulsein_handler(uint8_t num) {
+static void pulsein_exti_event_handler(uint8_t num) {
// Grab the current time first.
uint32_t current_overflow = overflow_count;
- uint32_t current_count = 0;
- #if HAS_BASIC_TIM
- current_count = TIM6->CNT;
- #endif
+ uint32_t current_count = tim_handle.Instance->CNT;
// Interrupt register must be cleared manually
EXTI->PR = 1 << num;
@@ -105,17 +103,14 @@ void pulsein_reset(void) {
}
memset(_objs, 0, sizeof(_objs));
- #if HAS_BASIC_TIM
- __HAL_RCC_TIM6_CLK_DISABLE();
+ HAL_TIM_Base_DeInit(&tim_handle);
+ tim_clock_disable(stm_peripherals_timer_get_index(tim_handle.Instance));
+ memset(&tim_handle, 0, sizeof(tim_handle));
refcount = 0;
- #endif
}
void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu_pin_obj_t* pin,
uint16_t maxlen, bool idle_state) {
-#if !(HAS_BASIC_TIM)
- mp_raise_NotImplementedError(translate("PulseIn not supported on this chip"));
-#else
// STM32 has one shared EXTI for each pin number, 0-15
uint8_t p_num = pin->number;
if(_objs[p_num]) {
@@ -141,24 +136,34 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu
self->last_count = 0;
self->last_overflow = 0;
- if (HAL_TIM_Base_GetState(&t6_handle) == HAL_TIM_STATE_RESET) {
- // Set the new period
- t6_handle.Instance = TIM6;
- t6_handle.Init.Prescaler = 168; // HCLK is 168 mhz so divide down to 1mhz
- t6_handle.Init.Period = 0xffff;
- HAL_TIM_Base_Init(&t6_handle);
+ if (HAL_TIM_Base_GetState(&tim_handle) == HAL_TIM_STATE_RESET) {
+ // Find a suitable timer
+ TIM_TypeDef * tim_instance = stm_peripherals_find_timer();
+ stm_peripherals_timer_reserve(tim_instance);
+
+ // Set ticks to 1us
+ uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance);
+ uint32_t prescaler = source/1000000;
+
+ // Enable clocks and IRQ, set callback
+ stm_peripherals_timer_preinit(tim_instance, 4, pulsein_timer_event_handler);
- // TIM6 has limited HAL support, set registers manually
- t6_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
- t6_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
- t6_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
- __HAL_TIM_ENABLE_IT(&t6_handle, TIM_IT_UPDATE);
+ // Set the new period
+ tim_handle.Instance = tim_instance;
+ tim_handle.Init.Prescaler = prescaler - 1;
+ tim_handle.Init.Period = 0x10000 - 1; //65 ms period (maximum)
+ HAL_TIM_Base_Init(&tim_handle);
+
+ // Set registers manually
+ tim_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
+ tim_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
+ tim_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
+ __HAL_TIM_ENABLE_IT(&tim_handle, TIM_IT_UPDATE);
overflow_count = 0;
}
// Add to active PulseIns
refcount++;
-#endif
// EXTI pins can also be read as an input
GPIO_InitTypeDef GPIO_InitStruct = {0};
@@ -170,7 +175,7 @@ void common_hal_pulseio_pulsein_construct(pulseio_pulsein_obj_t* self, const mcu
// Interrupt starts immediately
assign_EXTI_Interrupt(self, pin->number);
HAL_NVIC_EnableIRQ(self->irq);
- claim_pin(pin);
+ common_hal_mcu_pin_claim(pin);
}
bool common_hal_pulseio_pulsein_deinited(pulseio_pulsein_obj_t* self) {
@@ -182,16 +187,13 @@ void common_hal_pulseio_pulsein_deinit(pulseio_pulsein_obj_t* self) {
return;
}
//Remove pulsein slot from shared array
- HAL_NVIC_DisableIRQ(self->irq);
_objs[self->pin->number] = NULL;
reset_pin_number(self->pin->port, self->pin->number);
self->pin = NULL;
refcount--;
if (refcount == 0) {
- #if HAS_BASIC_TIM
- __HAL_RCC_TIM6_CLK_DISABLE();
- #endif
+ stm_peripherals_timer_free(tim_handle.Instance);
}
}
@@ -299,23 +301,23 @@ static void assign_EXTI_Interrupt(pulseio_pulsein_obj_t* self, uint8_t num) {
void EXTI0_IRQHandler(void)
{
- pulsein_handler(0);
+ pulsein_exti_event_handler(0);
}
void EXTI1_IRQHandler(void)
{
- pulsein_handler(1);
+ pulsein_exti_event_handler(1);
}
void EXTI2_IRQHandler(void)
{
- pulsein_handler(2);
+ pulsein_exti_event_handler(2);
}
void EXTI3_IRQHandler(void)
{
- pulsein_handler(3);
+ pulsein_exti_event_handler(3);
}
void EXTI4_IRQHandler(void)
{
- pulsein_handler(4);
+ pulsein_exti_event_handler(4);
}
void EXTI9_5_IRQHandler(void)
@@ -323,7 +325,7 @@ void EXTI9_5_IRQHandler(void)
uint32_t pending = EXTI->PR;
for (uint i = 5; i <= 9; i++) {
if(pending & (1 << i)) {
- pulsein_handler(i);
+ pulsein_exti_event_handler(i);
}
}
}
@@ -333,7 +335,7 @@ void EXTI15_10_IRQHandler(void)
uint32_t pending = EXTI->PR;
for (uint i = 10; i <= 15; i++) {
if(pending & (1 << i)) {
- pulsein_handler(i);
+ pulsein_exti_event_handler(i);
}
}
}
diff --git a/ports/stm/common-hal/pulseio/PulseOut.c b/ports/stm/common-hal/pulseio/PulseOut.c
index c7c879c88..bcc25d817 100644
--- a/ports/stm/common-hal/pulseio/PulseOut.c
+++ b/ports/stm/common-hal/pulseio/PulseOut.c
@@ -36,20 +36,20 @@
#include "supervisor/shared/translate.h"
#include STM32_HAL_H
-#include "common-hal/microcontroller/Pin.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "timers.h"
// A single timer is shared amongst all PulseOut objects under the assumption that
// the code is single threaded.
STATIC uint8_t refcount = 0;
-
STATIC uint16_t *pulse_array = NULL;
STATIC volatile uint16_t pulse_array_index = 0;
STATIC uint16_t pulse_array_length;
-
//Timer is shared, must be accessible by interrupt
-STATIC TIM_HandleTypeDef t7_handle;
+STATIC TIM_HandleTypeDef tim_handle;
pulseio_pulseout_obj_t *curr_pulseout = NULL;
+
STATIC void turn_on(pulseio_pulseout_obj_t *pulseout) {
// Turn on PWM
HAL_TIM_PWM_Start(&(pulseout->pwmout->handle), pulseout->pwmout->channel);
@@ -65,91 +65,78 @@ STATIC void turn_off(pulseio_pulseout_obj_t *pulseout) {
STATIC void start_timer(void) {
// Set the new period
- t7_handle.Init.Period = pulse_array[pulse_array_index] - 1;
- HAL_TIM_Base_Init(&t7_handle);
+ tim_handle.Init.Period = pulse_array[pulse_array_index] - 1;
+ HAL_TIM_Base_Init(&tim_handle);
// TIM7 has limited HAL support, set registers manually
- t7_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
- t7_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
- t7_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
- __HAL_TIM_ENABLE_IT(&t7_handle, TIM_IT_UPDATE);
-
+ tim_handle.Instance->SR = 0; // Prevent the SR from triggering an interrupt
+ tim_handle.Instance->CR1 |= TIM_CR1_CEN; // Resume timer
+ tim_handle.Instance->CR1 |= TIM_CR1_URS; // Disable non-overflow interrupts
+ __HAL_TIM_ENABLE_IT(&tim_handle, TIM_IT_UPDATE);
}
STATIC void pulseout_event_handler(void) {
- if (curr_pulseout->pwmout == NULL) {
- return; //invalid interrupt
- }
-
- HAL_GPIO_WritePin(pin_port(2),pin_mask(6), 1);
- HAL_GPIO_WritePin(pin_port(2),pin_mask(6), 0);
-
- pulse_array_index++;
-
- // No more pulses. Turn off output and don't restart.
- if (pulse_array_index >= pulse_array_length) {
- turn_off(curr_pulseout);
- return;
- }
-
- // Alternate on and off, starting with on.
- if (pulse_array_index % 2 == 0) {
- turn_on(curr_pulseout);
- } else {
- turn_off(curr_pulseout);
+ // Detect TIM Update event
+ if (__HAL_TIM_GET_FLAG(&tim_handle, TIM_FLAG_UPDATE) != RESET)
+ {
+ if (__HAL_TIM_GET_IT_SOURCE(&tim_handle, TIM_IT_UPDATE) != RESET)
+ {
+ __HAL_TIM_CLEAR_IT(&tim_handle, TIM_IT_UPDATE);
+ if (curr_pulseout->pwmout == NULL) {
+ return; //invalid interrupt
+ }
+
+ pulse_array_index++;
+
+ // No more pulses. Turn off output and don't restart.
+ if (pulse_array_index >= pulse_array_length) {
+ turn_off(curr_pulseout);
+ return;
+ }
+
+ // Alternate on and off, starting with on.
+ if (pulse_array_index % 2 == 0) {
+ turn_on(curr_pulseout);
+ } else {
+ turn_off(curr_pulseout);
+ }
+
+ // Count up to the next given value.
+ start_timer();
+ }
}
-
- // Count up to the next given value.
- start_timer();
}
void pulseout_reset() {
- #if HAS_BASIC_TIM
- __HAL_RCC_TIM7_CLK_DISABLE();
+ stm_peripherals_timer_free(tim_handle.Instance);
refcount = 0;
- #endif
}
void common_hal_pulseio_pulseout_construct(pulseio_pulseout_obj_t* self,
const pulseio_pwmout_obj_t* carrier) {
-#if !(HAS_BASIC_TIM)
- mp_raise_NotImplementedError(translate("PulseOut not supported on this chip"));
-#else
// Add to active PulseOuts
refcount++;
+ TIM_TypeDef * tim_instance = stm_peripherals_find_timer();
+ stm_peripherals_timer_reserve(tim_instance);
- // Calculate a 1 ms period
- uint32_t source, clk_div;
- source = HAL_RCC_GetPCLK1Freq(); // TIM7 is on APB1
- clk_div = RCC->CFGR & RCC_CFGR_PPRE1;
- // APB quirk, see See DM00031020 Rev 4, page 115.
- if (clk_div != 0) {
- // APB prescaler for this timer is > 1
- source *= 2;
- }
-
+ //calculate a 1ms period
+ uint32_t source = stm_peripherals_timer_get_source_freq(tim_instance);
uint32_t prescaler = source/1000000; //1us intervals
- __HAL_RCC_TIM7_CLK_ENABLE();
- HAL_NVIC_SetPriority(TIM7_IRQn, 4, 0);
- HAL_NVIC_EnableIRQ(TIM7_IRQn);
-
- // Timers 6 and 7 have no pins, so using them doesn't affect PWM availability
- t7_handle.Instance = TIM7;
- t7_handle.Init.Period = 100; //immediately replaced.
- t7_handle.Init.Prescaler = prescaler - 1;
- t7_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
- t7_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
- t7_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+ stm_peripherals_timer_preinit(tim_instance, 4, pulseout_event_handler);
+ tim_handle.Instance = tim_instance;
+ tim_handle.Init.Period = 100; //immediately replaced.
+ tim_handle.Init.Prescaler = prescaler - 1;
+ tim_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+ tim_handle.Init.CounterMode = TIM_COUNTERMODE_UP;
+ tim_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
- HAL_TIM_Base_Init(&t7_handle);
- t7_handle.Instance->SR = 0;
+ HAL_TIM_Base_Init(&tim_handle);
+ tim_handle.Instance->SR = 0;
// The HAL can't work with const, recast required.
self->pwmout = (pulseio_pwmout_obj_t*)carrier;
-
turn_off(self);
-#endif
}
bool common_hal_pulseio_pulseout_deinited(pulseio_pulseout_obj_t* self) {
@@ -165,9 +152,7 @@ void common_hal_pulseio_pulseout_deinit(pulseio_pulseout_obj_t* self) {
refcount--;
if (refcount == 0) {
- #if HAS_BASIC_TIM
- __HAL_RCC_TIM7_CLK_DISABLE();
- #endif
+ stm_peripherals_timer_free(tim_handle.Instance);
}
}
@@ -190,24 +175,11 @@ void common_hal_pulseio_pulseout_send(pulseio_pulseout_obj_t* self, uint16_t* pu
// signal.
RUN_BACKGROUND_TASKS;
- // Use when debugging, or issues are irrecoverable
+ // // Use when debugging, or issues are irrecoverable
// if ((supervisor_ticks_ms64() - starttime ) > timeout ) {
// mp_raise_RuntimeError(translate("Error: Send Timeout"));
// }
}
//turn off timer counter.
- t7_handle.Instance->CR1 &= ~TIM_CR1_CEN;
-}
-
-void TIM7_IRQHandler(void)
-{
- // Detect TIM Update event
- if (__HAL_TIM_GET_FLAG(&t7_handle, TIM_FLAG_UPDATE) != RESET)
- {
- if (__HAL_TIM_GET_IT_SOURCE(&t7_handle, TIM_IT_UPDATE) != RESET)
- {
- __HAL_TIM_CLEAR_IT(&t7_handle, TIM_IT_UPDATE);
- pulseout_event_handler();
- }
- }
+ tim_handle.Instance->CR1 &= ~TIM_CR1_CEN;
}
diff --git a/ports/stm/common-hal/rgbmatrix/RGBMatrix.c b/ports/stm/common-hal/rgbmatrix/RGBMatrix.c
index 9e60cc3e6..3b42631ad 100644
--- a/ports/stm/common-hal/rgbmatrix/RGBMatrix.c
+++ b/ports/stm/common-hal/rgbmatrix/RGBMatrix.c
@@ -27,28 +27,30 @@
#include <stddef.h>
#include "common-hal/rgbmatrix/RGBMatrix.h"
+#include "timers.h"
#include STM32_HAL_H
extern void _PM_IRQ_HANDLER(void);
void *common_hal_rgbmatrix_timer_allocate() {
- // TODO(jepler) properly handle resource allocation including never-reset
- return TIM6;
+ TIM_TypeDef * timer = stm_peripherals_find_timer();
+ stm_peripherals_timer_reserve(timer);
+ return timer;
}
-
void common_hal_rgbmatrix_timer_enable(void* ptr) {
- HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
+ TIM_TypeDef *tim = (TIM_TypeDef*)ptr;
+ HAL_NVIC_EnableIRQ(stm_peripherals_timer_get_irqnum(tim));
}
void common_hal_rgbmatrix_timer_disable(void* ptr) {
TIM_TypeDef *tim = (TIM_TypeDef*)ptr;
tim->DIER &= ~TIM_DIER_UIE;
- HAL_NVIC_DisableIRQ(TIM6_DAC_IRQn);
}
void common_hal_rgbmatrix_timer_free(void* ptr) {
+ TIM_TypeDef *tim = (TIM_TypeDef*)ptr;
+ stm_peripherals_timer_free(tim);
common_hal_rgbmatrix_timer_disable(ptr);
- // TODO(jepler) properly handle resource allocation including never-reset
}
diff --git a/ports/stm/fatfs_port.c b/ports/stm/fatfs_port.c
index 6a17f627b..631f7f098 100644
--- a/ports/stm/fatfs_port.c
+++ b/ports/stm/fatfs_port.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/stm/peripherals/stm32f4/stm32f405xx/periph.c b/ports/stm/peripherals/stm32f4/stm32f405xx/periph.c
index e75f0b206..e2124bc30 100644
--- a/ports/stm/peripherals/stm32f4/stm32f405xx/periph.c
+++ b/ports/stm/peripherals/stm32f4/stm32f405xx/periph.c
@@ -29,55 +29,57 @@
#include "peripherals/pins.h"
#include "peripherals/periph.h"
-// I2C
+I2C_TypeDef * mcu_i2c_banks[I2C_BANK_ARRAY_LEN] = {I2C1, I2C2, I2C3};
-I2C_TypeDef * mcu_i2c_banks[3] = {I2C1, I2C2, I2C3};
-
-const mcu_periph_obj_t mcu_i2c_sda_list[4] = {
+const mcu_periph_obj_t mcu_i2c_sda_list[I2C_SDA_ARRAY_LEN] = {
PERIPH(1, 4, &pin_PB07),
PERIPH(1, 4, &pin_PB09),
PERIPH(2, 4, &pin_PB11),
PERIPH(3, 4, &pin_PC09),
+ PERIPH(2, 4, &pin_PF00),
+ PERIPH(2, 4, &pin_PH05),
+ PERIPH(3, 4, &pin_PH08),
};
-
-const mcu_periph_obj_t mcu_i2c_scl_list[4] = {
+const mcu_periph_obj_t mcu_i2c_scl_list[I2C_SCL_ARRAY_LEN] = {
+ PERIPH(3, 4, &pin_PA08),
PERIPH(1, 4, &pin_PB06),
PERIPH(1, 4, &pin_PB08),
PERIPH(2, 4, &pin_PB10),
- PERIPH(3, 4, &pin_PA08)
+ PERIPH(2, 4, &pin_PF01),
+ PERIPH(2, 4, &pin_PH04),
+ PERIPH(3, 4, &pin_PH07),
};
-SPI_TypeDef * mcu_spi_banks[3] = {SPI1, SPI2, SPI3};
+SPI_TypeDef * mcu_spi_banks[SPI_BANK_ARRAY_LEN] = {SPI1, SPI2, SPI3};
-const mcu_periph_obj_t mcu_spi_sck_list[7] = {
+const mcu_periph_obj_t mcu_spi_sck_list[SPI_SCK_ARRAY_LEN] = {
PERIPH(1, 5, &pin_PA05),
PERIPH(1, 5, &pin_PB03),
+ PERIPH(3, 6, &pin_PB03),
PERIPH(2, 5, &pin_PB10),
PERIPH(2, 5, &pin_PB13),
- PERIPH(2, 5, &pin_PC07),
- PERIPH(3, 6, &pin_PB03),
PERIPH(3, 6, &pin_PC10),
+ PERIPH(2, 5, &pin_PI01),
};
-
-const mcu_periph_obj_t mcu_spi_mosi_list[6] = {
+const mcu_periph_obj_t mcu_spi_mosi_list[SPI_MOSI_ARRAY_LEN] = {
PERIPH(1, 5, &pin_PA07),
PERIPH(1, 5, &pin_PB05),
+ PERIPH(3, 6, &pin_PB05),
PERIPH(2, 5, &pin_PB15),
PERIPH(2, 5, &pin_PC03),
- PERIPH(3, 6, &pin_PB05),
PERIPH(3, 6, &pin_PC12),
+ PERIPH(2, 5, &pin_PI03),
};
-
-const mcu_periph_obj_t mcu_spi_miso_list[6] = {
+const mcu_periph_obj_t mcu_spi_miso_list[SPI_MISO_ARRAY_LEN] = {
PERIPH(1, 5, &pin_PA06),
PERIPH(1, 5, &pin_PB04),
+ PERIPH(3, 6, &pin_PB04),
PERIPH(2, 5, &pin_PB14),
PERIPH(2, 5, &pin_PC02),
- PERIPH(3, 6, &pin_PB04),
PERIPH(3, 6, &pin_PC11),
+ PERIPH(2, 5, &pin_PI02),
};
-
-const mcu_periph_obj_t mcu_spi_nss_list[6] = {
+const mcu_periph_obj_t mcu_spi_nss_list[SPI_NSS_ARRAY_LEN] = {
PERIPH(1, 5, &pin_PA04),
PERIPH(1, 5, &pin_PA15),
PERIPH(2, 5, &pin_PB09),
@@ -89,7 +91,7 @@ const mcu_periph_obj_t mcu_spi_nss_list[6] = {
USART_TypeDef * mcu_uart_banks[MAX_UART] = {USART1, USART2, USART3, UART4, UART5, USART6};
bool mcu_uart_has_usart[MAX_UART] = {true, true, true, false, false, true};
-const mcu_periph_obj_t mcu_uart_tx_list[12] = {
+const mcu_periph_obj_t mcu_uart_tx_list[UART_TX_ARRAY_LEN] = {
PERIPH(4, 8, &pin_PA00),
PERIPH(2, 7, &pin_PA02),
PERIPH(1, 7, &pin_PA09),
@@ -103,8 +105,7 @@ const mcu_periph_obj_t mcu_uart_tx_list[12] = {
PERIPH(3, 7, &pin_PD08),
PERIPH(6, 8, &pin_PG14),
};
-
-const mcu_periph_obj_t mcu_uart_rx_list[12] = {
+const mcu_periph_obj_t mcu_uart_rx_list[UART_RX_ARRAY_LEN] = {
PERIPH(4, 8, &pin_PA01),
PERIPH(2, 7, &pin_PA03),
PERIPH(1, 7, &pin_PA10),
@@ -121,74 +122,75 @@ const mcu_periph_obj_t mcu_uart_rx_list[12] = {
//Timers
//TIM6 and TIM7 are basic timers that are only used by DAC, and don't have pins
-TIM_TypeDef * mcu_tim_banks[14] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10,
+TIM_TypeDef * mcu_tim_banks[TIM_BANK_ARRAY_LEN] = {TIM1, TIM2, TIM3, TIM4, TIM5, NULL, NULL, TIM8, TIM9, TIM10,
TIM11, TIM12, TIM13, TIM14};
-const mcu_tim_pin_obj_t mcu_tim_pin_list[56] = {
- TIM(2,1,1,&pin_PA00),
- TIM(5,2,1,&pin_PA00),
- TIM(2,1,2,&pin_PA01),
- TIM(5,2,2,&pin_PA01),
- TIM(2,1,3,&pin_PA02),
- TIM(5,2,3,&pin_PA02),
- TIM(2,1,4,&pin_PA03),
- TIM(5,2,4,&pin_PA03),
- TIM(9,3,1,&pin_PA02),
- TIM(9,3,2,&pin_PA03),
- TIM(3,2,1,&pin_PA06),
- TIM(13,9,1,&pin_PA06),
- TIM(3,2,2,&pin_PA07),
- TIM(14,9,1,&pin_PA07),
- TIM(1,1,1,&pin_PA08),
- TIM(1,1,2,&pin_PA09),
- TIM(1,1,3,&pin_PA10),
- TIM(1,1,4,&pin_PA11),
- TIM(2,1,1,&pin_PA15),
- TIM(3,2,3,&pin_PB00),
- TIM(3,2,4,&pin_PB01),
- TIM(2,1,2,&pin_PB03),
- TIM(3,2,1,&pin_PB04),
- TIM(3,2,2,&pin_PB05),
- TIM(4,2,1,&pin_PB06),
- TIM(4,2,2,&pin_PB07),
- TIM(4,2,3,&pin_PB08),
- TIM(10,2,1,&pin_PB08),
- TIM(4,2,4,&pin_PB09),
- TIM(11,2,1,&pin_PB09),
- TIM(2,1,3,&pin_PB10),
- TIM(2,1,4,&pin_PB11),
- TIM(12,9,1,&pin_PB14),
- TIM(12,9,2,&pin_PB15),
- TIM(3,2,1,&pin_PC06),
- TIM(3,2,2,&pin_PC07),
- TIM(3,2,3,&pin_PC08),
- TIM(3,2,4,&pin_PC09),
- TIM(8,3,1,&pin_PC06),
- TIM(8,3,2,&pin_PC07),
- TIM(8,3,3,&pin_PC08),
- TIM(8,3,4,&pin_PC09),
- TIM(4,2,1,&pin_PD12),
- TIM(4,2,2,&pin_PD13),
- TIM(4,2,3,&pin_PD14),
- TIM(4,2,4,&pin_PD15),
- TIM(9,3,1,&pin_PE05),
- TIM(9,3,2,&pin_PE06),
- TIM(1,1,1,&pin_PE09),
- TIM(1,1,2,&pin_PE11),
- TIM(1,1,3,&pin_PE13),
- TIM(1,1,4,&pin_PE14),
- TIM(10,3,1,&pin_PF06),
- TIM(11,3,1,&pin_PF07),
- TIM(13,9,1,&pin_PF08),
- TIM(14,9,1,&pin_PF09),
- // TIM(12,9,1,&pin_PH06), //TODO: include these when pin map is expanded
- // TIM(12,9,2,&pin_PH09),
- // TIM(5,2,1,&pin_PH10),
- // TIM(5,2,2,&pin_PH11),
- // TIM(5,2,3,&pin_PH12),
- // TIM(5,2,4,&pin_PI00),
- // TIM(8,3,4,&pin_PI02),
- // TIM(8,3,1,&pin_PI05),
- // TIM(8,3,2,&pin_PI06),
- // TIM(8,3,3,&pin_PI07),
+const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN] = {
+ TIM(2, 1, 1, &pin_PA00),
+ TIM(5, 2, 1, &pin_PA00),
+ TIM(2, 1, 2, &pin_PA01),
+ TIM(5, 2, 2, &pin_PA01),
+ TIM(2, 1, 3, &pin_PA02),
+ TIM(5, 2, 3, &pin_PA02),
+ TIM(9, 3, 1, &pin_PA02),
+ TIM(2, 1, 4, &pin_PA03),
+ TIM(5, 2, 4, &pin_PA03),
+ TIM(9, 3, 2, &pin_PA03),
+ TIM(2, 1, 1, &pin_PA05),
+ TIM(3, 2, 1, &pin_PA06),
+ TIM(13, 9, 1, &pin_PA06),
+ TIM(3, 2, 2, &pin_PA07),
+ TIM(14, 9, 1, &pin_PA07),
+ TIM(1, 1, 1, &pin_PA08),
+ TIM(1, 1, 2, &pin_PA09),
+ TIM(1, 1, 3, &pin_PA10),
+ TIM(1, 1, 4, &pin_PA11),
+ TIM(2, 1, 1, &pin_PA15),
+ TIM(3, 2, 3, &pin_PB00),
+ TIM(3, 2, 4, &pin_PB01),
+ TIM(2, 1, 2, &pin_PB03),
+ TIM(3, 2, 1, &pin_PB04),
+ TIM(3, 2, 2, &pin_PB05),
+ TIM(4, 2, 1, &pin_PB06),
+ TIM(4, 2, 2, &pin_PB07),
+ TIM(4, 2, 3, &pin_PB08),
+ TIM(10, 3, 1, &pin_PB08),
+ TIM(4, 2, 4, &pin_PB09),
+ TIM(11, 3, 1, &pin_PB09),
+ TIM(2, 1, 3, &pin_PB10),
+ TIM(2, 1, 4, &pin_PB11),
+ TIM(12, 9, 1, &pin_PB14),
+ TIM(12, 9, 2, &pin_PB15),
+ TIM(3, 2, 1, &pin_PC06),
+ TIM(8, 3, 1, &pin_PC06),
+ TIM(3, 2, 2, &pin_PC07),
+ TIM(8, 3, 2, &pin_PC07),
+ TIM(3, 2, 3, &pin_PC08),
+ TIM(8, 3, 3, &pin_PC08),
+ TIM(3, 2, 4, &pin_PC09),
+ TIM(8, 3, 4, &pin_PC09),
+ TIM(4, 2, 1, &pin_PD12),
+ TIM(4, 2, 2, &pin_PD13),
+ TIM(4, 2, 3, &pin_PD14),
+ TIM(4, 2, 4, &pin_PD15),
+ TIM(9, 3, 1, &pin_PE05),
+ TIM(9, 3, 2, &pin_PE06),
+ TIM(1, 1, 1, &pin_PE09),
+ TIM(1, 1, 2, &pin_PE11),
+ TIM(1, 1, 3, &pin_PE13),
+ TIM(1, 1, 4, &pin_PE14),
+ TIM(10, 3, 1, &pin_PF06),
+ TIM(11, 3, 1, &pin_PF07),
+ TIM(13, 9, 1, &pin_PF08),
+ TIM(14, 9, 1, &pin_PF09),
+ TIM(12, 9, 1, &pin_PH06),
+ TIM(12, 9, 2, &pin_PH09),
+ TIM(5, 2, 1, &pin_PH10),
+ TIM(5, 2, 2, &pin_PH11),
+ TIM(5, 2, 3, &pin_PH12),
+ TIM(5, 2, 4, &pin_PI00),
+ TIM(8, 3, 4, &pin_PI02),
+ TIM(8, 3, 1, &pin_PI05),
+ TIM(8, 3, 2, &pin_PI06),
+ TIM(8, 3, 3, &pin_PI07),
};
diff --git a/ports/stm/peripherals/stm32f4/stm32f405xx/periph.h b/ports/stm/peripherals/stm32f4/stm32f405xx/periph.h
index df67a99d7..e52568c85 100644
--- a/ports/stm/peripherals/stm32f4/stm32f405xx/periph.h
+++ b/ports/stm/peripherals/stm32f4/stm32f405xx/periph.h
@@ -28,29 +28,36 @@
#define MICROPY_INCLUDED_STM32_PERIPHERALS_STM32F405XX_PERIPH_H
//I2C
-extern I2C_TypeDef * mcu_i2c_banks[3];
-
-extern const mcu_periph_obj_t mcu_i2c_sda_list[4];
-extern const mcu_periph_obj_t mcu_i2c_scl_list[4];
+#define I2C_BANK_ARRAY_LEN 3
+#define I2C_SDA_ARRAY_LEN 7
+#define I2C_SCL_ARRAY_LEN 7
+extern I2C_TypeDef * mcu_i2c_banks[I2C_BANK_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_i2c_sda_list[I2C_SDA_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_i2c_scl_list[I2C_SCL_ARRAY_LEN];
//SPI
-extern SPI_TypeDef * mcu_spi_banks[3];
-
-extern const mcu_periph_obj_t mcu_spi_sck_list[7];
-extern const mcu_periph_obj_t mcu_spi_mosi_list[6];
-extern const mcu_periph_obj_t mcu_spi_miso_list[6];
-extern const mcu_periph_obj_t mcu_spi_nss_list[6];
+#define SPI_BANK_ARRAY_LEN 3
+#define SPI_SCK_ARRAY_LEN 7
+#define SPI_MOSI_ARRAY_LEN 7
+#define SPI_MISO_ARRAY_LEN 7
+#define SPI_NSS_ARRAY_LEN 6
+extern SPI_TypeDef * mcu_spi_banks[SPI_BANK_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_spi_sck_list[SPI_SCK_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_spi_mosi_list[SPI_MOSI_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_spi_miso_list[SPI_MISO_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_spi_nss_list[SPI_NSS_ARRAY_LEN];
//UART
+#define UART_TX_ARRAY_LEN 12
+#define UART_RX_ARRAY_LEN 12
extern USART_TypeDef * mcu_uart_banks[MAX_UART];
extern bool mcu_uart_has_usart[MAX_UART];
-
-extern const mcu_periph_obj_t mcu_uart_tx_list[12];
-extern const mcu_periph_obj_t mcu_uart_rx_list[12];
+extern const mcu_periph_obj_t mcu_uart_tx_list[UART_TX_ARRAY_LEN];
+extern const mcu_periph_obj_t mcu_uart_rx_list[UART_RX_ARRAY_LEN];
//Timers
#define TIM_BANK_ARRAY_LEN 14
-#define TIM_PIN_ARRAY_LEN 56
+#define TIM_PIN_ARRAY_LEN 67
TIM_TypeDef * mcu_tim_banks[TIM_BANK_ARRAY_LEN];
const mcu_tim_pin_obj_t mcu_tim_pin_list[TIM_PIN_ARRAY_LEN];
diff --git a/ports/stm/peripherals/stm32f4/stm32f405xx/pins.c b/ports/stm/peripherals/stm32f4/stm32f405xx/pins.c
index 4282741a8..62acb1955 100644
--- a/ports/stm/peripherals/stm32f4/stm32f405xx/pins.c
+++ b/ports/stm/peripherals/stm32f4/stm32f405xx/pins.c
@@ -28,33 +28,6 @@
#include "py/mphal.h"
#include "peripherals/pins.h"
-const mcu_pin_obj_t pin_PE02 = PIN(4, 2, NO_ADC);
-const mcu_pin_obj_t pin_PE03 = PIN(4, 3, NO_ADC);
-const mcu_pin_obj_t pin_PE04 = PIN(4, 4, NO_ADC);
-const mcu_pin_obj_t pin_PE05 = PIN(4, 5, NO_ADC);
-const mcu_pin_obj_t pin_PE06 = PIN(4, 6, NO_ADC);
-
-const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC); //anti-tamp
-const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC); //OSC32_IN
-const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC); //OSC32_OUT
-
-const mcu_pin_obj_t pin_PF00 = PIN(5, 0, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF01 = PIN(5, 1, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF02 = PIN(5, 2, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF03 = PIN(5, 3, ADC_INPUT(ADC_3,9)); // 144 only
-const mcu_pin_obj_t pin_PF04 = PIN(5, 4, ADC_INPUT(ADC_3,14)); // 144 only
-const mcu_pin_obj_t pin_PF05 = PIN(5, 5, ADC_INPUT(ADC_3,15)); // 144 only
-const mcu_pin_obj_t pin_PF06 = PIN(5, 6, ADC_INPUT(ADC_3,4)); // 144 only
-const mcu_pin_obj_t pin_PF07 = PIN(5, 7, ADC_INPUT(ADC_3,5)); // 144 only
-const mcu_pin_obj_t pin_PF08 = PIN(5, 8, ADC_INPUT(ADC_3,6)); // 144 only
-const mcu_pin_obj_t pin_PF09 = PIN(5, 9, ADC_INPUT(ADC_3,7)); // 144 only
-const mcu_pin_obj_t pin_PF10 = PIN(5, 10, ADC_INPUT(ADC_3,8)); // 144 only
-
-const mcu_pin_obj_t pin_PC00 = PIN(2, 0, ADC_INPUT(ADC_123,10));
-const mcu_pin_obj_t pin_PC01 = PIN(2, 1, ADC_INPUT(ADC_123,11));
-const mcu_pin_obj_t pin_PC02 = PIN(2, 2, ADC_INPUT(ADC_123,12));
-const mcu_pin_obj_t pin_PC03 = PIN(2, 3, ADC_INPUT(ADC_123,13));
-
const mcu_pin_obj_t pin_PA00 = PIN(0, 0, ADC_INPUT(ADC_123,0));
const mcu_pin_obj_t pin_PA01 = PIN(0, 1, ADC_INPUT(ADC_123,1));
const mcu_pin_obj_t pin_PA02 = PIN(0, 2, ADC_INPUT(ADC_123,2));
@@ -63,75 +36,46 @@ const mcu_pin_obj_t pin_PA04 = PIN(0, 4, ADC_INPUT(ADC_12,4));
const mcu_pin_obj_t pin_PA05 = PIN(0, 5, ADC_INPUT(ADC_12,5));
const mcu_pin_obj_t pin_PA06 = PIN(0, 6, ADC_INPUT(ADC_12,6));
const mcu_pin_obj_t pin_PA07 = PIN(0, 7, ADC_INPUT(ADC_12,7));
-
-const mcu_pin_obj_t pin_PC04 = PIN(2, 4, ADC_INPUT(ADC_12,14));
-const mcu_pin_obj_t pin_PC05 = PIN(2, 5, ADC_INPUT(ADC_12,15));
-
+const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC);
+const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC);
+const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC);
+const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC);
+const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC);
+const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC);
+const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC);
+const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC);
const mcu_pin_obj_t pin_PB00 = PIN(1, 0, ADC_INPUT(ADC_12,8));
const mcu_pin_obj_t pin_PB01 = PIN(1, 1, ADC_INPUT(ADC_12,9));
-const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC); //BOOT1
-
-const mcu_pin_obj_t pin_PF11 = PIN(5, 11, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF12 = PIN(5, 12, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF13 = PIN(5, 13, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF14 = PIN(5, 14, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PF15 = PIN(5, 15, NO_ADC); // 144 only
-
-const mcu_pin_obj_t pin_PG00 = PIN(6, 0, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG01 = PIN(6, 1, NO_ADC); // 144 only
-
-const mcu_pin_obj_t pin_PE07 = PIN(4, 7, NO_ADC);
-const mcu_pin_obj_t pin_PE08 = PIN(4, 8, NO_ADC);
-const mcu_pin_obj_t pin_PE09 = PIN(4, 9, NO_ADC);
-const mcu_pin_obj_t pin_PE10 = PIN(4, 10, NO_ADC);
-const mcu_pin_obj_t pin_PE11 = PIN(4, 11, NO_ADC);
-const mcu_pin_obj_t pin_PE12 = PIN(4, 12, NO_ADC);
-const mcu_pin_obj_t pin_PE13 = PIN(4, 13, NO_ADC);
-const mcu_pin_obj_t pin_PE14 = PIN(4, 14, NO_ADC);
-const mcu_pin_obj_t pin_PE15 = PIN(4, 15, NO_ADC);
-
+const mcu_pin_obj_t pin_PB02 = PIN(1, 2, NO_ADC);
+const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC);
+const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC);
+const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC);
+const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC);
+const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC);
+const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC);
+const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC);
const mcu_pin_obj_t pin_PB10 = PIN(1, 10, NO_ADC);
const mcu_pin_obj_t pin_PB11 = PIN(1, 11, NO_ADC);
const mcu_pin_obj_t pin_PB12 = PIN(1, 12, NO_ADC);
const mcu_pin_obj_t pin_PB13 = PIN(1, 13, NO_ADC);
const mcu_pin_obj_t pin_PB14 = PIN(1, 14, NO_ADC);
const mcu_pin_obj_t pin_PB15 = PIN(1, 15, NO_ADC);
-
-const mcu_pin_obj_t pin_PD08 = PIN(3, 8, NO_ADC);
-const mcu_pin_obj_t pin_PD09 = PIN(3, 9, NO_ADC);
-const mcu_pin_obj_t pin_PD10 = PIN(3, 10, NO_ADC);
-const mcu_pin_obj_t pin_PD11 = PIN(3, 11, NO_ADC);
-const mcu_pin_obj_t pin_PD12 = PIN(3, 12, NO_ADC);
-const mcu_pin_obj_t pin_PD13 = PIN(3, 13, NO_ADC);
-const mcu_pin_obj_t pin_PD14 = PIN(3, 14, NO_ADC);
-const mcu_pin_obj_t pin_PD15 = PIN(3, 15, NO_ADC);
-
-const mcu_pin_obj_t pin_PG02 = PIN(6, 2, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG03 = PIN(6, 3, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG04 = PIN(6, 4, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG05 = PIN(6, 5, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG06 = PIN(6, 6, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG07 = PIN(6, 7, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG08 = PIN(6, 8, NO_ADC); // 144 only
-
+const mcu_pin_obj_t pin_PC00 = PIN(2, 0, ADC_INPUT(ADC_123,10));
+const mcu_pin_obj_t pin_PC01 = PIN(2, 1, ADC_INPUT(ADC_123,11));
+const mcu_pin_obj_t pin_PC02 = PIN(2, 2, ADC_INPUT(ADC_123,12));
+const mcu_pin_obj_t pin_PC03 = PIN(2, 3, ADC_INPUT(ADC_123,13));
+const mcu_pin_obj_t pin_PC04 = PIN(2, 4, ADC_INPUT(ADC_12,14));
+const mcu_pin_obj_t pin_PC05 = PIN(2, 5, ADC_INPUT(ADC_12,15));
const mcu_pin_obj_t pin_PC06 = PIN(2, 6, NO_ADC);
const mcu_pin_obj_t pin_PC07 = PIN(2, 7, NO_ADC);
const mcu_pin_obj_t pin_PC08 = PIN(2, 8, NO_ADC);
const mcu_pin_obj_t pin_PC09 = PIN(2, 9, NO_ADC);
-
-const mcu_pin_obj_t pin_PA08 = PIN(0, 8, NO_ADC);
-const mcu_pin_obj_t pin_PA09 = PIN(0, 9, NO_ADC);
-const mcu_pin_obj_t pin_PA10 = PIN(0, 10, NO_ADC);
-const mcu_pin_obj_t pin_PA11 = PIN(0, 11, NO_ADC);
-const mcu_pin_obj_t pin_PA12 = PIN(0, 12, NO_ADC);
-const mcu_pin_obj_t pin_PA13 = PIN(0, 13, NO_ADC);
-const mcu_pin_obj_t pin_PA14 = PIN(0, 14, NO_ADC);
-const mcu_pin_obj_t pin_PA15 = PIN(0, 15, NO_ADC);
-
const mcu_pin_obj_t pin_PC10 = PIN(2, 10, NO_ADC);
const mcu_pin_obj_t pin_PC11 = PIN(2, 11, NO_ADC);
const mcu_pin_obj_t pin_PC12 = PIN(2, 12, NO_ADC);
-
+const mcu_pin_obj_t pin_PC13 = PIN(2, 13, NO_ADC);
+const mcu_pin_obj_t pin_PC14 = PIN(2, 14, NO_ADC);
+const mcu_pin_obj_t pin_PC15 = PIN(2, 15, NO_ADC);
const mcu_pin_obj_t pin_PD00 = PIN(3, 0, NO_ADC);
const mcu_pin_obj_t pin_PD01 = PIN(3, 1, NO_ADC);
const mcu_pin_obj_t pin_PD02 = PIN(3, 2, NO_ADC);
@@ -140,22 +84,87 @@ const mcu_pin_obj_t pin_PD04 = PIN(3, 4, NO_ADC);
const mcu_pin_obj_t pin_PD05 = PIN(3, 5, NO_ADC);
const mcu_pin_obj_t pin_PD06 = PIN(3, 6, NO_ADC);
const mcu_pin_obj_t pin_PD07 = PIN(3, 7, NO_ADC);
-
-const mcu_pin_obj_t pin_PG09 = PIN(6, 9, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG10 = PIN(6, 10, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG11 = PIN(6, 11, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG12 = PIN(6, 12, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG13 = PIN(6, 13, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG14 = PIN(6, 14, NO_ADC); // 144 only
-const mcu_pin_obj_t pin_PG15 = PIN(6, 15, NO_ADC); // 144 only
-
-const mcu_pin_obj_t pin_PB03 = PIN(1, 3, NO_ADC);
-const mcu_pin_obj_t pin_PB04 = PIN(1, 4, NO_ADC);
-const mcu_pin_obj_t pin_PB05 = PIN(1, 5, NO_ADC);
-const mcu_pin_obj_t pin_PB06 = PIN(1, 6, NO_ADC);
-const mcu_pin_obj_t pin_PB07 = PIN(1, 7, NO_ADC);
-const mcu_pin_obj_t pin_PB08 = PIN(1, 8, NO_ADC);
-const mcu_pin_obj_t pin_PB09 = PIN(1, 9, NO_ADC);
-
+const mcu_pin_obj_t pin_PD08 = PIN(3, 8, NO_ADC);
+const mcu_pin_obj_t pin_PD09 = PIN(3, 9, NO_ADC);
+const mcu_pin_obj_t pin_PD10 = PIN(3, 10, NO_ADC);
+const mcu_pin_obj_t pin_PD11 = PIN(3, 11, NO_ADC);
+const mcu_pin_obj_t pin_PD12 = PIN(3, 12, NO_ADC);
+const mcu_pin_obj_t pin_PD13 = PIN(3, 13, NO_ADC);
+const mcu_pin_obj_t pin_PD14 = PIN(3, 14, NO_ADC);
+const mcu_pin_obj_t pin_PD15 = PIN(3, 15, NO_ADC);
const mcu_pin_obj_t pin_PE00 = PIN(4, 0, NO_ADC);
const mcu_pin_obj_t pin_PE01 = PIN(4, 1, NO_ADC);
+const mcu_pin_obj_t pin_PE02 = PIN(4, 2, NO_ADC);
+const mcu_pin_obj_t pin_PE03 = PIN(4, 3, NO_ADC);
+const mcu_pin_obj_t pin_PE04 = PIN(4, 4, NO_ADC);
+const mcu_pin_obj_t pin_PE05 = PIN(4, 5, NO_ADC);
+const mcu_pin_obj_t pin_PE06 = PIN(4, 6, NO_ADC);
+const mcu_pin_obj_t pin_PE07 = PIN(4, 7, NO_ADC);
+const mcu_pin_obj_t pin_PE08 = PIN(4, 8, NO_ADC);
+const mcu_pin_obj_t pin_PE09 = PIN(4, 9, NO_ADC);
+const mcu_pin_obj_t pin_PE10 = PIN(4, 10, NO_ADC);
+const mcu_pin_obj_t pin_PE11 = PIN(4, 11, NO_ADC);
+const mcu_pin_obj_t pin_PE12 = PIN(4, 12, NO_ADC);
+const mcu_pin_obj_t pin_PE13 = PIN(4, 13, NO_ADC);
+const mcu_pin_obj_t pin_PE14 = PIN(4, 14, NO_ADC);
+const mcu_pin_obj_t pin_PE15 = PIN(4, 15, NO_ADC);
+const mcu_pin_obj_t pin_PF00 = PIN(5, 0, NO_ADC);
+const mcu_pin_obj_t pin_PF01 = PIN(5, 1, NO_ADC);
+const mcu_pin_obj_t pin_PF02 = PIN(5, 2, NO_ADC);
+const mcu_pin_obj_t pin_PF03 = PIN(5, 3, ADC_INPUT(ADC_3,9));
+const mcu_pin_obj_t pin_PF04 = PIN(5, 4, ADC_INPUT(ADC_3,14));
+const mcu_pin_obj_t pin_PF05 = PIN(5, 5, ADC_INPUT(ADC_3,15));
+const mcu_pin_obj_t pin_PF06 = PIN(5, 6, ADC_INPUT(ADC_3,4));
+const mcu_pin_obj_t pin_PF07 = PIN(5, 7, ADC_INPUT(ADC_3,5));
+const mcu_pin_obj_t pin_PF08 = PIN(5, 8, ADC_INPUT(ADC_3,6));
+const mcu_pin_obj_t pin_PF09 = PIN(5, 9, ADC_INPUT(ADC_3,7));
+const mcu_pin_obj_t pin_PF10 = PIN(5, 10, ADC_INPUT(ADC_3,8));
+const mcu_pin_obj_t pin_PF11 = PIN(5, 11, NO_ADC);
+const mcu_pin_obj_t pin_PF12 = PIN(5, 12, NO_ADC);
+const mcu_pin_obj_t pin_PF13 = PIN(5, 13, NO_ADC);
+const mcu_pin_obj_t pin_PF14 = PIN(5, 14, NO_ADC);
+const mcu_pin_obj_t pin_PF15 = PIN(5, 15, NO_ADC);
+const mcu_pin_obj_t pin_PG00 = PIN(6, 0, NO_ADC);
+const mcu_pin_obj_t pin_PG01 = PIN(6, 1, NO_ADC);
+const mcu_pin_obj_t pin_PG02 = PIN(6, 2, NO_ADC);
+const mcu_pin_obj_t pin_PG03 = PIN(6, 3, NO_ADC);
+const mcu_pin_obj_t pin_PG04 = PIN(6, 4, NO_ADC);
+const mcu_pin_obj_t pin_PG05 = PIN(6, 5, NO_ADC);
+const mcu_pin_obj_t pin_PG06 = PIN(6, 6, NO_ADC);
+const mcu_pin_obj_t pin_PG07 = PIN(6, 7, NO_ADC);
+const mcu_pin_obj_t pin_PG08 = PIN(6, 8, NO_ADC);
+const mcu_pin_obj_t pin_PG09 = PIN(6, 9, NO_ADC);
+const mcu_pin_obj_t pin_PG10 = PIN(6, 10, NO_ADC);
+const mcu_pin_obj_t pin_PG11 = PIN(6, 11, NO_ADC);
+const mcu_pin_obj_t pin_PG12 = PIN(6, 12, NO_ADC);
+const mcu_pin_obj_t pin_PG13 = PIN(6, 13, NO_ADC);
+const mcu_pin_obj_t pin_PG14 = PIN(6, 14, NO_ADC);
+const mcu_pin_obj_t pin_PG15 = PIN(6, 15, NO_ADC);
+const mcu_pin_obj_t pin_PH00 = PIN(7, 0, NO_ADC);
+const mcu_pin_obj_t pin_PH01 = PIN(7, 1, NO_ADC);
+const mcu_pin_obj_t pin_PH02 = PIN(7, 2, NO_ADC);
+const mcu_pin_obj_t pin_PH03 = PIN(7, 3, NO_ADC);
+const mcu_pin_obj_t pin_PH04 = PIN(7, 4, NO_ADC);
+const mcu_pin_obj_t pin_PH05 = PIN(7, 5, NO_ADC);
+const mcu_pin_obj_t pin_PH06 = PIN(7, 6, NO_ADC);
+const mcu_pin_obj_t pin_PH07 = PIN(7, 7, NO_ADC);
+const mcu_pin_obj_t pin_PH08 = PIN(7, 8, NO_ADC);
+const mcu_pin_obj_t pin_PH09 = PIN(7, 9, NO_ADC);
+const mcu_pin_obj_t pin_PH10 = PIN(7, 10, NO_ADC);
+const mcu_pin_obj_t pin_PH11 = PIN(7, 11, NO_ADC);
+const mcu_pin_obj_t pin_PH12 = PIN(7, 12, NO_ADC);
+const mcu_pin_obj_t pin_PH13 = PIN(7, 13, NO_ADC);
+const mcu_pin_obj_t pin_PH14 = PIN(7, 14, NO_ADC);
+const mcu_pin_obj_t pin_PH15 = PIN(7, 15, NO_ADC);
+const mcu_pin_obj_t pin_PI00 = PIN(8, 0, NO_ADC);
+const mcu_pin_obj_t pin_PI01 = PIN(8, 1, NO_ADC);
+const mcu_pin_obj_t pin_PI02 = PIN(8, 2, NO_ADC);
+const mcu_pin_obj_t pin_PI03 = PIN(8, 3, NO_ADC);
+const mcu_pin_obj_t pin_PI04 = PIN(8, 4, NO_ADC);
+const mcu_pin_obj_t pin_PI05 = PIN(8, 5, NO_ADC);
+const mcu_pin_obj_t pin_PI06 = PIN(8, 6, NO_ADC);
+const mcu_pin_obj_t pin_PI07 = PIN(8, 7, NO_ADC);
+const mcu_pin_obj_t pin_PI08 = PIN(8, 8, NO_ADC);
+const mcu_pin_obj_t pin_PI09 = PIN(8, 9, NO_ADC);
+const mcu_pin_obj_t pin_PI10 = PIN(8, 10, NO_ADC);
+const mcu_pin_obj_t pin_PI11 = PIN(8, 11, NO_ADC);
diff --git a/ports/stm/peripherals/stm32f4/stm32f405xx/pins.h b/ports/stm/peripherals/stm32f4/stm32f405xx/pins.h
index e722b6e5a..fe0eb9e53 100644
--- a/ports/stm/peripherals/stm32f4/stm32f405xx/pins.h
+++ b/ports/stm/peripherals/stm32f4/stm32f405xx/pins.h
@@ -27,107 +27,54 @@
#ifndef MICROPY_INCLUDED_STM32_PERIPHERALS_STM32F405XX_PINS_H
#define MICROPY_INCLUDED_STM32_PERIPHERALS_STM32F405XX_PINS_H
-//Pins in datasheet order: DocID028087 Rev 7 page 50. LQFP100 only
-//pg 50
-extern const mcu_pin_obj_t pin_PE02;
-extern const mcu_pin_obj_t pin_PE03;
-extern const mcu_pin_obj_t pin_PE04;
-extern const mcu_pin_obj_t pin_PE05;
-extern const mcu_pin_obj_t pin_PE06;
-extern const mcu_pin_obj_t pin_PC13;
-extern const mcu_pin_obj_t pin_PC14;
-//pg 51
-extern const mcu_pin_obj_t pin_PC15;
-extern const mcu_pin_obj_t pin_PF00; // 144 only
-extern const mcu_pin_obj_t pin_PF01; // 144 only
-extern const mcu_pin_obj_t pin_PF02; // 144 only
-extern const mcu_pin_obj_t pin_PF03; // 144 only
-extern const mcu_pin_obj_t pin_PF04; // 144 only
-extern const mcu_pin_obj_t pin_PF05; // 144 only
-extern const mcu_pin_obj_t pin_PF06; // 144 only
-extern const mcu_pin_obj_t pin_PF07; // 144 only
-extern const mcu_pin_obj_t pin_PF08; // 144 only
-extern const mcu_pin_obj_t pin_PF09; // 144 only
-extern const mcu_pin_obj_t pin_PF10; // 144 only
-//pg 52
-extern const mcu_pin_obj_t pin_PC00;
-extern const mcu_pin_obj_t pin_PC01;
-extern const mcu_pin_obj_t pin_PC02;
-extern const mcu_pin_obj_t pin_PC03;
extern const mcu_pin_obj_t pin_PA00;
extern const mcu_pin_obj_t pin_PA01;
extern const mcu_pin_obj_t pin_PA02;
-//pg 53
extern const mcu_pin_obj_t pin_PA03;
extern const mcu_pin_obj_t pin_PA04;
extern const mcu_pin_obj_t pin_PA05;
extern const mcu_pin_obj_t pin_PA06;
extern const mcu_pin_obj_t pin_PA07;
-extern const mcu_pin_obj_t pin_PC04;
-//pg 54
-extern const mcu_pin_obj_t pin_PC05;
+extern const mcu_pin_obj_t pin_PA08;
+extern const mcu_pin_obj_t pin_PA09;
+extern const mcu_pin_obj_t pin_PA10;
+extern const mcu_pin_obj_t pin_PA11;
+extern const mcu_pin_obj_t pin_PA12;
+extern const mcu_pin_obj_t pin_PA13;
+extern const mcu_pin_obj_t pin_PA14;
+extern const mcu_pin_obj_t pin_PA15;
extern const mcu_pin_obj_t pin_PB00;
extern const mcu_pin_obj_t pin_PB01;
extern const mcu_pin_obj_t pin_PB02;
-extern const mcu_pin_obj_t pin_PF11; // 144 only
-extern const mcu_pin_obj_t pin_PF12; // 144 only
-extern const mcu_pin_obj_t pin_PF13; // 144 only
-extern const mcu_pin_obj_t pin_PF14; // 144 only
-extern const mcu_pin_obj_t pin_PF15; // 144 only
-extern const mcu_pin_obj_t pin_PG00; // 144 only
-extern const mcu_pin_obj_t pin_PG01; // 144 only
-//pg 55
-extern const mcu_pin_obj_t pin_PE07;
-extern const mcu_pin_obj_t pin_PE08;
-extern const mcu_pin_obj_t pin_PE09;
-extern const mcu_pin_obj_t pin_PE10;
-extern const mcu_pin_obj_t pin_PE11;
-extern const mcu_pin_obj_t pin_PE12;
-extern const mcu_pin_obj_t pin_PE13;
-extern const mcu_pin_obj_t pin_PE14;
-//pg 56
-extern const mcu_pin_obj_t pin_PE15;
+extern const mcu_pin_obj_t pin_PB03;
+extern const mcu_pin_obj_t pin_PB04;
+extern const mcu_pin_obj_t pin_PB05;
+extern const mcu_pin_obj_t pin_PB06;
+extern const mcu_pin_obj_t pin_PB07;
+extern const mcu_pin_obj_t pin_PB08;
+extern const mcu_pin_obj_t pin_PB09;
extern const mcu_pin_obj_t pin_PB10;
-extern const mcu_pin_obj_t pin_PB11; // 144 only
+extern const mcu_pin_obj_t pin_PB11;
extern const mcu_pin_obj_t pin_PB12;
extern const mcu_pin_obj_t pin_PB13;
-//pg 57
extern const mcu_pin_obj_t pin_PB14;
extern const mcu_pin_obj_t pin_PB15;
-extern const mcu_pin_obj_t pin_PD08;
-extern const mcu_pin_obj_t pin_PD09;
-extern const mcu_pin_obj_t pin_PD10;
-extern const mcu_pin_obj_t pin_PD11;
-extern const mcu_pin_obj_t pin_PD12;
-//pg 58
-extern const mcu_pin_obj_t pin_PD13;
-extern const mcu_pin_obj_t pin_PD14;
-extern const mcu_pin_obj_t pin_PD15;
-extern const mcu_pin_obj_t pin_PG02; // 144 only
-extern const mcu_pin_obj_t pin_PG03; // 144 only
-extern const mcu_pin_obj_t pin_PG04; // 144 only
-extern const mcu_pin_obj_t pin_PG05; // 144 only
-extern const mcu_pin_obj_t pin_PG06; // 144 only
-extern const mcu_pin_obj_t pin_PG07; // 144 only
-extern const mcu_pin_obj_t pin_PG08; // 144 only
-//pg 59
+extern const mcu_pin_obj_t pin_PC00;
+extern const mcu_pin_obj_t pin_PC01;
+extern const mcu_pin_obj_t pin_PC02;
+extern const mcu_pin_obj_t pin_PC03;
+extern const mcu_pin_obj_t pin_PC04;
+extern const mcu_pin_obj_t pin_PC05;
extern const mcu_pin_obj_t pin_PC06;
extern const mcu_pin_obj_t pin_PC07;
extern const mcu_pin_obj_t pin_PC08;
extern const mcu_pin_obj_t pin_PC09;
-extern const mcu_pin_obj_t pin_PA08;
-extern const mcu_pin_obj_t pin_PA09;
-extern const mcu_pin_obj_t pin_PA10;
-//pg 60
-extern const mcu_pin_obj_t pin_PA11;
-extern const mcu_pin_obj_t pin_PA12;
-extern const mcu_pin_obj_t pin_PA13;
-extern const mcu_pin_obj_t pin_PA14;
-extern const mcu_pin_obj_t pin_PA15;
extern const mcu_pin_obj_t pin_PC10;
extern const mcu_pin_obj_t pin_PC11;
-//pg 61
extern const mcu_pin_obj_t pin_PC12;
+extern const mcu_pin_obj_t pin_PC13;
+extern const mcu_pin_obj_t pin_PC14;
+extern const mcu_pin_obj_t pin_PC15;
extern const mcu_pin_obj_t pin_PD00;
extern const mcu_pin_obj_t pin_PD01;
extern const mcu_pin_obj_t pin_PD02;
@@ -136,23 +83,89 @@ extern const mcu_pin_obj_t pin_PD04;
extern const mcu_pin_obj_t pin_PD05;
extern const mcu_pin_obj_t pin_PD06;
extern const mcu_pin_obj_t pin_PD07;
-//pg 62
-extern const mcu_pin_obj_t pin_PG09; // 144 only
-extern const mcu_pin_obj_t pin_PG10; // 144 only
-extern const mcu_pin_obj_t pin_PG11; // 144 only
-extern const mcu_pin_obj_t pin_PG12; // 144 only
-extern const mcu_pin_obj_t pin_PG13; // 144 only
-extern const mcu_pin_obj_t pin_PG14; // 144 only
-extern const mcu_pin_obj_t pin_PG15; // 144 only
-extern const mcu_pin_obj_t pin_PB03;
-extern const mcu_pin_obj_t pin_PB04;
-//pg 63
-extern const mcu_pin_obj_t pin_PB05;
-extern const mcu_pin_obj_t pin_PB06;
-extern const mcu_pin_obj_t pin_PB07;
-extern const mcu_pin_obj_t pin_PB08;
-extern const mcu_pin_obj_t pin_PB09;
+extern const mcu_pin_obj_t pin_PD08;
+extern const mcu_pin_obj_t pin_PD09;
+extern const mcu_pin_obj_t pin_PD10;
+extern const mcu_pin_obj_t pin_PD11;
+extern const mcu_pin_obj_t pin_PD12;
+extern const mcu_pin_obj_t pin_PD13;
+extern const mcu_pin_obj_t pin_PD14;
+extern const mcu_pin_obj_t pin_PD15;
extern const mcu_pin_obj_t pin_PE00;
extern const mcu_pin_obj_t pin_PE01;
+extern const mcu_pin_obj_t pin_PE02;
+extern const mcu_pin_obj_t pin_PE03;
+extern const mcu_pin_obj_t pin_PE04;
+extern const mcu_pin_obj_t pin_PE05;
+extern const mcu_pin_obj_t pin_PE06;
+extern const mcu_pin_obj_t pin_PE07;
+extern const mcu_pin_obj_t pin_PE08;
+extern const mcu_pin_obj_t pin_PE09;
+extern const mcu_pin_obj_t pin_PE10;
+extern const mcu_pin_obj_t pin_PE11;
+extern const mcu_pin_obj_t pin_PE12;
+extern const mcu_pin_obj_t pin_PE13;
+extern const mcu_pin_obj_t pin_PE14;
+extern const mcu_pin_obj_t pin_PE15;
+extern const mcu_pin_obj_t pin_PF00;
+extern const mcu_pin_obj_t pin_PF01;
+extern const mcu_pin_obj_t pin_PF02;
+extern const mcu_pin_obj_t pin_PF03;
+extern const mcu_pin_obj_t pin_PF04;
+extern const mcu_pin_obj_t pin_PF05;
+extern const mcu_pin_obj_t pin_PF06;
+extern const mcu_pin_obj_t pin_PF07;
+extern const mcu_pin_obj_t pin_PF08;
+extern const mcu_pin_obj_t pin_PF09;
+extern const mcu_pin_obj_t pin_PF10;
+extern const mcu_pin_obj_t pin_PF11;
+extern const mcu_pin_obj_t pin_PF12;
+extern const mcu_pin_obj_t pin_PF13;
+extern const mcu_pin_obj_t pin_PF14;
+extern const mcu_pin_obj_t pin_PF15;
+extern const mcu_pin_obj_t pin_PG00;
+extern const mcu_pin_obj_t pin_PG01;
+extern const mcu_pin_obj_t pin_PG02;
+extern const mcu_pin_obj_t pin_PG03;
+extern const mcu_pin_obj_t pin_PG04;
+extern const mcu_pin_obj_t pin_PG05;
+extern const mcu_pin_obj_t pin_PG06;
+extern const mcu_pin_obj_t pin_PG07;
+extern const mcu_pin_obj_t pin_PG08;
+extern const mcu_pin_obj_t pin_PG09;
+extern const mcu_pin_obj_t pin_PG10;
+extern const mcu_pin_obj_t pin_PG11;
+extern const mcu_pin_obj_t pin_PG12;
+extern const mcu_pin_obj_t pin_PG13;
+extern const mcu_pin_obj_t pin_PG14;
+extern const mcu_pin_obj_t pin_PG15;
+extern const mcu_pin_obj_t pin_PH00;
+extern const mcu_pin_obj_t pin_PH01;
+extern const mcu_pin_obj_t pin_PH02;
+extern const mcu_pin_obj_t pin_PH03;
+extern const mcu_pin_obj_t pin_PH04;
+extern const mcu_pin_obj_t pin_PH05;
+extern const mcu_pin_obj_t pin_PH06;
+extern const mcu_pin_obj_t pin_PH07;
+extern const mcu_pin_obj_t pin_PH08;
+extern const mcu_pin_obj_t pin_PH09;
+extern const mcu_pin_obj_t pin_PH10;
+extern const mcu_pin_obj_t pin_PH11;
+extern const mcu_pin_obj_t pin_PH12;
+extern const mcu_pin_obj_t pin_PH13;
+extern const mcu_pin_obj_t pin_PH14;
+extern const mcu_pin_obj_t pin_PH15;
+extern const mcu_pin_obj_t pin_PI00;
+extern const mcu_pin_obj_t pin_PI01;
+extern const mcu_pin_obj_t pin_PI02;
+extern const mcu_pin_obj_t pin_PI03;
+extern const mcu_pin_obj_t pin_PI04;
+extern const mcu_pin_obj_t pin_PI05;
+extern const mcu_pin_obj_t pin_PI06;
+extern const mcu_pin_obj_t pin_PI07;
+extern const mcu_pin_obj_t pin_PI08;
+extern const mcu_pin_obj_t pin_PI09;
+extern const mcu_pin_obj_t pin_PI10;
+extern const mcu_pin_obj_t pin_PI11;
#endif // MICROPY_INCLUDED_STM32_PERIPHERALS_STM32F405XX_PINS_H
diff --git a/ports/stm/peripherals/timers.c b/ports/stm/peripherals/timers.c
new file mode 100644
index 000000000..baa81d2b5
--- /dev/null
+++ b/ports/stm/peripherals/timers.c
@@ -0,0 +1,460 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+ *
+ * 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 "timers.h"
+
+#include "py/mpconfig.h"
+#include "py/gc.h"
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "supervisor/shared/translate.h"
+
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/microcontroller/Pin.h"
+
+#if !(CPY_STM32H7)
+
+#define ALL_CLOCKS 0xFFFF
+#define NULL_IRQ 0xFF
+
+static bool stm_timer_reserved[MP_ARRAY_SIZE(mcu_tim_banks)];
+static bool stm_timer_never_reset[MP_ARRAY_SIZE(mcu_tim_banks)];
+static void (*stm_timer_callback[MP_ARRAY_SIZE(mcu_tim_banks)])(void);
+static size_t irq_map[] = {
+ #ifdef TIM1
+ TIM1_CC_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM2
+ TIM2_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM3
+ TIM3_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM4
+ TIM4_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM5
+ TIM5_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM6
+ #if !defined(DAC_BASE) && !defined(DAC1_BASE)
+ TIM6_IRQn,
+ #else
+ TIM6_DAC_IRQn,
+ #endif
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM7
+ TIM7_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM8
+ TIM8_CC_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM9
+ TIM1_BRK_TIM9_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM10
+ TIM1_UP_TIM10_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM11
+ TIM1_TRG_COM_TIM11_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM12
+ TIM8_BRK_TIM12_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM13
+ TIM8_UP_TIM13_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM14
+ TIM8_TRG_COM_TIM14_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM15
+ TIM15_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM16
+ TIM16_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+ #ifdef TIM17
+ TIM17_IRQn,
+ #else
+ NULL_IRQ,
+ #endif
+};
+
+// Get the frequency (in Hz) of the source clock for the given timer.
+// On STM32F405/407/415/417 there are 2 cases for how the clock freq is set.
+// If the APB prescaler is 1, then the timer clock is equal to its respective
+// APB clock. Otherwise (APB prescaler > 1) the timer clock is twice its
+// respective APB clock. See DM00031020 Rev 4, page 115.
+uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef * timer) {
+ size_t tim_id = stm_peripherals_timer_get_index(timer);
+ uint32_t source, clk_div;
+ if (tim_id == 1 || (8 <= tim_id && tim_id <= 11)) {
+ // TIM{1,8,9,10,11} are on APB2
+ source = HAL_RCC_GetPCLK2Freq();
+ clk_div = RCC->CFGR & RCC_CFGR_PPRE2;
+ } else {
+ // TIM{2,3,4,5,6,7,12,13,14} are on APB1
+ source = HAL_RCC_GetPCLK1Freq();
+ clk_div = RCC->CFGR & RCC_CFGR_PPRE1;
+ }
+ if (clk_div != 0) {
+ // APB prescaler for this timer is > 1
+ source *= 2;
+ }
+ return source;
+}
+
+size_t stm_peripherals_timer_get_irqnum(TIM_TypeDef * instance) {
+ size_t tim_id = stm_peripherals_timer_get_index(instance);
+ return irq_map[tim_id];
+}
+
+void timers_reset(void) {
+ uint16_t never_reset_mask = 0x00;
+ for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
+ if (!stm_timer_never_reset[i]) {
+ stm_timer_reserved[i] = false;
+ } else {
+ never_reset_mask |= 1 << i;
+ }
+ }
+ tim_clock_disable(ALL_CLOCKS & ~(never_reset_mask));
+}
+
+TIM_TypeDef * stm_peripherals_find_timer(void) {
+ // Check for timers on pins outside the package size
+ for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
+ bool timer_in_package = false;
+ // Find each timer instance on the given bank
+ for (size_t j = 0; j < MP_ARRAY_SIZE(mcu_tim_pin_list); j++) {
+ // If a pin is claimed, we skip it
+ if ( (mcu_tim_pin_list[j].tim_index == i + 1)
+ && (common_hal_mcu_pin_is_free(mcu_tim_pin_list[j].pin) == true) ) {
+ // Search whether any pins in the package array match it
+ for (size_t k = 0; k < mcu_pin_globals.map.alloc; k++) {
+ if ( (mcu_tim_pin_list[j].pin == (mcu_pin_obj_t*)(mcu_pin_globals.map.table[k].value)) ) {
+ timer_in_package = true;
+ }
+ }
+ }
+ }
+ // If no results are found, no unclaimed pins with this timer are in this package,
+ // and it is safe to pick
+ if (timer_in_package == false && mcu_tim_banks[i] != NULL) {
+ // DEBUG: print the timer
+ return mcu_tim_banks[i];
+ mp_printf(&mp_plat_print, "Timer: %d\n",i);
+ }
+ }
+ //TODO: secondary search for timers outside the pins in the board profile
+
+ // Work backwards - higher index timers have fewer pin allocations
+ for (size_t i = (MP_ARRAY_SIZE(mcu_tim_banks) - 1); i >= 0; i--) {
+ if ((!stm_timer_reserved[i]) && (mcu_tim_banks[i] != NULL)) {
+ // DEBUG: print the timer
+ mp_printf(&mp_plat_print, "Timer: %d\n",i);
+ return mcu_tim_banks[i];
+ }
+ }
+ mp_raise_RuntimeError(translate("All timers in use"));
+ return NULL;
+}
+
+void stm_peripherals_timer_preinit(TIM_TypeDef * instance, uint8_t prio, void (*callback)(void)) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_callback[tim_idx] = callback;
+ tim_clock_enable(1 << tim_idx);
+ HAL_NVIC_SetPriority(irq_map[tim_idx], prio, 0);
+ HAL_NVIC_EnableIRQ(irq_map[tim_idx]);
+}
+
+void stm_peripherals_timer_reserve(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_reserved[tim_idx] = true;
+}
+
+void stm_peripherals_timer_set_callback(void(*callback)(void), TIM_TypeDef * timer) {
+ stm_timer_callback[stm_peripherals_timer_get_index(timer)] = callback;
+}
+
+void stm_peripherals_timer_free(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ HAL_NVIC_DisableIRQ(irq_map[tim_idx]);
+ stm_timer_callback[tim_idx] = NULL;
+ tim_clock_disable(1 << tim_idx);
+ stm_timer_reserved[tim_idx] = false;
+ stm_timer_never_reset[tim_idx] = false;
+}
+
+void stm_peripherals_timer_never_reset(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_never_reset[tim_idx] = true;
+}
+void stm_peripherals_timer_reset_ok(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ stm_timer_never_reset[tim_idx] = false;
+}
+bool stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance){
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ return stm_timer_never_reset[tim_idx];
+}
+bool stm_peripherals_timer_is_reserved(TIM_TypeDef * instance) {
+ size_t tim_idx = stm_peripherals_timer_get_index(instance);
+ return stm_timer_reserved[tim_idx];
+}
+
+size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance) {
+ for (size_t i = 0; i < MP_ARRAY_SIZE(mcu_tim_banks); i++) {
+ if (instance == mcu_tim_banks[i]) {
+ return i;
+ }
+ }
+ return ~(size_t)0;
+}
+
+void tim_clock_enable(uint16_t mask) {
+ #ifdef TIM1
+ if (mask & (1 << 0)) {
+ __HAL_RCC_TIM1_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM2
+ if (mask & (1 << 1)) {
+ __HAL_RCC_TIM2_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM3
+ if (mask & (1 << 2)) {
+ __HAL_RCC_TIM3_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM4
+ if (mask & (1 << 3)) {
+ __HAL_RCC_TIM4_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM5
+ if (mask & (1 << 4)) {
+ __HAL_RCC_TIM5_CLK_ENABLE();
+ }
+ #endif
+ //6 and 7 are reserved ADC timers
+ #ifdef TIM8
+ if (mask & (1 << 7)) {
+ __HAL_RCC_TIM8_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM9
+ if (mask & (1 << 8)) {
+ __HAL_RCC_TIM9_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM10
+ if (mask & (1 << 9)) {
+ __HAL_RCC_TIM10_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM11
+ if (mask & (1 << 10)) {
+ __HAL_RCC_TIM11_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM12
+ if (mask & (1 << 11)) {
+ __HAL_RCC_TIM12_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM13
+ if (mask & (1 << 12)) {
+ __HAL_RCC_TIM13_CLK_ENABLE();
+ }
+ #endif
+ #ifdef TIM14
+ if (mask & (1 << 13)) {
+ __HAL_RCC_TIM14_CLK_ENABLE();
+ }
+ #endif
+}
+
+void tim_clock_disable(uint16_t mask) {
+ #ifdef TIM1
+ if (mask & (1 << 0)) {
+ __HAL_RCC_TIM1_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM2
+ if (mask & (1 << 1)) {
+ __HAL_RCC_TIM2_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM3
+ if (mask & (1 << 2)) {
+ __HAL_RCC_TIM3_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM4
+ if (mask & (1 << 3)) {
+ __HAL_RCC_TIM4_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM5
+ if (mask & (1 << 4)) {
+ __HAL_RCC_TIM5_CLK_DISABLE();
+ }
+ #endif
+ //6 and 7 are reserved ADC timers
+ #ifdef TIM8
+ if (mask & (1 << 7)) {
+ __HAL_RCC_TIM8_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM9
+ if (mask & (1 << 8)) {
+ __HAL_RCC_TIM9_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM10
+ if (mask & (1 << 9)) {
+ __HAL_RCC_TIM10_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM11
+ if (mask & (1 << 10)) {
+ __HAL_RCC_TIM11_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM12
+ if (mask & (1 << 11)) {
+ __HAL_RCC_TIM12_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM13
+ if (mask & (1 << 12)) {
+ __HAL_RCC_TIM13_CLK_DISABLE();
+ }
+ #endif
+ #ifdef TIM14
+ if (mask & (1 << 13)) {
+ __HAL_RCC_TIM14_CLK_DISABLE();
+ }
+ #endif
+}
+
+STATIC void callback_router(size_t index) {
+ if (stm_timer_callback[index - 1]) {
+ (*stm_timer_callback[index - 1])();
+ }
+}
+
+void TIM1_CC_IRQHandler(void) { // Advanced timer
+ callback_router(1);
+}
+void TIM2_IRQHandler(void) {
+ callback_router(2);
+}
+void TIM3_IRQHandler(void) {
+ callback_router(3);
+}
+void TIM4_IRQHandler(void) {
+ callback_router(4);
+}
+void TIM5_IRQHandler(void) {
+ callback_router(5);
+}
+void TIM6_DAC_IRQHandler(void) { // Basic timer (DAC)
+ callback_router(6);
+}
+void TIM7_IRQHandler(void) { // Basic timer
+ callback_router(7);
+}
+void TIM8_CC_IRQHandler(void) { // Advanced timer
+ callback_router(8);
+}
+
+// Advanced timer interrupts are currently unused.
+void TIM1_BRK_TIM9_IRQHandler(void) {
+ callback_router(9);
+}
+void TIM1_UP_TIM10_IRQHandler(void) {
+ callback_router(10);
+}
+void TIM1_TRG_COM_TIM11_IRQHandler(void) {
+ callback_router(11);
+}
+void TIM8_BRK_TIM12_IRQHandler(void) {
+ callback_router(12);
+}
+void TIM8_UP_TIM13_IRQHandler(void) {
+ callback_router(13);
+}
+void TIM8_TRG_COM_TIM14_IRQHandler(void) {
+ callback_router(14);
+}
+
+#if (CPY_STM32H7)
+void TIM15_IRQHandler(void) {
+ callback_router(15);
+}
+void TIM16_IRQHandler(void) {
+ callback_router(16);
+}
+void TIM17_IRQHandler(void) {
+ callback_router(17);
+}
+#endif
+
+#endif
diff --git a/ports/stm/peripherals/timers.h b/ports/stm/peripherals/timers.h
new file mode 100644
index 000000000..c4b6c6367
--- /dev/null
+++ b/ports/stm/peripherals/timers.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+#include "py/mphal.h"
+#include "peripherals/periph.h"
+
+#include STM32_HAL_H
+
+void tim_clock_enable(uint16_t mask);
+void tim_clock_disable(uint16_t mask);
+uint32_t stm_peripherals_timer_get_source_freq(TIM_TypeDef * timer);
+size_t stm_peripherals_timer_get_irqnum(TIM_TypeDef * instance);
+void timers_reset(void);
+TIM_TypeDef * stm_peripherals_find_timer(void);
+void stm_peripherals_timer_preinit(TIM_TypeDef * instance, uint8_t prio, void (*callback)(void));
+void stm_peripherals_timer_reserve(TIM_TypeDef * instance);
+void stm_peripherals_timer_free(TIM_TypeDef * instance);
+void stm_peripherals_timer_never_reset(TIM_TypeDef * instance);
+void stm_peripherals_timer_reset_ok(TIM_TypeDef * instance);
+bool stm_peripherals_timer_is_never_reset(TIM_TypeDef * instance);
+bool stm_peripherals_timer_is_reserved(TIM_TypeDef * instance);
+size_t stm_peripherals_timer_get_index(TIM_TypeDef * instance);
diff --git a/ports/stm/supervisor/internal_flash.c b/ports/stm/supervisor/internal_flash.c
index d37a54f60..864403c36 100644
--- a/ports/stm/supervisor/internal_flash.c
+++ b/ports/stm/supervisor/internal_flash.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2020 Lucian Copeland for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/stm/supervisor/internal_flash.h b/ports/stm/supervisor/internal_flash.h
index b4d07ff48..ad5cba62d 100644
--- a/ports/stm/supervisor/internal_flash.h
+++ b/ports/stm/supervisor/internal_flash.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2020 Lucian Copeland for Adafruit Industries
* Copyright (c) 2020 Mark Olsson <mark@markolsson.se>
*
@@ -41,14 +41,9 @@
#ifdef STM32F411xE
#define STM32_FLASH_SIZE 0x80000 //512KiB
-#if CIRCUITPY_NVM
-#define INTERNAL_FLASH_FILESYSTEM_SIZE 0x8000 //32KiB
-#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
-#else
#define INTERNAL_FLASH_FILESYSTEM_SIZE 0xC000 //48KiB
#define INTERNAL_FLASH_FILESYSTEM_START_ADDR 0x08004000
#endif
-#endif
#ifdef STM32F412Zx
#define STM32_FLASH_SIZE 0x100000 //1MB
diff --git a/ports/stm/supervisor/port.c b/ports/stm/supervisor/port.c
index 07a93c025..7c9fcf750 100644
--- a/ports/stm/supervisor/port.c
+++ b/ports/stm/supervisor/port.c
@@ -41,6 +41,7 @@
#include "common-hal/pulseio/PWMOut.h"
#include "common-hal/pulseio/PulseOut.h"
#include "common-hal/pulseio/PulseIn.h"
+#include "timers.h"
#endif
#include "clocks.h"
@@ -224,6 +225,7 @@ void reset_port(void) {
uart_reset();
#endif
#if CIRCUITPY_PULSEIO
+ timers_reset();
pwmout_reset();
pulseout_reset();
pulsein_reset();
diff --git a/ports/stm/supervisor/usb.c b/ports/stm/supervisor/usb.c
index 3dd0acafd..c0e012cc6 100644
--- a/ports/stm/supervisor/usb.c
+++ b/ports/stm/supervisor/usb.c
@@ -86,6 +86,8 @@ void init_usb_hardware(void) {
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
never_reset_pin_number(0, 11);
never_reset_pin_number(0, 12);
+ claim_pin(0, 11);
+ claim_pin(0, 12);
/* Configure VBUS Pin */
#if !(BOARD_NO_VBUS_SENSE)
@@ -94,6 +96,7 @@ void init_usb_hardware(void) {
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
never_reset_pin_number(0, 9);
+ claim_pin(0, 9);
#endif
/* This for ID line debug */
@@ -108,6 +111,7 @@ void init_usb_hardware(void) {
#endif
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
never_reset_pin_number(0, 10);
+ claim_pin(0, 10);
#ifdef STM32F412Zx
/* Configure POWER_SWITCH IO pin (F412 ONLY)*/
@@ -116,6 +120,7 @@ void init_usb_hardware(void) {
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
never_reset_pin_number(0, 8);
+ claim_pin(0, 8);
#endif
#if CPY_STM32H7
@@ -130,5 +135,5 @@ void init_usb_hardware(void) {
}
void OTG_FS_IRQHandler(void) {
- tud_int_handler(0);
+ usb_irq_handler();
}
diff --git a/ports/stm/tools/parse_af_csv.py b/ports/stm/tools/parse_af_csv.py
index 4e9725260..06af3bf1e 100644
--- a/ports/stm/tools/parse_af_csv.py
+++ b/ports/stm/tools/parse_af_csv.py
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2020 Lucian Copeland for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -52,6 +52,8 @@ def evaluate_tim(inper, inlist, altfn, pin):
if inper[:3] == "TIM" and inper[5:7] == "CH" and inper[-1:] != 'N':
inlist.append([inper[3:4],altfn,inper[-1:],pin])
+ elif inper[:3] == "TIM" and inper[6:8] == "CH" and inper[-1:] != 'N':
+ inlist.append([inper[3:5],altfn,inper[-1:],pin])
# Open target file
with open(sys.argv[1]) as csv_file:
diff --git a/ports/stm/tools/parse_pins_csv.py b/ports/stm/tools/parse_pins_csv.py
index 4ab3fc25c..68f6db586 100644
--- a/ports/stm/tools/parse_pins_csv.py
+++ b/ports/stm/tools/parse_pins_csv.py
@@ -2,7 +2,7 @@
#
# The MIT License (MIT)
#
-# Copyright (c) 2020 Lucian Copeland for Adafruit Industries
+# SPDX-FileCopyrightText: Copyright (c) 2020 Lucian Copeland for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/stm/tools/pins.csv b/ports/stm/tools/pins.csv
deleted file mode 100644
index b424c2f78..000000000
--- a/ports/stm/tools/pins.csv
+++ /dev/null
@@ -1,93 +0,0 @@
-A0,PA3
-A1,PC0
-A2,PC3
-A3,PB1
-A4,PC2
-A5,PF10
-A6,PF4
-A7,PF5
-A8,PF6
-D0,PB7
-D1,PB6
-D2,PG14
-D3,PE13
-D4,PE14
-D5,PE11
-D6,PE9
-D7,PG12
-D8,PF3
-D9,PD15
-D10,PD14
-D11,PB5
-D12,PA6
-D13,PA5
-D14,PB9
-D15,PB8
-D16,PC6
-D17,PB15
-D18,PB13
-D19,PB12
-D20,PA15
-D21,PC7
-D22,PB5
-D23,PB3
-D24,PA4
-D25,PB4
-D26,PG6
-D27,PB2
-D28,PD13
-D29,PD12
-D30,PD11
-D31,PE2
-D32,PA0
-D33,PB0
-D34,PE0
-D35,PB11
-D36,PB10
-D37,PE15
-D38,PE6
-D39,PE12
-D40,PE10
-D41,PE7
-D42,PE8
-D43,PC8
-D44,PC9
-D45,PC10
-D46,PC11
-D47,PC12
-D48,PD2
-D49,PG2
-D50,PG3
-D51,PD7
-D52,PD6
-D53,PD5
-D54,PD4
-D55,PD3
-D56,PE2
-D57,PE4
-D58,PE5
-D59,PE6
-D60,PE3
-D61,PF8
-D62,PF7
-D63,PF9
-D64,PG1
-D65,PG0
-D66,PD1
-D67,PD0
-D68,PF0
-D69,PF1
-D70,PF2
-D71,PE0
-D72,PB2
-SDA,PB9
-SCL,PB8
-MOSI,PB5
-MISO,PA6
-SCK,PA5
-RX,PB7
-TX,PB6
-LED1,PB00
-LED2,PE01
-LED3,PB14
-SW,PC13
diff --git a/ports/stm/tools/stm32f767_af.csv b/ports/stm/tools/stm32f767_af.csv
deleted file mode 100644
index 86f10b6dc..000000000
--- a/ports/stm/tools/stm32f767_af.csv
+++ /dev/null
@@ -1,168 +0,0 @@
-PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT,ADC123_IN0
-PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT,ADC123_IN1
-PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,MDIOS_MDIO,,LCD_R1,EVENTOUT,ADC123_IN2
-PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,LCD_B2,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT,ADC123_IN3
-PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,SPI6_NSS,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT,ADC12_IN4
-PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,SPI6_SCK,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT,ADC12_IN5
-PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,SPI6_MISO,TIM13_CH1,,,MDIOS_MDC,DCMI_PIXCLK,LCD_G2,EVENTOUT,ADC12_IN6
-PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,SPI6_MOSI,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT,ADC12_IN7
-PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,CAN3_RX,UART7_RX,LCD_B3,LCD_R6,EVENTOUT,
-PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,DCMI_D0,LCD_R5,EVENTOUT,
-PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,LCD_B4,OTG_FS_ID,,MDIOS_MDIO,DCMI_D1,LCD_B1,EVENTOUT,
-PortA,PA11,,TIM1_CH4,,,,SPI2_NSS/I2S2_WS,UART4_RX,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT,
-PortA,PA12,,TIM1_ETR,,,,SPI2_SCK/I2S2_CK,UART4_TX,USART1_RTS,SAI2_FS_B,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,,,HDMI_CEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,SPI6_NSS,UART4_RTS,,,CAN3_TX,UART7_TX,,,EVENTOUT,
-PortB,PB0,,TIM1_CH2N,TIM3_CH3,TIM8_CH2N,,,DFSDM1_CKOUT,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,LCD_G1,EVENTOUT,ADC12_IN8
-PortB,PB1,,TIM1_CH3N,TIM3_CH4,TIM8_CH3N,,,DFSDM1_DATAIN1,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,LCD_G0,EVENTOUT,ADC12_IN9
-PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,DFSDM1_CKIN1,,,,,EVENTOUT,
-PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,SPI6_SCK,,SDMMC2_D2,CAN3_RX,UART7_RX,,,EVENTOUT,
-PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,SPI6_MISO,,SDMMC2_D3,CAN3_TX,UART7_TX,,,EVENTOUT,
-PortB,PB5,,UART5_RX,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,SPI6_MOSI,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,LCD_G7,EVENTOUT,
-PortB,PB6,,UART5_TX,TIM4_CH1,HDMI_CEC,I2C1_SCL,,DFSDM1_DATAIN5,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,I2C4_SCL,FMC_SDNE1,DCMI_D5,,EVENTOUT,
-PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,DFSDM1_CKIN5,USART1_RX,,,,I2C4_SDA,FMC_NL,DCMI_VSYNC,,EVENTOUT,
-PortB,PB8,,I2C4_SCL,TIM4_CH3,TIM10_CH1,I2C1_SCL,,DFSDM1_CKIN7,UART5_RX,,CAN1_RX,SDMMC2_D4,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT,
-PortB,PB9,,I2C4_SDA,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,DFSDM1_DATAIN7,UART5_TX,,CAN1_TX,SDMMC2_D5,I2C4_SMBA,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT,
-PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,DFSDM1_DATAIN7,USART3_TX,,QUADSPI_BK1_NCS,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT,
-PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,DFSDM1_CKIN7,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DSI_TE,LCD_G5,EVENTOUT,
-PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,DFSDM1_DATAIN1,USART3_CK,UART5_RX,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT,
-PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,DFSDM1_CKIN1,USART3_CTS,UART5_TX,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT,
-PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,USART1_TX,SPI2_MISO,DFSDM1_DATAIN2,USART3_RTS,UART4_RTS,TIM12_CH1,SDMMC2_D0,,OTG_HS_DM,,,EVENTOUT,
-PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,USART1_RX,SPI2_MOSI/I2S2_SD,DFSDM1_CKIN2,,UART4_CTS,TIM12_CH2,SDMMC2_D1,,OTG_HS_DP,,,EVENTOUT,
-PortC,PC0,,,,DFSDM1_CKIN0,,,DFSDM1_DATAIN4,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT,ADC123_IN10
-PortC,PC1,TRACED0,,,DFSDM1_DATAIN0,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,DFSDM1_CKIN4,ETH_MDC,MDIOS_MDC,,,EVENTOUT,ADC123_IN11
-PortC,PC2,,,,DFSDM1_CKIN1,,SPI2_MISO,DFSDM1_CKOUT,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT,ADC123_IN12
-PortC,PC3,,,,DFSDM1_DATAIN1,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT,ADC123_IN13
-PortC,PC4,,,,DFSDM1_CKIN2,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT,ADC12_IN14
-PortC,PC5,,,,DFSDM1_DATAIN2,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT,ADC12_IN15
-PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,DFSDM1_CKIN3,USART6_TX,FMC_NWAIT,SDMMC2_D6,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT,
-PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,DFSDM1_DATAIN3,USART6_RX,FMC_NE1,SDMMC2_D7,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT,
-PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,FMC_NE2/FMC_NCE,,,SDMMC1_D0,DCMI_D2,,EVENTOUT,
-PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,LCD_G3,,SDMMC1_D1,DCMI_D3,LCD_B2,EVENTOUT,
-PortC,PC10,,,,DFSDM1_CKIN5,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT,
-PortC,PC11,,,,DFSDM1_DATAIN5,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT,
-PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT,
-PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT,
-PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT,
-PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT,
-PortD,PD0,,,,DFSDM1_CKIN6,,,DFSDM1_DATAIN7,,UART4_RX,CAN1_RX,,,FMC_D2,,,EVENTOUT,
-PortD,PD1,,,,DFSDM1_DATAIN6,,,DFSDM1_CKIN7,,UART4_TX,CAN1_TX,,,FMC_D3,,,EVENTOUT,
-PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT,
-PortD,PD3,,,,DFSDM1_CKOUT,,SPI2_SCK/I2S2_CK,DFSDM1_DATAIN0,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT,
-PortD,PD4,,,,,,,DFSDM1_CKIN0,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT,
-PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT,
-PortD,PD6,,,,DFSDM1_CKIN4,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,DFSDM1_DATAIN1,SDMMC2_CK,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT,
-PortD,PD7,,,,DFSDM1_DATAIN4,,SPI1_MOSI/I2S1_SD,DFSDM1_CKIN1,USART2_CK,SPDIFRX_IN0,,,SDMMC2_CMD,FMC_NE1,,,EVENTOUT,
-PortD,PD8,,,,DFSDM1_CKIN3,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT,
-PortD,PD9,,,,DFSDM1_DATAIN3,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT,
-PortD,PD10,,,,DFSDM1_CKOUT,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT,
-PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT,
-PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT,
-PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT,
-PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT,
-PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT,
-PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT,
-PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT,
-PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT,
-PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT,
-PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,DFSDM1_DATAIN3,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT,
-PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,DFSDM1_CKIN3,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT,
-PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT,
-PortE,PE7,,TIM1_ETR,,,,,DFSDM1_DATAIN2,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT,
-PortE,PE8,,TIM1_CH1N,,,,,DFSDM1_CKIN2,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT,
-PortE,PE9,,TIM1_CH1,,,,,DFSDM1_CKOUT,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT,
-PortE,PE10,,TIM1_CH2N,,,,,DFSDM1_DATAIN4,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT,
-PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,DFSDM1_CKIN4,,,,SAI2_SD_B,,FMC_D8,,LCD_G3,EVENTOUT,
-PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,DFSDM1_DATAIN5,,,,SAI2_SCK_B,,FMC_D9,,LCD_B4,EVENTOUT,
-PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,DFSDM1_CKIN5,,,,SAI2_FS_B,,FMC_D10,,LCD_DE,EVENTOUT,
-PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,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,QUADSPI_BK1_IO3,,,,,,EVENTOUT,ADC3_IN4
-PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT,ADC3_IN5
-PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT,ADC3_IN6
-PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT,ADC3_IN7
-PortF,PF10,,,,,,,,,,QUADSPI_CLK,,,,DCMI_D11,LCD_DE,EVENTOUT,ADC3_IN8
-PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT,
-PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT,
-PortF,PF13,,,,,I2C4_SMBA,,DFSDM1_DATAIN6,,,,,,FMC_A7,,,EVENTOUT,
-PortF,PF14,,,,,I2C4_SCL,,DFSDM1_CKIN6,,,,,,FMC_A8,,,EVENTOUT,
-PortF,PF15,,,,,I2C4_SDA,,,,,,,,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_NE3,DCMI_D12,LCD_R7,EVENTOUT,
-PortG,PG7,,,,,,,SAI1_MCLK_A,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT,
-PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,LCD_G7,EVENTOUT,
-PortG,PG9,,,,,,SPI1_MISO,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,SDMMC2_D0,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT,
-PortG,PG10,,,,,,SPI1_NSS/I2S1_WS,,,,LCD_G3,SAI2_SD_B,SDMMC2_D1,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT,
-PortG,PG11,,,,,,SPI1_SCK/I2S1_CK,,SPDIFRX_IN0,,,SDMMC2_D2,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT,
-PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,SDMMC2_D3,FMC_NE4,,LCD_B1,EVENTOUT,
-PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT,
-PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT,
-PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT,
-PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT,
-PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT,
-PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT,
-PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT,
-PortH,PH4,,,,,I2C2_SCL,,,,,LCD_G5,OTG_HS_ULPI_NXT,,,,LCD_G4,EVENTOUT,
-PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT,
-PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT,
-PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT,
-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,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT,
-PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT,
-PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT,
-PortH,PH13,,,,TIM8_CH1N,,,,,UART4_TX,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT,
-PortH,PH14,,,,TIM8_CH2N,,,,,UART4_RX,CAN1_RX,,,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,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT,
-PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT,
-PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT,
-PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT,
-PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT,
-PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT,
-PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT,
-PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT,
-PortI,PI9,,,,,,,,,UART4_RX,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT,
-PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT,
-PortI,PI11,,,,,,,,,,LCD_G6,OTG_HS_ULPI_DIR,,,,,EVENTOUT,
-PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT,
-PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT,
-PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT,
-PortI,PI15,,,,,,,,,,LCD_G2,,,,,LCD_R0,EVENTOUT,
-PortJ,PJ0,,,,,,,,,,LCD_R7,,,,,LCD_R1,EVENTOUT,
-PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT,
-PortJ,PJ2,,,,,,,,,,,,,,DSI_TE,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_G3,,,,,LCD_B0,EVENTOUT,
-PortJ,PJ13,,,,,,,,,,LCD_G4,,,,,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/unix/fdfile.h b/ports/unix/fdfile.h
index 69a9b6be4..d7da673be 100644
--- a/ports/unix/fdfile.h
+++ b/ports/unix/fdfile.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2016 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/unix/file.c b/ports/unix/file.c
index e5c73d26c..e4f62e3d5 100644
--- a/ports/unix/file.c
+++ b/ports/unix/file.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/gccollect.c b/ports/unix/gccollect.c
index 02f6fc91a..7cd74ec13 100644
--- a/ports/unix/gccollect.c
+++ b/ports/unix/gccollect.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/input.c b/ports/unix/input.c
index 7d60b46cc..b661ce3e2 100644
--- a/ports/unix/input.c
+++ b/ports/unix/input.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/main.c b/ports/unix/main.c
index d1187ae90..5a3cbaf47 100644
--- a/ports/unix/main.c
+++ b/ports/unix/main.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/modffi.c b/ports/unix/modffi.c
index 03dc9e4ec..c750f2eb7 100644
--- a/ports/unix/modffi.c
+++ b/ports/unix/modffi.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2014 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/unix/modmachine.c b/ports/unix/modmachine.c
index b2bca1206..61697cfb6 100644
--- a/ports/unix/modmachine.c
+++ b/ports/unix/modmachine.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/modos.c b/ports/unix/modos.c
index d99d0d62c..252b19a50 100644
--- a/ports/unix/modos.c
+++ b/ports/unix/modos.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2014 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c
index a8f6ed5c6..cc9b4a337 100644
--- a/ports/unix/modtime.c
+++ b/ports/unix/modtime.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/moduos_vfs.c b/ports/unix/moduos_vfs.c
index e9ac8e1f8..b45d4485b 100644
--- a/ports/unix/moduos_vfs.c
+++ b/ports/unix/moduos_vfs.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2017 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/moduselect.c b/ports/unix/moduselect.c
index 1ea7dc19a..dbda5e110 100644
--- a/ports/unix/moduselect.c
+++ b/ports/unix/moduselect.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2014 Damien P. George
* Copyright (c) 2015-2017 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/unix/modusocket.c b/ports/unix/modusocket.c
index 95da276ed..90651a19e 100644
--- a/ports/unix/modusocket.c
+++ b/ports/unix/modusocket.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
* Copyright (c) 2014 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h
index 3ac7ceaf2..3ae4ff786 100644
--- a/ports/unix/mpconfigport.h
+++ b/ports/unix/mpconfigport.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/mpconfigport_coverage.h b/ports/unix/mpconfigport_coverage.h
index 97c05cfee..51015a587 100644
--- a/ports/unix/mpconfigport_coverage.h
+++ b/ports/unix/mpconfigport_coverage.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013-2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013-2016 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
diff --git a/ports/unix/mpconfigport_fast.h b/ports/unix/mpconfigport_fast.h
index 442159eb4..76e02c1b0 100644
--- a/ports/unix/mpconfigport_fast.h
+++ b/ports/unix/mpconfigport_fast.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/mpconfigport_freedos.h b/ports/unix/mpconfigport_freedos.h
index 09c85ab1e..19c73b762 100644
--- a/ports/unix/mpconfigport_freedos.h
+++ b/ports/unix/mpconfigport_freedos.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2015 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2015 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
diff --git a/ports/unix/mpconfigport_minimal.h b/ports/unix/mpconfigport_minimal.h
index ef7a1a09a..1a13d5725 100644
--- a/ports/unix/mpconfigport_minimal.h
+++ b/ports/unix/mpconfigport_minimal.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2015 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2015 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
diff --git a/ports/unix/mpconfigport_nanbox.h b/ports/unix/mpconfigport_nanbox.h
index 7da2cf7b8..fa41407cf 100644
--- a/ports/unix/mpconfigport_nanbox.h
+++ b/ports/unix/mpconfigport_nanbox.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2016 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
diff --git a/ports/unix/mphalport.h b/ports/unix/mphalport.h
index ff7a51567..6f2880d4e 100644
--- a/ports/unix/mphalport.h
+++ b/ports/unix/mphalport.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2015 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2015 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
diff --git a/ports/unix/mpthreadport.c b/ports/unix/mpthreadport.c
index baca0a2b1..3641745bc 100644
--- a/ports/unix/mpthreadport.c
+++ b/ports/unix/mpthreadport.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/mpthreadport.h b/ports/unix/mpthreadport.h
index b158ed5bc..bd712ebee 100644
--- a/ports/unix/mpthreadport.h
+++ b/ports/unix/mpthreadport.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ * SPDX-FileCopyrightText: Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/qstrdefsport.h b/ports/unix/qstrdefsport.h
index ebfaa6cca..873e83272 100644
--- a/ports/unix/qstrdefsport.h
+++ b/ports/unix/qstrdefsport.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2013, 2014 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c
index f27c62fd1..e9494d7ff 100644
--- a/ports/unix/unix_mphal.c
+++ b/ports/unix/unix_mphal.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2015 Damien P. George
+ * SPDX-FileCopyrightText: Copyright (c) 2015 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