summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2018-01-02 21:25:41 -0500
committerDan Halbert <halbert@halwitz.org>2018-01-02 21:25:41 -0500
commit065e82015f0d2bd6732c62b7375fcc7af87fa0cf (patch)
treee48fa8caa5675d529d335a2b154e69eba8199cff /ports
parentce81c8dda9686d3cd78d9c5383b6982c148ac7ec (diff)
merge from 2.2.0 + fix up board defs
Diffstat (limited to 'ports')
-rw-r--r--ports/atmel-samd/Makefile4
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h36
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk13
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/board.c38
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/conf_access.h115
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/conf_board.h14
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h1
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h220
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h34
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk11
-rw-r--r--ports/atmel-samd/boards/feather_m0_supersized/pins.c28
-rw-r--r--ports/atmel-samd/boards/flash_S25FL064L.h55
-rw-r--r--ports/atmel-samd/boards/flash_W25Q80DV.h51
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/board.c37
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/conf_access.h115
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/conf_board.h14
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h1
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h221
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h36
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk11
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m0/pins.c42
-rw-r--r--ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld3
-rw-r--r--ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld3
-rw-r--r--ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld3
-rw-r--r--ports/atmel-samd/boards/samd21x18-bootloader.ld3
-rw-r--r--ports/atmel-samd/boards/samd21x18-external-flash.ld1
-rw-r--r--ports/atmel-samd/boards/samd21x18.ld1
-rw-r--r--ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld3
-rw-r--r--ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld3
-rw-r--r--ports/atmel-samd/boards/samd51x19-bootloader.ld3
-rw-r--r--ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld3
-rw-r--r--ports/atmel-samd/boards/samd51x20-bootloader.ld3
-rw-r--r--ports/atmel-samd/boards/samd51x20-external-flash.ld1
-rw-r--r--ports/atmel-samd/boards/samd51x20.ld1
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/ugame/board.c37
-rw-r--r--ports/atmel-samd/boards/ugame/conf_access.h115
-rw-r--r--ports/atmel-samd/boards/ugame/conf_board.h14
-rw-r--r--ports/atmel-samd/boards/ugame/conf_clocks.h1
-rw-r--r--ports/atmel-samd/boards/ugame/conf_usb.h221
-rw-r--r--ports/atmel-samd/boards/ugame/mpconfigboard.h48
-rw-r--r--ports/atmel-samd/boards/ugame/mpconfigboard.mk11
-rw-r--r--ports/atmel-samd/boards/ugame/pins.c18
-rw-r--r--ports/atmel-samd/common-hal/analogio/AnalogIn.c9
-rw-r--r--ports/atmel-samd/common-hal/audiobusio/PDMIn.c185
-rw-r--r--ports/atmel-samd/common-hal/busio/SPI.c17
-rw-r--r--ports/atmel-samd/common-hal/digitalio/DigitalInOut.c14
-rw-r--r--ports/atmel-samd/common-hal/microcontroller/__init__.c30
-rw-r--r--ports/atmel-samd/reset.c27
-rw-r--r--ports/atmel-samd/reset.h10
-rw-r--r--ports/atmel-samd/shared_dma.c17
-rw-r--r--ports/atmel-samd/shared_dma.h1
-rw-r--r--ports/esp8266/Makefile1
-rw-r--r--ports/esp8266/common-hal/busio/SPI.c20
-rw-r--r--ports/esp8266/common-hal/digitalio/DigitalInOut.c14
-rw-r--r--ports/esp8266/common-hal/microcontroller/__init__.c18
-rw-r--r--ports/nrf/mpconfigport.mk3
57 files changed, 1827 insertions, 135 deletions
diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile
index 7a842b9c6..f77910f6a 100644
--- a/ports/atmel-samd/Makefile
+++ b/ports/atmel-samd/Makefile
@@ -76,6 +76,9 @@ BASE_CFLAGS = \
-ffunction-sections \
-fdata-sections \
-fshort-enums \
+ -DCIRCUITPY_SOFTWARE_SAFE_MODE=0x0ADABEEF \
+ -DCIRCUITPY_CANARY_WORD=0xADAF00 \
+ -DCIRCUITPY_SAFE_RESTART_WORD=0xDEADBEEF \
--param max-inline-insns-single=500
# NDEBUG disables assert() statements. This reduces code size pretty dramatically, per tannewt.
@@ -312,6 +315,7 @@ SRC_BINDINGS_ENUMS = \
digitalio/Direction.c \
digitalio/DriveMode.c \
digitalio/Pull.c \
+ microcontroller/RunMode.c \
help.c \
math/__init__.c \
supervisor/__init__.c \
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
index 8648980c0..6b86a6890 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h
@@ -10,16 +10,29 @@
#define SPI_FLASH_BAUDRATE (8000000)
// On-board flash
-#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_E
-// Use default pinmux for the chip select since we manage it ourselves.
-#define SPI_FLASH_PAD0_PINMUX PINMUX_PA16D_SERCOM3_PAD0 // MISO
-#define SPI_FLASH_PAD1_PINMUX PINMUX_UNUSED // CS
-#define SPI_FLASH_PAD2_PINMUX PINMUX_PA20D_SERCOM3_PAD2 // MOSI
-#define SPI_FLASH_PAD3_PINMUX PINMUX_PA21D_SERCOM3_PAD3 // SCK
-
-#define SPI_FLASH_CS PIN_PB22
-#define SPI_FLASH_SERCOM SERCOM3
-
+#define SPI_FLASH_MOSI_PIN PIN_PA20
+#define SPI_FLASH_MISO_PIN PIN_PA16
+#define SPI_FLASH_SCK_PIN PIN_PA21
+#define SPI_FLASH_CS_PIN PIN_PB22
+
+#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA20D_SERCOM3_PAD2
+#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0
+#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA21D_SERCOM3_PAD3
+#define SPI_FLASH_SERCOM SERCOM3
+#define SPI_FLASH_SERCOM_INDEX 5
+#define SPI_FLASH_MOSI_PAD 2
+#define SPI_FLASH_MISO_PAD 0
+#define SPI_FLASH_SCK_PAD 3
+
+// <o> Transmit Data Pinout
+// <0x0=>PAD[0,1]_DO_SCK
+// <0x1=>PAD[2,3]_DO_SCK
+// <0x2=>PAD[3,1]_DO_SCK
+// <0x3=>PAD[0,3]_DO_SCK
+#define SPI_FLASH_DOPO 1
+#define SPI_FLASH_DIPO 0 // same as MISO PAD
+
+// These are pins not to reset.
// PA24 and PA25 are USB.
#define MICROPY_PORT_A (PORT_PA16 | PORT_PA20 | PORT_PA21 | PORT_PA24 | PORT_PA25)
#define MICROPY_PORT_B (PORT_PB22)
@@ -27,8 +40,7 @@
#define SPEAKER_ENABLE_PIN (&pin_PA30)
-#include "internal_flash.h"
-//#include "spi_flash.h"
+#include "spi_flash.h"
// If you change this, then make sure to update the linker scripts as well to
// make sure you don't overwrite code.
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index 6e975fdc1..1834a0ebe 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -4,16 +4,13 @@ USB_PID = 0x8019
USB_PRODUCT = "CircuitPlayground Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
-#SPI_FLASH_FILESYSTEM = 1
-INTERNAL_FLASH_FILESYSTEM = 1
+SPI_FLASH_FILESYSTEM = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
# Include these Python libraries in firmware.
-### TODO(halbert): disable some of these frozen modules; they don't fit in 3.0.0 build while internalfs
-### is in use
-###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
-###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
-###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
-###FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_BusDevice
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_LIS3DH
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
+FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_Thermistor
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/board.c b/ports/atmel-samd/boards/feather_m0_supersized/board.c
new file mode 100644
index 000000000..c8e20206a
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/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/atmel-samd/boards/feather_m0_supersized/conf_access.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_access.h
new file mode 100644
index 000000000..2326bfcdf
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_access.h
@@ -0,0 +1,115 @@
+/**
+ * \file
+ *
+ * \brief Memory access control configuration file.
+ *
+ * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * 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. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef _CONF_ACCESS_H_
+#define _CONF_ACCESS_H_
+
+#include "compiler.h"
+#include "board.h"
+
+
+/*! \name Activation of Logical Unit Numbers
+ */
+//! @{
+#define LUN_0 ENABLE //!< On-Chip Virtual Memory.
+#define LUN_1 DISABLE //!< AT45DBX Data Flash.
+#define LUN_2 DISABLE //!< SD/MMC Card over SPI.
+#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0.
+#define LUN_4 DISABLE
+#define LUN_5 DISABLE
+#define LUN_6 DISABLE
+#define LUN_7 DISABLE
+#define LUN_USB DISABLE //!< Host Mass-Storage Memory.
+//! @}
+
+/*! \name LUN 0 Definitions
+ */
+//! @{
+#define LUN_0_INCLUDE "access_vfs.h"
+#define Lun_0_test_unit_ready vfs_test_unit_ready
+#define Lun_0_read_capacity vfs_read_capacity
+#define Lun_0_unload NULL
+#define Lun_0_wr_protect vfs_wr_protect
+#define Lun_0_removal vfs_removal
+#define Lun_0_usb_read_10 vfs_usb_read_10
+#define Lun_0_usb_write_10 vfs_usb_write_10
+#define LUN_0_NAME "\"CircuitPython VFS[0]\""
+//! @}
+
+#define MEM_USB LUN_USB
+
+/*! \name Actions Associated with Memory Accesses
+ *
+ * Write here the action to associate with each memory access.
+ *
+ * \warning Be careful not to waste time in order not to disturb the functions.
+ */
+//! @{
+#define memory_start_read_action(nb_sectors)
+#define memory_stop_read_action()
+#define memory_start_write_action(nb_sectors)
+#define memory_stop_write_action()
+//! @}
+
+/*! \name Activation of Interface Features
+ */
+//! @{
+#define ACCESS_USB true //!< MEM <-> USB interface.
+#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface.
+#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface.
+#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode.
+#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface.
+#define ACCESS_CODEC false //!< Codec interface.
+//! @}
+
+/*! \name Specific Options for Access Control
+ */
+//! @{
+#define GLOBAL_WR_PROTECT false //!< Management of a global write protection.
+//! @}
+
+
+#endif // _CONF_ACCESS_H_
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/conf_board.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_board.h
new file mode 100644
index 000000000..7b88c97fc
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_board.h
@@ -0,0 +1,14 @@
+/**
+ * \file
+ *
+ * \brief User board configuration template
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef CONF_BOARD_H
+#define CONF_BOARD_H
+
+#endif // CONF_BOARD_H
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h
new file mode 100644
index 000000000..d3f3e6496
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_clocks.h
@@ -0,0 +1 @@
+#include "conf_clocks_external_32k.h"
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h b/ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h
new file mode 100644
index 000000000..e5e59663c
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/conf_usb.h
@@ -0,0 +1,220 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h"
+
+#ifndef CONF_USB_H_INCLUDED
+#define CONF_USB_H_INCLUDED
+
+#define USB_DEVICE_MAJOR_VERSION 1
+#define USB_DEVICE_MINOR_VERSION 0
+#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA)
+#define USB_DEVICE_ATTR \
+ (USB_CONFIG_ATTR_BUS_POWERED)
+// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
+// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
+
+//! USB Device string definitions (Optional)
+#ifndef USB_DEVICE_MANUFACTURE_NAME
+# define USB_DEVICE_MANUFACTURE_NAME "Dave Astels"
+#endif
+
+#ifndef USB_DEVICE_PRODUCT_NAME
+# define USB_DEVICE_PRODUCT_NAME "Hacked Feather M0 Express with 8Mbyte SPI flash"
+#endif
+
+#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number
+#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32
+extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH];
+
+//! Control endpoint size
+#define USB_DEVICE_EP_CTRL_SIZE 64
+
+//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd)
+#define USB_DEVICE_NB_INTERFACE 5
+
+// (3 | USB_EP_DIR_IN) // CDC Notify endpoint
+// (4 | USB_EP_DIR_IN) // CDC TX
+// (5 | USB_EP_DIR_OUT) // CDC RX
+// (1 | USB_EP_DIR_IN) // MSC IN
+// (2 | USB_EP_DIR_OUT) // MSC OUT
+// (6 | USB_EP_DIR_IN) // HID mouse report
+// (7 | USB_EP_DIR_IN) // HID keyboard report
+#define USB_DEVICE_MAX_EP 7
+
+#define UDI_CDC_PORT_NB 1
+#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port)
+extern bool mp_cdc_enable(uint8_t port);
+#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port)
+extern void mp_cdc_disable(uint8_t port);
+#define UDI_CDC_LOW_RATE
+
+#define UDI_CDC_DEFAULT_RATE 115200
+#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
+#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
+#define UDI_CDC_DEFAULT_DATABITS 8
+
+#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify()
+void usb_rx_notify(void);
+#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg)
+void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding);
+#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set)
+void usb_dtr_notify(uint8_t port, bool set);
+#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set)
+void usb_rts_notify(uint8_t port, bool set);
+
+/**
+ * USB CDC low level configuration
+ * In standalone these configurations are defined by the CDC module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+
+#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint
+#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX
+#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX
+
+//! Interface numbers
+#define UDI_CDC_COMM_IFACE_NUMBER_0 0
+#define UDI_CDC_DATA_IFACE_NUMBER_0 1
+
+/**
+ * Configuration of MSC interface
+ * @{
+ */
+//! Vendor name and Product version of MSC interface
+#define UDI_MSC_GLOBAL_VENDOR_ID \
+ 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' '
+#define UDI_MSC_GLOBAL_PRODUCT_VERSION \
+ '1', '.', '0', '0'
+
+//! Interface callback definition
+#define UDI_MSC_ENABLE_EXT() mp_msc_enable()
+extern bool mp_msc_enable(void);
+#define UDI_MSC_DISABLE_EXT() mp_msc_disable()
+extern void mp_msc_disable(void);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_MSC_STRING_ID 5
+
+/**
+ * USB MSC low level configuration
+ * In standalone these configurations are defined by the MSC module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN)
+#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT)
+
+//! Interface number
+#define UDI_MSC_IFACE_NUMBER 2
+/**
+ * Configuration of HID Mouse interface
+ * @{
+ */
+//! Interface callback definition
+#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable()
+extern bool mp_mouse_enable(void);
+#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable()
+extern void mp_mouse_disable(void);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_HID_MOUSE_STRING_ID 6
+
+/**
+ * USB HID Mouse low level configuration
+ * In standalone these configurations are defined by the HID Mouse module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN)
+
+//! Interface number
+#define UDI_HID_MOUSE_IFACE_NUMBER 3
+//@}
+//@}
+
+/**
+ * Configuration of HID Keyboard interface
+ * @{
+ */
+//! Interface callback definition
+#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable()
+extern bool mp_keyboard_enable(void);
+#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable()
+extern void mp_keyboard_disable(void);
+#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value)
+extern void mp_keyboard_led(uint8_t);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_HID_KBD_STRING_ID 7
+
+/**
+ * USB HID Keyboard low level configuration
+ * In standalone these configurations are defined by the HID Keyboard module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN)
+
+//! Interface number
+#define UDI_HID_KBD_IFACE_NUMBER 4
+
+/**
+ * Description of Composite Device
+ * @{
+ */
+//! USB Interfaces descriptor structure
+#define UDI_COMPOSITE_DESC_T \
+ usb_iad_desc_t udi_cdc_iad; \
+ udi_cdc_comm_desc_t udi_cdc_comm; \
+ udi_cdc_data_desc_t udi_cdc_data; \
+ udi_msc_desc_t udi_msc; \
+ udi_hid_mouse_desc_t udi_hid_mouse; \
+ udi_hid_kbd_desc_t udi_hid_kbd
+
+//! USB Interfaces descriptor value for Full Speed
+#define UDI_COMPOSITE_DESC_FS \
+ .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
+ .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
+ .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \
+ .udi_msc = UDI_MSC_DESC_FS, \
+ .udi_hid_mouse = UDI_HID_MOUSE_DESC, \
+ .udi_hid_kbd = UDI_HID_KBD_DESC
+
+//! USB Interfaces descriptor value for High Speed
+#define UDI_COMPOSITE_DESC_HS \
+ .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
+ .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
+ .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \
+ .udi_msc = UDI_MSC_DESC_HS, \
+ .udi_hid_mouse = UDI_HID_MOUSE_DESC, \
+ .udi_hid_kbd = UDI_HID_KBD_DESC
+
+//! USB Interface APIs
+#define UDI_COMPOSITE_API \
+ &udi_api_cdc_comm, \
+ &udi_api_cdc_data, \
+ &udi_api_msc, \
+ &udi_api_hid_mouse, \
+ &udi_api_hid_kbd
+//@}
+
+/**
+ * USB Device Driver Configuration
+ * @{
+ */
+//@}
+
+//! The includes of classes and other headers must be done at the end of this file to avoid compile error
+#include "udi_cdc.h"
+#include "udi_msc.h"
+#include "udi_hid_mouse.h"
+#include "udi_hid_kbd.h"
+
+#endif
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h
new file mode 100644
index 000000000..8eb59d9a0
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h
@@ -0,0 +1,34 @@
+/* Adafruit Feather M0 Express with an 8MB SPI flash instead of the usual 2MB */
+
+#define USB_REPL
+
+#define MICROPY_HW_BOARD_NAME "Hacked Feather M0 Express with 8Mbyte SPI flash"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define MICROPY_HW_NEOPIXEL (&pin_PA06)
+
+// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_C
+#define SPI_FLASH_PAD0_PINMUX PINMUX_PA08D_SERCOM2_PAD0 // MOSI
+// Use default pinmux for the chip select since we manage it ourselves.
+#define SPI_FLASH_PAD1_PINMUX PINMUX_PA09D_SERCOM2_PAD1 // SCK
+#define SPI_FLASH_PAD2_PINMUX PINMUX_PA14C_SERCOM2_PAD2 // MISO
+#define SPI_FLASH_PAD3_PINMUX PINMUX_UNUSED // SCK
+#define SPI_FLASH_SERCOM SERCOM2
+
+#define SPI_FLASH_CS PIN_PA13
+
+#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA14 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25)
+#define MICROPY_PORT_B ( 0 )
+
+#include "spi_flash.h"
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code.
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+#include "flash_S25FL064L.h"
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
new file mode 100644
index 000000000..340421f50
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk
@@ -0,0 +1,11 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash.ld
+USB_VID = 0x239A
+USB_PID = 0x8023
+USB_PRODUCT = "Feather M0 Supersized"
+USB_MANUFACTURER = "Dave Astels"
+
+SPI_FLASH_FILESYSTEM = 1
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
diff --git a/ports/atmel-samd/boards/feather_m0_supersized/pins.c b/ports/atmel-samd/boards/feather_m0_supersized/pins.c
new file mode 100644
index 000000000..c5c70ee5d
--- /dev/null
+++ b/ports/atmel-samd/boards/feather_m0_supersized/pins.c
@@ -0,0 +1,28 @@
+#include "samd21_pins.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) },
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) },
+ { 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_NEOPIXEL), MP_ROM_PTR(&pin_PA06) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/flash_S25FL064L.h b/ports/atmel-samd/boards/flash_S25FL064L.h
new file mode 100644
index 000000000..40cfa4cf0
--- /dev/null
+++ b/ports/atmel-samd/boards/flash_S25FL064L.h
@@ -0,0 +1,55 @@
+/*
+ * 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) 2017 Dave Astels
+ *
+ * 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_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL064L_H
+
+// Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash.
+// Datasheet: http://www.cypress.com/file/316661/download
+
+// The total flash size in bytes.
+#define SPI_FLASH_TOTAL_SIZE (1 << 23) // 8 MiB
+
+// The size of the smallest erase unit thats erased with command 0x20.
+#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB
+
+// The size of a page that is programmed with page program command 0x02.
+#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes
+
+// These are the first three response bytes to the JEDEC ID command 0x9f that is
+// used to confirm we're talking to the flash we expect.
+#ifndef SPI_FLASH_JEDEC_MANUFACTURER
+#define SPI_FLASH_JEDEC_MANUFACTURER 0x01
+#define SPI_FLASH_SECTOR_PROTECTION false
+#else
+#define SPI_FLASH_JEDEC_MANUFACTURER_2 0x013
+#define SPI_FLASH_SECTOR_PROTECTION_2 false
+#endif
+#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x60
+#define SPI_FLASH_JEDEC_CAPACITY 0x17
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_S25FL216K_H
diff --git a/ports/atmel-samd/boards/flash_W25Q80DV.h b/ports/atmel-samd/boards/flash_W25Q80DV.h
new file mode 100644
index 000000000..1e8003867
--- /dev/null
+++ b/ports/atmel-samd/boards/flash_W25Q80DV.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H
+
+// The total flash size in bytes.
+#define SPI_FLASH_TOTAL_SIZE (1 << 20) // 1 MiB
+
+// The size of the smallest erase unit thats erased with command 0x20.
+#define SPI_FLASH_ERASE_SIZE (1 << 12) // 4 KiB
+
+// The size of a page that is programmed with page program command 0x02.
+#define SPI_FLASH_PAGE_SIZE (256) // 256 bytes
+
+// These are the first three response bytes to the JEDEC ID command 0x9f that is
+// used to confirm we're talking to the flash we expect.
+#ifndef SPI_FLASH_JEDEC_MANUFACTURER
+#define SPI_FLASH_JEDEC_MANUFACTURER 0xef
+#define SPI_FLASH_SECTOR_PROTECTION false
+#else
+#define SPI_FLASH_JEDEC_MANUFACTURER_2 0xef
+#define SPI_FLASH_SECTOR_PROTECTION_2 false
+#endif
+#define SPI_FLASH_JEDEC_MEMORY_TYPE 0x40
+#define SPI_FLASH_JEDEC_CAPACITY 0x14
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_BOARD_FLASH_W25Q80DV_H
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/board.c b/ports/atmel-samd/boards/itsybitsy_m0/board.c
new file mode 100644
index 000000000..d7e856d61
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/board.c
@@ -0,0 +1,37 @@
+/*
+ * 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/atmel-samd/boards/itsybitsy_m0/conf_access.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_access.h
new file mode 100644
index 000000000..25109b75c
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_access.h
@@ -0,0 +1,115 @@
+/**
+ * \file
+ *
+ * \brief Memory access control configuration file.
+ *
+ * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * 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. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef _CONF_ACCESS_H_
+#define _CONF_ACCESS_H_
+
+#include "compiler.h"
+#include "board.h"
+
+
+/*! \name Activation of Logical Unit Numbers
+ */
+//! @{
+#define LUN_0 ENABLE //!< On-Chip Virtual Memory.
+#define LUN_1 DISABLE //!< AT45DBX Data Flash.
+#define LUN_2 DISABLE //!< SD/MMC Card over SPI.
+#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0.
+#define LUN_4 DISABLE
+#define LUN_5 DISABLE
+#define LUN_6 DISABLE
+#define LUN_7 DISABLE
+#define LUN_USB DISABLE //!< Host Mass-Storage Memory.
+//! @}
+
+/*! \name LUN 0 Definitions
+ */
+//! @{
+#define LUN_0_INCLUDE "access_vfs.h"
+#define Lun_0_test_unit_ready vfs_test_unit_ready
+#define Lun_0_read_capacity vfs_read_capacity
+#define Lun_0_unload NULL
+#define Lun_0_wr_protect vfs_wr_protect
+#define Lun_0_removal vfs_removal
+#define Lun_0_usb_read_10 vfs_usb_read_10
+#define Lun_0_usb_write_10 vfs_usb_write_10
+#define LUN_0_NAME "\"MicroPython VFS[0]\""
+//! @}
+
+#define MEM_USB LUN_USB
+
+/*! \name Actions Associated with Memory Accesses
+ *
+ * Write here the action to associate with each memory access.
+ *
+ * \warning Be careful not to waste time in order not to disturb the functions.
+ */
+//! @{
+#define memory_start_read_action(nb_sectors)
+#define memory_stop_read_action()
+#define memory_start_write_action(nb_sectors)
+#define memory_stop_write_action()
+//! @}
+
+/*! \name Activation of Interface Features
+ */
+//! @{
+#define ACCESS_USB true //!< MEM <-> USB interface.
+#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface.
+#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface.
+#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode.
+#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface.
+#define ACCESS_CODEC false //!< Codec interface.
+//! @}
+
+/*! \name Specific Options for Access Control
+ */
+//! @{
+#define GLOBAL_WR_PROTECT false //!< Management of a global write protection.
+//! @}
+
+
+#endif // _CONF_ACCESS_H_
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_board.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_board.h
new file mode 100644
index 000000000..7b88c97fc
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_board.h
@@ -0,0 +1,14 @@
+/**
+ * \file
+ *
+ * \brief User board configuration template
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef CONF_BOARD_H
+#define CONF_BOARD_H
+
+#endif // CONF_BOARD_H
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h
new file mode 100644
index 000000000..9e4f7876b
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_clocks.h
@@ -0,0 +1 @@
+#include "conf_clocks_crystalless.h"
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h b/ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h
new file mode 100644
index 000000000..5e8a61b88
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/conf_usb.h
@@ -0,0 +1,221 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h"
+
+#ifndef CONF_USB_H_INCLUDED
+#define CONF_USB_H_INCLUDED
+
+#define USB_DEVICE_MAJOR_VERSION 1
+#define USB_DEVICE_MINOR_VERSION 0
+#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA)
+#define USB_DEVICE_ATTR \
+ (USB_CONFIG_ATTR_BUS_POWERED)
+// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
+// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
+
+//! USB Device string definitions (Optional)
+#ifndef USB_DEVICE_MANUFACTURE_NAME
+# define USB_DEVICE_MANUFACTURE_NAME "Adafruit Industries"
+#endif
+
+#ifndef USB_DEVICE_PRODUCT_NAME
+# define USB_DEVICE_PRODUCT_NAME "ItsyBitsy M0"
+#endif
+// #define USB_DEVICE_SERIAL_NAME "12...EF"
+#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number
+#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32
+extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH];
+
+//! Control endpoint size
+#define USB_DEVICE_EP_CTRL_SIZE 64
+
+//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd)
+#define USB_DEVICE_NB_INTERFACE 5
+
+// (3 | USB_EP_DIR_IN) // CDC Notify endpoint
+// (4 | USB_EP_DIR_IN) // CDC TX
+// (5 | USB_EP_DIR_OUT) // CDC RX
+// (1 | USB_EP_DIR_IN) // MSC IN
+// (2 | USB_EP_DIR_OUT) // MSC OUT
+// (6 | USB_EP_DIR_IN) // HID mouse report
+// (7 | USB_EP_DIR_IN) // HID keyboard report
+#define USB_DEVICE_MAX_EP 7
+
+#define UDI_CDC_PORT_NB 1
+#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port)
+extern bool mp_cdc_enable(uint8_t port);
+#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port)
+extern void mp_cdc_disable(uint8_t port);
+#define UDI_CDC_LOW_RATE
+
+#define UDI_CDC_DEFAULT_RATE 115200
+#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
+#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
+#define UDI_CDC_DEFAULT_DATABITS 8
+
+#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify()
+void usb_rx_notify(void);
+
+#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg)
+void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding);
+#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set)
+void usb_dtr_notify(uint8_t port, bool set);
+#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set)
+void usb_rts_notify(uint8_t port, bool set);
+
+/**
+ * USB CDC low level configuration
+ * In standalone these configurations are defined by the CDC module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+
+#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint
+#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX
+#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX
+
+//! Interface numbers
+#define UDI_CDC_COMM_IFACE_NUMBER_0 0
+#define UDI_CDC_DATA_IFACE_NUMBER_0 1
+
+/**
+ * Configuration of MSC interface
+ * @{
+ */
+//! Vendor name and Product version of MSC interface
+#define UDI_MSC_GLOBAL_VENDOR_ID \
+ 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' '
+#define UDI_MSC_GLOBAL_PRODUCT_VERSION \
+ '1', '.', '0', '0'
+
+//! Interface callback definition
+#define UDI_MSC_ENABLE_EXT() mp_msc_enable()
+extern bool mp_msc_enable(void);
+#define UDI_MSC_DISABLE_EXT() mp_msc_disable()
+extern void mp_msc_disable(void);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_MSC_STRING_ID 5
+
+/**
+ * USB MSC low level configuration
+ * In standalone these configurations are defined by the MSC module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN)
+#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT)
+
+//! Interface number
+#define UDI_MSC_IFACE_NUMBER 2
+/**
+ * Configuration of HID Mouse interface
+ * @{
+ */
+//! Interface callback definition
+#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable()
+extern bool mp_mouse_enable(void);
+#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable()
+extern void mp_mouse_disable(void);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_HID_MOUSE_STRING_ID 6
+
+/**
+ * USB HID Mouse low level configuration
+ * In standalone these configurations are defined by the HID Mouse module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN)
+
+//! Interface number
+#define UDI_HID_MOUSE_IFACE_NUMBER 3
+//@}
+//@}
+
+/**
+ * Configuration of HID Keyboard interface
+ * @{
+ */
+//! Interface callback definition
+#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable()
+extern bool mp_keyboard_enable(void);
+#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable()
+extern void mp_keyboard_disable(void);
+#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value)
+extern void mp_keyboard_led(uint8_t);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_HID_KBD_STRING_ID 7
+
+/**
+ * USB HID Keyboard low level configuration
+ * In standalone these configurations are defined by the HID Keyboard module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN)
+
+//! Interface number
+#define UDI_HID_KBD_IFACE_NUMBER 4
+
+/**
+ * Description of Composite Device
+ * @{
+ */
+//! USB Interfaces descriptor structure
+#define UDI_COMPOSITE_DESC_T \
+ usb_iad_desc_t udi_cdc_iad; \
+ udi_cdc_comm_desc_t udi_cdc_comm; \
+ udi_cdc_data_desc_t udi_cdc_data; \
+ udi_msc_desc_t udi_msc; \
+ udi_hid_mouse_desc_t udi_hid_mouse; \
+ udi_hid_kbd_desc_t udi_hid_kbd
+
+//! USB Interfaces descriptor value for Full Speed
+#define UDI_COMPOSITE_DESC_FS \
+ .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
+ .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
+ .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \
+ .udi_msc = UDI_MSC_DESC_FS, \
+ .udi_hid_mouse = UDI_HID_MOUSE_DESC, \
+ .udi_hid_kbd = UDI_HID_KBD_DESC
+
+//! USB Interfaces descriptor value for High Speed
+#define UDI_COMPOSITE_DESC_HS \
+ .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
+ .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
+ .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \
+ .udi_msc = UDI_MSC_DESC_HS, \
+ .udi_hid_mouse = UDI_HID_MOUSE_DESC, \
+ .udi_hid_kbd = UDI_HID_KBD_DESC
+
+//! USB Interface APIs
+#define UDI_COMPOSITE_API \
+ &udi_api_cdc_comm, \
+ &udi_api_cdc_data, \
+ &udi_api_msc, \
+ &udi_api_hid_mouse, \
+ &udi_api_hid_kbd
+//@}
+
+/**
+ * USB Device Driver Configuration
+ * @{
+ */
+//@}
+
+//! The includes of classes and other headers must be done at the end of this file to avoid compile error
+#include "udi_cdc.h"
+#include "udi_msc.h"
+#include "udi_hid_mouse.h"
+#include "udi_hid_kbd.h"
+
+#endif
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h
new file mode 100644
index 000000000..e9fd08a5f
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.h
@@ -0,0 +1,36 @@
+#define USB_REPL
+
+#define MICROPY_HW_BOARD_NAME "Adafruit ItsyBitsy M0"
+#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define CIRCUITPY_BITBANG_APA102
+#define MICROPY_HW_APA102_MOSI (&pin_PA01)
+#define MICROPY_HW_APA102_SCK (&pin_PA00)
+
+#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25)
+#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 )
+
+// Salae reads 12mhz which is the limit even though we set it to the safer 8mhz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_F
+#define SPI_FLASH_PAD2_PINMUX PINMUX_PB22D_SERCOM5_PAD2 // MOSI
+// Use default pinmux for the chip select since we manage it ourselves.
+#define SPI_FLASH_PAD3_PINMUX PINMUX_PB23D_SERCOM5_PAD3 // SCK
+#define SPI_FLASH_PAD1_PINMUX PINMUX_PB03D_SERCOM5_PAD1 // MISO
+#define SPI_FLASH_PAD0_PINMUX PINMUX_UNUSED //
+#define SPI_FLASH_SERCOM SERCOM5
+
+#define SPI_FLASH_CS PIN_PA27
+
+
+#include "spi_flash.h"
+
+// If you change this, then make sure to update the linker scripts as well to
+// make sure you don't overwrite code.
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+//#include "flash_S25FL216K.h"
+#include "flash_W25Q80DV.h"
+//#include "flash_GD25Q16C.h"
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk
new file mode 100644
index 000000000..0fb0e38ed
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/mpconfigboard.mk
@@ -0,0 +1,11 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
+USB_VID = 0x239A
+USB_PID = 0x8012
+USB_PRODUCT = "Itsy Bitsy M0 Express"
+USB_MANUFACTURER = "Adafruit Industries LLC"
+
+SPI_FLASH_FILESYSTEM = 1
+
+CHIP_VARIANT = SAMD21G18A
+CHIP_FAMILY = samd21
+
diff --git a/ports/atmel-samd/boards/itsybitsy_m0/pins.c b/ports/atmel-samd/boards/itsybitsy_m0/pins.c
new file mode 100644
index 000000000..b70bb6a76
--- /dev/null
+++ b/ports/atmel-samd/boards/itsybitsy_m0/pins.c
@@ -0,0 +1,42 @@
+#include "samd21_pins.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_D0), MP_ROM_PTR(&pin_PA11) },
+ { MP_ROM_QSTR(MP_QSTR_RX), MP_ROM_PTR(&pin_PA11) },
+
+ { MP_ROM_QSTR(MP_QSTR_D1), MP_ROM_PTR(&pin_PA10) },
+ { MP_ROM_QSTR(MP_QSTR_TX), MP_ROM_PTR(&pin_PA10) },
+
+ { MP_ROM_QSTR(MP_QSTR_D2), MP_ROM_PTR(&pin_PA14) },
+ { MP_ROM_QSTR(MP_QSTR_D3), MP_ROM_PTR(&pin_PA09) },
+ { MP_ROM_QSTR(MP_QSTR_D4), MP_ROM_PTR(&pin_PA08) },
+ { MP_ROM_QSTR(MP_QSTR_D5), MP_ROM_PTR(&pin_PA15) },
+ { MP_ROM_QSTR(MP_QSTR_D6), MP_ROM_PTR(&pin_PA20) },
+ { MP_ROM_QSTR(MP_QSTR_D7), MP_ROM_PTR(&pin_PA21) },
+ { MP_ROM_QSTR(MP_QSTR_D8), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_D9), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_D10), MP_ROM_PTR(&pin_PA18) },
+ { 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_L), MP_ROM_PTR(&pin_PA17) }, // a.k.a D13
+
+ { MP_ROM_QSTR(MP_QSTR_A0), MP_ROM_PTR(&pin_PA02) },
+ { MP_ROM_QSTR(MP_QSTR_A1), MP_ROM_PTR(&pin_PB08) },
+ { MP_ROM_QSTR(MP_QSTR_A2), MP_ROM_PTR(&pin_PB09) },
+ { MP_ROM_QSTR(MP_QSTR_A3), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_A4), MP_ROM_PTR(&pin_PA05) },
+ { MP_ROM_QSTR(MP_QSTR_A5), MP_ROM_PTR(&pin_PB02) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PB10) },
+ { MP_ROM_QSTR(MP_QSTR_MISO), MP_ROM_PTR(&pin_PA12) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PB11) },
+
+ { MP_ROM_QSTR(MP_QSTR_SCL), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_SDA), MP_ROM_PTR(&pin_PA22) },
+
+ { MP_ROM_QSTR(MP_QSTR_APA102_MOSI), MP_ROM_PTR(&pin_PA01) },
+ { MP_ROM_QSTR(MP_QSTR_APA102_SCK), MP_ROM_PTR(&pin_PA00) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld b/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld
index 56ae5feb4..1d54bb88c 100644
--- a/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld
+++ b/ports/atmel-samd/boards/samd21x18-bootloader-crystalless.ld
@@ -11,7 +11,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld
index 1c0424747..81c1e8450 100644
--- a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld
+++ b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash-crystalless.ld
@@ -11,7 +11,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld
index 4346c170c..8563ed3cb 100644
--- a/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld
+++ b/ports/atmel-samd/boards/samd21x18-bootloader-external-flash.ld
@@ -10,7 +10,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd21x18-bootloader.ld b/ports/atmel-samd/boards/samd21x18-bootloader.ld
index 13a3f75c1..4d2005518 100644
--- a/ports/atmel-samd/boards/samd21x18-bootloader.ld
+++ b/ports/atmel-samd/boards/samd21x18-bootloader.ld
@@ -11,7 +11,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd21x18-external-flash.ld b/ports/atmel-samd/boards/samd21x18-external-flash.ld
index f5797cf6f..629e190b1 100644
--- a/ports/atmel-samd/boards/samd21x18-external-flash.ld
+++ b/ports/atmel-samd/boards/samd21x18-external-flash.ld
@@ -12,6 +12,7 @@ MEMORY
/* top end of the stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);
+_bootloader_dbl_tap = 0;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd21x18.ld b/ports/atmel-samd/boards/samd21x18.ld
index a68094758..9e318e948 100644
--- a/ports/atmel-samd/boards/samd21x18.ld
+++ b/ports/atmel-samd/boards/samd21x18.ld
@@ -12,6 +12,7 @@ MEMORY
/* top end of the stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);
+_bootloader_dbl_tap = 0;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld
index f4ad37c20..73012b200 100644
--- a/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld
+++ b/ports/atmel-samd/boards/samd51x18-bootloader-external-flash.ld
@@ -10,7 +10,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld
index 4e4e8b002..c9247ec73 100644
--- a/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld
+++ b/ports/atmel-samd/boards/samd51x19-bootloader-external-flash.ld
@@ -10,7 +10,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x19-bootloader.ld b/ports/atmel-samd/boards/samd51x19-bootloader.ld
index 63aada408..02f38f39f 100644
--- a/ports/atmel-samd/boards/samd51x19-bootloader.ld
+++ b/ports/atmel-samd/boards/samd51x19-bootloader.ld
@@ -10,7 +10,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld b/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld
index 57bf299fb..bae25385a 100644
--- a/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld
+++ b/ports/atmel-samd/boards/samd51x20-bootloader-external-flash.ld
@@ -10,7 +10,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x20-bootloader.ld b/ports/atmel-samd/boards/samd51x20-bootloader.ld
index 3d6621a5a..ee0dcfd7a 100644
--- a/ports/atmel-samd/boards/samd51x20-bootloader.ld
+++ b/ports/atmel-samd/boards/samd51x20-bootloader.ld
@@ -10,7 +10,8 @@ MEMORY
}
/* top end of the stack */
-_estack = ORIGIN(RAM) + LENGTH(RAM);
+_estack = ORIGIN(RAM) + LENGTH(RAM) - 4;
+_bootloader_dbl_tap = _estack;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x20-external-flash.ld b/ports/atmel-samd/boards/samd51x20-external-flash.ld
index b0a118507..4889700a4 100644
--- a/ports/atmel-samd/boards/samd51x20-external-flash.ld
+++ b/ports/atmel-samd/boards/samd51x20-external-flash.ld
@@ -11,6 +11,7 @@ MEMORY
/* top end of the stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);
+_bootloader_dbl_tap = 0;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/samd51x20.ld b/ports/atmel-samd/boards/samd51x20.ld
index ed26425f3..a30f4525b 100644
--- a/ports/atmel-samd/boards/samd51x20.ld
+++ b/ports/atmel-samd/boards/samd51x20.ld
@@ -11,6 +11,7 @@ MEMORY
/* top end of the stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);
+_bootloader_dbl_tap = 0;
/* define output sections */
SECTIONS
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index 04dc9e401..a904b2837 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -4,8 +4,7 @@ USB_PID = 0x801F
USB_PRODUCT="Trinket M0 Haxpress"
USB_MANUFACTURER="Radomir Dopieralski"
-#SPI_FLASH_FILESYSTEM = 1
-INTERNAL_FLASH_FILESYSTEM = 1
+SPI_FLASH_FILESYSTEM = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/ugame/board.c b/ports/atmel-samd/boards/ugame/board.c
new file mode 100644
index 000000000..d7e856d61
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/board.c
@@ -0,0 +1,37 @@
+/*
+ * 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/atmel-samd/boards/ugame/conf_access.h b/ports/atmel-samd/boards/ugame/conf_access.h
new file mode 100644
index 000000000..2326bfcdf
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/conf_access.h
@@ -0,0 +1,115 @@
+/**
+ * \file
+ *
+ * \brief Memory access control configuration file.
+ *
+ * Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
+ *
+ * \asf_license_start
+ *
+ * \page License
+ *
+ * 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. The name of Atmel may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * 4. This software may only be redistributed and used in connection with an
+ * Atmel microcontroller product.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
+ * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
+ *
+ * \asf_license_stop
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef _CONF_ACCESS_H_
+#define _CONF_ACCESS_H_
+
+#include "compiler.h"
+#include "board.h"
+
+
+/*! \name Activation of Logical Unit Numbers
+ */
+//! @{
+#define LUN_0 ENABLE //!< On-Chip Virtual Memory.
+#define LUN_1 DISABLE //!< AT45DBX Data Flash.
+#define LUN_2 DISABLE //!< SD/MMC Card over SPI.
+#define LUN_3 DISABLE //!< SD/MMC Card over MCI Slot 0.
+#define LUN_4 DISABLE
+#define LUN_5 DISABLE
+#define LUN_6 DISABLE
+#define LUN_7 DISABLE
+#define LUN_USB DISABLE //!< Host Mass-Storage Memory.
+//! @}
+
+/*! \name LUN 0 Definitions
+ */
+//! @{
+#define LUN_0_INCLUDE "access_vfs.h"
+#define Lun_0_test_unit_ready vfs_test_unit_ready
+#define Lun_0_read_capacity vfs_read_capacity
+#define Lun_0_unload NULL
+#define Lun_0_wr_protect vfs_wr_protect
+#define Lun_0_removal vfs_removal
+#define Lun_0_usb_read_10 vfs_usb_read_10
+#define Lun_0_usb_write_10 vfs_usb_write_10
+#define LUN_0_NAME "\"CircuitPython VFS[0]\""
+//! @}
+
+#define MEM_USB LUN_USB
+
+/*! \name Actions Associated with Memory Accesses
+ *
+ * Write here the action to associate with each memory access.
+ *
+ * \warning Be careful not to waste time in order not to disturb the functions.
+ */
+//! @{
+#define memory_start_read_action(nb_sectors)
+#define memory_stop_read_action()
+#define memory_start_write_action(nb_sectors)
+#define memory_stop_write_action()
+//! @}
+
+/*! \name Activation of Interface Features
+ */
+//! @{
+#define ACCESS_USB true //!< MEM <-> USB interface.
+#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface.
+#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface.
+#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode.
+#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface.
+#define ACCESS_CODEC false //!< Codec interface.
+//! @}
+
+/*! \name Specific Options for Access Control
+ */
+//! @{
+#define GLOBAL_WR_PROTECT false //!< Management of a global write protection.
+//! @}
+
+
+#endif // _CONF_ACCESS_H_
diff --git a/ports/atmel-samd/boards/ugame/conf_board.h b/ports/atmel-samd/boards/ugame/conf_board.h
new file mode 100644
index 000000000..7b88c97fc
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/conf_board.h
@@ -0,0 +1,14 @@
+/**
+ * \file
+ *
+ * \brief User board configuration template
+ *
+ */
+/*
+ * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
+ */
+
+#ifndef CONF_BOARD_H
+#define CONF_BOARD_H
+
+#endif // CONF_BOARD_H
diff --git a/ports/atmel-samd/boards/ugame/conf_clocks.h b/ports/atmel-samd/boards/ugame/conf_clocks.h
new file mode 100644
index 000000000..9e4f7876b
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/conf_clocks.h
@@ -0,0 +1 @@
+#include "conf_clocks_crystalless.h"
diff --git a/ports/atmel-samd/boards/ugame/conf_usb.h b/ports/atmel-samd/boards/ugame/conf_usb.h
new file mode 100644
index 000000000..b881ed149
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/conf_usb.h
@@ -0,0 +1,221 @@
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h"
+
+#ifndef CONF_USB_H_INCLUDED
+#define CONF_USB_H_INCLUDED
+
+#define USB_DEVICE_MAJOR_VERSION 1
+#define USB_DEVICE_MINOR_VERSION 0
+#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA)
+#define USB_DEVICE_ATTR \
+ (USB_CONFIG_ATTR_BUS_POWERED)
+// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
+// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
+
+//! USB Device string definitions (Optional)
+#ifndef USB_DEVICE_MANUFACTURE_NAME
+# define USB_DEVICE_MANUFACTURE_NAME "Radomir Dopieralski"
+#endif
+
+#ifndef USB_DEVICE_PRODUCT_NAME
+# define USB_DEVICE_PRODUCT_NAME "uGame"
+#endif
+// #define USB_DEVICE_SERIAL_NAME "12...EF"
+#define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number
+#define USB_DEVICE_GET_SERIAL_NAME_LENGTH 32
+extern char serial_number[USB_DEVICE_GET_SERIAL_NAME_LENGTH];
+
+//! Control endpoint size
+#define USB_DEVICE_EP_CTRL_SIZE 64
+
+//! Interfaces for this device (CDC COM + CDC DATA + MSC + HID mouse + HID kbd)
+#define USB_DEVICE_NB_INTERFACE 5
+
+// (3 | USB_EP_DIR_IN) // CDC Notify endpoint
+// (4 | USB_EP_DIR_IN) // CDC TX
+// (5 | USB_EP_DIR_OUT) // CDC RX
+// (1 | USB_EP_DIR_IN) // MSC IN
+// (2 | USB_EP_DIR_OUT) // MSC OUT
+// (6 | USB_EP_DIR_IN) // HID mouse report
+// (7 | USB_EP_DIR_IN) // HID keyboard report
+#define USB_DEVICE_MAX_EP 7
+
+#define UDI_CDC_PORT_NB 1
+#define UDI_CDC_ENABLE_EXT(port) mp_cdc_enable(port)
+extern bool mp_cdc_enable(uint8_t port);
+#define UDI_CDC_DISABLE_EXT(port) mp_cdc_disable(port)
+extern void mp_cdc_disable(uint8_t port);
+#define UDI_CDC_LOW_RATE
+
+#define UDI_CDC_DEFAULT_RATE 115200
+#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
+#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
+#define UDI_CDC_DEFAULT_DATABITS 8
+
+#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify()
+void usb_rx_notify(void);
+
+#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg)
+void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding);
+#define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set)
+void usb_dtr_notify(uint8_t port, bool set);
+#define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set)
+void usb_rts_notify(uint8_t port, bool set);
+
+/**
+ * USB CDC low level configuration
+ * In standalone these configurations are defined by the CDC module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+
+#define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint
+#define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX
+#define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT) // RX
+
+//! Interface numbers
+#define UDI_CDC_COMM_IFACE_NUMBER_0 0
+#define UDI_CDC_DATA_IFACE_NUMBER_0 1
+
+/**
+ * Configuration of MSC interface
+ * @{
+ */
+//! Vendor name and Product version of MSC interface
+#define UDI_MSC_GLOBAL_VENDOR_ID \
+ 'A', 'T', 'M', 'E', 'L', ' ', ' ', ' '
+#define UDI_MSC_GLOBAL_PRODUCT_VERSION \
+ '1', '.', '0', '0'
+
+//! Interface callback definition
+#define UDI_MSC_ENABLE_EXT() mp_msc_enable()
+extern bool mp_msc_enable(void);
+#define UDI_MSC_DISABLE_EXT() mp_msc_disable()
+extern void mp_msc_disable(void);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_MSC_STRING_ID 5
+
+/**
+ * USB MSC low level configuration
+ * In standalone these configurations are defined by the MSC module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN)
+#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT)
+
+//! Interface number
+#define UDI_MSC_IFACE_NUMBER 2
+/**
+ * Configuration of HID Mouse interface
+ * @{
+ */
+//! Interface callback definition
+#define UDI_HID_MOUSE_ENABLE_EXT() mp_mouse_enable()
+extern bool mp_mouse_enable(void);
+#define UDI_HID_MOUSE_DISABLE_EXT() mp_mouse_disable()
+extern void mp_mouse_disable(void);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_HID_MOUSE_STRING_ID 6
+
+/**
+ * USB HID Mouse low level configuration
+ * In standalone these configurations are defined by the HID Mouse module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_HID_MOUSE_EP_IN (6 | USB_EP_DIR_IN)
+
+//! Interface number
+#define UDI_HID_MOUSE_IFACE_NUMBER 3
+//@}
+//@}
+
+/**
+ * Configuration of HID Keyboard interface
+ * @{
+ */
+//! Interface callback definition
+#define UDI_HID_KBD_ENABLE_EXT() mp_keyboard_enable()
+extern bool mp_keyboard_enable(void);
+#define UDI_HID_KBD_DISABLE_EXT() mp_keyboard_disable()
+extern void mp_keyboard_disable(void);
+#define UDI_HID_KBD_CHANGE_LED(value) mp_keyboard_led(value)
+extern void mp_keyboard_led(uint8_t);
+
+//! Enable id string of interface to add an extra USB string
+#define UDI_HID_KBD_STRING_ID 7
+
+/**
+ * USB HID Keyboard low level configuration
+ * In standalone these configurations are defined by the HID Keyboard module.
+ * For composite device, these configuration must be defined here
+ * @{
+ */
+//! Endpoint numbers definition
+#define UDI_HID_KBD_EP_IN (7 | USB_EP_DIR_IN)
+
+//! Interface number
+#define UDI_HID_KBD_IFACE_NUMBER 4
+
+/**
+ * Description of Composite Device
+ * @{
+ */
+//! USB Interfaces descriptor structure
+#define UDI_COMPOSITE_DESC_T \
+ usb_iad_desc_t udi_cdc_iad; \
+ udi_cdc_comm_desc_t udi_cdc_comm; \
+ udi_cdc_data_desc_t udi_cdc_data; \
+ udi_msc_desc_t udi_msc; \
+ udi_hid_mouse_desc_t udi_hid_mouse; \
+ udi_hid_kbd_desc_t udi_hid_kbd
+
+//! USB Interfaces descriptor value for Full Speed
+#define UDI_COMPOSITE_DESC_FS \
+ .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
+ .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
+ .udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \
+ .udi_msc = UDI_MSC_DESC_FS, \
+ .udi_hid_mouse = UDI_HID_MOUSE_DESC, \
+ .udi_hid_kbd = UDI_HID_KBD_DESC
+
+//! USB Interfaces descriptor value for High Speed
+#define UDI_COMPOSITE_DESC_HS \
+ .udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
+ .udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
+ .udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \
+ .udi_msc = UDI_MSC_DESC_HS, \
+ .udi_hid_mouse = UDI_HID_MOUSE_DESC, \
+ .udi_hid_kbd = UDI_HID_KBD_DESC
+
+//! USB Interface APIs
+#define UDI_COMPOSITE_API \
+ &udi_api_cdc_comm, \
+ &udi_api_cdc_data, \
+ &udi_api_msc, \
+ &udi_api_hid_mouse, \
+ &udi_api_hid_kbd
+//@}
+
+/**
+ * USB Device Driver Configuration
+ * @{
+ */
+//@}
+
+//! The includes of classes and other headers must be done at the end of this file to avoid compile error
+#include "udi_cdc.h"
+#include "udi_msc.h"
+#include "udi_hid_mouse.h"
+#include "udi_hid_kbd.h"
+
+#endif
diff --git a/ports/atmel-samd/boards/ugame/mpconfigboard.h b/ports/atmel-samd/boards/ugame/mpconfigboard.h
new file mode 100644
index 000000000..17baf9b0f
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/mpconfigboard.h
@@ -0,0 +1,48 @@
+#define USB_REPL
+
+#define MICROPY_HW_BOARD_NAME "uGame"
+#define MICROPY_HW_MCU_NAME "samd21e18"
+
+#if 1
+// Salae reads 12mhz which is the limit even though we set it to the
+// safer 8mhz.
+#define SPI_FLASH_BAUDRATE (8000000)
+
+#define SPI_FLASH_MUX_SETTING SPI_SIGNAL_MUX_SETTING_D
+#define SPI_FLASH_PAD0_PINMUX PINMUX_PA16D_SERCOM3_PAD0 // MOSI
+#define SPI_FLASH_PAD1_PINMUX PINMUX_PA17D_SERCOM3_PAD1 // SCK
+#define SPI_FLASH_PAD2_PINMUX PINMUX_UNUSED // Use default pinmux for the chip
+ // select since we manage it
+ // ourselves.
+#define SPI_FLASH_PAD3_PINMUX PINMUX_PA19D_SERCOM3_PAD3 // MISO
+#define SPI_FLASH_SERCOM SERCOM3
+
+#define SPI_FLASH_CS PIN_PA11
+
+#define MICROPY_PORT_A (PORT_PA11 | PORT_PA16 |\
+ PORT_PA17 | PORT_PA18 | PORT_PA19 | PORT_PA24 |\
+ PORT_PA25)
+#define MICROPY_PORT_B (0)
+
+#define CALIBRATE_CRYSTALLESS 1
+
+#include "spi_flash.h"
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE 256
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE)
+
+//#include "flash_W25Q32BV.h"
+#include "flash_S25FL216K.h"
+
+#else
+
+#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25)
+#define MICROPY_PORT_B (0)
+
+#include "internal_flash.h"
+
+#define CIRCUITPY_INTERNAL_NVM_SIZE 0
+#define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000)
+
+#endif
+
diff --git a/ports/atmel-samd/boards/ugame/mpconfigboard.mk b/ports/atmel-samd/boards/ugame/mpconfigboard.mk
new file mode 100644
index 000000000..40f1bc06f
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/mpconfigboard.mk
@@ -0,0 +1,11 @@
+LD_FILE = boards/samd21x18-bootloader-external-flash-crystalless.ld
+#LD_FILE = boards/samd21x18-bootloader.ld
+USB_VID = 0x239A
+USB_PID = 0x801F
+USB_PRODUCT = "UGame"
+USB_MANUFACTURER = "Radomir Dopieralski"
+
+SPI_FLASH_FILESYSTEM = 1
+
+CHIP_VARIANT = SAMD21E18A
+CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/ugame/pins.c b/ports/atmel-samd/boards/ugame/pins.c
new file mode 100644
index 000000000..b9c8f2386
--- /dev/null
+++ b/ports/atmel-samd/boards/ugame/pins.c
@@ -0,0 +1,18 @@
+#include "samd21_pins.h"
+
+STATIC const mp_rom_map_elem_t board_global_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_X), MP_ROM_PTR(&pin_PA00) },
+ { MP_ROM_QSTR(MP_QSTR_O), MP_ROM_PTR(&pin_PA01) },
+
+ { MP_ROM_QSTR(MP_QSTR_SPEAKER), MP_ROM_PTR(&pin_PA02) },
+
+ { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_PTR(&pin_PA03) },
+ { MP_ROM_QSTR(MP_QSTR_LEFT), MP_ROM_PTR(&pin_PA04) },
+ { MP_ROM_QSTR(MP_QSTR_DOWN), MP_ROM_PTR(&pin_PA23) },
+ { MP_ROM_QSTR(MP_QSTR_RIGHT), MP_ROM_PTR(&pin_PA05) },
+
+ { MP_ROM_QSTR(MP_QSTR_MOSI), MP_ROM_PTR(&pin_PA06) },
+ { MP_ROM_QSTR(MP_QSTR_SCK), MP_ROM_PTR(&pin_PA07) },
+ { MP_ROM_QSTR(MP_QSTR_DC), MP_ROM_PTR(&pin_PA08) },
+};
+MP_DEFINE_CONST_DICT(board_module_globals, board_global_dict_table);
diff --git a/ports/atmel-samd/common-hal/analogio/AnalogIn.c b/ports/atmel-samd/common-hal/analogio/AnalogIn.c
index 03c502dff..cbb9f5de5 100644
--- a/ports/atmel-samd/common-hal/analogio/AnalogIn.c
+++ b/ports/atmel-samd/common-hal/analogio/AnalogIn.c
@@ -74,8 +74,10 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
config_adc.reference = ADC_REFERENCE_INTVCC1;
config_adc.gain_factor = ADC_GAIN_FACTOR_DIV2;
config_adc.positive_input = self->pin->adc_input;
- config_adc.resolution = ADC_RESOLUTION_16BIT;
- config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV128;
+ config_adc.resolution = ADC_RESOLUTION_12BIT;
+ // Default input clock is GCLK0 (48 MHz)
+ // 48Mhz / 32 = 1.5MHz. Max ADC clock is 2.1MHz
+ config_adc.clock_prescaler = ADC_CLOCK_PRESCALER_DIV32;
struct adc_module adc_instance;
// ADC must have been disabled before adc_init() is called.
@@ -108,7 +110,8 @@ uint16_t common_hal_analogio_analogin_get_value(analogio_analogin_obj_t *self) {
}
adc_disable(&adc_instance);
- return data;
+ // Scale to 16 bits. In the future we might make this be this be under API control.
+ return data * 16;
}
float common_hal_analogio_analogin_get_reference_voltage(analogio_analogin_obj_t *self) {
diff --git a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
index db671f213..50d3b180c 100644
--- a/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
+++ b/ports/atmel-samd/common-hal/audiobusio/PDMIn.c
@@ -26,6 +26,7 @@
#include <stdint.h>
#include <string.h>
+#include <math.h>
#include "py/gc.h"
#include "py/mperrno.h"
@@ -42,6 +43,12 @@
#include "shared_dma.h"
#include "tick.h"
+#define OVERSAMPLING 64
+#define SAMPLES_PER_BUFFER 32
+
+// MEMS microphones must be clocked at at least 1MHz.
+#define MIN_MIC_CLOCK 1000000
+
void pdmin_reset(void) {
while (I2S->SYNCBUSY.reg & I2S_SYNCBUSY_ENABLE) {}
I2S->INTENCLR.reg = I2S_INTENCLR_MASK;
@@ -96,8 +103,8 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
mp_raise_RuntimeError("Unable to allocate audio DMA block counter.");
}
- if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != 64) {
- mp_raise_NotImplementedError("Only 8 or 16 bit mono with 64 oversample is supported.");
+ if (!(bit_depth == 16 || bit_depth == 8) || !mono || oversample != OVERSAMPLING) {
+ mp_raise_NotImplementedError("Only 8 or 16 bit mono with " MP_STRINGIFY(OVERSAMPLING) "x oversampling is supported.");
}
// TODO(tannewt): Use the DPLL to get a more precise sampling rate.
@@ -112,12 +119,17 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
config_clock_unit.clock.mck_out_enable = false;
config_clock_unit.clock.sck_src = I2S_SERIAL_CLOCK_SOURCE_MCKDIV;
- config_clock_unit.clock.sck_div = 8000000 / frequency / oversample;
- self->frequency = 8000000 / config_clock_unit.clock.sck_div / oversample;
+ uint32_t clock_divisor = (uint32_t) roundf( 8000000.0f / frequency / oversample);
+ config_clock_unit.clock.sck_div = clock_divisor;
+ float mic_clock_freq = 8000000.0f / clock_divisor;
+ self->frequency = mic_clock_freq / oversample;
+ if (mic_clock_freq < MIN_MIC_CLOCK || clock_divisor == 0 || clock_divisor > 255) {
+ mp_raise_ValueError("sampling frequency out of range");
+ }
config_clock_unit.frame.number_slots = 2;
config_clock_unit.frame.slot_size = I2S_SLOT_SIZE_16_BIT;
- config_clock_unit.frame.data_delay = I2S_DATA_DELAY_1;
+ config_clock_unit.frame.data_delay = I2S_DATA_DELAY_0;
config_clock_unit.frame.frame_sync.width = I2S_FRAME_SYNC_WIDTH_SLOT;
@@ -141,6 +153,10 @@ void common_hal_audiobusio_pdmin_construct(audiobusio_pdmin_obj_t* self,
i2s_serializer_set_config(&self->i2s_instance, self->serializer, &config_serializer);
i2s_enable(&self->i2s_instance);
+ // Run the serializer all the time. This eliminates startup delay for the microphone.
+ i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit);
+ i2s_serializer_enable(&self->i2s_instance, self->serializer);
+
self->bytes_per_sample = oversample >> 3;
self->bit_depth = bit_depth;
}
@@ -154,6 +170,8 @@ void common_hal_audiobusio_pdmin_deinit(audiobusio_pdmin_obj_t* self) {
return;
}
i2s_disable(&self->i2s_instance);
+ i2s_serializer_disable(&self->i2s_instance, self->serializer);
+ i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit);
i2s_reset(&self->i2s_instance);
reset_pin(self->clock_pin->pin);
reset_pin(self->data_pin->pin);
@@ -195,11 +213,15 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length,
}
dma_descriptor_create(audio_dma.descriptor, &descriptor_config);
+ // Do we need more values than will fit in the first buffer?
+ // If so, set up a second buffer chained to be filled after the first buffer.
if (length * words_per_sample > words_per_buffer) {
block_transfer_count = words_per_buffer;
descriptor_config.next_descriptor_address = ((uint32_t)audio_dma.descriptor);
if (length * words_per_sample < 2 * words_per_buffer) {
- block_transfer_count = 2 * words_per_buffer - length * words_per_sample;
+ // Length needed is more than one buffer but less than two.
+ // Subtract off the size of the first buffer, and what remains is the count we need.
+ block_transfer_count = length * words_per_sample - words_per_buffer;
descriptor_config.next_descriptor_address = 0;
}
descriptor_config.block_transfer_count = block_transfer_count;
@@ -213,117 +235,150 @@ static void setup_dma(audiobusio_pdmin_obj_t* self, uint32_t length,
void start_dma(audiobusio_pdmin_obj_t* self) {
dma_start_transfer_job(&audio_dma);
tc_start_counter(MP_STATE_VM(audiodma_block_counter));
- i2s_clock_unit_enable(&self->i2s_instance, self->clock_unit);
- i2s_serializer_enable(&self->i2s_instance, self->serializer);
I2S->DATA[1].reg = I2S->DATA[1].reg;
}
void stop_dma(audiobusio_pdmin_obj_t* self) {
- // Turn off the I2S clock and serializer. Peripheral is still enabled.
- i2s_serializer_disable(&self->i2s_instance, self->serializer);
- i2s_clock_unit_disable(&self->i2s_instance, self->clock_unit);
-
- // Shutdown the DMA
+ // Shutdown the DMA: serializer keeps running.
tc_stop_counter(MP_STATE_VM(audiodma_block_counter));
dma_abort_job(&audio_dma);
}
-static const uint16_t sinc_filter[64] = {
- 0, 1, 6, 16, 29, 49, 75, 108,
- 149, 200, 261, 334, 418, 514, 622, 742,
- 872, 1012, 1161, 1315, 1472, 1631, 1787, 1938,
- 2081, 2212, 2329, 2429, 2509, 2568, 2604, 2616,
- 2604, 2568, 2509, 2429, 2329, 2212, 2081, 1938,
- 1787, 1631, 1472, 1315, 1161, 1012, 872, 742,
- 622, 514, 418, 334, 261, 200, 149, 108,
- 75, 49, 29, 16, 6, 1, 0, 0
+// a windowed sinc filter for 44 khz, 64 samples
+//
+// This filter is good enough to use for lower sample rates as
+// well. It does not increase the noise enough to be a problem.
+//
+// In the long run we could use a fast filter like this to do the
+// decimation and initial filtering in real time, filtering to a
+// higher sample rate than specified. Then after the audio is
+// recorded, a more expensive filter non-real-time filter could be
+// used to down-sample and low-pass.
+uint16_t sinc_filter [OVERSAMPLING] = {
+ 0, 2, 9, 21, 39, 63, 94, 132,
+ 179, 236, 302, 379, 467, 565, 674, 792,
+ 920, 1055, 1196, 1341, 1487, 1633, 1776, 1913,
+ 2042, 2159, 2263, 2352, 2422, 2474, 2506, 2516,
+ 2506, 2474, 2422, 2352, 2263, 2159, 2042, 1913,
+ 1776, 1633, 1487, 1341, 1196, 1055, 920, 792,
+ 674, 565, 467, 379, 302, 236, 179, 132,
+ 94, 63, 39, 21, 9, 2, 0, 0
};
+#define REPEAT_16_TIMES(X) X X X X X X X X X X X X X X X X
+
static uint16_t filter_sample(uint32_t pdm_samples[4]) {
- uint16_t sample = 0;
- for (uint8_t i = 0; i < 4; i++) {
- uint16_t pdm = pdm_samples[i] & 0xffff;
- for (uint8_t j = 0; j < 16; j++) {
- if ((pdm & 0x8000) != 0) {
- sample += sinc_filter[i * 16 + j];
+ uint16_t running_sum = 0;
+ const uint16_t *filter_ptr = sinc_filter;
+ for (uint8_t i = 0; i < OVERSAMPLING/16; i++) {
+ // The sample is 16-bits right channel in the upper two bytes and 16-bits left channel
+ // in the lower two bytes.
+ // We just ignore the upper bits
+ uint32_t pdm_sample = pdm_samples[i];
+ REPEAT_16_TIMES( {
+ if (pdm_sample & 0x8000) {
+ running_sum += *filter_ptr;
+ }
+ filter_ptr++;
+ pdm_sample <<= 1;
}
- pdm <<= 1;
- }
+ )
}
- return sample;
+ return running_sum;
}
+// output_buffer may be a byte buffer or a halfword buffer.
+// output_buffer_length is the number of slots, not the number of bytes.
uint32_t common_hal_audiobusio_pdmin_record_to_buffer(audiobusio_pdmin_obj_t* self,
- uint16_t* output_buffer, uint32_t length) {
- // Write the wave file header.
-
- // We allocate two 256 byte buffers on the stack to use for double buffering.
- // Our oversample rate is 64 (bits) so each buffer produces 32 samples.
- // TODO(tannewt): Can the compiler optimize better if we fix the size of
- // these buffers?
- uint8_t samples_per_buffer = 32;
+ uint16_t* output_buffer, uint32_t output_buffer_length) {
+ // We allocate two buffers on the stack to use for double buffering.
+ const uint8_t samples_per_buffer = SAMPLES_PER_BUFFER;
// For every word we record, we throw away 2 bytes of a phantom second channel.
- uint8_t words_per_sample = self->bytes_per_sample / 2;
- uint8_t words_per_buffer = samples_per_buffer * words_per_sample;
+ const uint8_t words_per_sample = self->bytes_per_sample / 2;
+ const uint8_t words_per_buffer = samples_per_buffer * words_per_sample;
uint32_t first_buffer[words_per_buffer];
uint32_t second_buffer[words_per_buffer];
COMPILER_ALIGNED(16) DmacDescriptor second_descriptor;
- setup_dma(self, length, &second_descriptor, words_per_buffer,
+ setup_dma(self, output_buffer_length, &second_descriptor, words_per_buffer,
words_per_sample, first_buffer, second_buffer);
start_dma(self);
// Record
uint32_t buffers_processed = 0;
- uint32_t total_bytes = 0;
+ uint32_t values_output = 0;
- uint64_t start_ticks = ticks_ms;
- while (total_bytes < length) {
+ uint32_t remaining_samples_needed = output_buffer_length;
+ while (values_output < output_buffer_length) {
// Wait for the next buffer to fill
- while (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) == buffers_processed) {
+ uint32_t block_counter;
+ while ((block_counter = tc_get_count_value(MP_STATE_VM(audiodma_block_counter))) == buffers_processed) {
#ifdef MICROPY_VM_HOOK_LOOP
MICROPY_VM_HOOK_LOOP
#endif
}
- if (tc_get_count_value(MP_STATE_VM(audiodma_block_counter)) != (buffers_processed + 1)) {
+ if (block_counter != (buffers_processed + 1)) {
+ // Looks like we aren't keeping up. We shouldn't skip a buffer.
break;
}
- // Throw away the first ~10ms of data because thats during mic start up.
- if (ticks_ms - start_ticks < 10) {
- buffers_processed++;
- continue;
- }
- uint32_t* buffer = first_buffer;
+
+ // The mic is running all the time, so we don't need to wait the usual 10msec or 100msec
+ // for it to start up.
+
+ // Flip back and forth between processing the first and second buffers.
+ uint32_t *buffer = first_buffer;
DmacDescriptor* descriptor = audio_dma.descriptor;
if (buffers_processed % 2 == 1) {
buffer = second_buffer;
descriptor = &second_descriptor;
}
- // Decimate and filter the last buffer
- int32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample;
- for (uint16_t i = 0; i < samples_gathered; i++) {
+ // Decimate and filter the buffer that was just filled.
+ uint32_t samples_gathered = descriptor->BTCNT.reg / words_per_sample;
+ // Don't run off the end of output buffer. Process only as many as needed.
+ uint32_t samples_to_process = min(remaining_samples_needed, samples_gathered);
+ for (uint32_t i = 0; i < samples_to_process; i++) {
+ // Call filter_sample just one place so it can be inlined.
+ uint16_t value = filter_sample(buffer + i * words_per_sample);
if (self->bit_depth == 8) {
- ((uint8_t*) output_buffer)[total_bytes] = filter_sample(buffer + i * words_per_sample) >> 8;
- total_bytes += 1;
- } else if (self->bit_depth == 16) {
- output_buffer[total_bytes / 2] = filter_sample(buffer + i * words_per_sample);
- total_bytes += 2;
+ // Truncate to 8 bits.
+ ((uint8_t*) output_buffer)[values_output] = value >> 8;
+ } else {
+ output_buffer[values_output] = value;
}
+ values_output++;
}
+
buffers_processed++;
- if (length - total_bytes < samples_per_buffer) {
- descriptor->BTCNT.reg = (length - total_bytes) * words_per_sample;
- descriptor->DSTADDR.reg = ((uint32_t) buffer) + (length - total_bytes) * self->bytes_per_sample;
+ // Compute how many more samples we need, and if the last buffer is the last
+ // set of samples needed, adjust the DMA count to only fetch as necessary.
+ remaining_samples_needed = output_buffer_length - values_output;
+ if (remaining_samples_needed <= samples_per_buffer*2 &&
+ remaining_samples_needed > samples_per_buffer) {
+ // Adjust the DMA settings for the current buffer, which will be processed
+ // after the other buffer, which is now receiving samples via DMA.
+ // We don't adjust the DMA in progress, but the one after that.
+ // Timeline:
+ // 1. current buffer (already processed)
+ // 2. alternate buffer (DMA in progress)
+ // 3. current buffer (last set of samples needed)
+
+ // Set up to receive the last set of samples (don't include the alternate buffer, now in use).
+ uint32_t samples_needed_for_last_buffer = remaining_samples_needed - samples_per_buffer;
+ descriptor->BTCNT.reg = samples_needed_for_last_buffer * words_per_sample;
+ descriptor->DSTADDR.reg = ((uint32_t) buffer)
+ + samples_needed_for_last_buffer * words_per_sample * sizeof(buffer[0]);
+
+ // Break chain to alternate buffer.
descriptor->DESCADDR.reg = 0;
}
}
stop_dma(self);
- return total_bytes;
+ return values_output;
}
void common_hal_audiobusio_pdmin_record_to_file(audiobusio_pdmin_obj_t* self, uint8_t* buffer, uint32_t length) {
diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c
index cb6a165de..4414d7ca9 100644
--- a/ports/atmel-samd/common-hal/busio/SPI.c
+++ b/ports/atmel-samd/common-hal/busio/SPI.c
@@ -262,3 +262,20 @@ 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) {
+ if (len == 0) {
+ return true;
+ }
+ int32_t status;
+// if (len >= 16) {
+// status = shared_dma_transfer(self->spi_master_instance.hw, data_out, data_in, len, 0 /*ignored*/);
+// } else {
+ struct spi_xfer xfer;
+ xfer.txbuf = data_out;
+ xfer.rxbuf = data_in;
+ xfer.size = len;
+ status = spi_m_sync_transfer(&self->spi_desc, &xfer);
+// }
+ return status >= 0; // Status is number of chars read or an error code < 0.
+}
diff --git a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c
index c5fff4ba2..109f14b04 100644
--- a/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c
+++ b/ports/atmel-samd/common-hal/digitalio/DigitalInOut.c
@@ -58,7 +58,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
}
void common_hal_digitalio_digitalinout_switch_to_input(
- digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
+ digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
self->output = false;
common_hal_digitalio_digitalinout_set_pull(self, pull);
@@ -66,7 +66,7 @@ void common_hal_digitalio_digitalinout_switch_to_input(
void common_hal_digitalio_digitalinout_switch_to_output(
digitalio_digitalinout_obj_t* self, bool value,
- enum digitalio_drive_mode_t drive_mode) {
+ digitalio_drive_mode_t drive_mode) {
const uint8_t pin = self->pin->pin;
gpio_set_pin_pull_mode(pin, GPIO_PULL_OFF);
gpio_set_pin_direction(pin, GPIO_DIRECTION_OUT);
@@ -79,7 +79,7 @@ void common_hal_digitalio_digitalinout_switch_to_output(
common_hal_digitalio_digitalinout_set_value(self, value);
}
-enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
+digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
digitalio_digitalinout_obj_t* self) {
return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT;
}
@@ -115,7 +115,7 @@ bool common_hal_digitalio_digitalinout_get_value(
void common_hal_digitalio_digitalinout_set_drive_mode(
digitalio_digitalinout_obj_t* self,
- enum digitalio_drive_mode_t drive_mode) {
+ digitalio_drive_mode_t drive_mode) {
bool value = common_hal_digitalio_digitalinout_get_value(self);
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
// True is implemented differently between modes so reset the value to make
@@ -125,7 +125,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
}
}
-enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
+digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
digitalio_digitalinout_obj_t* self) {
if (self->open_drain) {
return DRIVE_MODE_OPEN_DRAIN;
@@ -135,7 +135,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
}
void common_hal_digitalio_digitalinout_set_pull(
- digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
+ digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
enum gpio_pull_mode asf_pull = GPIO_PULL_OFF;
switch (pull) {
case PULL_UP:
@@ -151,7 +151,7 @@ void common_hal_digitalio_digitalinout_set_pull(
gpio_set_pin_pull_mode(self->pin->pin, asf_pull);
}
-enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
+digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
digitalio_digitalinout_obj_t* self) {
uint32_t pin = self->pin->pin;
if (self->output) {
diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c
index 5c119c439..614fac870 100644
--- a/ports/atmel-samd/common-hal/microcontroller/__init__.c
+++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c
@@ -27,10 +27,13 @@
#include "py/mphal.h"
#include "py/obj.h"
#include "hal/include/hal_atomic.h"
+#include "py/runtime.h"
+#include "reset.h"
#include "samd21_pins.h"
#include "shared-bindings/nvm/ByteArray.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
void common_hal_mcu_delay_us(uint32_t delay) {
@@ -48,9 +51,32 @@ void common_hal_mcu_enable_interrupts(void) {
atomic_leave_critical(&flags);
}
+extern uint32_t _ezero;
+
+void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
+ // Set up the defaults.
+ _bootloader_dbl_tap = DBL_TAP_MAGIC;
+ _ezero = CIRCUITPY_CANARY_WORD;
+
+ if (runmode == RUNMODE_BOOTLOADER) {
+ if (!bootloader_available()) {
+ mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present.");
+ }
+ // Pretend to be the first of the two reset presses needed to enter the
+ // bootloader. That way one reset will end in the bootloader.
+ _bootloader_dbl_tap = DBL_TAP_MAGIC;
+ } else if (runmode == RUNMODE_SAFE_MODE) {
+ _ezero = CIRCUITPY_SOFTWARE_SAFE_MODE;
+ }
+}
+
+void common_hal_mcu_reset(void) {
+ reset();
+}
+
// The singleton microcontroller.Processor object, bound to microcontroller.cpu
// It currently only has properties, and no state.
-mcu_processor_obj_t common_hal_mcu_processor_obj = {
+const mcu_processor_obj_t common_hal_mcu_processor_obj = {
.base = {
.type = &mcu_processor_type,
},
@@ -59,7 +85,7 @@ mcu_processor_obj_t common_hal_mcu_processor_obj = {
// NVM is only available on Express boards for now.
#if CIRCUITPY_INTERNAL_NVM_SIZE > 0
// The singleton nvm.ByteArray object.
-// nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
+// const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = {
// .base = {
// .type = &nvm_bytearray_type,
// },
diff --git a/ports/atmel-samd/reset.c b/ports/atmel-samd/reset.c
index ab940285b..ba5bf9ba1 100644
--- a/ports/atmel-samd/reset.c
+++ b/ports/atmel-samd/reset.c
@@ -24,23 +24,22 @@
* THE SOFTWARE.
*/
-#include "reset.h"
-
#include "include/sam.h"
-#include "supervisor/filesystem.h"
-// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21
-#ifdef SAMD21
-#define DBL_TAP_PTR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4))
-#else
- #ifdef SAMD51
- #define DBL_TAP_PTR ((volatile uint32_t *)(HSRAM_ADDR + HSRAM_SIZE - 4))
- #endif
-#endif
-#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
+#include "reset.h"
+#include "supervisor/filesystem.h"
-void reset_to_bootloader(void) {
+void reset(void) {
filesystem_flush();
- *DBL_TAP_PTR = DBL_TAP_MAGIC;
NVIC_SystemReset();
}
+
+void reset_to_bootloader(void) {
+ _bootloader_dbl_tap = DBL_TAP_MAGIC;
+ reset();
+}
+
+extern uint32_t _srelocate;
+bool bootloader_available(void) {
+ return &_bootloader_dbl_tap >= &_srelocate;
+}
diff --git a/ports/atmel-samd/reset.h b/ports/atmel-samd/reset.h
index 88140f3b8..ea955c655 100644
--- a/ports/atmel-samd/reset.h
+++ b/ports/atmel-samd/reset.h
@@ -26,6 +26,16 @@
#ifndef MICROPY_INCLUDED_ATMEL_SAMD_RESET_H
#define MICROPY_INCLUDED_ATMEL_SAMD_RESET_H
+#include <stdbool.h>
+#include <stdint.h>
+
+// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21
+#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set
+
+extern uint32_t _bootloader_dbl_tap;
+
void reset_to_bootloader(void);
+void reset(void);
+bool bootloader_available(void);
#endif // MICROPY_INCLUDED_ATMEL_SAMD_RESET_H
diff --git a/ports/atmel-samd/shared_dma.c b/ports/atmel-samd/shared_dma.c
index f8cef0992..59fca30c8 100644
--- a/ports/atmel-samd/shared_dma.c
+++ b/ports/atmel-samd/shared_dma.c
@@ -106,7 +106,7 @@ int32_t shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length)
}
dma_configure(general_dma_tx.channel_id, sercom_index(sercom) * 2 + 2, false);
- // Set up TX second.
+ // Set up TX. There is no RX job.
struct dma_descriptor_config descriptor_config;
dma_descriptor_get_config_defaults(&descriptor_config);
descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE;
@@ -141,6 +141,11 @@ int32_t shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length)
int32_t shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx) {
if (general_dma_tx.job_status != ERR_NONE) {
+}
+
+// Do write and read simultaneously. If buffer_out is NULL, write the tx byte over and over.
+// If buffer_out is a real buffer, ignore tx.
+enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx) {
return general_dma_tx.job_status;
}
@@ -156,17 +161,19 @@ int32_t shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_
descriptor_config.block_transfer_count = length;
// DATA register is consistently addressed across all SERCOM modes.
descriptor_config.source_address = ((uint32_t)&sercom->SPI.DATA.reg);
- descriptor_config.destination_address = ((uint32_t)buffer + length);
+ descriptor_config.destination_address = ((uint32_t)buffer_in + length);
dma_descriptor_create(general_dma_rx.descriptor, &descriptor_config);
- // Set up TX to retransmit the same byte over and over.
+ // Set up TX second.
dma_descriptor_get_config_defaults(&descriptor_config);
descriptor_config.beat_size = DMA_BEAT_SIZE_BYTE;
- descriptor_config.src_increment_enable = false;
+ // Increment write address only if we have a real buffer.
+ descriptor_config.src_increment_enable = buffer_out != NULL;
descriptor_config.dst_increment_enable = false;
descriptor_config.block_transfer_count = length;
- descriptor_config.source_address = ((uint32_t)&tx);
+ //
+ descriptor_config.source_address = ((uint32_t) (buffer_out != NULL ? buffer_out + length : &tx));
// DATA register is consistently addressed across all SERCOM modes.
descriptor_config.destination_address = ((uint32_t)&sercom->SPI.DATA.reg);
diff --git a/ports/atmel-samd/shared_dma.h b/ports/atmel-samd/shared_dma.h
index 1e9240338..2ddd81c4e 100644
--- a/ports/atmel-samd/shared_dma.h
+++ b/ports/atmel-samd/shared_dma.h
@@ -37,6 +37,7 @@ void init_shared_dma(void);
enum status_code shared_dma_write(Sercom* sercom, const uint8_t* buffer, uint32_t length);
enum status_code shared_dma_read(Sercom* sercom, uint8_t* buffer, uint32_t length, uint8_t tx);
+enum status_code shared_dma_transfer(Sercom* sercom, uint8_t* buffer_out, uint8_t* buffer_in, uint32_t length, uint8_t tx);
// Allocate a counter to track how far along we are in a DMA double buffer.
bool allocate_block_counter(void);
diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile
index ebb8981ef..70c5c9677 100644
--- a/ports/esp8266/Makefile
+++ b/ports/esp8266/Makefile
@@ -130,6 +130,7 @@ SRC_BINDINGS_ENUMS = \
digitalio/DriveMode.c \
digitalio/Pull.c \
math/__init__.c \
+ microcontroller/RunMode.c \
util.c
SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \
diff --git a/ports/esp8266/common-hal/busio/SPI.c b/ports/esp8266/common-hal/busio/SPI.c
index 50ad03460..aa2b3a354 100644
--- a/ports/esp8266/common-hal/busio/SPI.c
+++ b/ports/esp8266/common-hal/busio/SPI.c
@@ -185,3 +185,23 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
}
return true;
}
+
+bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
+ // Process data in chunks, let the pending tasks run in between
+ size_t chunk_size = 1024; // TODO this should depend on baudrate
+ size_t count = len / chunk_size;
+ size_t i = 0;
+ for (size_t j = 0; j < count; ++j) {
+ for (size_t k = 0; k < chunk_size; ++k) {
+ data_in[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out[i], 8, 0);
+ ++i;
+ }
+ ets_loop_iter();
+ }
+ while (i < len) {
+ data_in[i] = spi_transaction(HSPI, 0, 0, 0, 0, 8, data_out[i], 8, 0);
+ ++i;
+ }
+ return true;
+
+}
diff --git a/ports/esp8266/common-hal/digitalio/DigitalInOut.c b/ports/esp8266/common-hal/digitalio/DigitalInOut.c
index 70ed207d5..7101e6414 100644
--- a/ports/esp8266/common-hal/digitalio/DigitalInOut.c
+++ b/ports/esp8266/common-hal/digitalio/DigitalInOut.c
@@ -59,7 +59,7 @@ void common_hal_digitalio_digitalinout_deinit(digitalio_digitalinout_obj_t* self
}
void common_hal_digitalio_digitalinout_switch_to_input(
- digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
+ digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
self->output = false;
if (self->pin->gpio_number == 16) {
@@ -75,7 +75,7 @@ void common_hal_digitalio_digitalinout_switch_to_input(
void common_hal_digitalio_digitalinout_switch_to_output(
digitalio_digitalinout_obj_t* self, bool value,
- enum digitalio_drive_mode_t drive_mode) {
+ digitalio_drive_mode_t drive_mode) {
self->output = true;
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
if (self->pin->gpio_number == 16) {
@@ -89,7 +89,7 @@ void common_hal_digitalio_digitalinout_switch_to_output(
common_hal_digitalio_digitalinout_set_value(self, value);
}
-enum digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
+digitalio_direction_t common_hal_digitalio_digitalinout_get_direction(
digitalio_digitalinout_obj_t* self) {
return self->output? DIRECTION_OUTPUT : DIRECTION_INPUT;
}
@@ -136,7 +136,7 @@ bool common_hal_digitalio_digitalinout_get_value(
void common_hal_digitalio_digitalinout_set_drive_mode(
digitalio_digitalinout_obj_t* self,
- enum digitalio_drive_mode_t drive_mode) {
+ digitalio_drive_mode_t drive_mode) {
bool value = common_hal_digitalio_digitalinout_get_value(self);
self->open_drain = drive_mode == DRIVE_MODE_OPEN_DRAIN;
// True is implemented differently between modes so reset the value to make
@@ -146,7 +146,7 @@ void common_hal_digitalio_digitalinout_set_drive_mode(
}
}
-enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
+digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
digitalio_digitalinout_obj_t* self) {
if (self->open_drain) {
return DRIVE_MODE_OPEN_DRAIN;
@@ -156,7 +156,7 @@ enum digitalio_drive_mode_t common_hal_digitalio_digitalinout_get_drive_mode(
}
void common_hal_digitalio_digitalinout_set_pull(
- digitalio_digitalinout_obj_t* self, enum digitalio_pull_t pull) {
+ digitalio_digitalinout_obj_t* self, digitalio_pull_t pull) {
if (pull == PULL_DOWN) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
"ESP8266 does not support pull down."));
@@ -174,7 +174,7 @@ void common_hal_digitalio_digitalinout_set_pull(
}
}
-enum digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
+digitalio_pull_t common_hal_digitalio_digitalinout_get_pull(
digitalio_digitalinout_obj_t* self) {
if (self->pin->gpio_number < 16 &&
(READ_PERI_REG(self->pin->peripheral) & PERIPHS_IO_MUX_PULLUP) != 0) {
diff --git a/ports/esp8266/common-hal/microcontroller/__init__.c b/ports/esp8266/common-hal/microcontroller/__init__.c
index 6aef23761..6d446ceac 100644
--- a/ports/esp8266/common-hal/microcontroller/__init__.c
+++ b/ports/esp8266/common-hal/microcontroller/__init__.c
@@ -24,9 +24,12 @@
* THE SOFTWARE.
*/
+#include "py/runtime.h"
+
#include "common-hal/microcontroller/Pin.h"
#include "common-hal/microcontroller/Processor.h"
+#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "shared-bindings/microcontroller/Processor.h"
@@ -34,6 +37,7 @@
#include "ets_alt_task.h"
#include "etshal.h"
#include "osapi.h"
+#include "user_interface.h"
#include "xtirq.h"
#define ETS_LOOP_ITER_BIT (12)
@@ -54,9 +58,21 @@ void common_hal_mcu_enable_interrupts() {
enable_irq(saved_interrupt_state & ~(1 << ETS_LOOP_ITER_BIT));
}
+void common_hal_mcu_on_next_reset(mcu_runmode_t runmode) {
+ if (runmode == RUNMODE_BOOTLOADER) {
+ mp_raise_ValueError("Cannot reset into bootloader because no bootloader is present.");
+ } else if (runmode == RUNMODE_SAFE_MODE) {
+ mp_raise_ValueError("ESP8226 does not support safe mode.");
+ }
+}
+
+void common_hal_mcu_reset(void) {
+ system_restart();
+}
+
// The singleton microcontroller.Processor object, returned by microcontroller.cpu
// It currently only has properties, and no state.
-mcu_processor_obj_t common_hal_mcu_processor_obj = {
+const mcu_processor_obj_t common_hal_mcu_processor_obj = {
.base = {
.type = &mcu_processor_type,
},
diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk
index dc29a92cf..17304b783 100644
--- a/ports/nrf/mpconfigport.mk
+++ b/ports/nrf/mpconfigport.mk
@@ -2,3 +2,6 @@
# $(MPY-TOOL) needs to know what kind of longint to use (if any) to freeze long integers.
# This should correspond to the MICROPY_LONGINT_IMPL definition in mpconfigport.h.
MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz
+
+INTERNAL_LIBM = (1)
+