diff options
154 files changed, 2190 insertions, 3454 deletions
diff --git a/.gitmodules b/.gitmodules index 38b6ea5df..1c1f8eb65 100644 --- a/.gitmodules +++ b/.gitmodules @@ -78,7 +78,7 @@ url = https://github.com/adafruit/nrfx.git [submodule "lib/tinyusb"] path = lib/tinyusb - url = https://github.com/hathach/tinyusb.git + url = https://github.com/tannewt/tinyusb.git branch = develop [submodule "tools/huffman"] path = tools/huffman diff --git a/lib/tinyusb b/lib/tinyusb -Subproject 33c61bfda2c3aada3cb06d36e12d7cf57da0203 +Subproject 30e3c64134789416e10ed867fa12c210b808e98 @@ -51,6 +51,7 @@ #include "supervisor/shared/autoreload.h" #include "supervisor/shared/translate.h" #include "supervisor/shared/rgb_led_status.h" +#include "supervisor/shared/status_leds.h" #include "supervisor/shared/stack.h" #include "supervisor/serial.h" @@ -388,6 +389,8 @@ int __attribute__((used)) main(void) { // initialise the cpu and peripherals safe_mode_t safe_mode = port_init(); + // Turn on LEDs + init_status_leds(); rgb_led_status_init(); stack_init(); diff --git a/ports/atmel-samd/Makefile b/ports/atmel-samd/Makefile index 7861f4235..552be92be 100644 --- a/ports/atmel-samd/Makefile +++ b/ports/atmel-samd/Makefile @@ -45,16 +45,13 @@ INC += -I. \ -Iasf4/$(CHIP_FAMILY)/hpl/tc \ -Iasf4/$(CHIP_FAMILY)/include \ -Iasf4/$(CHIP_FAMILY)/CMSIS/Include \ - -Iasf4/$(CHIP_FAMILY)/usb \ - -Iasf4/$(CHIP_FAMILY)/usb/class/cdc \ - -Iasf4/$(CHIP_FAMILY)/usb/class/hid \ - -Iasf4/$(CHIP_FAMILY)/usb/class/msc \ - -Iasf4/$(CHIP_FAMILY)/usb/device \ -Iasf4_conf/$(CHIP_FAMILY) \ -Iboards/$(BOARD) \ -Iboards/ \ -Iperipherals/ \ -Ifreetouch \ + -I../../lib/tinyusb/src \ + -I../../supervisor/shared/usb \ -I$(BUILD) BASE_CFLAGS = \ @@ -90,11 +87,15 @@ BASE_CFLAGS = \ # NDEBUG disables assert() statements. This reduces code size pretty dramatically, per tannewt. ifeq ($(CHIP_FAMILY), samd21) -CFLAGS = -Os -DNDEBUG +CFLAGS += -Os -DNDEBUG +# TinyUSB defines +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD21 -DCFG_TUD_CDC_RX_BUFSIZE=128 -DCFG_TUD_CDC_TX_BUFSIZE=128 -DCFG_TUD_MSC_BUFSIZE=512 endif ifeq ($(CHIP_FAMILY), samd51) -CFLAGS = -Os -DNDEBUG +CFLAGS += -O0 -DNDEBUG +# TinyUSB defines +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_SAMD51 -DCFG_TUD_CDC_RX_BUFSIZE=256 -DCFG_TUD_CDC_TX_BUFSIZE=256 -DCFG_TUD_MSC_BUFSIZE=1024 endif #Debugging/Optimization @@ -104,7 +105,7 @@ ifeq ($(DEBUG), 1) # You may want to disable -flto if it interferes with debugging. CFLAGS += -flto # You may want to enable these flags to make setting breakpoints easier. -## CFLAGS += -fno-inline -fno-ipa-sra + # CFLAGS += -fno-inline -fno-ipa-sra ifeq ($(CHIP_FAMILY), samd21) CFLAGS += -DENABLE_MICRO_TRACE_BUFFER endif @@ -204,7 +205,6 @@ SRC_ASF := \ hal/src/hal_spi_m_sync.c \ hal/src/hal_timer.c \ hal/src/hal_usart_async.c \ - hal/src/hal_usb_device.c \ hpl/adc/hpl_adc.c \ hpl/core/hpl_init.c \ hpl/dac/hpl_dac.c \ @@ -214,12 +214,6 @@ SRC_ASF := \ hpl/rtc/hpl_rtc.c \ hpl/sercom/hpl_sercom.c \ hpl/systick/hpl_systick.c \ - hpl/usb/hpl_usb.c \ - usb/class/cdc/device/cdcdf_acm.c \ - usb/class/hid/device/hiddf_generic.c \ - usb/class/msc/device/mscdf.c \ - usb/device/usbdc.c \ - usb/usb_protocol.c \ hal/utils/src/utils_list.c \ hal/utils/src/utils_ringbuffer.c \ @@ -246,7 +240,6 @@ SRC_C = \ board_busses.c \ background.c \ fatfs_port.c \ - flash_api.c \ mphalport.c \ reset.c \ peripherals/samd/clocks.c \ @@ -265,8 +258,6 @@ SRC_C = \ peripherals/samd/$(CHIP_FAMILY)/sercom.c \ peripherals/samd/$(CHIP_FAMILY)/timers.c \ tick.c \ - usb.c \ - usb_mass_storage.c \ bindings/samd/__init__.c \ bindings/samd/Clock.c \ boards/$(BOARD)/board.c \ @@ -274,6 +265,8 @@ SRC_C = \ lib/oofatfs/ff.c \ lib/oofatfs/option/ccsbcs.c \ lib/timeutils/timeutils.c \ + lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/dcd.c \ + lib/tinyusb/src/portable/microchip/$(CHIP_FAMILY)/hal.c \ lib/utils/buffer_helper.c \ lib/utils/context_manager_helpers.c \ lib/utils/interrupt_char.c \ @@ -282,7 +275,6 @@ SRC_C = \ lib/utils/sys_stdio_mphal.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ - $(BUILD)/autogen_usb_descriptor.c \ freetouch/adafruit_ptc.c \ supervisor/shared/memory.c @@ -306,19 +298,6 @@ SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\ endif # MICROPY_PY_WIZNET5K endif # MICROPY_PY_NETWORK -# Choose which flash filesystem impl to use. -# (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. -# But that might not be true in the future.) -ifeq ($(INTERNAL_FLASH_FILESYSTEM),1) -SRC_C += internal_flash.c -endif -ifeq ($(SPI_FLASH_FILESYSTEM),1) -SRC_C += external_flash/external_flash.c external_flash/spi_flash.c -endif -ifeq ($(QSPI_FLASH_FILESYSTEM),1) -SRC_C += external_flash/external_flash.c external_flash/qspi_flash.c -endif - SRC_COMMON_HAL = \ board/__init__.c \ busio/__init__.c \ @@ -339,7 +318,6 @@ SRC_COMMON_HAL = \ rotaryio/IncrementalEncoder.c \ rtc/__init__.c \ rtc/RTC.c \ - storage/__init__.c \ supervisor/__init__.c \ supervisor/Runtime.c \ time/__init__.c \ @@ -352,10 +330,8 @@ SRC_COMMON_HAL = \ pulseio/PulseIn.c \ pulseio/PulseOut.c \ pulseio/PWMOut.c \ - usb_hid/__init__.c \ - usb_hid/Device.c \ touchio/__init__.c \ - touchio/TouchIn.c \ + touchio/TouchIn.c ifeq ($(INTERNAL_LIBM),1) SRC_LIBM = $(addprefix lib/,\ @@ -412,12 +388,17 @@ SRC_SHARED_MODULE = \ _stage/__init__.c \ _stage/Layer.c \ _stage/Text.c \ + storage/__init__.c \ os/__init__.c \ random/__init__.c \ - storage/__init__.c \ struct/__init__.c \ uheap/__init__.c \ - ustack/__init__.c + ustack/__init__.c \ + usb_hid/__init__.c \ + usb_hid/Device.c + + # usb_midi/__init__.c + # usb_midi/Port.c ifeq ($(MICROPY_PY_NETWORK),1) SRC_SHARED_MODULE += socket/__init__.c network/__init__.c @@ -489,21 +470,6 @@ $(BUILD)/firmware.uf2: $(BUILD)/firmware.bin $(STEPECHO) "Create $@" $(Q)$(PYTHON3) $(TOP)/tools/uf2/utils/uf2conv.py -b $(BOOTLOADER_SIZE) -c -o $@ $^ -$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: autogen_usb_descriptor.intermediate - -.INTERMEDIATE: autogen_usb_descriptor.intermediate - -autogen_usb_descriptor.intermediate: tools/gen_usb_descriptor.py Makefile | $(HEADER_BUILD) - $(STEPECHO) "GEN $@" - $(Q)install -d $(BUILD)/genhdr - $(Q)$(PYTHON3) tools/gen_usb_descriptor.py \ - --manufacturer $(USB_MANUFACTURER)\ - --product $(USB_PRODUCT)\ - --vid $(USB_VID)\ - --pid $(USB_PID)\ - --output_c_file $(BUILD)/autogen_usb_descriptor.c\ - --output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h - deploy: $(BUILD)/firmware.bin $(ECHO) "Writing $< to the board" $(BOSSAC) -u $< diff --git a/ports/atmel-samd/background.c b/ports/atmel-samd/background.c index 3cf6831a3..099cb8b23 100644 --- a/ports/atmel-samd/background.c +++ b/ports/atmel-samd/background.c @@ -27,8 +27,7 @@ #include "audio_dma.h" #include "tick.h" -#include "usb.h" -#include "usb_mass_storage.h" +#include "supervisor/usb.h" #include "shared-module/displayio/__init__.h" #include "shared-module/network/__init__.h" @@ -45,8 +44,8 @@ void run_background_tasks(void) { #if MICROPY_PY_NETWORK network_module_background(); #endif - usb_msc_background(); - usb_cdc_background(); + usb_background(); + last_finished_tick = ticks_ms; } diff --git a/ports/atmel-samd/boards/arduino_zero/board.c b/ports/atmel-samd/boards/arduino_zero/board.c index 2dc1683ea..770bc8259 100644 --- a/ports/atmel-samd/boards/arduino_zero/board.c +++ b/ports/atmel-samd/boards/arduino_zero/board.c @@ -30,13 +30,6 @@ void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h index 1382d4736..56e4dbcec 100644 --- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h +++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.h @@ -1,16 +1,14 @@ #define MICROPY_HW_BOARD_NAME "Arduino Zero" #define MICROPY_HW_MCU_NAME "samd21g18" -// #define MICROPY_HW_LED_MSC PIN_PA17 // red -#define MICROPY_HW_LED_TX PIN_PA27 -#define MICROPY_HW_LED_RX PIN_PB03 +// #define MICROPY_HW_LED_MSC &pin_PA17 // red +#define MICROPY_HW_LED_TX &pin_PA27 +#define MICROPY_HW_LED_RX &pin_PB03 #define MICROPY_PORT_A (PORT_PA24 | PORT_PA25 | PORT_PA27) #define MICROPY_PORT_B (PORT_PB03) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h index 5077840cb..6dfaf87e9 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.h @@ -8,52 +8,25 @@ #define SPI_FLASH_BAUDRATE (8000000) // On-board flash -#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 3 -#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 +#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 // 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) +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash/devices.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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define CALIBRATE_CRYSTALLESS 1 // Explanation of how a user got into safe mode. diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk index 831106adc..e5665afb6 100644 --- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "CircuitPlayground Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h index 638a6646c..250300858 100644 --- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.h @@ -11,52 +11,24 @@ #define SPI_FLASH_BAUDRATE (8000000) // On-board flash -#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 3 -#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 +#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 // 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) +#define MICROPY_PORT_A (0) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define SPEAKER_ENABLE_PIN (&pin_PA30) -#include "external_flash/devices.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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define CALIBRATE_CRYSTALLESS 1 // Explanation of how a user got into safe mode. diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk index 972c4b10d..b07d63984 100644 --- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk +++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "CircuitPlayground Express with Crickit libraries" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" # Turn off longints for Crickit build to make room for additional frozen libs. LONGINT_IMPL = NONE diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h index c8b5c56ee..c28c4aafb 100644 --- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h @@ -3,12 +3,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Adalogger" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h index dcac9749d..d66efb36f 100644 --- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.h @@ -4,12 +4,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Basic" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h index 03d0ba9bd..1f02ee995 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.h @@ -3,35 +3,16 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA06) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA08 -#define SPI_FLASH_MISO_PIN PIN_PA14 -#define SPI_FLASH_SCK_PIN PIN_PA09 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 -#define SPI_FLASH_SERCOM SERCOM2 -#define SPI_FLASH_SERCOM_INDEX 2 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <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 0 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA08 +#define SPI_FLASH_MISO_PIN &pin_PA14 +#define SPI_FLASH_SCK_PIN &pin_PA09 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_flash.h" // If you change this, then make sure to update the linker scripts as well to // make sure you don't overwrite code. @@ -39,14 +20,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA23) diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk index e9f9b09fb..57ce96285 100644 --- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h index 756462013..b5544e253 100644 --- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.h @@ -3,50 +3,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA06) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA08 -#define SPI_FLASH_MISO_PIN PIN_PA14 -#define SPI_FLASH_SCK_PIN PIN_PA09 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 -#define SPI_FLASH_SERCOM SERCOM2 -#define SPI_FLASH_SERCOM_INDEX 2 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <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 0 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA08 +#define SPI_FLASH_MISO_PIN &pin_PA14 +#define SPI_FLASH_SCK_PIN &pin_PA09 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA23) diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk index 7ff5337a3..f773bcb57 100644 --- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h index 4a530ed29..c385a97ea 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.h @@ -4,12 +4,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM69" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h index 3a6f28c12..1e3a0bda0 100644 --- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.h @@ -4,12 +4,10 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 RFM9x" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h index a7a2d7de0..6bf1df156 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.h @@ -5,49 +5,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA06) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA08 -#define SPI_FLASH_MISO_PIN PIN_PA14 -#define SPI_FLASH_SCK_PIN PIN_PA09 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA08D_SERCOM2_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA14C_SERCOM2_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA09D_SERCOM2_PAD1 -#define SPI_FLASH_SERCOM SERCOM2 -#define SPI_FLASH_SERCOM_INDEX 2 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <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 0 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA08 +#define SPI_FLASH_MISO_PIN &pin_PA14 +#define SPI_FLASH_SCK_PIN &pin_PA09 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA06 | PORT_PA08 | PORT_PA09 | PORT_PA13 | PORT_PA14 | PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (PORT_PA06) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES S25FL064L - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA23) #define DEFAULT_I2C_BUS_SDA (&pin_PA22) diff --git a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk index 79bf2d34a..4bae6ffa7 100644 --- a/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m0_supersized/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather M0 Supersized" USB_MANUFACTURER = "Dave Astels" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "S25FL064L" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h index e9e921b4d..98906a844 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.h @@ -23,15 +23,8 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C - #define EXTERNAL_FLASH_QSPI_DUAL -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA13) diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk index bbc5985a9..3f2cb6ce4 100644 --- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk @@ -5,6 +5,9 @@ USB_PRODUCT = "Feather M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 + +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q16C LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51J19A diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h index 32c549953..c4e025178 100755 --- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h +++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.h @@ -3,50 +3,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA22) -// Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA31 -#define SPI_FLASH_MISO_PIN PIN_PA30 -#define SPI_FLASH_SCK_PIN PIN_PA17 -#define SPI_FLASH_CS_PIN PIN_PA28 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA31D_SERCOM1_PAD3 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA30D_SERCOM1_PAD2 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA17C_SERCOM1_PAD1 -#define SPI_FLASH_SERCOM SERCOM1 -#define SPI_FLASH_SERCOM_INDEX 1 -#define SPI_FLASH_MOSI_PAD 3 -#define SPI_FLASH_MISO_PAD 2 -#define SPI_FLASH_SCK_PAD 1 -// <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 2 -#define SPI_FLASH_DIPO 2 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA31 +#define SPI_FLASH_MISO_PIN &pin_PA30 +#define SPI_FLASH_SCK_PIN &pin_PA17 +#define SPI_FLASH_CS_PIN &pin_PA28 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA17 | PORT_PA22 | PORT_PA24 | PORT_PA25 | PORT_PA28 | PORT_PA30 | PORT_PA31) +#define MICROPY_PORT_A (PORT_PA22) #define MICROPY_PORT_B ( 0 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA13) diff --git a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk index 42177d274..634a9ede7 100755 --- a/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk +++ b/ports/atmel-samd/boards/feather_radiofruit_zigbee/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Feather RadioFruit Zigbee" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMR21G18A diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h index 1ec217096..08d1803f2 100644 --- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.h @@ -18,8 +18,6 @@ #define DEFAULT_UART_BUS_RX (&pin_PA05) #define DEFAULT_UART_BUS_TX (&pin_PA04) -#include "internal_flash.h" - #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) #define IGNORE_PIN_PA03 1 diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/board.c b/ports/atmel-samd/boards/grandcentral_m4_express/board.c index 360b5d8f9..7599f02b8 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/board.c +++ b/ports/atmel-samd/boards/grandcentral_m4_express/board.c @@ -29,13 +29,6 @@ #include "hal/include/hal_gpio.h" void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h index 231bf20e0..0d2d65ba5 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.h @@ -5,8 +5,8 @@ // This is for Rev A which is green -#define MICROPY_HW_LED_TX PIN_PC30 -#define MICROPY_HW_LED_RX PIN_PC31 +#define MICROPY_HW_LED_TX &(pin_PC30) +#define MICROPY_HW_LED_RX &(pin_PC31) #define MICROPY_HW_NEOPIXEL (&pin_PC24) @@ -27,13 +27,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q64C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PB21) diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk index 3e8717ecf..2605c9f55 100644 --- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk @@ -5,6 +5,9 @@ USB_PRODUCT = "Grand Central M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 + +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q64C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51P20A diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h index 8450882b9..7dd4bf7c4 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.h @@ -3,51 +3,22 @@ #define MICROPY_HW_NEOPIXEL (&pin_PA12) -// Clock rates are off: Saleae reads 12MHz which is the limit even though we set it to the safer 8MHz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PB10 -#define SPI_FLASH_MISO_PIN PIN_PA13 -#define SPI_FLASH_SCK_PIN PIN_PB11 -#define SPI_FLASH_CS_PIN PIN_PA07 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB10D_SERCOM4_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA13D_SERCOM4_PAD1 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB11D_SERCOM4_PAD3 -#define SPI_FLASH_SERCOM SERCOM4 -#define SPI_FLASH_SERCOM_INDEX 4 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 1 -#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 0x1 -#define SPI_FLASH_DIPO 1 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PB10 +#define SPI_FLASH_MISO_PIN &pin_PA13 +#define SPI_FLASH_SCK_PIN &pin_PB11 +#define SPI_FLASH_CS_PIN &pin_PA07 // These are pins not to reset. -#define MICROPY_PORT_A ( PORT_PA01 | PORT_PA07 | PORT_PA12 | PORT_PA13 | PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA28) -#define MICROPY_PORT_B ( PORT_PB10 | PORT_PB11 | PORT_PB22 | PORT_PB23 ) +#define MICROPY_PORT_A ( PORT_PA01 | PORT_PA12 | PORT_PA27 | PORT_PA28) +#define MICROPY_PORT_B ( PORT_PB22 | PORT_PB23 ) #define MICROPY_PORT_C ( 0 ) -#include "external_flash/external_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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 - -#define EXTERNAL_FLASH_DEVICES W25Q64JV_IQ, \ - GD25Q64C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA17) #define DEFAULT_I2C_BUS_SDA (&pin_PA16) diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk index 817d93943..37f1bdef0 100644 --- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "HalloWing M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "W25Q64JV_IQ, GD25Q64C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h index f56f57c46..4de28d388 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.h @@ -5,32 +5,14 @@ #define MICROPY_HW_APA102_MOSI (&pin_PA01) #define MICROPY_HW_APA102_SCK (&pin_PA00) -// Saleae reads 12mhz which is the limit even though we set it to the safer 8mhz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PB22 -#define SPI_FLASH_MISO_PIN PIN_PB03 -#define SPI_FLASH_SCK_PIN PIN_PB23 -#define SPI_FLASH_CS_PIN PIN_PA27 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB22D_SERCOM5_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB03D_SERCOM5_PAD1 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB23D_SERCOM5_PAD3 -#define SPI_FLASH_SERCOM SERCOM5 -#define SPI_FLASH_SERCOM_INDEX 5 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 1 -#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 1 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PB22 +#define SPI_FLASH_MISO_PIN &pin_PB03 +#define SPI_FLASH_SCK_PIN &pin_PB23 +#define SPI_FLASH_CS_PIN &pin_PA27 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA27 | PORT_PA24 | PORT_PA25) -#define MICROPY_PORT_B (PORT_PB22 | PORT_PB23 | PORT_PB03 ) +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) // If you change this, then make sure to update the linker scripts as well to @@ -39,14 +21,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES W25Q16FW, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA23) #define DEFAULT_I2C_BUS_SDA (&pin_PA22) diff --git a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk index 9f62ae839..8fcf5208f 100644 --- a/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m0_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "ItsyBitsy M0 Express" USB_MANUFACTURER = "Adafruit Industries LLC" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "W25Q16FW, GD25Q16C" LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21G18A diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h index e47d5390d..5bbfec9ce 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.h @@ -25,13 +25,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA13) #define DEFAULT_I2C_BUS_SDA (&pin_PA12) diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk index 27f5ea2b8..2afff5965 100644 --- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "ItsyBitsy M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q16C LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51G19A diff --git a/ports/atmel-samd/boards/meowmeow/mpconfigboard.h b/ports/atmel-samd/boards/meowmeow/mpconfigboard.h index 3ce00b04f..f07eb9cce 100644 --- a/ports/atmel-samd/boards/meowmeow/mpconfigboard.h +++ b/ports/atmel-samd/boards/meowmeow/mpconfigboard.h @@ -1,15 +1,11 @@ #define MICROPY_HW_BOARD_NAME "Meow Meow" #define MICROPY_HW_MCU_NAME "samd21g18" - // These are pins not to reset. -// PA24 and PA25 are USB. -#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_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 0 diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h index 40ef3ce78..28bb1f293 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.h @@ -1,37 +1,22 @@ #define MICROPY_HW_BOARD_NAME "Adafruit Metro M0 Express" #define MICROPY_HW_MCU_NAME "samd21g18" -#define MICROPY_HW_LED_TX PIN_PA27 -//#define MICROPY_HW_LED_RX PIN_PA31 +//#define MICROPY_HW_LED_TX &pin_PA27 +//#define MICROPY_HW_LED_RX &pin_PA31 #define MICROPY_HW_NEOPIXEL (&pin_PA30) // Clock rates are off: Salae reads 12MHz which is the limit even though we set it to the safer 8MHz. #define SPI_FLASH_BAUDRATE (8000000) -#define SPI_FLASH_MOSI_PIN PIN_PB22 -#define SPI_FLASH_MISO_PIN PIN_PB03 -#define SPI_FLASH_SCK_PIN PIN_PB23 -#define SPI_FLASH_CS_PIN PIN_PA13 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PB22D_SERCOM5_PAD2 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PB03D_SERCOM5_PAD1 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PB23D_SERCOM5_PAD3 -#define SPI_FLASH_SERCOM SERCOM5 -#define SPI_FLASH_SERCOM_INDEX 5 -#define SPI_FLASH_MOSI_PAD 2 -#define SPI_FLASH_MISO_PAD 1 -#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 1 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PB22 +#define SPI_FLASH_MISO_PIN &pin_PB03 +#define SPI_FLASH_SCK_PIN &pin_PB23 +#define SPI_FLASH_CS_PIN &pin_PA13 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA13 |PORT_PA24 | PORT_PA25 | PORT_PA27 | PORT_PA30 | PORT_PA31) -#define MICROPY_PORT_B (PORT_PB03 | PORT_PB22 | PORT_PB23) +#define MICROPY_PORT_A (PORT_PA24 | PORT_PA25 | PORT_PA30 | PORT_PA31) +#define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) // If you change this, then make sure to update the linker scripts as well to @@ -40,14 +25,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 2 -#define EXTERNAL_FLASH_DEVICES S25FL216K, \ - GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PA23) diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk index 40a0092ac..49a94144b 100644 --- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk @@ -12,3 +12,7 @@ CHIP_FAMILY = samd21 MICROPY_PY_NETWORK = 1 MICROPY_PY_WIZNET5K = 5500 + +SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 2 +EXTERNAL_FLASH_DEVICES = "S25FL216K, GD25Q16C" diff --git a/ports/atmel-samd/boards/metro_m4_express/board.c b/ports/atmel-samd/boards/metro_m4_express/board.c index a98385d29..0f60736a2 100644 --- a/ports/atmel-samd/boards/metro_m4_express/board.c +++ b/ports/atmel-samd/boards/metro_m4_express/board.c @@ -29,13 +29,6 @@ #include "hal/include/hal_gpio.h" void board_init(void) { - gpio_set_pin_function(MICROPY_HW_LED_TX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_TX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_TX, true); - - gpio_set_pin_function(MICROPY_HW_LED_RX, GPIO_PIN_FUNCTION_OFF); - gpio_set_pin_direction(MICROPY_HW_LED_RX, GPIO_DIRECTION_OUT); - gpio_set_pin_level(MICROPY_HW_LED_RX, true); } bool board_requests_safe_mode(void) { diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h index f1201c8a0..06feb1a22 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.h @@ -5,16 +5,16 @@ // This is for Rev F which is green -#define MICROPY_HW_LED_TX PIN_PA27 -#define MICROPY_HW_LED_RX PIN_PB06 +#define MICROPY_HW_LED_TX (&pin_PA27) +#define MICROPY_HW_LED_RX (&pin_PB06) #define MICROPY_HW_NEOPIXEL (&pin_PB22) // These are pins not to reset. -// QSPI Data pins and TX LED -#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11 | PORT_PA27) -// RX LED, QSPI CS, QSPI SCK and NeoPixel pin -#define MICROPY_PORT_B ( PORT_PB06 | PORT_PB10 | PORT_PB11 | PORT_PB22) +// QSPI Data pins +#define MICROPY_PORT_A (PORT_PA08 | PORT_PA09 | PORT_PA10 | PORT_PA11) +// QSPI CS, QSPI SCK and NeoPixel pin +#define MICROPY_PORT_B (PORT_PB10 | PORT_PB11 | PORT_PB22) #define MICROPY_PORT_C (0) #define MICROPY_PORT_D (0) @@ -26,13 +26,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 3 -#define EXTERNAL_FLASH_DEVICES S25FL116K, S25FL216K, GD25Q16C - -#include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 1 #define DEFAULT_I2C_BUS_SCL (&pin_PB03) diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk index cbc89159f..633856362 100644 --- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk @@ -5,6 +5,9 @@ USB_PRODUCT = "Metro M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 3 +EXTERNAL_FLASH_DEVICES = "S25FL116K, S25FL216K, GD25Q16C" + LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51J19A diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h index 15979ae77..cbbd4b569 100644 --- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.h @@ -15,8 +15,6 @@ // A number of modules are removed for pIRKey to make room for frozen libraries. #define PIRKEY_M0 (1) -#include "internal_flash.h" - #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) #define IGNORE_PIN_PA02 1 diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h index 1464d100c..6870b86ba 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h +++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.h @@ -26,13 +26,6 @@ #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - CIRCUITPY_INTERNAL_NVM_SIZE) -#include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q64C - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PB08) #define DEFAULT_I2C_BUS_SDA (&pin_PB09) diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk index 3841a87c7..7094b79be 100644 --- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT = "Trellis M4 Express" USB_MANUFACTURER = "Adafruit Industries LLC" QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = GD25Q64C LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD51G19A diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h index 9036f8e7b..24f3004e9 100644 --- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.h @@ -9,8 +9,6 @@ #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) -#include "internal_flash.h" - #define CIRCUITPY_INTERNAL_NVM_SIZE 0 #define BOARD_FLASH_SIZE (0x00040000 - 0x2000 - 0x010000) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h index 8e3fdd7a8..dfbd873b6 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.h @@ -5,56 +5,24 @@ // #define MICROPY_HW_APA102_MOSI (&pin_PA00) // #define MICROPY_HW_APA102_SCK (&pin_PA01) -// Salae reads 12mhz which is the limit even though we set it to the -// safer 8mhz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA16 -#define SPI_FLASH_MISO_PIN PIN_PA19 -#define SPI_FLASH_SCK_PIN PIN_PA17 -#define SPI_FLASH_CS_PIN PIN_PA11 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA19D_SERCOM3_PAD3 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA17D_SERCOM3_PAD1 -#define SPI_FLASH_SERCOM SERCOM3 -#define SPI_FLASH_SERCOM_INDEX 3 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 3 -#define SPI_FLASH_SCK_PAD 1 -// <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 0 -#define SPI_FLASH_DIPO 3 // same as MISO pad - -#define SPI_FLASH_CS PIN_PA11 +#define SPI_FLASH_MOSI_PIN &pin_PA16 +#define SPI_FLASH_MISO_PIN &pin_PA19 +#define SPI_FLASH_SCK_PIN &pin_PA17 +#define SPI_FLASH_CS_PIN &pin_PA11 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA11 | PORT_PA16 |\ - PORT_PA17 | PORT_PA18 | PORT_PA19 | PORT_PA24 |\ - PORT_PA25) +#define MICROPY_PORT_A (PORT_PA00 | PORT_PA01 | PORT_PA18) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash/external_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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES W25Q32BV - -#include "external_flash/external_flash.h" - #define DEFAULT_I2C_BUS_SCL (&pin_PA09) #define DEFAULT_I2C_BUS_SDA (&pin_PA08) diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk index d97aa08ab..c9c196da7 100644 --- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk +++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk @@ -5,6 +5,8 @@ USB_PRODUCT="Trinket M0 Haxpress" USB_MANUFACTURER="Radomir Dopieralski" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = W25Q32BV LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21E18A diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.h b/ports/atmel-samd/boards/ugame10/mpconfigboard.h index ed822952d..c22a3f735 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.h +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.h @@ -1,53 +1,24 @@ #define MICROPY_HW_BOARD_NAME "uGame10" #define MICROPY_HW_MCU_NAME "samd21e18" -// Salae reads 12mhz which is the limit even though we set it to the -// safer 8mhz. -#define SPI_FLASH_BAUDRATE (8000000) - -#define SPI_FLASH_MOSI_PIN PIN_PA16 -#define SPI_FLASH_MISO_PIN PIN_PA19 -#define SPI_FLASH_SCK_PIN PIN_PA17 -#define SPI_FLASH_CS_PIN PIN_PA18 -#define SPI_FLASH_MOSI_PIN_FUNCTION PINMUX_PA16D_SERCOM3_PAD0 -#define SPI_FLASH_MISO_PIN_FUNCTION PINMUX_PA19D_SERCOM3_PAD3 -#define SPI_FLASH_SCK_PIN_FUNCTION PINMUX_PA17D_SERCOM3_PAD1 -#define SPI_FLASH_SERCOM SERCOM3 -#define SPI_FLASH_SERCOM_INDEX 3 -#define SPI_FLASH_MOSI_PAD 0 -#define SPI_FLASH_MISO_PAD 3 -#define SPI_FLASH_SCK_PAD 1 -// <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 0 -#define SPI_FLASH_DIPO 3 // same as MISO pad +#define SPI_FLASH_MOSI_PIN &pin_PA16 +#define SPI_FLASH_MISO_PIN &pin_PA19 +#define SPI_FLASH_SCK_PIN &pin_PA17 +#define SPI_FLASH_CS_PIN &pin_PA18 // These are pins not to reset. -#define MICROPY_PORT_A (PORT_PA16 | PORT_PA17 | PORT_PA18 | PORT_PA19 |\ - PORT_PA24 | PORT_PA25) +#define MICROPY_PORT_A (0) #define MICROPY_PORT_B (0) #define MICROPY_PORT_C (0) #define CALIBRATE_CRYSTALLESS 1 -#include "external_flash/external_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 "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES S25FL216K - -#include "external_flash/external_flash.h" - #define EXTRA_BUILTIN_MODULES \ { MP_OBJ_NEW_QSTR(MP_QSTR_audioio), (mp_obj_t)&audioio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_gamepad),(mp_obj_t)&gamepad_module }, \ diff --git a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk index 2386531f9..6dc0af9cf 100644 --- a/ports/atmel-samd/boards/ugame10/mpconfigboard.mk +++ b/ports/atmel-samd/boards/ugame10/mpconfigboard.mk @@ -6,6 +6,8 @@ USB_PRODUCT = "uGame10" USB_MANUFACTURER = "Radomir Dopieralski" SPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = S25FL216K LONGINT_IMPL = MPZ CHIP_VARIANT = SAMD21E18A diff --git a/ports/atmel-samd/common-hal/busio/SPI.c b/ports/atmel-samd/common-hal/busio/SPI.c index a292f9e3d..4de34c975 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.c +++ b/ports/atmel-samd/common-hal/busio/SPI.c @@ -31,6 +31,8 @@ #include "hpl_sercom_config.h" #include "peripheral_clk_config.h" +#include "boards/board.h" +#include "common-hal/microcontroller/Pin.h" #include "hal/include/hal_gpio.h" #include "hal/include/hal_spi_m_sync.h" #include "hal/include/hpl_spi_m_sync.h" @@ -39,6 +41,43 @@ #include "samd/dma.h" #include "samd/sercom.h" +bool never_reset_sercoms[SERCOM_INST_NUM]; + +void never_reset_sercom(Sercom* sercom) { + // Reset all SERCOMs except the ones being used by on-board devices. + Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; + for (int i = 0; i < SERCOM_INST_NUM; i++) { + if (sercom_instances[i] == sercom) { + never_reset_sercoms[i] = true; + break; + } + } +} + +void reset_sercoms(void) { + // Reset all SERCOMs except the ones being used by on-board devices. + Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; + for (int i = 0; i < SERCOM_INST_NUM; i++) { + if (never_reset_sercoms[i]) { + continue; + } + #ifdef MICROPY_HW_APA102_SERCOM + if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) { + continue; + } + #endif + #ifdef CIRCUITPY_DISPLAYIO + // TODO(tannewt): Make this dynamic. + if (sercom_instances[i] == board_display_obj.bus.spi_desc.dev.prvt) { + continue; + } + #endif + // SWRST is same for all modes of SERCOMs. + sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; + } +} + + void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t * clock, const mcu_pin_obj_t * mosi, const mcu_pin_obj_t * miso) { @@ -186,6 +225,14 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, spi_m_sync_enable(&self->spi_desc); } +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + never_reset_sercom(self->spi_desc.dev.prvt); + + never_reset_pin_number(self->clock_pin); + never_reset_pin_number(self->MOSI_pin); + never_reset_pin_number(self->MISO_pin); +} + bool common_hal_busio_spi_deinited(busio_spi_obj_t *self) { return self->clock_pin == NO_PIN; } diff --git a/ports/atmel-samd/common-hal/busio/SPI.h b/ports/atmel-samd/common-hal/busio/SPI.h index 2fced6d64..56d163a9d 100644 --- a/ports/atmel-samd/common-hal/busio/SPI.h +++ b/ports/atmel-samd/common-hal/busio/SPI.h @@ -42,4 +42,7 @@ typedef struct { uint8_t MISO_pin; } busio_spi_obj_t; +void reset_sercoms(void); + + #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_BUSIO_SPI_H diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.c b/ports/atmel-samd/common-hal/microcontroller/Pin.c index 0f179a6c1..9af5aeaf7 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.c +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.c @@ -43,8 +43,12 @@ bool apa102_mosi_in_use; bool speaker_enable_in_use; #endif +#define PORT_COUNT (PORT_BITS / 32 + 1) + +STATIC uint32_t never_reset_pins[PORT_COUNT]; + void reset_all_pins(void) { - uint32_t pin_mask[PORT_BITS / 32 + 1] = PORT_OUT_IMPLEMENTED; + uint32_t pin_mask[PORT_COUNT] = PORT_OUT_IMPLEMENTED; // Do not full reset USB or SWD lines. pin_mask[0] &= ~(PORT_PA24 | PORT_PA25 | PORT_PA30 | PORT_PA31); @@ -53,6 +57,11 @@ void reset_all_pins(void) { pin_mask[0] &= ~(PORT_PA31); #endif + for (uint32_t i = 0; i < PORT_COUNT; i++) { + pin_mask[i] &= ~(PORT_PA31); + pin_mask[i] &= ~never_reset_pins[i]; + } + gpio_set_port_direction(GPIO_PORTA, pin_mask[0] & ~MICROPY_PORT_A, GPIO_DIRECTION_OFF); gpio_set_port_direction(GPIO_PORTB, pin_mask[1] & ~MICROPY_PORT_B, GPIO_DIRECTION_OFF); #if PORT_BITS > 64 @@ -91,6 +100,10 @@ void reset_all_pins(void) { #endif } +void never_reset_pin_number(uint8_t pin_number) { + never_reset_pins[GPIO_PORT(pin_number)] |= 1 << GPIO_PIN(pin_number); +} + void reset_pin_number(uint8_t pin_number) { if (pin_number >= PORT_BITS) { return; diff --git a/ports/atmel-samd/common-hal/microcontroller/Pin.h b/ports/atmel-samd/common-hal/microcontroller/Pin.h index dcd80997e..f798ea300 100644 --- a/ports/atmel-samd/common-hal/microcontroller/Pin.h +++ b/ports/atmel-samd/common-hal/microcontroller/Pin.h @@ -43,6 +43,7 @@ void reset_all_pins(void); // reset_pin_number takes the pin number instead of the pointer so that objects don't // need to store a full pointer. void reset_pin_number(uint8_t pin_number); +void never_reset_pin_number(uint8_t pin_number); void claim_pin(const mcu_pin_obj_t* pin); #endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_MICROCONTROLLER_PIN_H diff --git a/ports/atmel-samd/common-hal/microcontroller/__init__.c b/ports/atmel-samd/common-hal/microcontroller/__init__.c index 746207787..0ca3a0835 100644 --- a/ports/atmel-samd/common-hal/microcontroller/__init__.c +++ b/ports/atmel-samd/common-hal/microcontroller/__init__.c @@ -107,7 +107,6 @@ const nvm_bytearray_obj_t common_hal_mcu_nvm_obj = { // This maps MCU pin names to pin objects. STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { -// Pins in datasheet order. #if defined(PIN_PA00) && !defined(IGNORE_PIN_PA00) { MP_ROM_QSTR(MP_QSTR_PA00), MP_ROM_PTR(&pin_PA00) }, #endif @@ -120,24 +119,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA03) && !defined(IGNORE_PIN_PA03) { MP_ROM_QSTR(MP_QSTR_PA03), MP_ROM_PTR(&pin_PA03) }, #endif -#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04) - { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, -#endif -#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05) - { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, -#endif -#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06) - { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, -#endif -#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07) - { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, -#endif -#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08) - { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, -#endif -#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09) - { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, -#endif #if defined(PIN_PA04) && !defined(IGNORE_PIN_PA04) { MP_ROM_QSTR(MP_QSTR_PA04), MP_ROM_PTR(&pin_PA04) }, #endif @@ -162,26 +143,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA11) && !defined(IGNORE_PIN_PA11) { MP_ROM_QSTR(MP_QSTR_PA11), MP_ROM_PTR(&pin_PA11) }, #endif -#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10) - { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, -#endif -#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11) - { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, -#endif -#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12) - { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, -#endif -#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13) - { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, -#endif -#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14) - { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, -#endif - -// Second page. -#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15) - { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, -#endif #if defined(PIN_PA12) && !defined(IGNORE_PIN_PA12) { MP_ROM_QSTR(MP_QSTR_PA12), MP_ROM_PTR(&pin_PA12) }, #endif @@ -206,12 +167,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA19) && !defined(IGNORE_PIN_PA19) { MP_ROM_QSTR(MP_QSTR_PA19), MP_ROM_PTR(&pin_PA19) }, #endif -#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16) - { MP_ROM_QSTR(MP_QSTR_PB16), MP_ROM_PTR(&pin_PB16) }, -#endif -#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17) - { MP_ROM_QSTR(MP_QSTR_PB17), MP_ROM_PTR(&pin_PB17) }, -#endif #if defined(PIN_PA20) && !defined(IGNORE_PIN_PA20) { MP_ROM_QSTR(MP_QSTR_PA20), MP_ROM_PTR(&pin_PA20) }, #endif @@ -230,12 +185,6 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA25) && !defined(IGNORE_PIN_PA25) { MP_ROM_QSTR(MP_QSTR_PA25), MP_ROM_PTR(&pin_PA25) }, #endif -#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22) - { MP_ROM_QSTR(MP_QSTR_PB22), MP_ROM_PTR(&pin_PB22) }, -#endif -#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23) - { MP_ROM_QSTR(MP_QSTR_PB23), MP_ROM_PTR(&pin_PB23) }, -#endif #if defined(PIN_PA27) && !defined(IGNORE_PIN_PA27) { MP_ROM_QSTR(MP_QSTR_PA27), MP_ROM_PTR(&pin_PA27) }, #endif @@ -248,12 +197,7 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PA31) && !defined(IGNORE_PIN_PA31) { MP_ROM_QSTR(MP_QSTR_PA31), MP_ROM_PTR(&pin_PA31) }, #endif -#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30) - { MP_ROM_QSTR(MP_QSTR_PB30), MP_ROM_PTR(&pin_PB30) }, -#endif -#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31) - { MP_ROM_QSTR(MP_QSTR_PB31), MP_ROM_PTR(&pin_PB31) }, -#endif + #if defined(PIN_PB00) && !defined(IGNORE_PIN_PB00) { MP_ROM_QSTR(MP_QSTR_PB00), MP_ROM_PTR(&pin_PB00) }, #endif @@ -266,14 +210,176 @@ STATIC const mp_rom_map_elem_t mcu_pin_global_dict_table[] = { #if defined(PIN_PB03) && !defined(IGNORE_PIN_PB03) { MP_ROM_QSTR(MP_QSTR_PB03), MP_ROM_PTR(&pin_PB03) }, #endif +#if defined(PIN_PB04) && !defined(IGNORE_PIN_PB04) + { MP_ROM_QSTR(MP_QSTR_PB04), MP_ROM_PTR(&pin_PB04) }, +#endif +#if defined(PIN_PB05) && !defined(IGNORE_PIN_PB05) + { MP_ROM_QSTR(MP_QSTR_PB05), MP_ROM_PTR(&pin_PB05) }, +#endif +#if defined(PIN_PB06) && !defined(IGNORE_PIN_PB06) + { MP_ROM_QSTR(MP_QSTR_PB06), MP_ROM_PTR(&pin_PB06) }, +#endif +#if defined(PIN_PB07) && !defined(IGNORE_PIN_PB07) + { MP_ROM_QSTR(MP_QSTR_PB07), MP_ROM_PTR(&pin_PB07) }, +#endif +#if defined(PIN_PB08) && !defined(IGNORE_PIN_PB08) + { MP_ROM_QSTR(MP_QSTR_PB08), MP_ROM_PTR(&pin_PB08) }, +#endif +#if defined(PIN_PB09) && !defined(IGNORE_PIN_PB09) + { MP_ROM_QSTR(MP_QSTR_PB09), MP_ROM_PTR(&pin_PB09) }, +#endif +#if defined(PIN_PB10) && !defined(IGNORE_PIN_PB10) + { MP_ROM_QSTR(MP_QSTR_PB10), MP_ROM_PTR(&pin_PB10) }, +#endif +#if defined(PIN_PB11) && !defined(IGNORE_PIN_PB11) + { MP_ROM_QSTR(MP_QSTR_PB11), MP_ROM_PTR(&pin_PB11) }, +#endif +#if defined(PIN_PB12) && !defined(IGNORE_PIN_PB12) + { MP_ROM_QSTR(MP_QSTR_PB12), MP_ROM_PTR(&pin_PB12) }, +#endif +#if defined(PIN_PB13) && !defined(IGNORE_PIN_PB13) + { MP_ROM_QSTR(MP_QSTR_PB13), MP_ROM_PTR(&pin_PB13) }, +#endif +#if defined(PIN_PB14) && !defined(IGNORE_PIN_PB14) + { MP_ROM_QSTR(MP_QSTR_PB14), MP_ROM_PTR(&pin_PB14) }, +#endif +#if defined(PIN_PB15) && !defined(IGNORE_PIN_PB15) + { MP_ROM_QSTR(MP_QSTR_PB15), MP_ROM_PTR(&pin_PB15) }, +#endif +#if defined(PIN_PB16) && !defined(IGNORE_PIN_PB16) + { MP_ROM_QSTR(MP_QSTR_PB16), MP_ROM_PTR(&pin_PB16) }, +#endif +#if defined(PIN_PB17) && !defined(IGNORE_PIN_PB17) + { MP_ROM_QSTR(MP_QSTR_PB17), MP_ROM_PTR(&pin_PB17) }, +#endif +#if defined(PIN_PB22) && !defined(IGNORE_PIN_PB22) + { MP_ROM_QSTR(MP_QSTR_PB22), MP_ROM_PTR(&pin_PB22) }, +#endif +#if defined(PIN_PB23) && !defined(IGNORE_PIN_PB23) + { MP_ROM_QSTR(MP_QSTR_PB23), MP_ROM_PTR(&pin_PB23) }, +#endif +#if defined(PIN_PB30) && !defined(IGNORE_PIN_PB30) + { MP_ROM_QSTR(MP_QSTR_PB30), MP_ROM_PTR(&pin_PB30) }, +#endif +#if defined(PIN_PB31) && !defined(IGNORE_PIN_PB31) + { MP_ROM_QSTR(MP_QSTR_PB31), MP_ROM_PTR(&pin_PB31) }, +#endif + +// These are SAMD51 specific so we assume we want them in RAM +#if defined(PIN_PC00) + { MP_ROM_QSTR(MP_QSTR_PC00), MP_ROM_PTR(&pin_PC00) }, +#endif +#if defined(PIN_PC01) + { MP_ROM_QSTR(MP_QSTR_PC01), MP_ROM_PTR(&pin_PC01) }, +#endif +#if defined(PIN_PC02) + { MP_ROM_QSTR(MP_QSTR_PC02), MP_ROM_PTR(&pin_PC02) }, +#endif +#if defined(PIN_PC03) + { MP_ROM_QSTR(MP_QSTR_PC03), MP_ROM_PTR(&pin_PC03) }, +#endif +#if defined(PIN_PC04) + { MP_ROM_QSTR(MP_QSTR_PC04), MP_ROM_PTR(&pin_PC04) }, +#endif +#if defined(PIN_PC05) + { MP_ROM_QSTR(MP_QSTR_PC05), MP_ROM_PTR(&pin_PC05) }, +#endif +#if defined(PIN_PC06) + { MP_ROM_QSTR(MP_QSTR_PC06), MP_ROM_PTR(&pin_PC06) }, +#endif +#if defined(PIN_PC07) + { MP_ROM_QSTR(MP_QSTR_PC07), MP_ROM_PTR(&pin_PC07) }, +#endif +#if defined(PIN_PC10) + { MP_ROM_QSTR(MP_QSTR_PC10), MP_ROM_PTR(&pin_PC10) }, +#endif +#if defined(PIN_PC11) + { MP_ROM_QSTR(MP_QSTR_PC11), MP_ROM_PTR(&pin_PC11) }, +#endif +#if defined(PIN_PC12) + { MP_ROM_QSTR(MP_QSTR_PC12), MP_ROM_PTR(&pin_PC12) }, +#endif +#if defined(PIN_PC13) + { MP_ROM_QSTR(MP_QSTR_PC13), MP_ROM_PTR(&pin_PC13) }, +#endif +#if defined(PIN_PC14) + { MP_ROM_QSTR(MP_QSTR_PC14), MP_ROM_PTR(&pin_PC14) }, +#endif +#if defined(PIN_PC15) + { MP_ROM_QSTR(MP_QSTR_PC15), MP_ROM_PTR(&pin_PC15) }, +#endif #if defined(PIN_PC16) { MP_ROM_QSTR(MP_QSTR_PC16), MP_ROM_PTR(&pin_PC16) }, #endif +#if defined(PIN_PC17) + { MP_ROM_QSTR(MP_QSTR_PC17), MP_ROM_PTR(&pin_PC17) }, +#endif #if defined(PIN_PC18) { MP_ROM_QSTR(MP_QSTR_PC18), MP_ROM_PTR(&pin_PC18) }, #endif #if defined(PIN_PC19) { MP_ROM_QSTR(MP_QSTR_PC19), MP_ROM_PTR(&pin_PC19) }, #endif +#if defined(PIN_PC20) + { MP_ROM_QSTR(MP_QSTR_PC20), MP_ROM_PTR(&pin_PC20) }, +#endif +#if defined(PIN_PC21) + { MP_ROM_QSTR(MP_QSTR_PC21), MP_ROM_PTR(&pin_PC21) }, +#endif +#if defined(PIN_PC22) + { MP_ROM_QSTR(MP_QSTR_PC22), MP_ROM_PTR(&pin_PC22) }, +#endif +#if defined(PIN_PC23) + { MP_ROM_QSTR(MP_QSTR_PC23), MP_ROM_PTR(&pin_PC23) }, +#endif +#if defined(PIN_PC24) + { MP_ROM_QSTR(MP_QSTR_PC24), MP_ROM_PTR(&pin_PC24) }, +#endif +#if defined(PIN_PC25) + { MP_ROM_QSTR(MP_QSTR_PC25), MP_ROM_PTR(&pin_PC25) }, +#endif +#if defined(PIN_PC26) + { MP_ROM_QSTR(MP_QSTR_PC26), MP_ROM_PTR(&pin_PC26) }, +#endif +#if defined(PIN_PC27) + { MP_ROM_QSTR(MP_QSTR_PC27), MP_ROM_PTR(&pin_PC27) }, +#endif +#if defined(PIN_PC28) + { MP_ROM_QSTR(MP_QSTR_PC28), MP_ROM_PTR(&pin_PC28) }, +#endif +#if defined(PIN_PC30) + { MP_ROM_QSTR(MP_QSTR_PC30), MP_ROM_PTR(&pin_PC30) }, +#endif +#if defined(PIN_PC31) + { MP_ROM_QSTR(MP_QSTR_PC31), MP_ROM_PTR(&pin_PC31) }, +#endif + +#if defined(PIN_PD00) + { MP_ROM_QSTR(MP_QSTR_PD00), MP_ROM_PTR(&pin_PD00) }, +#endif +#if defined(PIN_PD01) + { MP_ROM_QSTR(MP_QSTR_PD01), MP_ROM_PTR(&pin_PD01) }, +#endif +#if defined(PIN_PD08) + { MP_ROM_QSTR(MP_QSTR_PD08), MP_ROM_PTR(&pin_PD08) }, +#endif +#if defined(PIN_PD09) + { MP_ROM_QSTR(MP_QSTR_PD09), MP_ROM_PTR(&pin_PD09) }, +#endif +#if defined(PIN_PD10) + { MP_ROM_QSTR(MP_QSTR_PD10), MP_ROM_PTR(&pin_PD10) }, +#endif +#if defined(PIN_PD11) + { MP_ROM_QSTR(MP_QSTR_PD11), MP_ROM_PTR(&pin_PD11) }, +#endif +#if defined(PIN_PD12) + { MP_ROM_QSTR(MP_QSTR_PD12), MP_ROM_PTR(&pin_PD12) }, +#endif +#if defined(PIN_PD20) + { MP_ROM_QSTR(MP_QSTR_PD20), MP_ROM_PTR(&pin_PD20) }, +#endif +#if defined(PIN_PD21) + { MP_ROM_QSTR(MP_QSTR_PD21), MP_ROM_PTR(&pin_PD21) }, +#endif }; MP_DEFINE_CONST_DICT(mcu_pin_globals, mcu_pin_global_dict_table); diff --git a/ports/atmel-samd/common-hal/supervisor/Runtime.c b/ports/atmel-samd/common-hal/supervisor/Runtime.c index 2636fe646..ea663f897 100755 --- a/ports/atmel-samd/common-hal/supervisor/Runtime.c +++ b/ports/atmel-samd/common-hal/supervisor/Runtime.c @@ -26,13 +26,12 @@ #include <stdbool.h> #include "shared-bindings/supervisor/Runtime.h" -#include "usb.h" +#include "supervisor/serial.h" bool common_hal_get_serial_connected(void) { - return (bool) usb_connected(); + return (bool) serial_connected(); } bool common_hal_get_serial_bytes_available(void) { - return (bool) usb_bytes_available(); + return (bool) serial_bytes_available(); } - diff --git a/ports/atmel-samd/common-hal/usb_hid/Device.c b/ports/atmel-samd/common-hal/usb_hid/Device.c deleted file mode 100644 index 31bace018..000000000 --- a/ports/atmel-samd/common-hal/usb_hid/Device.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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 <string.h> - -#include "common-hal/usb_hid/Device.h" - -#include "py/runtime.h" -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/usb_hid/Device.h" -#include "supervisor/shared/translate.h" -#include "genhdr/autogen_usb_descriptor.h" - -#include "tick.h" - -#include "usb/class/hid/device/hiddf_generic.h" - -static uint32_t usb_hid_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) { - - int32_t status; - - // Don't get stuck if USB fails in some way; timeout after a while. - uint64_t end_ticks = ticks_ms + 2000; - - while (ticks_ms < end_ticks) { - status = usb_d_ep_get_status(self->endpoint, NULL); - if (status == USB_BUSY) { - continue; - } - if (status == USB_OK) { - break; - } - // Some error. Give up. - return status; - } - - // Copy the data only when endpoint is ready to send. The previous - // buffer load gets zero'd out when transaction completes, so if - // you copy before it's ready, only zeros will get sent. - - // Prefix with a report id if one is supplied. - if (self->report_id > 0) { - self->report_buffer[0] = self->report_id; - memcpy(&(self->report_buffer[1]), report, len); - return hiddf_generic_write(self->report_buffer, len + 1); - } else { - memcpy(self->report_buffer, report, len); - return hiddf_generic_write(self->report_buffer, len); - } - -} - -void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t* report, uint8_t len) { - if (len != self->report_length) { - mp_raise_ValueError_varg(translate("Buffer incorrect size. Should be %d bytes."), self->report_length); - } - int32_t status = usb_hid_send_report(self, report, len); - if (status != ERR_NONE) { - mp_raise_msg(&mp_type_OSError, status == USB_BUSY ? translate("USB Busy") : translate("USB Error")); - } -} - -uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) { - return self->usage_page; -} - -uint8_t common_hal_usb_hid_device_get_usage(usb_hid_device_obj_t *self) { - return self->usage; -} - - -void usb_hid_init() { -} - -void usb_hid_reset() { - // We don't actually reset. We just set a report that is empty to prevent - // long keypresses and such. - uint8_t report[USB_HID_MAX_REPORT_LENGTH] = {0}; - - for (size_t i = 0; i < USB_HID_NUM_DEVICES; i++) { - usb_hid_send_report(&usb_hid_devices[i], report, usb_hid_devices[i].report_length); - } -} diff --git a/ports/atmel-samd/common-hal/usb_hid/__init__.c b/ports/atmel-samd/common-hal/usb_hid/__init__.c deleted file mode 100644 index 770d221c7..000000000 --- a/ports/atmel-samd/common-hal/usb_hid/__init__.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 "py/obj.h" -#include "py/mphal.h" -#include "py/runtime.h" - -#include "common-hal/usb_hid/Device.h" - -#include "shared-bindings/usb_hid/Device.h" - -#include "genhdr/autogen_usb_descriptor.h" - -// Buffers are report size + 1 to include the Report ID prefix byte if needed. -#ifdef USB_HID_REPORT_ID_KEYBOARD -static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD + 1]; -#endif -#ifdef USB_HID_REPORT_ID_MOUSE -static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE + 1]; -#endif -#ifdef USB_HID_REPORT_ID_CONSUMER -static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER + 1]; -#endif -#ifdef USB_HID_REPORT_ID_SYS_CONTROL -static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL + 1]; -#endif -#ifdef USB_HID_REPORT_ID_GAMEPAD -static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD + 1]; -#endif -#ifdef USB_HID_REPORT_ID_DIGITIZER -static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER + 1]; -#endif - -usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES] = { -#ifdef USB_HID_REPORT_ID_KEYBOARD - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = keyboard_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_KEYBOARD, - .report_length = USB_HID_REPORT_LENGTH_KEYBOARD, - .usage_page = 0x01, - .usage = 0x06, - }, -#endif -#ifdef USB_HID_REPORT_ID_MOUSE - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = mouse_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_MOUSE, - .report_length = USB_HID_REPORT_LENGTH_MOUSE, - .usage_page = 0x01, - .usage = 0x02, - }, -#endif -#ifdef USB_HID_REPORT_ID_CONSUMER - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = consumer_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_CONSUMER, - .report_length = USB_HID_REPORT_LENGTH_CONSUMER, - .usage_page = 0x0C, - .usage = 0x01, - }, -#endif -#ifdef USB_HID_REPORT_ID_SYS_CONTROL - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = sys_control_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_SYS_CONTROL, - .report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL, - .usage_page = 0x01, - .usage = 0x80, - }, -#endif -#ifdef USB_HID_REPORT_ID_GAMEPAD - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = gamepad_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_GAMEPAD, - .report_length = USB_HID_REPORT_LENGTH_GAMEPAD, - .usage_page = 0x01, - .usage = 0x05, - }, -#endif -#ifdef USB_HID_REPORT_ID_DIGITIZER - { - .base = { .type = &usb_hid_device_type }, - .report_buffer = digitizer_report_buffer, - .endpoint = USB_HID_ENDPOINT_IN, - .report_id = USB_HID_REPORT_ID_DIGITIZER, - .report_length = USB_HID_REPORT_LENGTH_DIGITIZER, - .usage_page = 0x0D, - .usage = 0x02, - }, -#endif -}; - - -mp_obj_tuple_t common_hal_usb_hid_devices = { - .base = { - .type = &mp_type_tuple, - }, - .len = USB_HID_NUM_DEVICES, - .items = { -#if USB_HID_NUM_DEVICES >= 1 - (mp_obj_t) &usb_hid_devices[0], -#endif -#if USB_HID_NUM_DEVICES >= 2 - (mp_obj_t) &usb_hid_devices[1], -#endif -#if USB_HID_NUM_DEVICES >= 3 - (mp_obj_t) &usb_hid_devices[2], -#endif -#if USB_HID_NUM_DEVICES >= 4 - (mp_obj_t) &usb_hid_devices[3], -#endif -#if USB_HID_NUM_DEVICES >= 5 - (mp_obj_t) &usb_hid_devices[4], -#endif -#if USB_HID_NUM_DEVICES >= 6 - (mp_obj_t) &usb_hid_devices[5], -#endif - } -}; diff --git a/ports/atmel-samd/external_flash/external_flash.h b/ports/atmel-samd/external_flash/external_flash.h deleted file mode 100644 index f8ec5673c..000000000 --- a/ports/atmel-samd/external_flash/external_flash.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * 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_EXTERNAL_FLASH_H -#define MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H - -#include <stdbool.h> - -#include "mpconfigport.h" - -// We use this when we can allocate the whole cache in RAM. -#define FLASH_ROOT_POINTERS \ - uint8_t** flash_ram_cache; \ - -// Erase sector size. -#define SPI_FLASH_SECTOR_SIZE (0x1000 - 100) - -// These are common across all NOR Flash. -#define SPI_FLASH_ERASE_SIZE (1 << 12) -#define SPI_FLASH_PAGE_SIZE (256) - -#define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms -#define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2) - -void external_flash_init(void); -uint32_t external_flash_get_block_size(void); -uint32_t external_flash_get_block_count(void); -void external_flash_irq_handler(void); -void external_flash_flush(void); -bool external_flash_read_block(uint8_t *dest, uint32_t block); -bool external_flash_write_block(const uint8_t *src, uint32_t block); - -// these return 0 on success, non-zero on error -mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); - -extern const struct _mp_obj_type_t external_flash_type; - -struct _fs_user_mount_t; -void flash_init_vfs(struct _fs_user_mount_t *vfs); - -#endif // MICROPY_INCLUDED_ATMEL_SAMD_EXTERNAL_FLASH_H diff --git a/ports/atmel-samd/mpconfigport.h b/ports/atmel-samd/mpconfigport.h index a4c763d05..3b95aefa9 100644 --- a/ports/atmel-samd/mpconfigport.h +++ b/ports/atmel-samd/mpconfigport.h @@ -154,6 +154,7 @@ typedef long mp_off_t; #define CIRCUITPY_MCU_FAMILY samd21 #define MICROPY_PY_SYS_PLATFORM "Atmel SAMD21" #define PORT_HEAP_SIZE (16384 + 4096) +#define SPI_FLASH_MAX_BAUDRATE 8000000 #define CIRCUITPY_DEFAULT_STACK_SIZE 4096 #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_MODULE_WEAK_LINKS (0) @@ -169,6 +170,7 @@ typedef long mp_off_t; #define CIRCUITPY_MCU_FAMILY samd51 #define MICROPY_PY_SYS_PLATFORM "MicroChip SAMD51" #define PORT_HEAP_SIZE (0x20000) // 128KiB +#define SPI_FLASH_MAX_BAUDRATE 24000000 #define CIRCUITPY_DEFAULT_STACK_SIZE 8192 #define MICROPY_CPYTHON_COMPAT (1) #define MICROPY_MODULE_WEAK_LINKS (1) @@ -421,8 +423,13 @@ extern const struct _mp_obj_module_t wiznet_module; #define MP_STATE_PORT MP_STATE_VM +void run_background_tasks(void); +#define MICROPY_VM_HOOK_LOOP run_background_tasks(); +#define MICROPY_VM_HOOK_RETURN run_background_tasks(); + #include "peripherals/samd/dma.h" +#include "supervisor/flash_root_pointers.h" #if MICROPY_PY_NETWORK #define NETWORK_ROOT_POINTERS mp_obj_list_t mod_network_nic_list; #else @@ -438,9 +445,6 @@ extern const struct _mp_obj_module_t wiznet_module; mp_obj_t gamepad_singleton; \ NETWORK_ROOT_POINTERS \ -void run_background_tasks(void); -#define MICROPY_VM_HOOK_LOOP run_background_tasks(); -#define MICROPY_VM_HOOK_RETURN run_background_tasks(); #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 #define CIRCUITPY_BOOT_OUTPUT_FILE "/boot_out.txt" diff --git a/ports/atmel-samd/mpconfigport.mk b/ports/atmel-samd/mpconfigport.mk index d5c9f2ce6..7db581dd6 100644 --- a/ports/atmel-samd/mpconfigport.mk +++ b/ports/atmel-samd/mpconfigport.mk @@ -14,6 +14,6 @@ ifeq ($(LONGINT_IMPL),LONGLONG) MPY_TOOL_LONGINT_IMPL = -mlongint-impl=longlong endif - INTERNAL_LIBM = 1 +USB_SERIAL_NUMBER_LENGTH = 32 diff --git a/ports/atmel-samd/mphalport.c b/ports/atmel-samd/mphalport.c index a4eca1c74..ac5b0fbca 100644 --- a/ports/atmel-samd/mphalport.c +++ b/ports/atmel-samd/mphalport.c @@ -46,43 +46,9 @@ #include "mphalport.h" #include "reset.h" #include "tick.h" -#include "usb.h" -extern struct usart_module usart_instance; extern uint32_t common_hal_mcu_processor_get_frequency(void); -int mp_hal_stdin_rx_chr(void) { - for (;;) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - // if (reload_requested) { - // return CHAR_CTRL_D; - // } - if (usb_bytes_available()) { - #ifdef MICROPY_HW_LED_RX - gpio_toggle_pin_level(MICROPY_HW_LED_RX); - #endif - return usb_read(); - } - } -} - -void mp_hal_stdout_tx_strn(const char *str, size_t len) { - #ifdef MICROPY_HW_LED_TX - gpio_toggle_pin_level(MICROPY_HW_LED_TX); - #endif - - #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - if (boot_output_file != NULL) { - UINT bytes_written = 0; - f_write(boot_output_file, str, len, &bytes_written); - } - #endif - - usb_write(str, len); -} - void mp_hal_delay_ms(mp_uint_t delay) { uint64_t start_tick = ticks_ms; uint64_t duration = 0; diff --git a/ports/atmel-samd/mphalport.h b/ports/atmel-samd/mphalport.h index 3bc824d4e..64269b201 100644 --- a/ports/atmel-samd/mphalport.h +++ b/ports/atmel-samd/mphalport.h @@ -41,8 +41,6 @@ static inline mp_uint_t mp_hal_ticks_ms(void) { volatile uint8_t usb_rx_count; volatile bool mp_cdc_enabled; -FIL* boot_output_file; - int receive_usb(void); void mp_hal_set_interrupt_char(int c); diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals -Subproject d0dcba251c27f629c0a89b5ced4433dd0a609ca +Subproject f20fcf642b5654ee68d7d551ea7db39716ef83b diff --git a/ports/atmel-samd/reset.c b/ports/atmel-samd/reset.c index ba5bf9ba1..735639cc4 100644 --- a/ports/atmel-samd/reset.c +++ b/ports/atmel-samd/reset.c @@ -34,10 +34,6 @@ void reset(void) { NVIC_SystemReset(); } -void reset_to_bootloader(void) { - _bootloader_dbl_tap = DBL_TAP_MAGIC; - reset(); -} extern uint32_t _srelocate; bool bootloader_available(void) { diff --git a/ports/atmel-samd/internal_flash.c b/ports/atmel-samd/supervisor/internal_flash.c index 35eb52da2..bf12ad0cd 100644 --- a/ports/atmel-samd/internal_flash.c +++ b/ports/atmel-samd/supervisor/internal_flash.c @@ -23,7 +23,6 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "internal_flash.h" #include <stdint.h> #include <string.h> @@ -42,9 +41,9 @@ #include "supervisor/shared/rgb_led_status.h" -static struct flash_descriptor internal_flash_desc; +static struct flash_descriptor supervisor_flash_desc; -void internal_flash_init(void) { +void supervisor_flash_init(void) { // Activity LED for flash writes. #ifdef MICROPY_HW_LED_MSC struct port_config pin_conf; @@ -61,22 +60,22 @@ void internal_flash_init(void) { #ifdef SAMD21 _pm_enable_bus_clock(PM_BUS_APBB, NVMCTRL); #endif - flash_init(&internal_flash_desc, NVMCTRL); + flash_init(&supervisor_flash_desc, NVMCTRL); } -uint32_t internal_flash_get_block_size(void) { +uint32_t supervisor_flash_get_block_size(void) { return FILESYSTEM_BLOCK_SIZE; } -uint32_t internal_flash_get_block_count(void) { +uint32_t supervisor_flash_get_block_count(void) { return INTERNAL_FLASH_PART1_START_BLOCK + INTERNAL_FLASH_PART1_NUM_BLOCKS; } -void internal_flash_flush(void) { +void supervisor_flash_flush(void) { } void flash_flush(void) { - internal_flash_flush(); + supervisor_flash_flush(); } static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) { @@ -125,7 +124,7 @@ static int32_t convert_block_to_flash_addr(uint32_t block) { return -1; } -bool internal_flash_read_block(uint8_t *dest, uint32_t block) { +bool supervisor_flash_read_block(uint8_t *dest, uint32_t block) { if (block == 0) { // fake the MBR so we can decide on our own partition table @@ -150,12 +149,12 @@ bool internal_flash_read_block(uint8_t *dest, uint32_t block) { // bad block number return false; } - int32_t error_code = flash_read(&internal_flash_desc, src, dest, FILESYSTEM_BLOCK_SIZE); + int32_t error_code = flash_read(&supervisor_flash_desc, src, dest, FILESYSTEM_BLOCK_SIZE); return error_code == ERR_NONE; } } -bool internal_flash_write_block(const uint8_t *src, uint32_t block) { +bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) { if (block == 0) { // can't write MBR, but pretend we did return true; @@ -172,14 +171,14 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) { return false; } int32_t error_code; - error_code = flash_erase(&internal_flash_desc, + error_code = flash_erase(&supervisor_flash_desc, dest, - FILESYSTEM_BLOCK_SIZE / flash_get_page_size(&internal_flash_desc)); + FILESYSTEM_BLOCK_SIZE / flash_get_page_size(&supervisor_flash_desc)); if (error_code != ERR_NONE) { return false; } - error_code = flash_append(&internal_flash_desc, dest, src, FILESYSTEM_BLOCK_SIZE); + error_code = flash_append(&supervisor_flash_desc, dest, src, FILESYSTEM_BLOCK_SIZE); if (error_code != ERR_NONE) { return false; } @@ -191,95 +190,20 @@ bool internal_flash_write_block(const uint8_t *src, uint32_t block) { } } -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { + if (!supervisor_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error } } return 0; // success } -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { - if (!internal_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { + if (!supervisor_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error } } return 0; // success } - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t internal_flash_obj = {&internal_flash_type}; - -STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&internal_flash_obj; -} - -STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); - -STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); - -STATIC mp_obj_t internal_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: internal_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_ioctl_obj, internal_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t internal_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&internal_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&internal_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&internal_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(internal_flash_obj_locals_dict, internal_flash_obj_locals_dict_table); - -const mp_obj_type_t internal_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_InternalFlash, - .make_new = internal_flash_obj_make_new, - .locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict, -}; - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version - vfs->writeblocks[0] = (mp_obj_t)&internal_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)internal_flash_write_blocks; // native version - vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj; -} diff --git a/ports/atmel-samd/internal_flash.h b/ports/atmel-samd/supervisor/internal_flash.h index 88c105386..88c105386 100644 --- a/ports/atmel-samd/internal_flash.h +++ b/ports/atmel-samd/supervisor/internal_flash.h diff --git a/ports/atmel-samd/supervisor/internal_flash_root_pointers.h b/ports/atmel-samd/supervisor/internal_flash_root_pointers.h new file mode 100644 index 000000000..3e9148ce0 --- /dev/null +++ b/ports/atmel-samd/supervisor/internal_flash_root_pointers.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H + +#define FLASH_ROOT_POINTERS + +#endif // MICROPY_INCLUDED_ATMEL_SAMD_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c index 45b8ed1a4..9f951b035 100644 --- a/ports/atmel-samd/supervisor/port.c +++ b/ports/atmel-samd/supervisor/port.c @@ -32,7 +32,6 @@ #include "hal/include/hal_delay.h" #include "hal/include/hal_gpio.h" #include "hal/include/hal_init.h" -#include "hal/include/hal_usb_device.h" #include "hpl/gclk/hpl_gclk_base.h" #include "hpl/pm/hpl_pm_base.h" @@ -48,13 +47,13 @@ #include "common-hal/audiobusio/PDMIn.h" #include "common-hal/audiobusio/I2SOut.h" #include "common-hal/audioio/AudioOut.h" +#include "common-hal/busio/SPI.h" #include "common-hal/microcontroller/Pin.h" #include "common-hal/pulseio/PulseIn.h" #include "common-hal/pulseio/PulseOut.h" #include "common-hal/pulseio/PWMOut.h" #include "common-hal/rtc/RTC.h" #include "common-hal/touchio/TouchIn.h" -#include "common-hal/usb_hid/Device.h" #include "samd/cache.h" #include "samd/clocks.h" #include "samd/events.h" @@ -62,8 +61,10 @@ #include "samd/dma.h" #include "shared-bindings/rtc/__init__.h" #include "board_busses.h" +#include "reset.h" #include "tick.h" -#include "usb.h" + +#include "tusb.h" #ifdef CIRCUITPY_GAMEPAD_TICKS #include "shared-module/gamepad/__init__.h" @@ -225,28 +226,7 @@ safe_mode_t port_init(void) { } void reset_port(void) { - // Reset all SERCOMs except the ones being used by on-board devices. - Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS; - for (int i = 0; i < SERCOM_INST_NUM; i++) { -#ifdef SPI_FLASH_SERCOM - if (sercom_instances[i] == SPI_FLASH_SERCOM) { - continue; - } -#endif -#ifdef MICROPY_HW_APA102_SERCOM - if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) { - continue; - } -#endif -#ifdef CIRCUITPY_DISPLAYIO - // TODO(tannewt): Make this dynamic. - if (sercom_instances[i] == board_display_obj.bus.spi_desc.dev.prvt) { - continue; - } -#endif - // SWRST is same for all modes of SERCOMs. - sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1; - } + reset_sercoms(); #if defined(EXPRESS_BOARD) && !defined(__SAMR21G18A__) audio_dma_reset(); @@ -290,13 +270,16 @@ void reset_port(void) { // gpio_set_pin_function(PIN_PB15, GPIO_PIN_FUNCTION_M); // GCLK1, D6 // #endif - usb_hid_reset(); - - if (usb_connected()) { + if (tud_cdc_connected()) { save_usb_clock_calibration(); } } +void reset_to_bootloader(void) { + _bootloader_dbl_tap = DBL_TAP_MAGIC; + reset(); +} + /** * \brief Default interrupt handler for unused IRQs. */ diff --git a/ports/atmel-samd/external_flash/qspi_flash.c b/ports/atmel-samd/supervisor/qspi_flash.c index f6dc00d50..eca47b164 100644 --- a/ports/atmel-samd/external_flash/qspi_flash.c +++ b/ports/atmel-samd/supervisor/qspi_flash.c @@ -24,14 +24,15 @@ * THE SOFTWARE. */ -#include "spi_flash_api.h" +#include "supervisor/spi_flash_api.h" #include <stdint.h> #include <string.h> #include "mpconfigboard.h" // for EXTERNAL_FLASH_QSPI_DUAL -#include "external_flash/common_commands.h" +#include "supervisor/shared/external_flash/common_commands.h" +#include "supervisor/shared/external_flash/qspi_flash.h" #include "samd/cache.h" #include "samd/dma.h" @@ -225,18 +226,7 @@ void spi_flash_init(void) { } void spi_flash_init_device(const external_flash_device* device) { - // Verify that QSPI mode is enabled. - uint8_t status; - spi_flash_read_command(CMD_READ_STATUS2, &status, 1); - - // Bit 1 is Quad Enable - if ((status & 0x2) == 0) { - uint8_t full_status[2] = {0x0, 0x2}; - spi_flash_command(CMD_ENABLE_WRITE); - if (device->write_status_register_split) { - spi_flash_write_command(CMD_WRITE_STATUS_BYTE2, full_status + 1, 1); - } else { - spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); - } - } + check_quad_enable(device); + + // TODO(tannewt): Adjust the speed for the found device. } diff --git a/ports/atmel-samd/supervisor/serial.c b/ports/atmel-samd/supervisor/serial.c deleted file mode 100644 index 4917dfb5b..000000000 --- a/ports/atmel-samd/supervisor/serial.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 <string.h> - -#include "supervisor/serial.h" - -#include "common-hal/usb_hid/Device.h" - -#include "usb.h" -#include "genhdr/autogen_usb_descriptor.h" - -// Serial number as hex characters. This writes directly to the USB -// descriptor. -void load_serial_number(void) { - char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F'}; - #ifdef SAMD21 - uint32_t* addresses[4] = {(uint32_t *) 0x0080A00C, (uint32_t *) 0x0080A040, - (uint32_t *) 0x0080A044, (uint32_t *) 0x0080A048}; - #endif - #ifdef SAMD51 - uint32_t* addresses[4] = {(uint32_t *) 0x008061FC, (uint32_t *) 0x00806010, - (uint32_t *) 0x00806014, (uint32_t *) 0x00806018}; - #endif - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 8; j++) { - uint8_t nibble = (*(addresses[i]) >> j * 4) & 0xf; - // Strings are UTF-16-LE encoded. - serial_number[i * 16 + j * 2] = nibble_to_hex[nibble]; - serial_number[i * 16 + j * 2 + 1] = 0; - } - } -} - -void serial_init(void) { - load_serial_number(); - init_usb(); - usb_hid_init(); -} - -bool serial_connected(void) { - return usb_connected(); -} - -char serial_read(void) { - return usb_read(); -} - -bool serial_bytes_available(void) { - return usb_bytes_available(); -} - -void serial_write(const char* text) { - usb_write(text, strlen(text)); -} diff --git a/ports/atmel-samd/supervisor/usb.c b/ports/atmel-samd/supervisor/usb.c new file mode 100644 index 000000000..d13ca0ef1 --- /dev/null +++ b/ports/atmel-samd/supervisor/usb.c @@ -0,0 +1,59 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2017, 2018 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 "atmel_start_pins.h" +#include "hpl/pm/hpl_pm_base.h" +#include "hpl/gclk/hpl_gclk_base.h" +#include "hal_gpio.h" + +void init_usb_hardware(void) { + #ifdef SAMD21 + _pm_enable_bus_clock(PM_BUS_APBB, USB); + _pm_enable_bus_clock(PM_BUS_AHB, USB); + _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); + #endif + + #ifdef SAMD51 + hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN); + hri_mclk_set_AHBMASK_USB_bit(MCLK); + hri_mclk_set_APBBMASK_USB_bit(MCLK); + #endif + + gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA24, false); + gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); + gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); + gpio_set_pin_level(PIN_PA25, false); + gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); + #ifdef SAMD21 + gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); + #endif + #ifdef SAMD51 + gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); + gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); + #endif +} diff --git a/ports/atmel-samd/tick.h b/ports/atmel-samd/tick.h index 80e7bc9af..c8c8d739a 100644 --- a/ports/atmel-samd/tick.h +++ b/ports/atmel-samd/tick.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_ATMEL_SAMD_TICK_H #define MICROPY_INCLUDED_ATMEL_SAMD_TICK_H -#include "mpconfigport.h" +#include "py/mpconfig.h" extern volatile uint64_t ticks_ms; diff --git a/ports/atmel-samd/usb.c b/ports/atmel-samd/usb.c deleted file mode 100644 index 1f1ba550f..000000000 --- a/ports/atmel-samd/usb.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * This file is part of the Micro Python 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 "usb.h" - -#include <stdint.h> - -// We must include this early because it sets values used in the ASF4 includes -// below. -#include "py/mpconfig.h" - -#include "hal/include/hal_gpio.h" -#include "usb/class/cdc/device/cdcdf_acm.h" -#include "usb/class/hid/device/hiddf_generic.h" -#include "usb/class/composite/device/composite_desc.h" -#include "usb/class/msc/device/mscdf.h" -#include "peripheral_clk_config.h" -#include "hpl/pm/hpl_pm_base.h" -#include "hpl/gclk/hpl_gclk_base.h" - -#include "lib/utils/interrupt_char.h" -#include "genhdr/autogen_usb_descriptor.h" -#include "reset.h" -#include "usb_mass_storage.h" - -#include "supervisor/shared/autoreload.h" - -extern struct usbd_descriptors descriptor_bounds; - -// Store received characters on our own so that we can filter control characters -// and act immediately on CTRL-C for example. - -// Receive buffer -static uint8_t usb_rx_buf[USB_RX_BUF_SIZE]; - -// Receive buffer head -static volatile uint8_t usb_rx_buf_head = 0; - -// Receive buffer tail -static volatile uint8_t usb_rx_buf_tail = 0; - -// Number of bytes in receive buffer -volatile uint8_t usb_rx_count = 0; - -volatile bool mp_cdc_enabled = false; -volatile bool usb_transmitting = false; - -/** Ctrl endpoint buffer */ -COMPILER_ALIGNED(4) static uint8_t ctrl_buffer[64]; - -static void init_hardware(void) { - #ifdef SAMD21 - _pm_enable_bus_clock(PM_BUS_APBB, USB); - _pm_enable_bus_clock(PM_BUS_AHB, USB); - _gclk_enable_channel(USB_GCLK_ID, GCLK_CLKCTRL_GEN_GCLK0_Val); - #endif - - #ifdef SAMD51 - hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, CONF_GCLK_USB_SRC | GCLK_PCHCTRL_CHEN); - hri_mclk_set_AHBMASK_USB_bit(MCLK); - hri_mclk_set_APBBMASK_USB_bit(MCLK); - #endif - - usb_d_init(); - - gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA24, false); - gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF); - gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT); - gpio_set_pin_level(PIN_PA25, false); - gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF); - #ifdef SAMD21 - gpio_set_pin_function(PIN_PA24, PINMUX_PA24G_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25G_USB_DP); - #endif - #ifdef SAMD51 - gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM); - gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP); - #endif -} - -#define CDC_BULKOUT_SIZE CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKOUT_MAXPKSZ -COMPILER_ALIGNED(4) uint8_t cdc_packet_buffer[CDC_BULKOUT_SIZE]; -static volatile bool pending_read; - -static int32_t start_read(void) { - pending_read = true; - int32_t result = cdcdf_acm_read(cdc_packet_buffer, CDC_BULKOUT_SIZE); - if (result != ERR_NONE) { - pending_read = false; - } - return result; -} - -static bool read_complete(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count) { - if (rc != USB_XFER_DONE) { - return false; // No errors. - } - pending_read = false; - volatile hal_atomic_t flags; - atomic_enter_critical(&flags); - // If our buffer can't fit the data received, then error out. - if (count > (uint8_t) (USB_RX_BUF_SIZE - usb_rx_count)) { - atomic_leave_critical(&flags); - return true; - } - - for (uint16_t i = 0; i < count; i++) { - uint8_t c = cdc_packet_buffer[i]; - if (c == mp_interrupt_char) { - mp_keyboard_interrupt(); - // If interrupted, flush all the input. - usb_rx_count = 0; - usb_rx_buf_head = 0; - usb_rx_buf_tail = 0; - break; - } else { - // The count of characters present in receive buffer is - // incremented. - usb_rx_count++; - usb_rx_buf[usb_rx_buf_tail] = c; - usb_rx_buf_tail++; - if (usb_rx_buf_tail == USB_RX_BUF_SIZE) { - // Reached the end of buffer, revert back to beginning of - // buffer. - usb_rx_buf_tail = 0; - } - } - } - atomic_leave_critical(&flags); - - /* No error. */ - return false; -} - -static bool write_complete(const uint8_t ep, - const enum usb_xfer_code rc, - const uint32_t count) { - if (rc != USB_XFER_DONE) { - return false; // No errors. - } - // This is called after writes are finished. - - usb_transmitting = false; - - /* No error. */ - return false; -} - -volatile bool reset_on_disconnect = false; -volatile bool cdc_connected = false; - -static bool usb_device_cb_state_c(usb_cdc_control_signal_t state) -{ - cdc_connected = state.rs232.DTR; - if (state.rs232.DTR) { - } else if (!state.rs232.DTR && reset_on_disconnect) { - reset_to_bootloader(); - } - - /* No error. */ - return false; -} - -static bool usb_device_cb_line_coding_c(const usb_cdc_line_coding_t* coding) -{ - reset_on_disconnect = coding->dwDTERate == 1200; - /* Ok to change. */ - return true; -} - -void init_usb(void) { - init_hardware(); - - mp_cdc_enabled = false; - - usbdc_init(ctrl_buffer); - - /* usbdc_register_function inside */ - cdcdf_acm_init(); - pending_read = false; - - mscdf_init(1); - mscdf_register_callback(MSCDF_CB_INQUIRY_DISK, (FUNC_PTR)usb_msc_inquiry_info); - mscdf_register_callback(MSCDF_CB_GET_DISK_CAPACITY, (FUNC_PTR)usb_msc_get_capacity); - mscdf_register_callback(MSCDF_CB_START_READ_DISK, (FUNC_PTR)usb_msc_new_read); - mscdf_register_callback(MSCDF_CB_START_WRITE_DISK, (FUNC_PTR)usb_msc_new_write); - mscdf_register_callback(MSCDF_CB_EJECT_DISK, (FUNC_PTR)usb_msc_disk_eject); - mscdf_register_callback(MSCDF_CB_TEST_DISK_READY, (FUNC_PTR)usb_msc_disk_is_ready); - mscdf_register_callback(MSCDF_CB_XFER_BLOCKS_DONE, (FUNC_PTR)usb_msc_xfer_done); - mscdf_register_callback(MSCDF_CB_IS_WRITABLE, (FUNC_PTR)usb_msc_disk_is_writable); - - hiddf_generic_init(hid_report_descriptor, sizeof(hid_report_descriptor)); - - usbdc_start(&descriptor_bounds); - - usbdc_attach(); - - -} - -static bool cdc_enabled(void) { - if (!cdcdf_acm_is_enabled()) { - mp_cdc_enabled = false; - return false; - } - if (!mp_cdc_enabled) { - cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)read_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)write_complete); - cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c); - cdcdf_acm_register_callback(CDCDF_ACM_CB_LINE_CODING_C, (FUNC_PTR)usb_device_cb_line_coding_c); - mp_cdc_enabled = true; - } - - return true; -} - -bool usb_bytes_available(void) { - // Check if the buffer has data, but not enough - // space to hold another read. - if (usb_rx_count > USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE) { - return true; - } - // Buffer has enough room - if (cdc_enabled() && !pending_read) { - start_read(); - } - // Buffer is empty and/or no new data is available - if (usb_rx_count == 0) { - return false; - } - return usb_rx_count > 0; -} - -int usb_read(void) { - if (!cdc_enabled() || usb_rx_count == 0) { - return 0; - } - - // Copy from head. - int data; - CRITICAL_SECTION_ENTER(); - data = usb_rx_buf[usb_rx_buf_head]; - usb_rx_buf_head++; - usb_rx_count--; - if (usb_rx_buf_head == USB_RX_BUF_SIZE) { - usb_rx_buf_head = 0; - } - CRITICAL_SECTION_LEAVE(); - - return data; -} - -// TODO(tannewt): See if we can disable the internal CDC IN cache since we -// we manage this one ourselves. -#define CDC_BULKIN_SIZE CONF_USB_COMPOSITE_CDC_ACM_DATA_BULKIN_MAXPKSZ -COMPILER_ALIGNED(4) uint8_t cdc_output_buffer[CDC_BULKIN_SIZE]; - -void usb_write(const char* buffer, uint32_t len) { - if (!cdc_enabled()) { - return; - } - if (!cdc_connected) { - // TODO(tannewt): Should we write to a file instead? - return; - } - uint8_t * output_buffer; - uint32_t output_len; - while (len > 0) { - while (usb_transmitting) {} - output_buffer = (uint8_t *) buffer; - output_len = len; - // Use our own cache in two different cases: - // * When we're at the end of a transmission and we'll return before - // the given buffer is actually transferred to the USB device. - // * When our given buffer isn't aligned on word boundaries. - if (output_len <= CDC_BULKIN_SIZE || ((uint32_t) buffer) % 4 != 0) { - output_buffer = cdc_output_buffer; - output_len = output_len > CDC_BULKIN_SIZE ? CDC_BULKIN_SIZE : output_len; - memcpy(cdc_output_buffer, buffer, output_len); - } else { - output_len = CDC_BULKIN_SIZE; - } - usb_transmitting = true; - cdcdf_acm_write(output_buffer, output_len); - buffer += output_len * sizeof(char); - len -= output_len; - } -} - -bool usb_connected(void) { - return cdc_enabled(); -} - -// Poll for input if keyboard interrupts are enabled, -// so that we can check for the interrupt char. read_complete() does the checking. -// also make sure we have enough room in the local buffer -void usb_cdc_background() { - // - if (mp_interrupt_char != -1 && cdc_enabled() && !pending_read && (usb_rx_count < USB_RX_BUF_SIZE - CDC_BULKOUT_SIZE)) { - start_read(); - } -} diff --git a/ports/atmel-samd/usb_mass_storage.c b/ports/atmel-samd/usb_mass_storage.c deleted file mode 100644 index 9b6715158..000000000 --- a/ports/atmel-samd/usb_mass_storage.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 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 <string.h> - -#include "usb_mass_storage.h" -#include "supervisor/shared/autoreload.h" - -#include "hal/utils/include/err_codes.h" -#include "hal/utils/include/utils.h" -#include "usb/class/msc/device/mscdf.h" - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -#include "lib/oofatfs/ff.h" -#include "lib/oofatfs/diskio.h" -#include "lib/oofatfs/ffconf.h" -#include "py/mpconfig.h" -#include "py/mphal.h" -#include "py/mpstate.h" -#include "py/misc.h" - -// The root FS is always at the end of the list. -static fs_user_mount_t* get_vfs(int lun) { - // TODO(tannewt): Return the mount which matches the lun where 0 is the end - // and is counted in reverse. - if (lun > 0) { - return NULL; - } - mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); - if (current_mount == NULL) { - return NULL; - } - while (current_mount->next != NULL) { - current_mount = current_mount->next; - } - return current_mount->obj; -} - -/* Inquiry Information */ -// This is designed to handle the common case where we have an internal file -// system and an optional SD card. -COMPILER_ALIGNED(4) static uint8_t inquiry_info[2][36]; - -/* Capacities of Disk */ -COMPILER_ALIGNED(4) static uint8_t format_capa[2][8]; - -/** - * \brief Eject Disk - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_disk_eject(uint8_t lun) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - fs_user_mount_t* current_mount = get_vfs(lun); - // Return ERR_NOT_READY if not ready, otherwise ERR_NONE. - if (current_mount == NULL) { - return ERR_NOT_FOUND; - } - // TODO(tannewt): Should we flush here? - return ERR_NONE; -} - -/** - * \brief Inquiry whether Disk is writable. ERR_DENIED if it is not writable. - * ERR_NONE if it is. ERR_NOT_FOUND if its missing. - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_disk_is_writable(uint8_t lun) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - fs_user_mount_t* vfs = get_vfs(lun); - if (vfs == NULL) { - return ERR_NOT_FOUND; - } - if (vfs->writeblocks[0] == MP_OBJ_NULL || - (vfs->flags & FSUSER_USB_WRITABLE) == 0) { - return ERR_DENIED; - } - return ERR_NONE; -} - -/** - * \brief Inquiry whether Disk is ready - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_disk_is_ready(uint8_t lun) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - fs_user_mount_t* current_mount = get_vfs(lun); - if (current_mount == NULL) { - return ERR_NOT_FOUND; - } - return ERR_NONE; -} - -/** - * \brief Callback invoked when inquiry data command received - * \param[in] lun logic unit number - * \return Operation status. - */ -uint8_t *usb_msc_inquiry_info(uint8_t lun) { - if (lun > 1) { - return NULL; - } else { - for (uint8_t i = 0; i < 36; i++) { - inquiry_info[lun][i] = 0; - } - inquiry_info[lun][0] = SCSI_INQ_PQ_CONNECTED | SCSI_INQ_DT_DIR_ACCESS; - // connected, direct access - inquiry_info[lun][1] = SCSI_INQ_RMB; // removable medium - inquiry_info[lun][2] = SCSI_INQ_VER_SPC; // SBC version of SCSI primary commands - inquiry_info[lun][3] = SCSI_INQ_RSP_SPC2;// SPC-2 response format - inquiry_info[lun][4] = 31; // 31 bytes following - return &inquiry_info[lun][0]; - } -} - -/** - * \brief Callback invoked when read format capacities command received - * \param[in] lun logic unit number - */ -uint8_t *usb_msc_get_capacity(uint8_t lun) { - if (lun > 1) { - return NULL; - } else { - fs_user_mount_t * vfs = get_vfs(lun); - uint32_t last_valid_sector = 0; - uint32_t sector_size = 0; - if (vfs == NULL || - disk_ioctl(vfs, GET_SECTOR_COUNT, &last_valid_sector) != RES_OK || - disk_ioctl(vfs, GET_SECTOR_SIZE, §or_size) != RES_OK) { - return NULL; - } - // Subtract one from the sector count to get the last valid sector. - last_valid_sector--; - - format_capa[lun][0] = (uint8_t)(last_valid_sector >> 24); - format_capa[lun][1] = (uint8_t)(last_valid_sector >> 16); - format_capa[lun][2] = (uint8_t)(last_valid_sector >> 8); - format_capa[lun][3] = (uint8_t)(last_valid_sector >> 0); - format_capa[lun][4] = (uint8_t)(sector_size >> 24); - format_capa[lun][5] = (uint8_t)(sector_size >> 16); - format_capa[lun][6] = (uint8_t)(sector_size >> 8); - format_capa[lun][7] = (uint8_t)(sector_size >> 0); - - // 8 byte response. First 4 bytes are last block address. Second 4 - // bytes are sector size. - return &format_capa[lun][0]; - } -} - -// USB transfer state. -volatile bool usb_busy; -volatile bool active_read; -volatile bool active_write; -volatile uint8_t active_lun; -volatile uint32_t active_addr; -volatile uint32_t active_nblocks; -volatile bool sector_loaded; -COMPILER_ALIGNED(4) uint8_t sector_buffer[512]; - -/** - * \brief Callback invoked when a new read blocks command received - * \param[in] lun logic unit number - * \param[in] addr start address of disk to be read - * \param[in] nblocks block amount to be read - * \return Operation status. - */ -int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - // Store transfer info so we can service it in the "background". - active_lun = lun; - active_addr = addr; - active_nblocks = nblocks; - active_read = true; - - return ERR_NONE; -} - -/** - * \brief Callback invoked when a new write blocks command received - * \param[in] lun logic unit number - * \param[in] addr start address of disk to be written - * \param[in] nblocks block amount to be written - * \return Operation status. - */ -int32_t usb_msc_new_write(uint8_t lun, uint32_t addr, uint32_t nblocks) { - if (lun > 1) { - return ERR_NOT_FOUND; - } - - fs_user_mount_t * vfs = get_vfs(lun); - // This is used to determine the writeability of the disk from USB. - if (vfs == NULL) { - return ERR_NOT_FOUND; - } - if (vfs->writeblocks[0] == MP_OBJ_NULL || - (vfs->flags & FSUSER_USB_WRITABLE) == 0) { - return ERR_DENIED; - } - - // Store transfer info so we can service it in the "background". - active_lun = lun; - active_addr = addr; - active_nblocks = nblocks; - active_write = true; - sector_loaded = false; - - // Return ERR_DENIED when the file system is read-only to the USB host. - - return ERR_NONE; -} - -/** - * \brief Callback invoked when a blocks transfer is done - * \param[in] lun logic unit number - * \return Operation status. - */ -int32_t usb_msc_xfer_done(uint8_t lun) { - if (lun > 1) { - return ERR_DENIED; - } - - CRITICAL_SECTION_ENTER(); - if (active_read) { - active_addr += 1; - active_nblocks--; - if (active_nblocks == 0) { - active_read = false; - } - } - - if (active_write) { - sector_loaded = true; - } - usb_busy = false; - CRITICAL_SECTION_LEAVE(); - - return ERR_NONE; -} - -// The start_read callback begins a read transaction which we accept -// but delay our response until the "main thread" calls -// usb_msc_background. Once it does, we read immediately from the -// drive into our cache and trigger the USB DMA to output the -// sector. Once the sector is transmitted, xfer_done will be called. -void usb_msc_background(void) { - // Check USB busy first because we never want to queue another transfer if it is. Checking - // active_read or active_write first leaves the possibility that they are true, an xfer done - // interrupt occurs (setting them false), turning off usb_busy and causing us to queue a - // spurious transfer. - if (usb_busy) { - return; - } - if (active_read) { - fs_user_mount_t * vfs = get_vfs(active_lun); - disk_read(vfs, sector_buffer, active_addr, 1); - CRITICAL_SECTION_ENTER(); - int32_t result = mscdf_xfer_blocks(true, sector_buffer, 1); - usb_busy = result == ERR_NONE; - CRITICAL_SECTION_LEAVE(); - } - if (active_write) { - if (sector_loaded) { - fs_user_mount_t * vfs = get_vfs(active_lun); - disk_write(vfs, sector_buffer, active_addr, 1); - // Since by getting here we assume the mount is read-only to - // MicroPython let's update the cached FatFs sector if it's the one - // we just wrote. - #if _MAX_SS != _MIN_SS - if (vfs->ssize == FILESYSTEM_BLOCK_SIZE) { - #else - // The compiler can optimize this away. - if (_MAX_SS == FILESYSTEM_BLOCK_SIZE) { - #endif - if (active_addr == vfs->fatfs.winsect && active_addr > 0) { - memcpy(vfs->fatfs.win, - sector_buffer, - FILESYSTEM_BLOCK_SIZE); - } - } - sector_loaded = false; - active_addr += 1; - active_nblocks--; - } - // Load more blocks from USB if they are needed. - if (active_nblocks > 0) { - // Turn off interrupts because with them on, - // usb_msc_xfer_done could be called before we update - // usb_busy. If that happened, we'd overwrite the fact that - // the transfer actually already finished. - CRITICAL_SECTION_ENTER(); - int32_t result = mscdf_xfer_blocks(false, sector_buffer, 1); - usb_busy = result == ERR_NONE; - CRITICAL_SECTION_LEAVE(); - } else { - mscdf_xfer_blocks(false, NULL, 0); - active_write = false; - // This write is complete, start the autoreload clock. - autoreload_start(); - } - } -} diff --git a/ports/esp8266/Makefile b/ports/esp8266/Makefile index 3b6cc1fb4..03d5a65cb 100644 --- a/ports/esp8266/Makefile +++ b/ports/esp8266/Makefile @@ -119,7 +119,6 @@ SRC_COMMON_HAL = \ multiterminal/__init__.c \ neopixel_write/__init__.c \ os/__init__.c \ - storage/__init__.c \ time/__init__.c \ board/__init__.c @@ -147,7 +146,6 @@ SRC_SHARED_MODULE = \ multiterminal/__init__.c \ os/__init__.c \ random/__init__.c \ - storage/__init__.c \ struct/__init__.c SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ diff --git a/ports/esp8266/mpconfigport.h b/ports/esp8266/mpconfigport.h index eca3f525d..435f2c5cd 100644 --- a/ports/esp8266/mpconfigport.h +++ b/ports/esp8266/mpconfigport.h @@ -162,7 +162,6 @@ extern const struct _mp_obj_module_t esp_module; extern const struct _mp_obj_module_t network_module; extern const struct _mp_obj_module_t os_module; extern const struct _mp_obj_module_t random_module; -extern const struct _mp_obj_module_t storage_module; extern const struct _mp_obj_module_t struct_module; extern const struct _mp_obj_module_t mp_module_lwip; extern const struct _mp_obj_module_t mp_module_machine; @@ -194,7 +193,6 @@ extern const struct _mp_obj_module_t neopixel_write_module; { MP_OBJ_NEW_QSTR(MP_QSTR_pulseio), (mp_obj_t)&pulseio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_busio), (mp_obj_t)&busio_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_bitbangio), (mp_obj_t)&bitbangio_module }, \ - { MP_OBJ_NEW_QSTR(MP_QSTR_storage), (mp_obj_t)&storage_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&struct_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_math), (mp_obj_t)&math_module }, \ diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 25ddebc57..8d0d6d000 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -29,6 +29,10 @@ FROZEN_MPY_DIR = freeze # include py core make definitions include ../../py/py.mk +ifneq ($(MCU_SUB_VARIANT),nrf52840) +USB = FALSE +endif + include $(TOP)/supervisor/supervisor.mk FATFS_DIR = lib/oofatfs @@ -51,7 +55,7 @@ INC += -I./bluetooth INC += -I./peripherals INC += -I../../lib/mp-readline INC += -I../../lib/tinyusb/src -INC += -I./usb +INC += -I../../supervisor/shared/usb NRF_DEFINES += -DCONFIG_GPIO_AS_PINRESET @@ -68,6 +72,9 @@ LDFLAGS += -Xlinker -Map=$(@:.elf=.map) LDFLAGS += -mthumb -mabi=aapcs -T $(LD_FILE) -L boards/ LDFLAGS += -Wl,--gc-sections +# TinyUSB defines +CFLAGS += -DCFG_TUSB_MCU=OPT_MCU_NRF5X -DCFG_TUD_CDC_RX_BUFSIZE=1024 -DCFG_TUD_CDC_TX_BUFSIZE=1024 -DCFG_TUD_MSC_BUFSIZE=4096 + #Debugging/Optimization ifeq ($(DEBUG), 1) #ASMFLAGS += -g -gtabs+ @@ -94,10 +101,16 @@ SRC_NRFX = $(addprefix nrfx/,\ drivers/src/nrfx_uarte.c \ ) +ifdef EXTERNAL_FLASH_DEVICES + ifeq ($(QSPI_FLASH_FILESYSTEM),1) + SRC_NRFX += nrfx/drivers/src/nrfx_qspi.c + endif +endif + + SRC_C += \ background.c \ fatfs_port.c \ - internal_flash.c \ mphalport.c \ tick.c \ board_busses.c \ @@ -147,7 +160,6 @@ SRC_COMMON_HAL += \ pulseio/PulseIn.c \ pulseio/PulseOut.c \ pulseio/__init__.c \ - storage/__init__.c \ supervisor/Runtime.c \ supervisor/__init__.c \ time/__init__.c \ @@ -185,14 +197,9 @@ SRC_BINDINGS_ENUMS += \ bleio/UUIDType.c endif -SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ - $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ - $(addprefix common-hal/, $(SRC_COMMON_HAL)) - SRC_SHARED_MODULE = \ os/__init__.c \ random/__init__.c \ - storage/__init__.c \ struct/__init__.c \ gamepad/__init__.c \ gamepad/GamePad.c \ @@ -201,44 +208,36 @@ SRC_SHARED_MODULE = \ bitbangio/OneWire.c \ bitbangio/SPI.c \ busio/OneWire.c \ + storage/__init__.c # uheap/__init__.c \ ustack/__init__.c -SRC_SHARED_BINDINGS = \ - struct/__init__.c \ - gamepad/__init__.c \ - gamepad/GamePad.c \ - bitbangio/__init__.c \ - bitbangio/I2C.c \ - bitbangio/SPI.c \ - bitbangio/OneWire.c \ - random/__init__.c \ - # USB source files for nrf52840 ifeq ($(MCU_SUB_VARIANT),nrf52840) SRC_C += \ - usb/usb.c \ - usb/usb_msc_flash.c \ - usb/usb_desc.c \ lib/tinyusb/src/portable/nordic/nrf5x/dcd_nrf5x.c \ lib/tinyusb/src/portable/nordic/nrf5x/hal_nrf5x.c \ lib/tinyusb/src/common/tusb_fifo.c \ + lib/tinyusb/src/device/control.c \ lib/tinyusb/src/device/usbd.c \ lib/tinyusb/src/class/msc/msc_device.c \ lib/tinyusb/src/class/cdc/cdc_device.c \ lib/tinyusb/src/class/hid/hid_device.c \ lib/tinyusb/src/tusb.c \ -SRC_COMMON_HAL += \ +SRC_SHARED_MODULE += \ usb_hid/__init__.c \ usb_hid/Device.c \ endif +SRC_COMMON_HAL_EXPANDED = $(addprefix shared-bindings/, $(SRC_COMMON_HAL)) \ + $(addprefix shared-bindings/, $(SRC_BINDINGS_ENUMS)) \ + $(addprefix common-hal/, $(SRC_COMMON_HAL)) -SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_BINDINGS)) \ +SRC_SHARED_MODULE_EXPANDED = $(addprefix shared-bindings/, $(SRC_SHARED_MODULE)) \ $(addprefix shared-module/, $(SRC_SHARED_MODULE)) SRC_S = supervisor/cpu.s @@ -346,9 +345,10 @@ dfu-gen: $(BUILD)/dfu-package.zip $(BUILD)/dfu-package.zip: $(BUILD)/$(OUTPUT_FILENAME).hex $(NRFUTIL) dfu genpkg --sd-req 0xFFFE --dev-type 0x0052 --application $^ $(BUILD)/dfu-package.zip +# You must have $^ here because it deduplicates entries in $(OBJ) $(BUILD)/$(OUTPUT_FILENAME).elf: $(OBJ) $(ECHO) "LINK $@" - $(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) -Wl,--start-group $(LIBS) -Wl,--end-group + $(Q)$(CC) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group $(Q)$(SIZE) $@ # List of sources for qstr extraction diff --git a/ports/nrf/README.md b/ports/nrf/README.md index 4bd865400..34e58cb78 100644 --- a/ports/nrf/README.md +++ b/ports/nrf/README.md @@ -61,7 +61,7 @@ To build and flash issue the following command inside the ports/nrf/ folder: First prepare the bluetooth folder by downloading Bluetooth LE stacks and headers: - ./drivers/bluetooth/download_ble_stack.sh + ./bluetooth/download_ble_stack.sh If the Bluetooth stacks has been downloaded, compile the target with the following command: diff --git a/ports/nrf/background.c b/ports/nrf/background.c index d19604f68..f614b6bd0 100644 --- a/ports/nrf/background.c +++ b/ports/nrf/background.c @@ -24,11 +24,12 @@ * THE SOFTWARE. */ -#include "tusb.h" +#ifdef NRF52840 +#include "supervisor/usb.h" +#endif void run_background_tasks(void) { -#ifdef NRF52840_XXAA - tusb_task(); - tud_cdc_write_flush(); -#endif + #ifdef NRF52840 + usb_background(); + #endif } diff --git a/ports/nrf/board_busses.c b/ports/nrf/board_busses.c index 91f0def6d..6d5cbd041 100644 --- a/ports/nrf/board_busses.c +++ b/ports/nrf/board_busses.c @@ -30,8 +30,8 @@ #include "shared-bindings/microcontroller/Pin.h" #include "supervisor/shared/translate.h" -#include "mpconfigboard.h" #include "nrf/pins.h" +#include "py/mpconfig.h" #include "py/runtime.h" #if !defined(DEFAULT_I2C_BUS_SDA) || !defined(DEFAULT_I2C_BUS_SCL) diff --git a/ports/nrf/boards/feather_nrf52840_express/board.c b/ports/nrf/boards/feather_nrf52840_express/board.c index a6d050fce..4421970ee 100644 --- a/ports/nrf/boards/feather_nrf52840_express/board.c +++ b/ports/nrf/boards/feather_nrf52840_express/board.c @@ -25,10 +25,8 @@ */ #include "boards/board.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h index bd6d4b244..68914c626 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.h @@ -25,6 +25,8 @@ * THE SOFTWARE. */ +#include "nrfx/hal/nrf_gpio.h" + #define FEATHER52840 #define MICROPY_HW_BOARD_NAME "Adafruit Feather nRF52840 Express" @@ -33,12 +35,12 @@ #define MICROPY_HW_NEOPIXEL (&pin_P0_13) -#define MICROPY_QSPI_DATA0 (&pin_P1_09) -#define MICROPY_QSPI_DATA1 (&pin_P0_11) -#define MICROPY_QSPI_DATA2 (&pin_P0_12) -#define MICROPY_QSPI_DATA3 (&pin_P0_14) -#define MICROPY_QSPI_SCK (&pin_P0_08) -#define MICROPY_QSPI_CS (&pin_P1_08) +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 9) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 11) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 12) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 14) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 8) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(1, 8) #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 @@ -49,14 +51,7 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -// TODO #include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -#define EXTERNAL_FLASH_DEVICES GD25Q16C - -#define EXTERNAL_FLASH_QSPI_DUAL - -// TODO include "external_flash/external_flash.h" +#define EXTERNAL_FLASH_QSPI_DUAL (1) #define BOARD_HAS_CRYSTAL 1 diff --git a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk index caf580ec4..f03109319 100644 --- a/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk +++ b/ports/nrf/boards/feather_nrf52840_express/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "Feather nRF52840 Express" +USB_MANUFACTURER = "Adafruit Industries LLC" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 @@ -14,3 +19,7 @@ else endif NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "GD25Q64C" diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/board.c b/ports/nrf/boards/makerdiary_nrf52840_mdk/board.c index a6d050fce..4421970ee 100644 --- a/ports/nrf/boards/makerdiary_nrf52840_mdk/board.c +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/board.c @@ -25,10 +25,8 @@ */ #include "boards/board.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h index b33fb2dd6..40b6487ec 100644 --- a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.h @@ -25,18 +25,20 @@ * THE SOFTWARE. */ +#include "nrfx/hal/nrf_gpio.h" + #define MAKERDIARYNRF52840MDK #define MICROPY_HW_BOARD_NAME "MakerDiary nRF52840 MDK" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "MakerDiary52840MDK" -#define MICROPY_QSPI_DATA0 (&pin_P1_05) -#define MICROPY_QSPI_DATA1 (&pin_P1_04) -#define MICROPY_QSPI_DATA2 (&pin_P1_02) -#define MICROPY_QSPI_DATA3 (&pin_P1_01) -#define MICROPY_QSPI_SCK (&pin_P1_03) -#define MICROPY_QSPI_CS (&pin_P1_06) +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 5) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 4) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(1, 2) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(1, 1) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(1, 3) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(1, 8) #define CIRCUITPY_AUTORELOAD_DELAY_MS 500 @@ -47,17 +49,6 @@ #define BOARD_FLASH_SIZE (FLASH_SIZE - 0x4000 - CIRCUITPY_INTERNAL_NVM_SIZE) -// TODO #include "external_flash/devices.h" - -#define EXTERNAL_FLASH_DEVICE_COUNT 1 -// Datasheet for when this is implemented: -// http://www.mxic.com.tw/Lists/Datasheet/Attachments/7428/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.4.pdf -#define EXTERNAL_FLASH_DEVICES MX25R6435F - -#define EXTERNAL_FLASH_QSPI_DUAL - -// TODO include "external_flash/external_flash.h" - #define BOARD_HAS_CRYSTAL 0 #define DEFAULT_UART_BUS_RX (&pin_P0_19) diff --git a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk index caf580ec4..84dff0bc4 100644 --- a/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk +++ b/ports/nrf/boards/makerdiary_nrf52840_mdk/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "nRF52840-MDK" +USB_MANUFACTURER = "makerdiary" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 @@ -14,3 +19,7 @@ else endif NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "MX25R6435F" diff --git a/ports/nrf/boards/pca10056/board.c b/ports/nrf/boards/pca10056/board.c index a6d050fce..4421970ee 100644 --- a/ports/nrf/boards/pca10056/board.c +++ b/ports/nrf/boards/pca10056/board.c @@ -25,10 +25,8 @@ */ #include "boards/board.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/pca10056/mpconfigboard.h b/ports/nrf/boards/pca10056/mpconfigboard.h index 00a73005c..83c3f66c1 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.h +++ b/ports/nrf/boards/pca10056/mpconfigboard.h @@ -24,6 +24,8 @@ * THE SOFTWARE. */ +#include "nrfx/hal/nrf_gpio.h" + #define MICROPY_HW_BOARD_NAME "PCA10056 nRF52840-DK" #define MICROPY_HW_MCU_NAME "nRF52840" #define MICROPY_PY_SYS_PLATFORM "nRF52840-DK" @@ -40,3 +42,24 @@ #define DEFAULT_UART_BUS_RX (&pin_P1_01) #define DEFAULT_UART_BUS_TX (&pin_P1_02) + +// Flash operation mode is determined by MICROPY_QSPI_DATAn pin configuration. +// A pin config is valid if it is defined and its value is not 0xFF. +// Quad mode: If all DATA0 --> DATA3 are valid +// Dual mode: If DATA0 and DATA1 are valid while either DATA2 and/or DATA3 are invalid +// Single mode: If only DATA0 is valid +#ifdef QSPI_FLASH_FILESYSTEM +#define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(0, 20) +#define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(0, 21) +#define MICROPY_QSPI_DATA2 NRF_GPIO_PIN_MAP(0, 22) +#define MICROPY_QSPI_DATA3 NRF_GPIO_PIN_MAP(0, 23) +#define MICROPY_QSPI_SCK NRF_GPIO_PIN_MAP(0, 19) +#define MICROPY_QSPI_CS NRF_GPIO_PIN_MAP(0, 17) +#endif + +#ifdef SPI_FLASH_FILESYSTEM +#define SPI_FLASH_MOSI_PIN &pin_P0_20 +#define SPI_FLASH_MISO_PIN &pin_P0_21 +#define SPI_FLASH_SCK_PIN &pin_P0_19 +#define SPI_FLASH_CS_PIN &pin_P0_17 +#endif diff --git a/ports/nrf/boards/pca10056/mpconfigboard.mk b/ports/nrf/boards/pca10056/mpconfigboard.mk index caf580ec4..49c708cff 100644 --- a/ports/nrf/boards/pca10056/mpconfigboard.mk +++ b/ports/nrf/boards/pca10056/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "PCA10056" +USB_MANUFACTURER = "Nordic Semiconductor" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 @@ -14,3 +19,7 @@ else endif NRF_DEFINES += -DNRF52840_XXAA -DNRF52840 + +QSPI_FLASH_FILESYSTEM = 1 +EXTERNAL_FLASH_DEVICE_COUNT = 1 +EXTERNAL_FLASH_DEVICES = "MX25R6435F" diff --git a/ports/nrf/boards/pca10059/board.c b/ports/nrf/boards/pca10059/board.c index cbb4ef3b6..4421970ee 100644 --- a/ports/nrf/boards/pca10059/board.c +++ b/ports/nrf/boards/pca10059/board.c @@ -24,14 +24,9 @@ * THE SOFTWARE. */ -#include <string.h> -#include <stdbool.h> #include "boards/board.h" -#include "nrfx.h" -#include "usb.h" void board_init(void) { - usb_init(); } bool board_requests_safe_mode(void) { diff --git a/ports/nrf/boards/pca10059/mpconfigboard.mk b/ports/nrf/boards/pca10059/mpconfigboard.mk index f399927fd..030c9a823 100644 --- a/ports/nrf/boards/pca10059/mpconfigboard.mk +++ b/ports/nrf/boards/pca10059/mpconfigboard.mk @@ -1,3 +1,8 @@ +USB_VID = 0x239A +USB_PID = 0x802A +USB_PRODUCT = "PCA10059" +USB_MANUFACTURER = "Nordic Semiconductor" + MCU_SERIES = m4 MCU_VARIANT = nrf52 MCU_SUB_VARIANT = nrf52840 diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c index f094b7f24..19bd4d1ba 100644 --- a/ports/nrf/common-hal/busio/SPI.c +++ b/ports/nrf/common-hal/busio/SPI.c @@ -59,12 +59,30 @@ STATIC spim_peripheral_t spim_peripherals[] = { #endif }; +STATIC bool never_reset[4]; + void spi_reset(void) { for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) { + if (never_reset[i]) { + continue; + } nrf_spim_disable(spim_peripherals[i].spim.p_reg); } } +void common_hal_busio_spi_never_reset(busio_spi_obj_t *self) { + for (size_t i = 0 ; i < MP_ARRAY_SIZE(spim_peripherals); i++) { + if (self->spim_peripheral == &spim_peripherals[i]) { + never_reset[i] = true; + + never_reset_pin_number(self->clock_pin_number); + never_reset_pin_number(self->MOSI_pin_number); + never_reset_pin_number(self->MISO_pin_number); + break; + } + } +} + // Convert frequency to clock-speed-dependent value. Choose the next lower baudrate if in between // available baudrates. static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate) { diff --git a/ports/nrf/common-hal/busio/UART.c b/ports/nrf/common-hal/busio/UART.c index b9e79381a..516a7747d 100644 --- a/ports/nrf/common-hal/busio/UART.c +++ b/ports/nrf/common-hal/busio/UART.c @@ -27,7 +27,7 @@ #include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/busio/UART.h" -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "py/gc.h" #include "py/mperrno.h" #include "py/runtime.h" diff --git a/ports/nrf/common-hal/digitalio/DigitalInOut.c b/ports/nrf/common-hal/digitalio/DigitalInOut.c index f05cf568f..0836962c6 100644 --- a/ports/nrf/common-hal/digitalio/DigitalInOut.c +++ b/ports/nrf/common-hal/digitalio/DigitalInOut.c @@ -30,6 +30,11 @@ #include "nrf_gpio.h" +void common_hal_digitalio_digitalinout_never_reset( + digitalio_digitalinout_obj_t *self) { + never_reset_pin_number(self->pin->number); +} + digitalinout_result_t common_hal_digitalio_digitalinout_construct( digitalio_digitalinout_obj_t *self, const mcu_pin_obj_t *pin) { claim_pin(pin); diff --git a/ports/nrf/common-hal/microcontroller/Pin.c b/ports/nrf/common-hal/microcontroller/Pin.c index 7a069eeda..0522bfef3 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.c +++ b/ports/nrf/common-hal/microcontroller/Pin.c @@ -45,13 +45,18 @@ bool speaker_enable_in_use; // Bit mask of claimed pins on each of up to two ports. nrf52832 has one port; nrf52840 has two. STATIC uint32_t claimed_pins[GPIO_COUNT]; +STATIC uint32_t never_reset_pins[GPIO_COUNT]; void reset_all_pins(void) { + return; for (size_t i = 0; i < GPIO_COUNT; i++) { - claimed_pins[i] = 0; + claimed_pins[i] = never_reset_pins[i]; } for (uint32_t pin = 0; pin < NUMBER_OF_PINS; ++pin) { + if (!(never_reset_pins[nrf_pin_port(pin)] & (1 << nrf_relative_pin_number(pin)))) { + continue; + } nrf_gpio_cfg_default(pin); } @@ -72,6 +77,7 @@ void reset_all_pins(void) { // Mark pin as free and return it to a quiescent state. void reset_pin_number(uint8_t pin_number) { + return; if (pin_number == NO_PIN) { return; } @@ -108,6 +114,11 @@ void reset_pin_number(uint8_t pin_number) { #endif } + +void never_reset_pin_number(uint8_t pin_number) { + never_reset_pins[nrf_pin_port(pin_number)] |= 1 << nrf_relative_pin_number(pin_number); +} + void claim_pin(const mcu_pin_obj_t* pin) { // Set bit in claimed_pins bitmask. claimed_pins[nrf_pin_port(pin->number)] |= 1 << nrf_relative_pin_number(pin->number); diff --git a/ports/nrf/common-hal/microcontroller/Pin.h b/ports/nrf/common-hal/microcontroller/Pin.h index 2cdf440b5..61be8bc35 100644 --- a/ports/nrf/common-hal/microcontroller/Pin.h +++ b/ports/nrf/common-hal/microcontroller/Pin.h @@ -44,6 +44,7 @@ void reset_all_pins(void); // need to store a full pointer. void reset_pin_number(uint8_t pin); void claim_pin(const mcu_pin_obj_t* pin); +void never_reset_pin_number(uint8_t pin_number); // Lower 5 bits of a pin number are the pin number in a port. // upper bits (just one bit for current chips) is port number. diff --git a/ports/nrf/common-hal/microcontroller/Processor.c b/ports/nrf/common-hal/microcontroller/Processor.c index 2ce3e8bf5..e4d9439c9 100644 --- a/ports/nrf/common-hal/microcontroller/Processor.c +++ b/ports/nrf/common-hal/microcontroller/Processor.c @@ -72,12 +72,7 @@ uint32_t common_hal_mcu_processor_get_frequency(void) { } void common_hal_mcu_processor_get_uid(uint8_t raw_id[]) { - - uint32_t* id_addresses[2] = {(uint32_t *) 0x060, (uint32_t *) 0x064}; - for (int i=0; i<2; i++) { - for (int k=0; k<4; k++) { - raw_id[4 * i + k] = (*(id_addresses[i]) >> k * 8) & 0xff; - } + ((uint32_t*) raw_id)[i] = NRF_FICR->DEVICEID[i]; } } diff --git a/ports/nrf/common-hal/pulseio/PulseIn.c b/ports/nrf/common-hal/pulseio/PulseIn.c index 950cc877d..3d6d266af 100644 --- a/ports/nrf/common-hal/pulseio/PulseIn.c +++ b/ports/nrf/common-hal/pulseio/PulseIn.c @@ -28,7 +28,7 @@ #include <stdint.h> -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "py/gc.h" #include "py/runtime.h" diff --git a/ports/nrf/common-hal/pulseio/PulseOut.c b/ports/nrf/common-hal/pulseio/PulseOut.c index 044c4d3a8..be5deca9f 100644 --- a/ports/nrf/common-hal/pulseio/PulseOut.c +++ b/ports/nrf/common-hal/pulseio/PulseOut.c @@ -28,7 +28,7 @@ #include <stdint.h> -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "nrf/pins.h" #include "nrf/timers.h" #include "py/gc.h" diff --git a/ports/nrf/common-hal/usb_hid/Device.h b/ports/nrf/common-hal/usb_hid/Device.h deleted file mode 100644 index 612423715..000000000 --- a/ports/nrf/common-hal/usb_hid/Device.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 hathach 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 COMMON_HAL_USB_HID_DEVICE_H -#define COMMON_HAL_USB_HID_DEVICE_H - -#include <stdint.h> -#include <stdbool.h> - -#include "py/obj.h" - -#ifdef __cplusplus - extern "C" { -#endif - -// 1 to enable device, 0 to disable -#define USB_HID_DEVICE_KEYBOARD 1 -#define USB_HID_DEVICE_MOUSE 1 -#define USB_HID_DEVICE_CONSUMER 1 -#define USB_HID_DEVICE_SYS_CONTROL 1 -#define USB_HID_DEVICE_GAMEPAD 1 -#define USB_HID_DEVICE_DIGITIZER 0 // not supported yet - -enum { - USB_HID_REPORT_ID_UNUSED = 0, - -#if USB_HID_DEVICE_KEYBOARD - USB_HID_REPORT_ID_KEYBOARD, -#endif - -#if USB_HID_DEVICE_MOUSE - USB_HID_REPORT_ID_MOUSE, -#endif - -#if USB_HID_DEVICE_CONSUMER - USB_HID_REPORT_ID_CONSUMER, -#endif - -#if USB_HID_DEVICE_SYS_CONTROL - USB_HID_REPORT_ID_SYS_CONTROL, -#endif - -#if USB_HID_DEVICE_GAMEPAD - USB_HID_REPORT_ID_GAMEPAD, -#endif - -#if USB_HID_DEVICE_DIGITIZER - USB_HID_REPORT_ID_DIGITIZER, -#endif -}; - -#define USB_HID_NUM_DEVICES (USB_HID_DEVICE_KEYBOARD + USB_HID_DEVICE_MOUSE + USB_HID_DEVICE_CONSUMER + \ - USB_HID_DEVICE_SYS_CONTROL + USB_HID_DEVICE_GAMEPAD + USB_HID_DEVICE_DIGITIZER ) - -typedef struct { - mp_obj_base_t base; - uint8_t* report_buffer; - uint8_t report_id; - uint8_t report_length; - uint8_t usage_page; - uint8_t usage; -} usb_hid_device_obj_t; - - -extern usb_hid_device_obj_t usb_hid_devices[]; - -#ifdef __cplusplus - } -#endif - -#endif /* COMMON_HAL_USB_HID_DEVICE_H */ diff --git a/ports/nrf/internal_flash.c b/ports/nrf/internal_flash.c deleted file mode 100644 index 812ef4d3f..000000000 --- a/ports/nrf/internal_flash.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2013, 2014 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * 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 "internal_flash.h" - -#include <stdint.h> -#include <string.h> - -#include "extmod/vfs.h" -#include "extmod/vfs_fat.h" -#include "py/mphal.h" -#include "py/obj.h" -#include "py/runtime.h" -#include "lib/oofatfs/ff.h" -#include "supervisor/shared/rgb_led_status.h" - -#include "nrf_nvmc.h" - -#ifdef BLUETOOTH_SD -#include "nrf_sdm.h" -#endif - -// defined in linker -extern uint32_t __fatfs_flash_start_addr[]; -extern uint32_t __fatfs_flash_length[]; - -#define NO_CACHE 0xffffffff -#define FL_PAGE_SZ 4096 - -uint8_t _flash_cache[FL_PAGE_SZ] __attribute__((aligned(4))); -uint32_t _flash_page_addr = NO_CACHE; - - -/*------------------------------------------------------------------*/ -/* Internal Flash API - *------------------------------------------------------------------*/ -static inline uint32_t lba2addr(uint32_t block) { - return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE; -} - -void internal_flash_init(void) { - // Activity LED for flash writes. -#ifdef MICROPY_HW_LED_MSC - struct port_config pin_conf; - port_get_config_defaults(&pin_conf); - - pin_conf.direction = PORT_PIN_DIR_OUTPUT; - port_pin_set_config(MICROPY_HW_LED_MSC, &pin_conf); - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif -} - -uint32_t internal_flash_get_block_size(void) { - return FILESYSTEM_BLOCK_SIZE; -} - -uint32_t internal_flash_get_block_count(void) { - return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; -} - -// TODO support flashing with SD enabled -void internal_flash_flush(void) { - if (_flash_page_addr == NO_CACHE) return; - - // Skip if data is the same - if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) { -// _is_flashing = true; - nrf_nvmc_page_erase(_flash_page_addr); - nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); - } - - _flash_page_addr = NO_CACHE; -} - -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { - uint32_t src = lba2addr(block); - memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); - return 0; // success -} - -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) { - -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, true); -#endif - - while (num_blocks) { - uint32_t const addr = lba2addr(lba); - uint32_t const page_addr = addr & ~(FL_PAGE_SZ - 1); - - uint32_t count = 8 - (lba % 8); // up to page boundary - count = MIN(num_blocks, count); - - if (page_addr != _flash_page_addr) { - internal_flash_flush(); - - // writing previous cached data, skip current data until flashing is done - // tinyusb stack will invoke write_block() with the same parameters later on - // if ( _is_flashing ) return; - - _flash_page_addr = page_addr; - memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ); - } - - memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE); - - // adjust for next run - lba += count; - src += count * FILESYSTEM_BLOCK_SIZE; - num_blocks -= count; - } - -#ifdef MICROPY_HW_LED_MSC - port_pin_set_output_level(MICROPY_HW_LED_MSC, false); -#endif - - return 0; // success -} - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t internal_flash_obj = {&internal_flash_type}; - -STATIC mp_obj_t internal_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&internal_flash_obj; -} - -STATIC mp_obj_t internal_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = internal_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_readblocks_obj, internal_flash_obj_readblocks); - -STATIC mp_obj_t internal_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = internal_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_writeblocks_obj, internal_flash_obj_writeblocks); - -STATIC mp_obj_t internal_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: internal_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: internal_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(internal_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(internal_flash_obj_ioctl_obj, internal_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t internal_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&internal_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&internal_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&internal_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(internal_flash_obj_locals_dict, internal_flash_obj_locals_dict_table); - -const mp_obj_type_t internal_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_InternalFlash, - .make_new = internal_flash_obj_make_new, - .locals_dict = (mp_obj_t)&internal_flash_obj_locals_dict, -}; - -/*------------------------------------------------------------------*/ -/* Flash API - *------------------------------------------------------------------*/ - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - -// vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&internal_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->readblocks[2] = (mp_obj_t)internal_flash_read_blocks; // native version - - vfs->writeblocks[0] = (mp_obj_t)&internal_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&internal_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)internal_flash_write_blocks; // native version - - vfs->u.ioctl[0] = (mp_obj_t)&internal_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&internal_flash_obj; -} - -void flash_flush(void) { - internal_flash_flush(); -} diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index 8b193fb59..c9c03427f 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -58,7 +58,7 @@ #define MICROPY_FATFS_LFN_CODE_PAGE (437) /* 1=SFN/ANSI 437=LFN/U.S.(OEM) */ #define MICROPY_FATFS_USE_LABEL (1) #define MICROPY_FATFS_RPATH (2) -#define MICROPY_FATFS_MULTI_PARTITION (0) +#define MICROPY_FATFS_MULTI_PARTITION (1) #define MICROPY_FATFS_NUM_PERSISTENT (1) //#define MICROPY_FATFS_MAX_SS (4096) @@ -216,9 +216,12 @@ extern const struct _mp_obj_module_t bleio_module; #define MP_STATE_PORT MP_STATE_VM +#include "supervisor/flash_root_pointers.h" + #define MICROPY_PORT_ROOT_POINTERS \ const char *readline_hist[8]; \ mp_obj_t gamepad_singleton; \ + FLASH_ROOT_POINTERS \ // We need to provide a declaration/definition of alloca() #include <alloca.h> diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk index 17304b783..f43e29fce 100644 --- a/ports/nrf/mpconfigport.mk +++ b/ports/nrf/mpconfigport.mk @@ -5,3 +5,4 @@ MPY_TOOL_LONGINT_IMPL = -mlongint-impl=mpz INTERNAL_LIBM = (1) +USB_SERIAL_NUMBER_LENGTH = 16 diff --git a/ports/nrf/mphalport.c b/ports/nrf/mphalport.c index e9a8722c6..73f38bada 100644 --- a/ports/nrf/mphalport.c +++ b/ports/nrf/mphalport.c @@ -31,86 +31,6 @@ #include "py/mpstate.h" #include "py/gc.h" -#if (MICROPY_PY_BLE_NUS == 0) - -#if !defined( NRF52840_XXAA) -int mp_hal_stdin_rx_chr(void) { - uint8_t data; - nrfx_uarte_rx(&serial_instance, &data, 1); - return data; -} - -bool mp_hal_stdin_any(void) { - return nrf_uarte_event_check(serial_instance.p_reg, NRF_UARTE_EVENT_RXDRDY); -} - -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { - if (len == 0) { - return; - } - - // EasyDMA can only access SRAM - uint8_t * tx_buf = (uint8_t*) str; - if ( !nrfx_is_in_ram(str) ) { - tx_buf = (uint8_t *) gc_alloc(len, false, false); - memcpy(tx_buf, str, len); - } - - nrfx_uarte_tx(&serial_instance, tx_buf, len); - - if ( !nrfx_is_in_ram(str) ) { - gc_free(tx_buf); - } -} - -#else - -#include "tusb.h" - -int mp_hal_stdin_rx_chr(void) { - for (;;) { - #ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP - #endif - // if (reload_requested) { - // return CHAR_CTRL_D; - // } - - if (tud_cdc_available()) { - #ifdef MICROPY_HW_LED_RX - gpio_toggle_pin_level(MICROPY_HW_LED_RX); - #endif - return tud_cdc_read_char(); - } - } - - return 0; -} - -bool mp_hal_stdin_any(void) { - return tud_cdc_available() > 0; -} - -void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) { - - #ifdef MICROPY_HW_LED_TX - gpio_toggle_pin_level(MICROPY_HW_LED_TX); - #endif - - #ifdef CIRCUITPY_BOOT_OUTPUT_FILE - if (boot_output_file != NULL) { - UINT bytes_written = 0; - f_write(boot_output_file, str, len, &bytes_written); - } - #endif - - tud_cdc_write(str, len); -} - -#endif // USB - -#endif // MICROPY_PY_BLE_NUS - /*------------------------------------------------------------------*/ /* delay *------------------------------------------------------------------*/ @@ -129,4 +49,3 @@ void mp_hal_delay_ms(mp_uint_t delay) { // TODO(tannewt): Go to sleep for a little while while we wait. } } - diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index 69b8e6a0c..1d3085e2b 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -37,6 +37,9 @@ #define NRFX_SPIM_DEFAULT_CONFIG_IRQ_PRIORITY 7 #define NRFX_SPIM_MISO_PULL_CFG 1 +// QSPI +#define NRFX_QSPI_ENABLED 1 + // TWI aka. I2C; enable TWIM0 and TWIM1 (no conflict with SPIM choices) #define NRFX_TWIM_ENABLED 1 #define NRFX_TWIM0_ENABLED 1 diff --git a/ports/nrf/peripherals/nrf/timers.c b/ports/nrf/peripherals/nrf/timers.c index 0027d526f..7f7a003d3 100644 --- a/ports/nrf/peripherals/nrf/timers.c +++ b/ports/nrf/peripherals/nrf/timers.c @@ -31,7 +31,7 @@ #include "nrfx.h" #include "nrfx_timer.h" -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "py/runtime.h" STATIC nrfx_timer_t nrfx_timers[] = { diff --git a/ports/nrf/supervisor/filesystem.c b/ports/nrf/supervisor/filesystem.c deleted file mode 100644 index b6611417d..000000000 --- a/ports/nrf/supervisor/filesystem.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * 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 "extmod/vfs_fat.h" -#include "lib/oofatfs/ff.h" -#include "lib/oofatfs/diskio.h" - -#include "py/mpstate.h" - -#include "internal_flash.h" - -static mp_vfs_mount_t _mp_vfs; -static fs_user_mount_t _internal_vfs; - - -void filesystem_init(bool create_allowed, bool force_create) { - // init the vfs object - fs_user_mount_t *int_vfs = &_internal_vfs; - int_vfs->flags = 0; - flash_init_vfs(int_vfs); - - // try to mount the flash - FRESULT res = f_mount(&int_vfs->fatfs); - - if ((res == FR_NO_FILESYSTEM && create_allowed) || force_create) { - // no filesystem so create a fresh one - uint8_t working_buf[_MAX_SS]; - res = f_mkfs(&int_vfs->fatfs, FM_FAT | FM_SFD, 4096, working_buf, sizeof(working_buf)); - // Flush the new file system to make sure its repaired immediately. - flash_flush(); - if (res != FR_OK) { - return; - } - - // set label - f_setlabel(&int_vfs->fatfs, "CIRCUITPY"); - - // create lib folder - f_mkdir(&int_vfs->fatfs, "/lib"); - - flash_flush(); - } else if (res != FR_OK) { - return; - } - - mp_vfs_mount_t *mp_vfs = &_mp_vfs; - mp_vfs->str = "/"; - mp_vfs->len = 1; - mp_vfs->obj = MP_OBJ_FROM_PTR(int_vfs); - mp_vfs->next = NULL; - MP_STATE_VM(vfs_mount_table) = mp_vfs; - - // The current directory is used as the boot up directory. - // It is set to the internal flash filesystem by default. - MP_STATE_PORT(vfs_cur) = mp_vfs; -} - -void filesystem_flush(void) { - flash_flush(); -} - -void filesystem_writable_by_python(bool writable) { - fs_user_mount_t *vfs = &_internal_vfs; - - if (writable) { - vfs->flags |= FSUSER_USB_WRITABLE; - } else { - vfs->flags &= ~FSUSER_USB_WRITABLE; - } -} - -bool filesystem_present(void) { - return true; -} diff --git a/ports/nrf/supervisor/internal_flash.c b/ports/nrf/supervisor/internal_flash.c new file mode 100644 index 000000000..a648afa17 --- /dev/null +++ b/ports/nrf/supervisor/internal_flash.c @@ -0,0 +1,121 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * 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 "supervisor/flash.h" + +#include <stdint.h> +#include <string.h> + +#include "extmod/vfs.h" +#include "extmod/vfs_fat.h" +#include "py/mphal.h" +#include "py/obj.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" + +#include "nrf_nvmc.h" + +#ifdef BLUETOOTH_SD +#include "nrf_sdm.h" +#endif + +// defined in linker +extern uint32_t __fatfs_flash_start_addr[]; +extern uint32_t __fatfs_flash_length[]; + +#define NO_CACHE 0xffffffff +#define FL_PAGE_SZ 4096 + +uint8_t _flash_cache[FL_PAGE_SZ] __attribute__((aligned(4))); +uint32_t _flash_page_addr = NO_CACHE; + + +/*------------------------------------------------------------------*/ +/* Internal Flash API + *------------------------------------------------------------------*/ +static inline uint32_t lba2addr(uint32_t block) { + return ((uint32_t)__fatfs_flash_start_addr) + block * FILESYSTEM_BLOCK_SIZE; +} + +void supervisor_flash_init(void) { +} + +uint32_t supervisor_flash_get_block_size(void) { + return FILESYSTEM_BLOCK_SIZE; +} + +uint32_t supervisor_flash_get_block_count(void) { + return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; +} + +// TODO support flashing with SD enabled +void supervisor_flash_flush(void) { + if (_flash_page_addr == NO_CACHE) return; + + // Skip if data is the same + if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) { +// _is_flashing = true; + nrf_nvmc_page_erase(_flash_page_addr); + nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); + } + + _flash_page_addr = NO_CACHE; +} + +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t num_blocks) { + uint32_t src = lba2addr(block); + memcpy(dest, (uint8_t*) src, FILESYSTEM_BLOCK_SIZE*num_blocks); + return 0; // success +} + +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32_t num_blocks) { + while (num_blocks) { + uint32_t const addr = lba2addr(lba); + uint32_t const page_addr = addr & ~(FL_PAGE_SZ - 1); + + uint32_t count = 8 - (lba % 8); // up to page boundary + count = MIN(num_blocks, count); + + if (page_addr != _flash_page_addr) { + supervisor_flash_flush(); + + // writing previous cached data, skip current data until flashing is done + // tinyusb stack will invoke write_block() with the same parameters later on + // if ( _is_flashing ) return; + + _flash_page_addr = page_addr; + memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ); + } + + memcpy(_flash_cache + (addr & (FL_PAGE_SZ - 1)), src, count * FILESYSTEM_BLOCK_SIZE); + + // adjust for next run + lba += count; + src += count * FILESYSTEM_BLOCK_SIZE; + num_blocks -= count; + } + + return 0; // success +} diff --git a/ports/nrf/internal_flash.h b/ports/nrf/supervisor/internal_flash.h index 3811815e2..adcb9bbc2 100644 --- a/ports/nrf/internal_flash.h +++ b/ports/nrf/supervisor/internal_flash.h @@ -29,7 +29,7 @@ #include <stdbool.h> #include <stdint.h> -#include "mpconfigport.h" +#include "py/mpconfig.h" #define FLASH_ROOT_POINTERS @@ -39,21 +39,4 @@ #define INTERNAL_FLASH_SYSTICK_MASK (0x1ff) // 512ms #define INTERNAL_FLASH_IDLE_TICK(tick) (((tick) & INTERNAL_FLASH_SYSTICK_MASK) == 2) -void internal_flash_init(void); -uint32_t internal_flash_get_block_size(void); -uint32_t internal_flash_get_block_count(void); -void internal_flash_irq_handler(void); -void internal_flash_flush(void); - -// these return 0 on success, non-zero on error -mp_uint_t internal_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); -mp_uint_t internal_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); - -extern const struct _mp_obj_type_t internal_flash_type; - -struct _fs_user_mount_t; - -void flash_init_vfs(struct _fs_user_mount_t *vfs); -void flash_flush(void); - #endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_H diff --git a/ports/nrf/supervisor/internal_flash_root_pointers.h b/ports/nrf/supervisor/internal_flash_root_pointers.h new file mode 100644 index 000000000..cc6074585 --- /dev/null +++ b/ports/nrf/supervisor/internal_flash_root_pointers.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H + +#define FLASH_ROOT_POINTERS + +#endif // MICROPY_INCLUDED_NRF_INTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index f98b05f5a..fcb3ae55c 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -89,6 +89,13 @@ void reset_port(void) { reset_all_pins(); } +void reset_to_bootloader(void) { + enum { DFU_MAGIC_SERIAL = 0x4e }; + + NRF_POWER->GPREGRET = DFU_MAGIC_SERIAL; + NVIC_SystemReset(); +} + void HardFault_Handler(void) { diff --git a/ports/nrf/supervisor/qspi_flash.c b/ports/nrf/supervisor/qspi_flash.c new file mode 100644 index 000000000..24b06c420 --- /dev/null +++ b/ports/nrf/supervisor/qspi_flash.c @@ -0,0 +1,146 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * Copyright (c) 2018 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 "supervisor/spi_flash_api.h" + +#include <stdint.h> +#include <string.h> + +#include "py/mpconfig.h" // for EXTERNAL_FLASH_QSPI_DUAL +#include "nrfx_qspi.h" + +#include "shared-bindings/microcontroller/__init__.h" + +#include "supervisor/shared/external_flash/common_commands.h" +#include "supervisor/shared/external_flash/qspi_flash.h" + +bool spi_flash_command(uint8_t command) { + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = 0, + .length = 0, + .io2_level = true, + .io3_level = true, + .wipwait = false, + .wren = false + }; + cinstr_cfg.opcode = command; + cinstr_cfg.length = 1; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL); + return true; +} + +bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) { + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = command, + .length = length + 1, + .io2_level = true, + .io3_level = true, + .wipwait = false, + .wren = false + }; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, response); + return true; +} + +bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { + nrf_qspi_cinstr_conf_t cinstr_cfg = { + .opcode = command, + .length = length + 1, + .io2_level = true, + .io3_level = true, + .wipwait = false, + .wren = false // We do this manually. + }; + nrfx_qspi_cinstr_xfer(&cinstr_cfg, data, NULL); + return true; +} + +bool spi_flash_sector_command(uint8_t command, uint32_t address) { + if (command != CMD_SECTOR_ERASE) { + return false; + } + return nrfx_qspi_erase(NRF_QSPI_ERASE_LEN_4KB, address) == NRFX_SUCCESS; +} + +bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { + return nrfx_qspi_write(data, length, address) == NRFX_SUCCESS; +} + +bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { + nrfx_qspi_read(data, length, address); + return true; +} + +void spi_flash_init(void) { + // Init QSPI flash + nrfx_qspi_config_t qspi_cfg = { + .xip_offset = 0, + .pins = { + .sck_pin = MICROPY_QSPI_SCK, + .csn_pin = MICROPY_QSPI_CS, + .io0_pin = MICROPY_QSPI_DATA0, + .io1_pin = NRF_QSPI_PIN_NOT_CONNECTED, + .io2_pin = NRF_QSPI_PIN_NOT_CONNECTED, + .io3_pin = NRF_QSPI_PIN_NOT_CONNECTED, + + }, + .prot_if = { + .readoc = NRF_QSPI_READOC_FASTREAD, + .writeoc = NRF_QSPI_WRITEOC_PP, + .addrmode = NRF_QSPI_ADDRMODE_24BIT, + .dpmconfig = false + }, + .phy_if = { + .sck_freq = NRF_QSPI_FREQ_32MDIV16, + .sck_delay = 10, // min time CS must stay high before going low again. in unit of 62.5 ns + .spi_mode = NRF_QSPI_MODE_0, + .dpmen = false + }, + .irq_priority = 7, + }; + +#if EXTERNAL_FLASH_QSPI_DUAL + qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1; + qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ2O; + qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP2O; +#else + qspi_cfg.pins.io1_pin = MICROPY_QSPI_DATA1; + qspi_cfg.pins.io2_pin = MICROPY_QSPI_DATA2; + qspi_cfg.pins.io3_pin = MICROPY_QSPI_DATA3; + qspi_cfg.prot_if.readoc = NRF_QSPI_READOC_READ4IO; + qspi_cfg.prot_if.writeoc = NRF_QSPI_WRITEOC_PP4IO; +#endif + + // No callback for blocking API + nrfx_qspi_init(&qspi_cfg, NULL, NULL); +} + +void spi_flash_init_device(const external_flash_device* device) { + check_quad_enable(device); + + // TODO(tannewt): Adjust the speed for the found device. +} diff --git a/ports/nrf/supervisor/serial.c b/ports/nrf/supervisor/serial.c index c7744fd79..6fd89eb3e 100644 --- a/ports/nrf/supervisor/serial.c +++ b/ports/nrf/supervisor/serial.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2017, 2018 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 @@ -26,9 +26,12 @@ #include "py/mphal.h" +#include "supervisor/serial.h" + #if (MICROPY_PY_BLE_NUS == 1) #include "ble_uart.h" #else +#include <string.h> #include "nrf_gpio.h" #include "nrfx_uarte.h" #endif @@ -89,39 +92,36 @@ bool serial_connected(void) { } char serial_read(void) { - return (char) mp_hal_stdin_rx_chr(); + uint8_t data; + nrfx_uarte_rx(&serial_instance, &data, 1); + return data; } bool serial_bytes_available(void) { - return mp_hal_stdin_any(); + return nrf_uarte_event_check(serial_instance.p_reg, NRF_UARTE_EVENT_RXDRDY); } -void serial_write(const char *text) { - mp_hal_stdout_tx_str(text); -} - -#else - -#include "tusb.h" - -void serial_init(void) { - // usb is already initialized in board_init() +void serial_write(const char* text) { + serial_write_substring(text, strlen(text)); } -bool serial_connected(void) { - return tud_cdc_connected(); -} +void serial_write_substring(const char *text, uint32_t len) { + if (len == 0) { + return; + } -char serial_read(void) { - return (char) tud_cdc_read_char(); -} + // EasyDMA can only access SRAM + uint8_t * tx_buf = (uint8_t*) text; + if ( !nrfx_is_in_ram(text) ) { + tx_buf = (uint8_t *) m_malloc(len, false); + memcpy(tx_buf, text, len); + } -bool serial_bytes_available(void) { - return tud_cdc_available() > 0; -} + nrfx_uarte_tx(&serial_instance, tx_buf, len); -void serial_write(const char* text) { - tud_cdc_write(text, strlen(text)); + if ( !nrfx_is_in_ram(text) ) { + m_free(tx_buf); + } } #endif diff --git a/ports/nrf/supervisor/usb.c b/ports/nrf/supervisor/usb.c new file mode 100644 index 000000000..a67c9311a --- /dev/null +++ b/ports/nrf/supervisor/usb.c @@ -0,0 +1,83 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach for Adafruit Industries + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "nrfx.h" +#include "nrfx_power.h" +#include "tick.h" +#include "supervisor/usb.h" +#include "lib/utils/interrupt_char.h" +#include "lib/mp-readline/readline.h" + +#ifdef SOFTDEVICE_PRESENT +#include "nrf_sdm.h" +#include "nrf_soc.h" +#endif + +/* tinyusb function that handles power event (detected, ready, removed) + * We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. + */ +extern void tusb_hal_nrf_power_event(uint32_t event); + +void init_usb_hardware(void) { + + // USB power may already be ready at this time -> no event generated + // We need to invoke the handler based on the status initially + uint32_t usb_reg; + +#ifdef SOFTDEVICE_PRESENT + uint8_t sd_en = false; + (void) sd_softdevice_is_enabled(&sd_en); + + if ( sd_en ) { + sd_power_usbdetected_enable(true); + sd_power_usbpwrrdy_enable(true); + sd_power_usbremoved_enable(true); + + sd_power_usbregstatus_get(&usb_reg); + }else +#endif + { + // Power module init + const nrfx_power_config_t pwr_cfg = { 0 }; + nrfx_power_init(&pwr_cfg); + + // Register tusb function as USB power handler + const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event }; + nrfx_power_usbevt_init(&config); + + nrfx_power_usbevt_enable(); + + usb_reg = NRF_POWER->USBREGSTATUS; + } + + if ( usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); + } + + if ( usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { + tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); + } +} diff --git a/ports/nrf/tick.h b/ports/nrf/tick.h index 73f17d703..838e9fbea 100644 --- a/ports/nrf/tick.h +++ b/ports/nrf/tick.h @@ -26,7 +26,7 @@ #ifndef MICROPY_INCLUDED_NRF_TICK_H #define MICROPY_INCLUDED_NRF_TICK_H -#include "mpconfigport.h" +#include "py/mpconfig.h" #include <stdint.h> diff --git a/ports/nrf/usb/usb_desc.c b/ports/nrf/usb/usb_desc.c deleted file mode 100644 index 10d603528..000000000 --- a/ports/nrf/usb/usb_desc.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 hathach 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 "usb_desc.h" -#include "common-hal/usb_hid/Device.h" - -//--------------------------------------------------------------------+ -// MACRO TYPEDEF CONSTANT ENUM DECLARATION -//--------------------------------------------------------------------+ -#define USB_VID 0x239A - -/* Note: different class combination e.g CDC and (CDC + MSC) should have different - * PID since Host OS will "remembered" device driver after the first plug */ -#define USB_PID 0x802A - -/*------------- Interface Numbering -------------*/ -enum { - ITF_NUM_CDC = 0 , - ITF_NUM_CDC_DATA , - ITF_NUM_MSC , - ITF_NUM_HID_GEN , - ITF_NUM_TOTAL -}; - -enum { - ITF_STR_LANGUAGE = 0 , - ITF_STR_MANUFACTURER , - ITF_STR_PRODUCT , - ITF_STR_SERIAL , - ITF_STR_CDC , - ITF_STR_MSC , - ITF_STR_HID -}; - -/*------------- Endpoint Numbering & Size -------------*/ -#define _EP_IN(x) (0x80 | (x)) -#define _EP_OUT(x) (x) - -// CDC -#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 ) -#define EP_CDC_NOTIF_SIZE 8 - -#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 ) -#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 ) - -// Mass Storage -#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 ) -#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 ) - -// HID composite = keyboard + mouse + gamepad + etc ... -#define EP_HID_GEN _EP_IN ( ITF_NUM_HID_GEN+1 ) -#define EP_HID_GEN_SIZE 16 - -//--------------------------------------------------------------------+ -// STRING DESCRIPTORS -//--------------------------------------------------------------------+ - -uint16_t usb_desc_str_serial[1+16] = { TUD_DESC_STR_HEADER(16) }; - -// array of pointer to string descriptors -uint16_t const * const string_desc_arr [] = -{ - // 0 index is supported language = English - TUD_DESC_STRCONV(0x0409), - - // 1 Manufacturer - TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'), - - // 2 Product - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','n','R','F','5','2'), - - // 3 Serials TODO use chip ID - usb_desc_str_serial, - - // 4 CDC Interface - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','S','e','r','i','a','l'), - - // 5 MSC Interface - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','S','t','o','r','a','g','e'), - - // 6 HID Interface - TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','H','I','D'), - - // Custom Interface -// TUD_DESC_STRCONV('C','i','r','c','u','i','t','P','y',' ','C','u','s','t','o','m') -}; - - -//--------------------------------------------------------------------+ -// Device Descriptor -//--------------------------------------------------------------------+ -tusb_desc_device_t const usb_desc_dev = -{ - .bLength = sizeof(tusb_desc_device_t), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - - #if CFG_TUD_CDC - // Use Interface Association Descriptor (IAD) for CDC - // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - #else - .bDeviceClass = 0x00, - .bDeviceSubClass = 0x00, - .bDeviceProtocol = 0x00, - #endif - - .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, - - .idVendor = USB_VID, - .idProduct = USB_PID, - .bcdDevice = 0x0100, - - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - - .bNumConfigurations = 0x01 // TODO multiple configurations -}; - -//--------------------------------------------------------------------+ -// HID Report Descriptor -//--------------------------------------------------------------------+ -uint8_t const usb_desc_hid_generic_report[] = -{ -#if USB_HID_DEVICE_KEYBOARD - HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(USB_HID_REPORT_ID_KEYBOARD), ), -#endif - -#if USB_HID_DEVICE_MOUSE - HID_REPORT_DESC_MOUSE( HID_REPORT_ID(USB_HID_REPORT_ID_MOUSE), ), -#endif - -#if USB_HID_DEVICE_CONSUMER - HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(USB_HID_REPORT_ID_CONSUMER), ), -#endif - -#if USB_HID_DEVICE_SYS_CONTROL - HID_REPORT_DESC_SYSTEM_CONTROL( HID_REPORT_ID(USB_HID_REPORT_ID_SYS_CONTROL ), ), -#endif - -#if USB_HID_DEVICE_GAMEPAD - HID_REPORT_DESC_GAMEPAD( HID_REPORT_ID(USB_HID_REPORT_ID_GAMEPAD ), ) -#endif - -}; - -//--------------------------------------------------------------------+ -// Configuration Descriptor -//--------------------------------------------------------------------+ -usb_desc_cfg_t const usb_desc_cfg = -{ - .config = - { - .bLength = sizeof(tusb_desc_configuration_t), - .bDescriptorType = TUSB_DESC_CONFIGURATION, - .wTotalLength = sizeof(usb_desc_cfg_t), - .bNumInterfaces = ITF_NUM_TOTAL, - .bConfigurationValue = 1, - .iConfiguration = 0x00, - .bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER, - .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100) - }, - - // IAD points to CDC Interfaces - .cdc = - { - .iad = - { - .bLength = sizeof(tusb_desc_interface_assoc_t), - .bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION, - - .bFirstInterface = ITF_NUM_CDC, - .bInterfaceCount = 2, - - .bFunctionClass = TUSB_CLASS_CDC, - .bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, - .iFunction = 0 - }, - - //------------- CDC Communication Interface -------------// - .comm_itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_CDC, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = TUSB_CLASS_CDC, - .bInterfaceSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, - .bInterfaceProtocol = CDC_COMM_PROTOCOL_ATCOMMAND, - .iInterface = ITF_STR_CDC - }, - - .header = - { - .bLength = sizeof(cdc_desc_func_header_t), - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_HEADER, - .bcdCDC = 0x0120 - }, - - .call = - { - .bLength = sizeof(cdc_desc_func_call_management_t), - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_CALL_MANAGEMENT, - .bmCapabilities = { 0 }, - .bDataInterface = ITF_NUM_CDC+1, - }, - - .acm = - { - .bLength = sizeof(cdc_desc_func_acm_t), - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, - .bmCapabilities = { // 0x02 - .support_line_request = 1, - } - }, - - .union_func = - { - .bLength = sizeof(cdc_desc_func_union_t), // plus number of - .bDescriptorType = TUSB_DESC_CLASS_SPECIFIC, - .bDescriptorSubType = CDC_FUNC_DESC_UNION, - .bControlInterface = ITF_NUM_CDC, - .bSubordinateInterface = ITF_NUM_CDC+1, - }, - - .ep_notif = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_CDC_NOTIF, - .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT }, - .wMaxPacketSize = { .size = EP_CDC_NOTIF_SIZE }, - .bInterval = 0x10 - }, - - //------------- CDC Data Interface -------------// - .data_itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_CDC+1, - .bAlternateSetting = 0x00, - .bNumEndpoints = 2, - .bInterfaceClass = TUSB_CLASS_CDC_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0x00 - }, - - .ep_out = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_CDC_OUT, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE }, - .bInterval = 0 - }, - - .ep_in = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_CDC_IN, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE }, - .bInterval = 0 - }, - }, - - //------------- Mass Storage-------------// - .msc = - { - .itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_MSC, - .bAlternateSetting = 0x00, - .bNumEndpoints = 2, - .bInterfaceClass = TUSB_CLASS_MSC, - .bInterfaceSubClass = MSC_SUBCLASS_SCSI, - .bInterfaceProtocol = MSC_PROTOCOL_BOT, - .iInterface = ITF_STR_MSC - }, - - .ep_out = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_MSC_OUT, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE}, - .bInterval = 1 - }, - - .ep_in = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_MSC_IN, - .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE}, - .bInterval = 1 - } - }, - - //------------- HID Generic Multiple report -------------// - .hid_generic = - { - .itf = - { - .bLength = sizeof(tusb_desc_interface_t), - .bDescriptorType = TUSB_DESC_INTERFACE, - .bInterfaceNumber = ITF_NUM_HID_GEN, - .bAlternateSetting = 0x00, - .bNumEndpoints = 1, - .bInterfaceClass = TUSB_CLASS_HID, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = ITF_STR_HID - }, - - .hid_desc = - { - .bLength = sizeof(tusb_hid_descriptor_hid_t), - .bDescriptorType = HID_DESC_TYPE_HID, - .bcdHID = 0x0111, - .bCountryCode = HID_Local_NotSupported, - .bNumDescriptors = 1, - .bReportType = HID_DESC_TYPE_REPORT, - .wReportLength = sizeof(usb_desc_hid_generic_report) - }, - - .ep_in = - { - .bLength = sizeof(tusb_desc_endpoint_t), - .bDescriptorType = TUSB_DESC_ENDPOINT, - .bEndpointAddress = EP_HID_GEN, - .bmAttributes = { .xfer = TUSB_XFER_INTERRUPT }, - .wMaxPacketSize = { .size = EP_HID_GEN_SIZE }, - .bInterval = 0x0A - } - } -}; - - -// tud_desc_set is required by tinyusb stack -tud_desc_set_t tud_desc_set = -{ - .device = &usb_desc_dev, - .config = &usb_desc_cfg, - .string_arr = (uint8_t const **) string_desc_arr, - .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]), - - .hid_report = - { - .generic = usb_desc_hid_generic_report, - .boot_keyboard = NULL, - .boot_mouse = NULL - } -}; diff --git a/ports/nrf/usb/usb_desc.h b/ports/nrf/usb/usb_desc.h deleted file mode 100644 index 19f3f6d5b..000000000 --- a/ports/nrf/usb/usb_desc.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2018 hathach 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 USB_DESC_H_ -#define USB_DESC_H_ - -#include "tusb.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/*------------- Configuration Descriptor -------------*/ -typedef struct ATTR_PACKED -{ - tusb_desc_configuration_t config; - - //------------- CDC -------------// - struct ATTR_PACKED - { - tusb_desc_interface_assoc_t iad; - - //CDC Control Interface - tusb_desc_interface_t comm_itf; - cdc_desc_func_header_t header; - cdc_desc_func_call_management_t call; - cdc_desc_func_acm_t acm; - cdc_desc_func_union_t union_func; - tusb_desc_endpoint_t ep_notif; - - //CDC Data Interface - tusb_desc_interface_t data_itf; - tusb_desc_endpoint_t ep_out; - tusb_desc_endpoint_t ep_in; - }cdc; - - //------------- Mass Storage -------------// - struct ATTR_PACKED - { - tusb_desc_interface_t itf; - tusb_desc_endpoint_t ep_out; - tusb_desc_endpoint_t ep_in; - } msc; - - //------------- HID -------------// - struct ATTR_PACKED - { - tusb_desc_interface_t itf; - tusb_hid_descriptor_hid_t hid_desc; - tusb_desc_endpoint_t ep_in; - } hid_generic; - -} usb_desc_cfg_t; - - -// Descriptors set used by tinyusb stack -extern tud_desc_set_t tud_desc_set; - - -#ifdef __cplusplus - } -#endif - -#endif /* USB_DESC_H_ */ diff --git a/shared-bindings/busio/SPI.h b/shared-bindings/busio/SPI.h index 555f32c92..2d12b8b76 100644 --- a/shared-bindings/busio/SPI.h +++ b/shared-bindings/busio/SPI.h @@ -61,4 +61,7 @@ extern bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_o // Return actual SPI bus frequency. uint32_t common_hal_busio_spi_get_frequency(busio_spi_obj_t* self); +// This is used by the supervisor to claim SPI devices indefinitely. +extern void common_hal_busio_spi_never_reset(busio_spi_obj_t *self); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BUSIO_SPI_H diff --git a/shared-bindings/usb_hid/Device.h b/shared-bindings/usb_hid/Device.h index 2bc553c4a..cb9a64b5e 100644 --- a/shared-bindings/usb_hid/Device.h +++ b/shared-bindings/usb_hid/Device.h @@ -27,7 +27,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_USB_HID_DEVICE_H #define MICROPY_INCLUDED_SHARED_BINDINGS_USB_HID_DEVICE_H -#include "common-hal/usb_hid/Device.h" +#include "shared-module/usb_hid/Device.h" const mp_obj_type_t usb_hid_device_type; diff --git a/shared-module/bitbangio/SPI.c b/shared-module/bitbangio/SPI.c index 9e4508355..6d3a28523 100644 --- a/shared-module/bitbangio/SPI.c +++ b/shared-module/bitbangio/SPI.c @@ -24,8 +24,7 @@ * THE SOFTWARE. */ -#include "mpconfigport.h" - +#include "py/mpconfig.h" #include "py/obj.h" #include "py/runtime.h" diff --git a/shared-module/storage/__init__.c b/shared-module/storage/__init__.c index edce286b1..f09edd785 100644 --- a/shared-module/storage/__init__.c +++ b/shared-module/storage/__init__.c @@ -32,8 +32,12 @@ #include "py/mperrno.h" #include "py/obj.h" #include "py/runtime.h" +#include "shared-bindings/microcontroller/__init__.h" #include "shared-bindings/os/__init__.h" #include "shared-bindings/storage/__init__.h" +#include "supervisor/filesystem.h" +#include "supervisor/flash.h" +#include "supervisor/usb.h" STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) { if (vfs == MP_VFS_NONE) { @@ -138,3 +142,25 @@ void common_hal_storage_umount_path(const char* mount_path) { mp_obj_t common_hal_storage_getmount(const char *mount_path) { return storage_object_from_path(mount_path); } + +void common_hal_storage_remount(const char *mount_path, bool readonly) { + if (strcmp(mount_path, "/") != 0) { + mp_raise_OSError(MP_EINVAL); + } + + #ifdef USB_AVAILABLE + // TODO(dhalbert): is this is a good enough check? It checks for + // CDC enabled. There is no "MSC enabled" check. + if (usb_enabled()) { + mp_raise_RuntimeError(translate("Cannot remount '/' when USB is active.")); + } + #endif + + supervisor_flash_set_usb_writable(readonly); +} + +void common_hal_storage_erase_filesystem(void) { + filesystem_init(false, true); // Force a re-format. + common_hal_mcu_reset(); + // We won't actually get here, since we're resetting. +} diff --git a/ports/nrf/common-hal/usb_hid/Device.c b/shared-module/usb_hid/Device.c index 6acb2717f..820e14ad0 100644 --- a/ports/nrf/common-hal/usb_hid/Device.c +++ b/shared-module/usb_hid/Device.c @@ -26,9 +26,9 @@ #include <string.h> #include "tick.h" -#include "common-hal/usb_hid/Device.h" #include "py/runtime.h" #include "shared-bindings/usb_hid/Device.h" +#include "shared-module/usb_hid/Device.h" #include "supervisor/shared/translate.h" #include "tusb.h" diff --git a/ports/atmel-samd/common-hal/usb_hid/Device.h b/shared-module/usb_hid/Device.h index b81c0e709..10f2ee897 100644 --- a/ports/atmel-samd/common-hal/usb_hid/Device.h +++ b/shared-module/usb_hid/Device.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2018 hathach 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 @@ -24,30 +24,32 @@ * THE SOFTWARE. */ -#ifndef COMMON_HAL_USB_HID_DEVICE_H -#define COMMON_HAL_USB_HID_DEVICE_H +#ifndef SHARED_MODULE_USB_HID_DEVICE_H +#define SHARED_MODULE_USB_HID_DEVICE_H #include <stdint.h> #include <stdbool.h> #include "py/obj.h" -#include "genhdr/autogen_usb_descriptor.h" +#ifdef __cplusplus + extern "C" { +#endif -typedef struct { +typedef struct { mp_obj_base_t base; uint8_t* report_buffer; - uint8_t endpoint; - uint8_t report_id; // If non-zero, prefix report with given id. - uint8_t report_length; // Length not including Report ID. + uint8_t report_id; + uint8_t report_length; uint8_t usage_page; uint8_t usage; - } usb_hid_device_obj_t; -extern usb_hid_device_obj_t usb_hid_devices[USB_HID_NUM_DEVICES]; -void usb_hid_init(void); -void usb_hid_reset(void); +extern usb_hid_device_obj_t usb_hid_devices[]; + +#ifdef __cplusplus + } +#endif -#endif // COMMON_HAL_USB_HID_DEVICE_H +#endif /* SHARED_MODULE_USB_HID_DEVICE_H */ diff --git a/ports/nrf/common-hal/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c index 00fc8bd00..c0f9c897c 100644 --- a/ports/nrf/common-hal/usb_hid/__init__.c +++ b/shared-module/usb_hid/__init__.c @@ -28,43 +28,37 @@ #include "py/mphal.h" #include "py/runtime.h" -#include "common-hal/usb_hid/Device.h" +#include "genhdr/autogen_usb_descriptor.h" +#include "shared-module/usb_hid/Device.h" #include "shared-bindings/usb_hid/Device.h" #include "tusb.h" -#define USB_HID_REPORT_LENGTH_KEYBOARD 8 -#define USB_HID_REPORT_LENGTH_MOUSE 4 -#define USB_HID_REPORT_LENGTH_CONSUMER 2 -#define USB_HID_REPORT_LENGTH_SYS_CONTROL 1 -#define USB_HID_REPORT_LENGTH_GAMEPAD 6 -#define USB_HID_REPORT_LENGTH_DIGITIZER 5 - -#if USB_HID_DEVICE_KEYBOARD +#ifdef USB_HID_REPORT_ID_KEYBOARD static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD]; #endif -#if USB_HID_DEVICE_MOUSE +#ifdef USB_HID_REPORT_ID_MOUSE static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE]; #endif -#if USB_HID_DEVICE_CONSUMER +#ifdef USB_HID_REPORT_ID_CONSUMER static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER]; #endif -#if USB_HID_DEVICE_SYS_CONTROL +#ifdef USB_HID_REPORT_ID_SYS_CONTROL static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL]; #endif -#if USB_HID_DEVICE_GAMEPAD +#ifdef USB_HID_REPORT_ID_GAMEPAD static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD]; #endif -#if USB_HID_DEVICE_DIGITIZER +#ifdef USB_HID_REPORT_ID_DIGITIZER static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER]; #endif usb_hid_device_obj_t usb_hid_devices[] = { -#if USB_HID_DEVICE_KEYBOARD +#if USB_HID_REPORT_ID_KEYBOARD { .base = { .type = &usb_hid_device_type } , .report_buffer = keyboard_report_buffer , @@ -75,7 +69,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_MOUSE +#if USB_HID_REPORT_ID_MOUSE { .base = { .type = &usb_hid_device_type } , .report_buffer = mouse_report_buffer , @@ -86,7 +80,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_CONSUMER +#if USB_HID_REPORT_ID_CONSUMER { .base = { .type = &usb_hid_device_type } , .report_buffer = consumer_report_buffer , @@ -97,7 +91,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_SYS_CONTROL +#if USB_HID_REPORT_ID_SYS_CONTROL { .base = { .type = &usb_hid_device_type } , .report_buffer = sys_control_report_buffer , @@ -108,7 +102,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_GAMEPAD +#if USB_HID_REPORT_ID_GAMEPAD { .base = { .type = &usb_hid_device_type } , .report_buffer = gamepad_report_buffer , @@ -119,7 +113,7 @@ usb_hid_device_obj_t usb_hid_devices[] = { }, #endif -#if USB_HID_DEVICE_DIGITIZER +#if USB_HID_REPORT_ID_DIGITIZER { .base = { .type = &usb_hid_device_type } , .report_buffer = digitizer_report_buffer , diff --git a/ports/atmel-samd/usb_mass_storage.h b/supervisor/flash.h index 767a6779c..ae6a44fd0 100644 --- a/ports/atmel-samd/usb_mass_storage.h +++ b/supervisor/flash.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,26 +23,32 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef MICROPY_INCLUDED_SUPERVISOR_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_FLASH_H -// This adapts the ASF4 USB mass storage API to MicroPython's VFS API so we can -// expose all VFS block devices as Lun's over USB mass storage control. +#include <stdint.h> +#include <stdbool.h> -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_USB_MASS_STORAGE_H -#define MICROPY_INCLUDED_ATMEL_SAMD_USB_MASS_STORAGE_H +#include "py/mpconfig.h" -#include <stdint.h> +#ifdef EXTERNAL_FLASH_DEVICE_COUNT +#include "supervisor/shared/external_flash/external_flash.h" +#else +#include "supervisor/internal_flash.h" +#endif + +void supervisor_flash_set_usb_writable(bool usb_writable); +void supervisor_flash_init(void); +uint32_t supervisor_flash_get_block_size(void); +uint32_t supervisor_flash_get_block_count(void); +void supervisor_flash_flush(void); -// "background" task that actually manages loading to and from the file systems. -void usb_msc_background(void); +// these return 0 on success, non-zero on error +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks); +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks); -// Callbacks that hook into ASF4's USB stack. -int32_t usb_msc_disk_eject(uint8_t lun); -int32_t usb_msc_disk_is_writable(uint8_t lun); -int32_t usb_msc_disk_is_ready(uint8_t lun); -int32_t usb_msc_new_read(uint8_t lun, uint32_t addr, uint32_t nblocks); -int32_t usb_msc_new_write(uint8_t lun, uint32_t addr, uint32_t nblocks); -int32_t usb_msc_xfer_done(uint8_t lun); -uint8_t *usb_msc_inquiry_info(uint8_t lun); -uint8_t *usb_msc_get_capacity(uint8_t lun); +struct _fs_user_mount_t; +void supervisor_flash_init_vfs(struct _fs_user_mount_t *vfs); +void supervisor_flash_flush(void); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_USB_MASS_STORAGE_H +#endif // MICROPY_INCLUDED_SUPERVISOR_FLASH_H diff --git a/supervisor/flash_root_pointers.h b/supervisor/flash_root_pointers.h new file mode 100644 index 000000000..634ae58d3 --- /dev/null +++ b/supervisor/flash_root_pointers.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H + +#ifdef EXTERNAL_FLASH_DEVICE_COUNT +#include "supervisor/shared/external_flash/external_flash_root_pointers.h" +#else +#include "supervisor/internal_flash_root_pointers.h" +#endif + +#endif // MICROPY_INCLUDED_SUPERVISOR_FLASH_ROOT_POINTERS_H diff --git a/supervisor/port.h b/supervisor/port.h index f30d87b47..dd4a82209 100644 --- a/supervisor/port.h +++ b/supervisor/port.h @@ -57,6 +57,9 @@ void reset_port(void); // Reset the rest of the board. void reset_board(void); +// Reset to the bootloader +void reset_to_bootloader(void); + #ifdef NRF52_SERIES void HardFault_Handler(void); #endif diff --git a/supervisor/serial.h b/supervisor/serial.h index 9446ee71c..84b3062a3 100644 --- a/supervisor/serial.h +++ b/supervisor/serial.h @@ -30,8 +30,18 @@ #include <stdbool.h> #include <stdint.h> +#include "py/mpconfig.h" + +#ifdef CIRCUITPY_BOOT_OUTPUT_FILE +#include "lib/oofatfs/ff.h" + +FIL* boot_output_file; +#endif + void serial_init(void); void serial_write(const char* text); +// Only writes up to given length. Does not check for null termination at all. +void serial_write_substring(const char* text, uint32_t length); char serial_read(void); bool serial_bytes_available(void); bool serial_connected(void); diff --git a/ports/atmel-samd/external_flash/common_commands.h b/supervisor/shared/external_flash/common_commands.h index d82d2c046..cc0da2175 100644 --- a/ports/atmel-samd/external_flash/common_commands.h +++ b/supervisor/shared/external_flash/common_commands.h @@ -28,6 +28,7 @@ #define CMD_READ_JEDEC_ID 0x9f #define CMD_READ_DATA 0x03 +#define CMD_FAST_READ_DATA 0x0B #define CMD_SECTOR_ERASE 0x20 // #define CMD_SECTOR_ERASE CMD_READ_JEDEC_ID #define CMD_DISABLE_WRITE 0x04 diff --git a/ports/atmel-samd/external_flash/devices.h b/supervisor/shared/external_flash/devices.h index 58da2e509..06fc178cb 100644 --- a/ports/atmel-samd/external_flash/devices.h +++ b/supervisor/shared/external_flash/devices.h @@ -40,6 +40,11 @@ typedef struct { // Max clock speed for all operations and the fastest read mode. uint8_t max_clock_speed_mhz; + + // Bitmask for Quad Enable bit if present. 0x00 otherwise. This is for the highest byte in the + // status register. + uint8_t quad_enable_bit_mask; + bool has_sector_protection : 1; // Supports the 0x0b fast read command with 8 dummy cycles. @@ -48,9 +53,6 @@ typedef struct { // Supports the fast read, quad output command 0x6b with 8 dummy cycles. bool supports_qspi : 1; - // Requires quad enable set in status bit 9. - bool has_quad_enable : 1; - // Supports the quad input page program command 0x32. This is known as 1-1-4 because it only // uses all four lines for data. bool supports_qspi_writes: 1; @@ -58,6 +60,10 @@ typedef struct { // Requires a separate command 0x31 to write to the second byte of the status register. // Otherwise two byte are written via 0x01. bool write_status_register_split: 1; + + // True when the status register is a single byte. This implies the Quad Enable bit is in the + // first byte and the Read Status Register 2 command (0x35) is unsupported. + bool single_status_byte: 1; } external_flash_device; // Settings for the Adesto Tech AT25DF081A 1MiB SPI flash. Its on the SAMD21 @@ -70,12 +76,13 @@ typedef struct { .memory_type = 0x45, \ .capacity = 0x01, \ .max_clock_speed_mhz = 85, \ + .quad_enable_bit_mask = 0x00, \ .has_sector_protection = true, \ .supports_fast_read = true, \ .supports_qspi = false, \ - .has_quad_enable = false, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Gigadevice GD25Q16C 2MiB SPI flash. @@ -87,12 +94,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Gigadevice GD25Q64C 8MiB SPI flash. @@ -104,12 +112,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x17, \ .max_clock_speed_mhz = 104, /* if we need 120 then we can turn on high performance mode */ \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = true, \ + .single_status_byte = false, \ } // Settings for the Cypress (was Spansion) S25FL064L 8MiB SPI flash. @@ -121,12 +130,13 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x17, \ .max_clock_speed_mhz = 108, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Cypress (was Spansion) S25FL116K 2MiB SPI flash. @@ -138,12 +148,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 108, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Cypress (was Spansion) S25FL216K 2MiB SPI flash. @@ -155,12 +166,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 65, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = false, \ - .has_quad_enable = false, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q16FW 2MiB SPI flash. @@ -172,12 +184,13 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x15, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q16JV-IQ 2MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) @@ -189,12 +202,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x15, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q16JV-IM 2MiB SPI flash. Note that JV-IQ has a different .memory_type (0x40) @@ -223,12 +237,13 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x16, \ .max_clock_speed_mhz = 104, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q32JV-IM 4MiB SPI flash. // Datasheet: https://www.winbond.com/resource-files/w25q32jv%20revg%2003272018%20plus.pdf @@ -256,12 +271,14 @@ typedef struct { .memory_type = 0x70, \ .capacity = 0x17, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q64JV-IQ 8MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) @@ -273,12 +290,13 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x17, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } // Settings for the Winbond W25Q80DL 1MiB SPI flash. @@ -290,12 +308,13 @@ typedef struct { .memory_type = 0x60, \ .capacity = 0x14, \ .max_clock_speed_mhz = 104, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = false, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } @@ -308,14 +327,33 @@ typedef struct { .memory_type = 0x40, \ .capacity = 0x18, \ .max_clock_speed_mhz = 133, \ + .quad_enable_bit_mask = 0x02, \ .has_sector_protection = false, \ .supports_fast_read = true, \ .supports_qspi = true, \ - .has_quad_enable = true, \ .supports_qspi_writes = true, \ .write_status_register_split = false, \ + .single_status_byte = false, \ } +// Settings for the Macronix MX25R6435F 8MiB SPI flash. +// Datasheet: http://www.macronix.com/Lists/Datasheet/Attachments/7428/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.4.pdf +// By default its in lower power mode which can only do 8mhz. In high power mode it can do 80mhz. +#define MX25R6435F {\ + .total_size = (1 << 23), /* 8 MiB */ \ + .start_up_time_us = 5000, \ + .manufacturer_id = 0xc2, \ + .memory_type = 0x28, \ + .capacity = 0x17, \ + .max_clock_speed_mhz = 8, \ + .quad_enable_bit_mask = 0x40, \ + .has_sector_protection = false, \ + .supports_fast_read = true, \ + .supports_qspi = true, \ + .supports_qspi_writes = true, \ + .write_status_register_split = false, \ + .single_status_byte = true, \ +} // Settings for the Winbond W25Q128JV-PM 16MiB SPI flash. Note that JV-IM has a different .memory_type (0x70) // Datasheet: https://www.winbond.com/resource-files/w25q128jv%20revf%2003272018%20plus.pdf diff --git a/ports/atmel-samd/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index b4a637be4..defdfa393 100644 --- a/ports/atmel-samd/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -28,8 +28,8 @@ #include <stdint.h> #include <string.h> -#include "external_flash/spi_flash_api.h" -#include "external_flash/common_commands.h" +#include "supervisor/spi_flash_api.h" +#include "supervisor/shared/external_flash/common_commands.h" #include "extmod/vfs.h" #include "extmod/vfs_fat.h" #include "py/misc.h" @@ -40,15 +40,10 @@ #include "supervisor/memory.h" #include "supervisor/shared/rgb_led_status.h" -#include "hal_gpio.h" -#include "hal_spi_m_sync.h" - #define SPI_FLASH_PART1_START_BLOCK (0x1) #define NO_SECTOR_LOADED 0xFFFFFFFF -struct spi_m_sync_descriptor spi_flash_desc; - // The currently cached sector in the cache, ram or flash based. static uint32_t current_sector; @@ -181,7 +176,7 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) { return true; } -void external_flash_init(void) { +void supervisor_flash_init(void) { if (flash_device != NULL) { return; } @@ -265,12 +260,12 @@ void external_flash_init(void) { } // The size of each individual block. -uint32_t external_flash_get_block_size(void) { +uint32_t supervisor_flash_get_block_size(void) { return FILESYSTEM_BLOCK_SIZE; } // The total number of available blocks. -uint32_t external_flash_get_block_count(void) { +uint32_t supervisor_flash_get_block_count(void) { // We subtract one erase sector size because we may use it as a staging area // for writes. return SPI_FLASH_PART1_START_BLOCK + (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE; @@ -445,14 +440,10 @@ static void spi_flash_flush_keep_cache(bool keep_cache) { // External flash function used. If called externally we assume we won't need // the cache after. -void external_flash_flush(void) { +void supervisor_flash_flush(void) { spi_flash_flush_keep_cache(false); } -void flash_flush(void) { - external_flash_flush(); -} - // Builds a partition entry for the MBR. static void build_partition(uint8_t *buf, int boot, int type, uint32_t start_block, uint32_t num_blocks) { @@ -492,7 +483,7 @@ static void build_partition(uint8_t *buf, int boot, int type, } static int32_t convert_block_to_flash_addr(uint32_t block) { - if (SPI_FLASH_PART1_START_BLOCK <= block && block < external_flash_get_block_count()) { + if (SPI_FLASH_PART1_START_BLOCK <= block && block < supervisor_flash_get_block_count()) { // a block in partition 1 block -= SPI_FLASH_PART1_START_BLOCK; return block * FILESYSTEM_BLOCK_SIZE; @@ -510,7 +501,7 @@ bool external_flash_read_block(uint8_t *dest, uint32_t block) { build_partition(dest + 446, 0, 0x01 /* FAT12 */, SPI_FLASH_PART1_START_BLOCK, - external_flash_get_block_count() - SPI_FLASH_PART1_START_BLOCK); + supervisor_flash_get_block_count() - SPI_FLASH_PART1_START_BLOCK); build_partition(dest + 462, 0, 0, 0, 0); build_partition(dest + 478, 0, 0, 0, 0); build_partition(dest + 494, 0, 0, 0, 0); @@ -605,7 +596,7 @@ bool external_flash_write_block(const uint8_t *data, uint32_t block) { } } -mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { +mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { if (!external_flash_read_block(dest + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error @@ -614,7 +605,7 @@ mp_uint_t external_flash_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t return 0; // success } -mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { +mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) { for (size_t i = 0; i < num_blocks; i++) { if (!external_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) { return 1; // error @@ -622,78 +613,3 @@ mp_uint_t external_flash_write_blocks(const uint8_t *src, uint32_t block_num, ui } return 0; // success } - -/******************************************************************************/ -// MicroPython bindings -// -// Expose the flash as an object with the block protocol. - -// there is a singleton Flash object -STATIC const mp_obj_base_t external_flash_obj = {&external_flash_type}; - -STATIC mp_obj_t external_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { - // check arguments - mp_arg_check_num(n_args, n_kw, 0, 0, false); - - // return singleton object - return (mp_obj_t)&external_flash_obj; -} - -STATIC mp_obj_t external_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); - mp_uint_t ret = external_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_readblocks_obj, external_flash_obj_readblocks); - -STATIC mp_obj_t external_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); - mp_uint_t ret = external_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); - return MP_OBJ_NEW_SMALL_INT(ret); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_writeblocks_obj, external_flash_obj_writeblocks); - -STATIC mp_obj_t external_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { - mp_int_t cmd = mp_obj_get_int(cmd_in); - switch (cmd) { - case BP_IOCTL_INIT: external_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_DEINIT: external_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly - case BP_IOCTL_SYNC: external_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); - case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(external_flash_get_block_count()); - case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(external_flash_get_block_size()); - default: return mp_const_none; - } -} -STATIC MP_DEFINE_CONST_FUN_OBJ_3(external_flash_obj_ioctl_obj, external_flash_obj_ioctl); - -STATIC const mp_rom_map_elem_t external_flash_obj_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&external_flash_obj_readblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&external_flash_obj_writeblocks_obj) }, - { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&external_flash_obj_ioctl_obj) }, -}; - -STATIC MP_DEFINE_CONST_DICT(external_flash_obj_locals_dict, external_flash_obj_locals_dict_table); - -const mp_obj_type_t external_flash_type = { - { &mp_type_type }, - .name = MP_QSTR_SPIFlash, - .make_new = external_flash_obj_make_new, - .locals_dict = (mp_obj_t)&external_flash_obj_locals_dict, -}; - -void flash_init_vfs(fs_user_mount_t *vfs) { - vfs->base.type = &mp_fat_vfs_type; - vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; - vfs->fatfs.drv = vfs; - vfs->fatfs.part = 1; // flash filesystem lives on first partition - vfs->readblocks[0] = (mp_obj_t)&external_flash_obj_readblocks_obj; - vfs->readblocks[1] = (mp_obj_t)&external_flash_obj; - vfs->readblocks[2] = (mp_obj_t)external_flash_read_blocks; // native version - vfs->writeblocks[0] = (mp_obj_t)&external_flash_obj_writeblocks_obj; - vfs->writeblocks[1] = (mp_obj_t)&external_flash_obj; - vfs->writeblocks[2] = (mp_obj_t)external_flash_write_blocks; // native version - vfs->u.ioctl[0] = (mp_obj_t)&external_flash_obj_ioctl_obj; - vfs->u.ioctl[1] = (mp_obj_t)&external_flash_obj; -} diff --git a/ports/atmel-samd/flash_api.c b/supervisor/shared/external_flash/external_flash.h index b8a212718..852d183a7 100644 --- a/ports/atmel-samd/flash_api.c +++ b/supervisor/shared/external_flash/external_flash.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2013, 2014 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,29 +23,26 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H -#include "flash_api.h" +#include <stdbool.h> +#include <stdint.h> -#include "py/mpstate.h" +#include "py/mpconfig.h" -#define VFS_INDEX 0 +// Erase sector size. +#define SPI_FLASH_SECTOR_SIZE (0x1000 - 100) -void flash_set_usb_writable(bool usb_writable) { - mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); - for (uint8_t i = 0; current_mount != NULL; i++) { - if (i == VFS_INDEX) { - break; - } - current_mount = current_mount->next; - } - if (current_mount == NULL) { - return; - } - fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj; +// These are common across all NOR Flash. +#define SPI_FLASH_ERASE_SIZE (1 << 12) +#define SPI_FLASH_PAGE_SIZE (256) - if (usb_writable) { - vfs->flags |= FSUSER_USB_WRITABLE; - } else { - vfs->flags &= ~FSUSER_USB_WRITABLE; - } -} +#define SPI_FLASH_SYSTICK_MASK (0x1ff) // 512ms +#define SPI_FLASH_IDLE_TICK(tick) (((tick) & SPI_FLASH_SYSTICK_MASK) == 2) + +#ifndef SPI_FLASH_MAX_BAUDRATE +#define SPI_FLASH_MAX_BAUDRATE 8000000 +#endif + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_H diff --git a/supervisor/shared/external_flash/external_flash_root_pointers.h b/supervisor/shared/external_flash/external_flash_root_pointers.h new file mode 100644 index 000000000..cb1b86d19 --- /dev/null +++ b/supervisor/shared/external_flash/external_flash_root_pointers.h @@ -0,0 +1,35 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H + +#include <stdint.h> + +// We use this when we can allocate the whole cache in RAM. +#define FLASH_ROOT_POINTERS \ + uint8_t** flash_ram_cache; \ + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_EXTERNAL_FLASH_ROOT_POINTERS_H diff --git a/ports/atmel-samd/common-hal/storage/__init__.c b/supervisor/shared/external_flash/qspi_flash.c index 501a19dd7..48266540c 100644 --- a/ports/atmel-samd/common-hal/storage/__init__.c +++ b/supervisor/shared/external_flash/qspi_flash.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2016, 2017, 2018 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 @@ -24,35 +24,33 @@ * THE SOFTWARE. */ -#include <string.h> +#include "supervisor/spi_flash_api.h" -#include "flash_api.h" -#include "py/mperrno.h" -#include "py/runtime.h" -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/storage/__init__.h" -#include "supervisor/filesystem.h" -#include "supervisor/shared/translate.h" -#include "usb.h" +#include "supervisor/shared/external_flash/common_commands.h" -extern volatile bool mp_msc_enabled; - -void common_hal_storage_remount(const char* mount_path, bool readonly) { - if (strcmp(mount_path, "/") != 0) { - mp_raise_OSError(MP_EINVAL); +void check_quad_enable(const external_flash_device* device) { + if (device->quad_enable_bit_mask == 0x00) { + return; } - // TODO(dhalbert): is this is a good enough check? It checks for - // CDC enabled. There is no "MSC enabled" check. - if (usb_connected()) { - mp_raise_RuntimeError(translate("Cannot remount '/' when USB is active.")); + // Verify that QSPI mode is enabled. + uint8_t status; + if (device->single_status_byte) { + spi_flash_read_command(CMD_READ_STATUS, &status, 1); + } else { + spi_flash_read_command(CMD_READ_STATUS2, &status, 1); } - flash_set_usb_writable(readonly); -} - -void common_hal_storage_erase_filesystem(void) { - filesystem_init(false, true); // Force a re-format. - common_hal_mcu_reset(); - // We won't actually get here, since we're resetting. + // Check the quad enable bit. + if ((status & device->quad_enable_bit_mask) == 0) { + uint8_t full_status[2] = {0x00, device->quad_enable_bit_mask}; + spi_flash_command(CMD_ENABLE_WRITE); + if (device->write_status_register_split) { + spi_flash_write_command(CMD_WRITE_STATUS_BYTE2, full_status + 1, 1); + } else if (device->single_status_byte) { + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status + 1, 1); + } else { + spi_flash_write_command(CMD_WRITE_STATUS_BYTE1, full_status, 2); + } + } } diff --git a/supervisor/shared/external_flash/qspi_flash.h b/supervisor/shared/external_flash/qspi_flash.h new file mode 100644 index 000000000..b72e37b26 --- /dev/null +++ b/supervisor/shared/external_flash/qspi_flash.h @@ -0,0 +1,31 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_QSPI_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_QSPI_FLASH_H + +void check_quad_enable(const external_flash_device* device); + +#endif // MICROPY_INCLUDED_SUPERVISOR_SHARED_EXTERNAL_FLASH_QSPI_FLASH_H diff --git a/ports/atmel-samd/external_flash/spi_flash.c b/supervisor/shared/external_flash/spi_flash.c index 273915df7..ec7101bc9 100644 --- a/ports/atmel-samd/external_flash/spi_flash.c +++ b/supervisor/shared/external_flash/spi_flash.c @@ -23,40 +23,50 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#include "spi_flash_api.h" +#include "supervisor/spi_flash_api.h" #include <stdint.h> #include <string.h> -#include "external_flash/common_commands.h" -#include "samd/sercom.h" +#include "shared-bindings/busio/SPI.h" +#include "shared-bindings/digitalio/DigitalInOut.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "supervisor/shared/external_flash/common_commands.h" +#include "supervisor/shared/external_flash/external_flash.h" #include "py/mpconfig.h" -#include "hal_gpio.h" -#include "hal_spi_m_sync.h" +digitalio_digitalinout_obj_t cs_pin; +busio_spi_obj_t spi; -struct spi_m_sync_descriptor spi_flash_desc; +const external_flash_device* flash_device; +uint32_t spi_flash_baudrate; // Enable the flash over SPI. static void flash_enable(void) { - gpio_set_pin_level(SPI_FLASH_CS_PIN, false); + while (!common_hal_busio_spi_try_lock(&spi)) {} + common_hal_digitalio_digitalinout_set_value(&cs_pin, false); } // Disable the flash over SPI. static void flash_disable(void) { - gpio_set_pin_level(SPI_FLASH_CS_PIN, true); + common_hal_digitalio_digitalinout_set_value(&cs_pin, true); + common_hal_busio_spi_unlock(&spi); } static bool transfer(uint8_t* command, uint32_t command_length, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { - struct spi_xfer xfer = { command, NULL, command_length }; flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); - if (status >= 0 && !(data_in == NULL && data_out == NULL)) { - struct spi_xfer data_xfer = {data_in, data_out, data_length}; - status = spi_m_sync_transfer(&spi_flash_desc, &data_xfer); + bool status = common_hal_busio_spi_write(&spi, command, command_length); + if (status) { + if (data_in != NULL && data_out != NULL) { + status = common_hal_busio_spi_transfer(&spi, data_out, data_in, data_length); + } else if (data_out != NULL) { + status = common_hal_busio_spi_read(&spi, data_out, data_length, 0xff); + } else if (data_in != NULL) { + status = common_hal_busio_spi_write(&spi, data_in, data_length); + } } flash_disable(); - return status >= 0; + return status; } static bool transfer_command(uint8_t command, uint8_t* data_in, uint8_t* data_out, uint32_t data_length) { @@ -92,67 +102,49 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t data_length) uint8_t request[4] = {CMD_PAGE_PROGRAM, 0x00, 0x00, 0x00}; // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); - struct spi_xfer xfer = { request, NULL, 4 }; flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); - if (status >= 0) { - status = sercom_dma_write(spi_flash_desc.dev.prvt, data, data_length); + common_hal_busio_spi_configure(&spi, spi_flash_baudrate, 0, 0, 8); + bool status = common_hal_busio_spi_write(&spi, request, 4); + if (status) { + status = common_hal_busio_spi_write(&spi, data, data_length); } flash_disable(); - return status >= 0; + return status; } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length) { - uint8_t request[4] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; + uint8_t request[5] = {CMD_READ_DATA, 0x00, 0x00, 0x00}; + uint8_t command_length = 4; + if (flash_device->supports_fast_read) { + request[0] = CMD_FAST_READ_DATA; + command_length = 5; + } // Write the SPI flash write address into the bytes following the command byte. address_to_bytes(address, request + 1); - struct spi_xfer xfer = { request, NULL, 4 }; flash_enable(); - int32_t status = spi_m_sync_transfer(&spi_flash_desc, &xfer); - if (status >= 0) { - status = sercom_dma_read(spi_flash_desc.dev.prvt, data, data_length, 0xff); + common_hal_busio_spi_configure(&spi, spi_flash_baudrate, 0, 0, 8); + bool status = common_hal_busio_spi_write(&spi, request, command_length); + if (status) { + status = common_hal_busio_spi_read(&spi, data, data_length, 0xff); } flash_disable(); - return status >= 0; + return status; } void spi_flash_init(void) { - samd_peripherals_sercom_clock_init(SPI_FLASH_SERCOM, SPI_FLASH_SERCOM_INDEX); - - // Set up with defaults, then change. - spi_m_sync_init(&spi_flash_desc, SPI_FLASH_SERCOM); - - hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO); - hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO); - - gpio_set_pin_direction(SPI_FLASH_SCK_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(SPI_FLASH_SCK_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_SCK_PIN, SPI_FLASH_SCK_PIN_FUNCTION); - - gpio_set_pin_direction(SPI_FLASH_MOSI_PIN, GPIO_DIRECTION_OUT); - gpio_set_pin_pull_mode(SPI_FLASH_MOSI_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_MOSI_PIN, SPI_FLASH_MOSI_PIN_FUNCTION); - - gpio_set_pin_direction(SPI_FLASH_MISO_PIN, GPIO_DIRECTION_IN); - gpio_set_pin_pull_mode(SPI_FLASH_MISO_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_MISO_PIN, SPI_FLASH_MISO_PIN_FUNCTION); - - hri_sercomspi_write_CTRLA_DOPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DOPO); - hri_sercomspi_write_CTRLA_DIPO_bf(SPI_FLASH_SERCOM, SPI_FLASH_DIPO); - - spi_m_sync_set_baudrate(&spi_flash_desc, samd_peripherals_spi_baudrate_to_baud_reg_value(SPI_FLASH_BAUDRATE)); - - gpio_set_pin_direction(SPI_FLASH_CS_PIN, GPIO_DIRECTION_OUT); - // There's already a pull-up on the board. - gpio_set_pin_pull_mode(SPI_FLASH_CS_PIN, GPIO_PULL_OFF); - gpio_set_pin_function(SPI_FLASH_CS_PIN, GPIO_PIN_FUNCTION_OFF); + common_hal_digitalio_digitalinout_construct(&cs_pin, SPI_FLASH_CS_PIN); // Set CS high (disabled). - flash_disable(); + common_hal_digitalio_digitalinout_switch_to_output(&cs_pin, true, DRIVE_MODE_PUSH_PULL); - spi_m_sync_enable(&spi_flash_desc); + common_hal_busio_spi_construct(&spi, SPI_FLASH_SCK_PIN, SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN); + common_hal_busio_spi_never_reset(&spi); } void spi_flash_init_device(const external_flash_device* device) { - + flash_device = device; + spi_flash_baudrate = device->max_clock_speed_mhz * 1000000; + if (spi_flash_baudrate > SPI_FLASH_MAX_BAUDRATE) { + spi_flash_baudrate = SPI_FLASH_MAX_BAUDRATE; + } } diff --git a/ports/atmel-samd/supervisor/filesystem.c b/supervisor/shared/filesystem.c index 8a6010951..264ba25f0 100644 --- a/ports/atmel-samd/supervisor/filesystem.c +++ b/supervisor/shared/filesystem.c @@ -30,10 +30,10 @@ #include "py/mpstate.h" -#include "flash_api.h" +#include "supervisor/flash.h" -fs_user_mount_t fs_user_mount_flash; -mp_vfs_mount_t mp_vfs_mount_flash; +static mp_vfs_mount_t _mp_vfs; +static fs_user_mount_t _internal_vfs; static void make_empty_file(FATFS *fatfs, const char *path) { FIL fp; @@ -45,9 +45,9 @@ static void make_empty_file(FATFS *fatfs, const char *path) { // want it to be executed without using stack within main() function void filesystem_init(bool create_allowed, bool force_create) { // init the vfs object - fs_user_mount_t *vfs_fat = &fs_user_mount_flash; + fs_user_mount_t *vfs_fat = &_internal_vfs; vfs_fat->flags = 0; - flash_init_vfs(vfs_fat); + supervisor_flash_init_vfs(vfs_fat); // try to mount the flash FRESULT res = f_mount(&vfs_fat->fatfs); @@ -57,8 +57,9 @@ void filesystem_init(bool create_allowed, bool force_create) { uint8_t working_buf[_MAX_SS]; res = f_mkfs(&vfs_fat->fatfs, FM_FAT, 0, working_buf, sizeof(working_buf)); // Flush the new file system to make sure it's repaired immediately. - flash_flush(); + supervisor_flash_flush(); if (res != FR_OK) { + asm("bkpt"); return; } @@ -72,11 +73,12 @@ void filesystem_init(bool create_allowed, bool force_create) { make_empty_file(&vfs_fat->fatfs, "/.fseventsd/no_log"); // and ensure everything is flushed - flash_flush(); + supervisor_flash_flush(); } else if (res != FR_OK) { + asm("bkpt"); return; } - mp_vfs_mount_t *vfs = &mp_vfs_mount_flash; + mp_vfs_mount_t *vfs = &_mp_vfs; vfs->str = "/"; vfs->len = 1; vfs->obj = MP_OBJ_FROM_PTR(vfs_fat); @@ -89,11 +91,17 @@ void filesystem_init(bool create_allowed, bool force_create) { } void filesystem_flush(void) { - flash_flush(); + supervisor_flash_flush(); } void filesystem_writable_by_python(bool writable) { - flash_set_usb_writable(!writable); + fs_user_mount_t *vfs = &_internal_vfs; + + if (writable) { + vfs->flags |= FSUSER_USB_WRITABLE; + } else { + vfs->flags &= ~FSUSER_USB_WRITABLE; + } } bool filesystem_present(void) { diff --git a/supervisor/shared/flash.c b/supervisor/shared/flash.c new file mode 100644 index 000000000..4fa2d8f75 --- /dev/null +++ b/supervisor/shared/flash.c @@ -0,0 +1,123 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Scott Shawcroft + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include "supervisor/flash.h" + +#include "extmod/vfs_fat.h" +#include "py/runtime.h" +#include "lib/oofatfs/ff.h" + +#define VFS_INDEX 0 + +void supervisor_flash_set_usb_writable(bool usb_writable) { + mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); + for (uint8_t i = 0; current_mount != NULL; i++) { + if (i == VFS_INDEX) { + break; + } + current_mount = current_mount->next; + } + if (current_mount == NULL) { + return; + } + fs_user_mount_t *vfs = (fs_user_mount_t *) current_mount->obj; + + if (usb_writable) { + vfs->flags |= FSUSER_USB_WRITABLE; + } else { + vfs->flags &= ~FSUSER_USB_WRITABLE; + } +} + +// there is a singleton Flash object +const mp_obj_type_t supervisor_flash_type; +STATIC const mp_obj_base_t supervisor_flash_obj = {&supervisor_flash_type}; + +STATIC mp_obj_t supervisor_flash_obj_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { + // check arguments + mp_arg_check_num(n_args, n_kw, 0, 0, false); + + // return singleton object + return (mp_obj_t)&supervisor_flash_obj; +} + +STATIC mp_obj_t supervisor_flash_obj_readblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_WRITE); + mp_uint_t ret = supervisor_flash_read_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_readblocks_obj, supervisor_flash_obj_readblocks); + +STATIC mp_obj_t supervisor_flash_obj_writeblocks(mp_obj_t self, mp_obj_t block_num, mp_obj_t buf) { + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(buf, &bufinfo, MP_BUFFER_READ); + mp_uint_t ret = supervisor_flash_write_blocks(bufinfo.buf, mp_obj_get_int(block_num), bufinfo.len / FILESYSTEM_BLOCK_SIZE); + return MP_OBJ_NEW_SMALL_INT(ret); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_writeblocks_obj, supervisor_flash_obj_writeblocks); + +STATIC mp_obj_t supervisor_flash_obj_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in) { + mp_int_t cmd = mp_obj_get_int(cmd_in); + switch (cmd) { + case BP_IOCTL_INIT: supervisor_flash_init(); return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_DEINIT: supervisor_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); // TODO properly + case BP_IOCTL_SYNC: supervisor_flash_flush(); return MP_OBJ_NEW_SMALL_INT(0); + case BP_IOCTL_SEC_COUNT: return MP_OBJ_NEW_SMALL_INT(supervisor_flash_get_block_count()); + case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(supervisor_flash_get_block_size()); + default: return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_3(supervisor_flash_obj_ioctl_obj, supervisor_flash_obj_ioctl); + +STATIC const mp_rom_map_elem_t supervisor_flash_obj_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&supervisor_flash_obj_readblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&supervisor_flash_obj_writeblocks_obj) }, + { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&supervisor_flash_obj_ioctl_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(supervisor_flash_obj_locals_dict, supervisor_flash_obj_locals_dict_table); + +const mp_obj_type_t supervisor_flash_type = { + { &mp_type_type }, + .name = MP_QSTR_Flash, + .make_new = supervisor_flash_obj_make_new, + .locals_dict = (mp_obj_t)&supervisor_flash_obj_locals_dict, +}; + +void supervisor_flash_init_vfs(fs_user_mount_t *vfs) { + vfs->base.type = &mp_fat_vfs_type; + vfs->flags |= FSUSER_NATIVE | FSUSER_HAVE_IOCTL; + vfs->fatfs.drv = vfs; + vfs->fatfs.part = 1; // flash filesystem lives on first partition + vfs->readblocks[0] = (mp_obj_t)&supervisor_flash_obj_readblocks_obj; + vfs->readblocks[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->readblocks[2] = (mp_obj_t)supervisor_flash_read_blocks; // native version + vfs->writeblocks[0] = (mp_obj_t)&supervisor_flash_obj_writeblocks_obj; + vfs->writeblocks[1] = (mp_obj_t)&supervisor_flash_obj; + vfs->writeblocks[2] = (mp_obj_t)supervisor_flash_write_blocks; // native version + vfs->u.ioctl[0] = (mp_obj_t)&supervisor_flash_obj_ioctl_obj; + vfs->u.ioctl[1] = (mp_obj_t)&supervisor_flash_obj; +} diff --git a/supervisor/shared/micropython.c b/supervisor/shared/micropython.c new file mode 100644 index 000000000..245db11d4 --- /dev/null +++ b/supervisor/shared/micropython.c @@ -0,0 +1,58 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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 <string.h> + +#include "supervisor/serial.h" +#include "lib/oofatfs/ff.h" +#include "py/mpconfig.h" + +#include "supervisor/shared/status_leds.h" + +int mp_hal_stdin_rx_chr(void) { + for (;;) { + #ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP + #endif + if (serial_bytes_available()) { + toggle_rx_led(); + return serial_read(); + } + } +} + +void mp_hal_stdout_tx_strn(const char *str, size_t len) { + toggle_tx_led(); + + #ifdef CIRCUITPY_BOOT_OUTPUT_FILE + if (boot_output_file != NULL) { + UINT bytes_written = 0; + f_write(boot_output_file, str, len, &bytes_written); + } + #endif + + serial_write_substring(str, len); +} diff --git a/supervisor/shared/rgb_led_status.h b/supervisor/shared/rgb_led_status.h index 24e071aac..9542b3197 100644 --- a/supervisor/shared/rgb_led_status.h +++ b/supervisor/shared/rgb_led_status.h @@ -33,7 +33,7 @@ #include "lib/utils/pyexec.h" #include "supervisor/port.h" -#include "mpconfigport.h" +#include "py/mpconfig.h" #include "rgb_led_colors.h" // Overall, the time module must be implemented. diff --git a/ports/nrf/common-hal/storage/__init__.c b/supervisor/shared/serial.c index 4ff5f0dac..058c4a7a4 100644 --- a/ports/nrf/common-hal/storage/__init__.c +++ b/supervisor/shared/serial.c @@ -26,22 +26,31 @@ #include <string.h> -#include "py/mperrno.h" -#include "py/runtime.h" -#include "shared-bindings/microcontroller/__init__.h" -#include "shared-bindings/storage/__init__.h" -#include "supervisor/filesystem.h" - -extern volatile bool mp_msc_enabled; - -void common_hal_storage_remount(const char *mount_path, bool readonly) { - if (strcmp(mount_path, "/") != 0) { - mp_raise_OSError(MP_EINVAL); - } +#include "supervisor/serial.h" +#include "supervisor/usb.h" + +#include "tusb.h" + +void serial_init(void) { + usb_init(); +} + +bool serial_connected(void) { + return tud_cdc_connected(); +} + +char serial_read(void) { + return (char) tud_cdc_read_char(); +} + +bool serial_bytes_available(void) { + return tud_cdc_available() > 0; +} + +void serial_write(const char* text) { + tud_cdc_write(text, strlen(text)); } -void common_hal_storage_erase_filesystem(void) { - filesystem_init(false, true); // Force a re-format. - common_hal_mcu_reset(); - // We won't actually get here, since we're resetting. +void serial_write_substring(const char* text, uint32_t length) { + tud_cdc_write(text, length); } diff --git a/supervisor/shared/status_leds.c b/supervisor/shared/status_leds.c new file mode 100644 index 000000000..d99853ceb --- /dev/null +++ b/supervisor/shared/status_leds.c @@ -0,0 +1,62 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 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 "supervisor/shared/status_leds.h" + +#include "common-hal/digitalio/DigitalInOut.h" +#include "shared-bindings/digitalio/DigitalInOut.h" + +#ifdef MICROPY_HW_LED_RX +digitalio_digitalinout_obj_t rx_led; +#endif + +#ifdef MICROPY_HW_LED_TX +digitalio_digitalinout_obj_t tx_led; +#endif + +void init_status_leds(void) { + #ifdef MICROPY_HW_LED_RX + common_hal_digitalio_digitalinout_construct(&rx_led, MICROPY_HW_LED_RX); + common_hal_digitalio_digitalinout_switch_to_output(&rx_led, true, DRIVE_MODE_PUSH_PULL); + #endif + #ifdef MICROPY_HW_LED_TX + common_hal_digitalio_digitalinout_construct(&tx_led, MICROPY_HW_LED_TX); + common_hal_digitalio_digitalinout_switch_to_output(&tx_led, true, DRIVE_MODE_PUSH_PULL); + #endif +} + +void toggle_rx_led(void) { + #ifdef MICROPY_HW_LED_RX + common_hal_digitalio_digitalinout_set_value(&rx_led, !common_hal_digitalio_digitalinout_get_value(&rx_led)); + #endif +} + + +void toggle_tx_led(void) { + #ifdef MICROPY_HW_LED_TX + common_hal_digitalio_digitalinout_set_value(&tx_led, !common_hal_digitalio_digitalinout_get_value(&tx_led)); + #endif +} diff --git a/ports/atmel-samd/flash_api.h b/supervisor/shared/status_leds.h index 3e41f59a2..30132753f 100644 --- a/ports/atmel-samd/flash_api.h +++ b/supervisor/shared/status_leds.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2018 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 @@ -23,14 +23,14 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H -#define MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H -#include "extmod/vfs_fat.h" +#ifndef MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H +#define MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H -extern void flash_init_vfs(fs_user_mount_t *vfs); -extern void flash_flush(void); +void init_status_leds(void); -void flash_set_usb_writable(bool usb_writable); +void toggle_rx_led(void); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_FLASH_API_H +void toggle_tx_led(void); + +#endif // MICROPY_INCLUDED_SUPERVISOR_STATUS_LEDS_H diff --git a/ports/nrf/usb/tusb_config.h b/supervisor/shared/usb/tusb_config.h index 626b99eeb..4693bfced 100644 --- a/ports/nrf/usb/tusb_config.h +++ b/supervisor/shared/usb/tusb_config.h @@ -38,6 +38,8 @@ #ifndef _TUSB_CONFIG_H_ #define _TUSB_CONFIG_H_ +#include "genhdr/autogen_usb_descriptor.h" + #ifdef __cplusplus extern "C" { #endif @@ -45,7 +47,6 @@ //--------------------------------------------------------------------+ // COMMON CONFIGURATION //--------------------------------------------------------------------+ -#define CFG_TUSB_MCU OPT_MCU_NRF5X #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #define CFG_TUSB_DEBUG 0 @@ -79,11 +80,6 @@ /* CLASS DRIVER *------------------------------------------------------------------*/ -/*------------- CDC -------------*/ -// FIFO size of CDC TX and RX -#define CFG_TUD_CDC_RX_BUFSIZE 1024 -#define CFG_TUD_CDC_TX_BUFSIZE 1024 - /* TX is sent automatically on every Start of Frame event ~ 1ms. * If not enabled, application must call tud_cdc_flush() periodically * Note: Enabled this could overflow device task, if it does, define @@ -99,17 +95,7 @@ // Number of Blocks #define CFG_TUD_MSC_BLOCK_NUM (256*1024)/512 -// Block size -#define CFG_TUD_MSC_BLOCK_SZ 512 - -// Buffer size for each read/write transfer, the more the better -#define CFG_TUD_MSC_BUFSIZE (4*1024) - -// Vendor name included in Inquiry response, max 8 bytes -#define CFG_TUD_MSC_VENDOR "Adafruit" -// Product name included in Inquiry response, max 16 bytes -#define CFG_TUD_MSC_PRODUCT "CircuitPY nRF52" // Product revision string included in Inquiry response, max 4 bytes #define CFG_TUD_MSC_PRODUCT_REV "1.0" diff --git a/ports/nrf/usb/usb.c b/supervisor/shared/usb/usb.c index 248d31e21..1aa34e9e6 100644 --- a/ports/nrf/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -24,79 +24,47 @@ * THE SOFTWARE. */ -#include "nrfx.h" -#include "nrfx_power.h" #include "tick.h" -#include "usb.h" +#include "shared-bindings/microcontroller/Processor.h" +#include "supervisor/port.h" +#include "supervisor/usb.h" #include "lib/utils/interrupt_char.h" #include "lib/mp-readline/readline.h" -#ifdef SOFTDEVICE_PRESENT -#include "nrf_sdm.h" -#include "nrf_soc.h" -#endif - -/* tinyusb function that handles power event (detected, ready, removed) - * We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. - */ -extern void tusb_hal_nrf_power_event(uint32_t event); - -void usb_init(void) { - - // USB power may already be ready at this time -> no event generated - // We need to invoke the handler based on the status initially - uint32_t usb_reg; - -#ifdef SOFTDEVICE_PRESENT - uint8_t sd_en = false; - (void) sd_softdevice_is_enabled(&sd_en); - - if ( sd_en ) { - sd_power_usbdetected_enable(true); - sd_power_usbpwrrdy_enable(true); - sd_power_usbremoved_enable(true); - - sd_power_usbregstatus_get(&usb_reg); - }else -#endif - { - // Power module init - const nrfx_power_config_t pwr_cfg = { 0 }; - nrfx_power_init(&pwr_cfg); - - // Register tusb function as USB power handler - const nrfx_power_usbevt_config_t config = { .handler = (nrfx_power_usb_event_handler_t) tusb_hal_nrf_power_event }; - nrfx_power_usbevt_init(&config); - - nrfx_power_usbevt_enable(); - - usb_reg = NRF_POWER->USBREGSTATUS; - } +#include "tusb.h" - if ( usb_reg & POWER_USBREGSTATUS_VBUSDETECT_Msk ) { - tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_DETECTED); - } - - if ( usb_reg & POWER_USBREGSTATUS_OUTPUTRDY_Msk ) { - tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY); - } +// Serial number as hex characters. This writes directly to the USB +// descriptor. +extern uint16_t usb_serial_number[1 + COMMON_HAL_MCU_PROCESSOR_UID_LENGTH * 2]; +void load_serial_number(void) { // create serial number based on device unique id - extern uint16_t usb_desc_str_serial[1 + 16]; + uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; + common_hal_mcu_processor_get_uid(raw_id); + + const char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F'}; + for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) { + for (int j = 0; j < 2; j++) { + uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf; + // Strings are UTF-16-LE encoded. + usb_serial_number[1 + i * 2 + j] = nibble_to_hex[nibble]; + } + } +} - char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; +bool _usb_enabled = false; - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 8; j++) { - uint8_t nibble = (NRF_FICR->DEVICEID[i] >> j * 4) & 0xf; +bool usb_enabled(void) { + return _usb_enabled; +} - // Invert order since it is LE, +1 for skipping descriptor header - uint8_t const idx = (15 - (i * 8 + j)) + 1; - usb_desc_str_serial[idx] = nibble_to_hex[nibble]; - } - } +void usb_init(void) { + init_usb_hardware(); + load_serial_number(); tusb_init(); + _usb_enabled = true; #if MICROPY_KBD_EXCEPTION // Set Ctrl+C as wanted char, tud_cdc_rx_wanted_cb() callback will be invoked when Ctrl+C is received @@ -105,6 +73,13 @@ void usb_init(void) { #endif } +void usb_background(void) { + if (usb_enabled()) { + tusb_task(); + tud_cdc_write_flush(); + } +} + //--------------------------------------------------------------------+ // tinyusb callbacks //--------------------------------------------------------------------+ @@ -138,10 +113,7 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { if ( coding.bit_rate == 1200 ) { - enum { DFU_MAGIC_SERIAL = 0x4e }; - - NRF_POWER->GPREGRET = DFU_MAGIC_SERIAL; - NVIC_SystemReset(); + reset_to_bootloader(); } } } @@ -166,4 +138,3 @@ void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char) } #endif - diff --git a/supervisor/shared/usb/usb_desc.c b/supervisor/shared/usb/usb_desc.c new file mode 100644 index 000000000..5a0de1ffc --- /dev/null +++ b/supervisor/shared/usb/usb_desc.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 hathach 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 "supervisor/shared/usb/usb_desc.h" +#include "shared-module/usb_hid/Device.h" + +#include "genhdr/autogen_usb_descriptor.h" + +// tud_desc_set is required by tinyusb stack +tud_desc_set_t tud_desc_set = +{ + .device = &usb_desc_dev, + .config = &usb_desc_cfg, + .string_arr = (uint8_t const **) string_desc_arr, + .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]), + + .hid_report = + { + .generic = hid_report_descriptor, + .boot_keyboard = NULL, + .boot_mouse = NULL + } +}; diff --git a/ports/nrf/usb/usb.h b/supervisor/shared/usb/usb_desc.h index 203260874..250147aa6 100644 --- a/ports/nrf/usb/usb.h +++ b/supervisor/shared/usb/usb_desc.h @@ -1,5 +1,5 @@ /* - * This file is part of the Micro Python project, http://micropython.org/ + * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * @@ -24,11 +24,20 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_NRF_USB_H -#define MICROPY_INCLUDED_NRF_USB_H +#ifndef USB_DESC_H_ +#define USB_DESC_H_ -#include "tusb.h" +#include "lib/tinyusb/src/tusb.h" -void usb_init(void); +#ifdef __cplusplus + extern "C" { +#endif -#endif // MICROPY_INCLUDED_NRF_USB_H +// Descriptors set used by tinyusb stack +extern tud_desc_set_t tud_desc_set; + +#ifdef __cplusplus + } +#endif + +#endif /* USB_DESC_H_ */ diff --git a/ports/nrf/usb/usb_msc_flash.c b/supervisor/shared/usb/usb_msc_flash.c index f78c24145..72dc40204 100644 --- a/ports/nrf/usb/usb_msc_flash.c +++ b/supervisor/shared/usb/usb_msc_flash.c @@ -25,29 +25,39 @@ */ #include "tusb.h" -#include "internal_flash.h" +// // #include "supervisor/flash.h" // For updating fatfs's cache #include "extmod/vfs.h" #include "extmod/vfs_fat.h" +#include "lib/oofatfs/diskio.h" #include "lib/oofatfs/ff.h" #include "py/mpstate.h" #include "supervisor/shared/autoreload.h" -/*------------------------------------------------------------------*/ -/* MACRO TYPEDEF CONSTANT ENUM - *------------------------------------------------------------------*/ -#define MSC_FLASH_ADDR_END 0xED000 -#define MSC_FLASH_SIZE (256*1024) -#define MSC_FLASH_ADDR_START (MSC_FLASH_ADDR_END-MSC_FLASH_SIZE) #define MSC_FLASH_BLOCK_SIZE 512 -#define FL_PAGE_SZ 4096 +// The root FS is always at the end of the list. +static fs_user_mount_t* get_vfs(int lun) { + // TODO(tannewt): Return the mount which matches the lun where 0 is the end + // and is counted in reverse. + if (lun > 0) { + return NULL; + } + mp_vfs_mount_t* current_mount = MP_STATE_VM(vfs_mount_table); + if (current_mount == NULL) { + return NULL; + } + while (current_mount->next != NULL) { + current_mount = current_mount->next; + } + return current_mount->obj; +} // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE -// - READ10 and WRITE10 has their own callbacks +// - READ10 and WRITE10 have their own callbacks int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, uint16_t bufsize) { const void* response = NULL; uint16_t resplen = 0; @@ -56,6 +66,14 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, case SCSI_CMD_TEST_UNIT_READY: // Command that host uses to check our readiness before sending other commands resplen = 0; + if (lun > 1) { + resplen = -1; + } else { + fs_user_mount_t* current_mount = get_vfs(lun); + if (current_mount == NULL) { + resplen = -1; + } + } break; case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL: @@ -64,14 +82,23 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, break; case SCSI_CMD_START_STOP_UNIT: + { // Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power - /* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + const scsi_start_stop_unit_t* start_stop = (const scsi_start_stop_unit_t*) scsi_cmd; // Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well // Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage - start_stop->start; - start_stop->load_eject; - */ resplen = 0; + if (start_stop->load_eject == 1) { + if (lun > 1) { + resplen = -1; + } else { + fs_user_mount_t* current_mount = get_vfs(lun); + if (current_mount == NULL) { + resplen = -1; + } + } + } + } break; default: @@ -96,6 +123,35 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer, return resplen; } +bool tud_lun_capacity_cb(uint8_t lun, uint32_t* last_valid_sector, uint16_t* sector_size) { + fs_user_mount_t * vfs = get_vfs(lun); + if (vfs == NULL || + disk_ioctl(vfs, GET_SECTOR_COUNT, last_valid_sector) != RES_OK || + disk_ioctl(vfs, GET_SECTOR_SIZE, sector_size) != RES_OK) { + return false; + } + // Subtract one from the sector count to get the last valid sector. + (*last_valid_sector)--; + + return true; +} + +bool tud_msc_is_writable_cb(uint8_t lun) { + if (lun > 1) { + return false; + } + + fs_user_mount_t* vfs = get_vfs(lun); + if (vfs == NULL) { + return false; + } + if (vfs->writeblocks[0] == MP_OBJ_NULL || + (vfs->flags & FSUSER_USB_WRITABLE) == 0) { + return false; + } + return true; +} + // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { @@ -104,27 +160,36 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; - internal_flash_read_blocks(buffer, lba, block_count); + fs_user_mount_t * vfs = get_vfs(lun); + disk_read(vfs, buffer, lba, block_count); return block_count * MSC_FLASH_BLOCK_SIZE; } // Callback invoked when received WRITE10 command. // Process data in buffer to disk's storage and return number of written bytes -int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) { +int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) { (void) lun; (void) offset; const uint32_t block_count = bufsize / MSC_FLASH_BLOCK_SIZE; - // bufsize <= CFG_TUD_MSC_BUFSIZE (4096) - internal_flash_write_blocks(buffer, lba, block_count); - - // update fatfs's cache if address matches - fs_user_mount_t* vfs = MP_STATE_VM(vfs_mount_table)->obj; - - if ( (lba <= vfs->fatfs.winsect) && (vfs->fatfs.winsect <= (lba + bufsize / MSC_FLASH_BLOCK_SIZE)) ) { - memcpy(vfs->fatfs.win, buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), MSC_FLASH_BLOCK_SIZE); + fs_user_mount_t * vfs = get_vfs(lun); + disk_write(vfs, buffer, lba, block_count); + // Since by getting here we assume the mount is read-only to + // MicroPython let's update the cached FatFs sector if it's the one + // we just wrote. + #if _MAX_SS != _MIN_SS + if (vfs->ssize == MSC_FLASH_BLOCK_SIZE) { + #else + // The compiler can optimize this away. + if (_MAX_SS == FILESYSTEM_BLOCK_SIZE) { + #endif + if (lba == vfs->fatfs.winsect && lba > 0) { + memcpy(vfs->fatfs.win, + buffer + MSC_FLASH_BLOCK_SIZE * (vfs->fatfs.winsect - lba), + MSC_FLASH_BLOCK_SIZE); + } } return block_count * MSC_FLASH_BLOCK_SIZE; @@ -135,9 +200,6 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* bu void tud_msc_write10_complete_cb (uint8_t lun) { (void) lun; - // flush pending cache when write10 is complete - internal_flash_flush(); - // This write is complete, start the autoreload clock. autoreload_start(); } diff --git a/ports/atmel-samd/external_flash/spi_flash_api.h b/supervisor/spi_flash_api.h index a6df0c459..28cccb1b1 100644 --- a/ports/atmel-samd/external_flash/spi_flash_api.h +++ b/supervisor/spi_flash_api.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2018 Scott Shawcroft for Adafruit Industries LLC * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,13 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H -#define MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#ifndef MICROPY_INCLUDED_SUPERVISOR_SPI_FLASH_H +#define MICROPY_INCLUDED_SUPERVISOR_SPI_FLASH_H #include <stdbool.h> #include <stdint.h> -#include "external_flash/devices.h" +#include "supervisor/shared/external_flash/devices.h" // This API is implemented for both normal SPI peripherals and QSPI peripherals. @@ -42,4 +42,4 @@ bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t data_length); void spi_flash_init(void); void spi_flash_init_device(const external_flash_device* device); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_SPI_FLASH_H +#endif // MICROPY_INCLUDED_SUPERVISOR_SPI_FLASH_H diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk index e516dcb2d..d870f799f 100644 --- a/supervisor/supervisor.mk +++ b/supervisor/supervisor.mk @@ -2,22 +2,78 @@ SRC_SUPERVISOR = \ main.c \ supervisor/port.c \ supervisor/shared/autoreload.c \ + supervisor/shared/filesystem.c \ + supervisor/shared/flash.c \ + supervisor/shared/micropython.c \ supervisor/shared/rgb_led_status.c \ supervisor/shared/stack.c \ + supervisor/shared/status_leds.c \ supervisor/shared/translate.c -ifeq ($(wildcard atmel-samd/supervisor/filesystem.c),) - SRC_SUPERVISOR += supervisor/filesystem.c +ifndef $(NO_USB) +NO_USB = $(wildcard supervisor/usb.c) +endif + + +# Choose which flash filesystem impl to use. +# (Right now INTERNAL_FLASH_FILESYSTEM and SPI_FLASH_FILESYSTEM are mutually exclusive. +# But that might not be true in the future.) +ifdef EXTERNAL_FLASH_DEVICES + CFLAGS += -DEXTERNAL_FLASH_DEVICES=$(EXTERNAL_FLASH_DEVICES) \ + -DEXTERNAL_FLASH_DEVICE_COUNT=$(EXTERNAL_FLASH_DEVICE_COUNT) + + SRC_SUPERVISOR += supervisor/shared/external_flash/external_flash.c + ifeq ($(SPI_FLASH_FILESYSTEM),1) + CFLAGS += -DSPI_FLASH_FILESYSTEM + SRC_SUPERVISOR += supervisor/shared/external_flash/spi_flash.c + endif + ifeq ($(QSPI_FLASH_FILESYSTEM),1) + CFLAGS += -DQSPI_FLASH_FILESYSTEM + SRC_SUPERVISOR += supervisor/qspi_flash.c supervisor/shared/external_flash/qspi_flash.c + endif else - SRC_SUPERVISOR += supervisor/stub/filesystem.c + SRC_SUPERVISOR += supervisor/internal_flash.c endif -ifeq ($(wildcard atmel-samd/supervisor/serial.c),) - SRC_SUPERVISOR += supervisor/serial.c +ifeq ($(USB),FALSE) + ifeq ($(wildcard supervisor/serial.c),) + SRC_SUPERVISOR += supervisor/stub/serial.c + else + SRC_SUPERVISOR += supervisor/serial.c + endif else - SRC_SUPERVISOR += supervisor/stub/serial.c + SRC_SUPERVISOR += lib/tinyusb/src/common/tusb_fifo.c \ + lib/tinyusb/src/device/control.c \ + lib/tinyusb/src/device/usbd.c \ + lib/tinyusb/src/class/msc/msc_device.c \ + lib/tinyusb/src/class/cdc/cdc_device.c \ + lib/tinyusb/src/class/hid/hid_device.c \ + lib/tinyusb/src/tusb.c \ + supervisor/shared/serial.c \ + supervisor/usb.c \ + supervisor/shared/usb/usb_desc.c \ + supervisor/shared/usb/usb.c \ + supervisor/shared/usb/usb_msc_flash.c \ + shared-bindings/usb_hid/__init__.c \ + shared-bindings/usb_hid/Device.c \ + shared-module/usb_hid/__init__.c \ + shared-module/usb_hid/Device.c \ + $(BUILD)/autogen_usb_descriptor.c + CFLAGS += -DUSB_AVAILABLE endif SUPERVISOR_O = $(addprefix $(BUILD)/, $(SRC_SUPERVISOR:.c=.o)) $(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h + +$(BUILD)/autogen_usb_descriptor.c $(BUILD)/genhdr/autogen_usb_descriptor.h: ../../tools/gen_usb_descriptor.py Makefile | $(HEADER_BUILD) + $(STEPECHO) "GEN $@" + $(Q)install -d $(BUILD)/genhdr + $(PYTHON3) ../../tools/gen_usb_descriptor.py \ + --manufacturer $(USB_MANUFACTURER)\ + --product $(USB_PRODUCT)\ + --vid $(USB_VID)\ + --pid $(USB_PID)\ + --serial_number_length $(USB_SERIAL_NUMBER_LENGTH)\ + --output_c_file $(BUILD)/autogen_usb_descriptor.c\ + --output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h diff --git a/ports/atmel-samd/usb.h b/supervisor/usb.h index f01c5ebfb..c87540d40 100644 --- a/ports/atmel-samd/usb.h +++ b/supervisor/usb.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries + * Copyright (c) 2018 hathach 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 @@ -24,19 +24,21 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_ATMEL_SAMD_USB_H -#define MICROPY_INCLUDED_ATMEL_SAMD_USB_H +#ifndef MICROPY_INCLUDED_SUPERVISOR_USB_H +#define MICROPY_INCLUDED_SUPERVISOR_USB_H #include <stdbool.h> -#include <stdint.h> -#define USB_RX_BUF_SIZE 128 +// Ports must call this as frequently as they can in order to keep the USB connection +// alive and responsive. +void usb_background(void); -void init_usb(void); -int usb_read(void); -void usb_write(const char* buffer, uint32_t len); -bool usb_bytes_available(void); -bool usb_connected(void); -void usb_cdc_background(void); +// Only inits the USB peripheral clocks and pins. The peripheral will be initialized by +// TinyUSB. +void init_usb_hardware(void); -#endif // MICROPY_INCLUDED_ATMEL_SAMD_USB_H +// Shared implementation. +bool usb_enabled(void); +void usb_init(void); + +#endif // MICROPY_INCLUDED_SUPERVISOR_USB_H diff --git a/ports/atmel-samd/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py index efa8124bf..b50c0798f 100644 --- a/ports/atmel-samd/tools/gen_usb_descriptor.py +++ b/tools/gen_usb_descriptor.py @@ -3,10 +3,9 @@ import argparse import os import sys -# path hacking sys.path.append("../../tools/usb_descriptor") -from adafruit_usb_descriptor import cdc, hid, msc, standard, util +from adafruit_usb_descriptor import audio, audio10, cdc, hid, midi, msc, standard, util import hid_report_descriptors parser = argparse.ArgumentParser(description='Generate USB descriptors.') @@ -28,16 +27,21 @@ args = parser.parse_args() class StringIndex: """Assign a monotonically increasing index to each unique string. Start with 0.""" string_to_index = {} + index_to_variable = {} strings = [] @classmethod - def index(cls, string): + def index(cls, string, *, variable_name = None): if string in cls.string_to_index: - return cls.string_to_index[string] + idx = cls.string_to_index[string] + if not cls.index_to_variable[idx]: + cls.index_to_variable[idx] = variable_name + return idx else: idx = len(cls.strings) cls.string_to_index[string] = idx cls.strings.append(string) + cls.index_to_variable[idx] = variable_name return idx @classmethod @@ -47,9 +51,9 @@ class StringIndex: # langid must be the 0th string descriptor -LANGID_INDEX = StringIndex.index("\u0409") +LANGID_INDEX = StringIndex.index("\u0409", variable_name="language_id") assert LANGID_INDEX == 0 -SERIAL_NUMBER_INDEX = StringIndex.index("S" * args.serial_number_length) +SERIAL_NUMBER_INDEX = StringIndex.index("S" * args.serial_number_length, variable_name="usb_serial_number") device = standard.DeviceDescriptor( description="top", @@ -76,7 +80,7 @@ cdc_comm_interface = standard.InterfaceDescriptor( description="CDC comm", bInterfaceClass=cdc.CDC_CLASS_COMM, # Communications Device Class bInterfaceSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model - bInterfaceProtocol=cdc.CDC_PROTOCOL_NONE, + bInterfaceProtocol=cdc.CDC_PROTOCOL_V25TER, iInterface=StringIndex.index("CircuitPython CDC control"), subdescriptors=[ cdc.Header( @@ -155,12 +159,6 @@ hid_endpoint_in_descriptor = standard.EndpointDescriptor( bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, bInterval=10) -hid_endpoint_out_descriptor = standard.EndpointDescriptor( - description="HID out", - bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, - bmAttributes=standard.EndpointDescriptor.TYPE_INTERRUPT, - bInterval=10) - hid_interfaces = [ standard.InterfaceDescriptor( description="HID Multiple Devices", @@ -173,11 +171,71 @@ hid_interfaces = [ description="HID", wDescriptorLength=len(bytes(combined_hid_report_descriptor))), hid_endpoint_in_descriptor, - hid_endpoint_out_descriptor, ] ), ] +# Audio! +midi_in_jack = midi.InJackDescriptor( + description="MIDI PC <- CircuitPython internals", + bJackType=midi.JACK_TYPE_EMBEDDED, + iJack=0) +midi_out_jack = midi.OutJackDescriptor( + description="MIDI PC -> CircuitPython internals", + bJackType=midi.JACK_TYPE_EMBEDDED, + iJack=0) +audio_midi_interface = standard.InterfaceDescriptor( + description="All the audio", + bInterfaceClass=audio.AUDIO_CLASS_DEVICE, + bInterfaceSubClass=audio.AUDIO_SUBCLASS_MIDI_STREAMING, + bInterfaceProtocol=audio.AUDIO_PROTOCOL_V1, + iInterface=StringIndex.index("CircuitPython MIDI"), + subdescriptors=[ + midi.Header( + jacks_and_elements=[ + midi_in_jack, + midi.InJackDescriptor( + description="MIDI data in from user code.", + bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0), + midi_out_jack, + midi.OutJackDescriptor( + description="MIDI data out to user code.", + bJackType=midi.JACK_TYPE_EXTERNAL, iJack=0), + ] + ), + standard.EndpointDescriptor( + description="MIDI data out", + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_OUT, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + midi.DataEndpointDescriptor(baAssocJack=[midi_out_jack]), + standard.EndpointDescriptor( + description="MIDI data in", + bEndpointAddress=0x0 | standard.EndpointDescriptor.DIRECTION_IN, + bmAttributes=standard.EndpointDescriptor.TYPE_BULK), + midi.DataEndpointDescriptor(baAssocJack=[midi_in_jack]), + ]) + +cs_ac_interface = audio10.AudioControlInterface( + description="Empty audio control", + audio_streaming_interfaces = [], + midi_streaming_interfaces = [ + audio_midi_interface + ] + ) + +audio_control_interface = standard.InterfaceDescriptor( + description="All the audio", + bInterfaceClass=audio.AUDIO_CLASS_DEVICE, + bInterfaceSubClass=audio.AUDIO_SUBCLASS_CONTROL, + bInterfaceProtocol=audio.AUDIO_PROTOCOL_V1, + iInterface=StringIndex.index("CircuitPython Audio"), + subdescriptors=[ + cs_ac_interface, + ]) + +# Audio streaming interfaces must occur before MIDI ones. +# audio_interfaces = [audio_control_interface] + cs_ac_interface.audio_streaming_interfaces + cs_ac_interface.midi_streaming_interfaces + # This will renumber the endpoints to make them unique across descriptors, # and renumber the interfaces in order. But we still need to fix up certain # interface cross-references. @@ -194,23 +252,25 @@ cdc_iad = standard.InterfaceAssociationDescriptor( description="CDC IAD", bFirstInterface=cdc_comm_interface.bInterfaceNumber, bInterfaceCount=len(cdc_interfaces), - bFunctionClass=0x2, # Communications Device Class - bFunctionSubClass=0x2, # Abstract control model - bFunctionProtocol=0x1) + bFunctionClass=cdc.CDC_CLASS_COMM, # Communications Device Class + bFunctionSubClass=cdc.CDC_SUBCLASS_ACM, # Abstract control model + bFunctionProtocol=cdc.CDC_PROTOCOL_V25TER) # TODO(tannewt): can this be NONE (aka 0)? + +# audio_iad = standard.InterfaceAssociationDescriptor( +# description="Audio IAD", +# bFirstInterface=audio_control_interface.bInterfaceNumber, +# bInterfaceCount=len(audio_interfaces), +# bFunctionClass=audio.AUDIO_CLASS_DEVICE, +# bFunctionSubClass=audio.AUDIO_SUBCLASS_UNKNOWN, +# bFunctionProtocol=audio.AUDIO_PROTOCOL_V1) -configuration = standard.ConfigurationDescriptor( - description="Composite configuration", - wTotalLength=(standard.ConfigurationDescriptor.bLength + - cdc_iad.bLength + - sum([len(bytes(x)) for x in interfaces])), - bNumInterfaces=len(interfaces)) descriptor_list = [] -descriptor_list.append(device) -descriptor_list.append(configuration) descriptor_list.append(cdc_iad) +# descriptor_list.append(audio_iad) descriptor_list.extend(cdc_interfaces) descriptor_list.extend(msc_interfaces) +# descriptor_list.append(audio_control_interface) # Put the CDC IAD just before the CDC interfaces. # There appears to be a bug in the Windows composite USB driver that requests the # HID report descriptor with the wrong interface number if the HID interface is not given @@ -219,9 +279,15 @@ descriptor_list.extend(msc_interfaces) # there for backwards compatibility. descriptor_list.extend(hid_interfaces) +configuration = standard.ConfigurationDescriptor( + description="Composite configuration", + wTotalLength=(standard.ConfigurationDescriptor.bLength + + sum([len(bytes(x)) for x in descriptor_list])), + bNumInterfaces=len(interfaces)) +descriptor_list.insert(0, configuration) + string_descriptors = [standard.StringDescriptor(string) for string in StringIndex.strings_in_order()] serial_number_descriptor = string_descriptors[SERIAL_NUMBER_INDEX] -descriptor_list.extend(string_descriptors) c_file = args.output_c_file h_file = args.output_h_file @@ -232,17 +298,29 @@ c_file.write("""\ #include "{H_FILE_NAME}" -#include "usb/device/usbdc.h" - """.format(H_FILE_NAME=h_file.name)) c_file.write("""\ -uint8_t usb_descriptors[] = { +// {DESCRIPTION} : {CLASS} +""".format(DESCRIPTION=device.description, + CLASS=device.__class__)) + +c_file.write("""\ +const uint8_t usb_desc_dev[] = { +""") +for b in bytes(device): + c_file.write("0x{:02x}, ".format(b)) + +c_file.write("""\ +}; +""") + +c_file.write("""\ +const uint8_t usb_desc_cfg[] = { """) # Write out all the regular descriptors as one long array (that's how ASF4 does it). descriptor_length = 0 -serial_number_offset = None for descriptor in descriptor_list: c_file.write("""\ // {DESCRIPTION} : {CLASS} @@ -250,91 +328,140 @@ for descriptor in descriptor_list: CLASS=descriptor.__class__)) b = bytes(descriptor) + notes = descriptor.notes() i = 0 - if descriptor == serial_number_descriptor: - # Add two for bLength and bDescriptorType. - serial_number_offset = descriptor_length + 2 - # This prints each subdescriptor on a separate line. + n = 0 while i < len(b): length = b[i] for j in range(length): c_file.write("0x{:02x}, ".format(b[i + j])) + c_file.write("// " + notes[n]) + n += 1 c_file.write("\n") i += length - descriptor_length += length + descriptor_length += len(b) +c_file.write("""\ +}; +""") + +pointers_to_strings = [] + +for idx, descriptor in enumerate(string_descriptors): + c_file.write("""\ +// {DESCRIPTION} : {CLASS} +""".format(DESCRIPTION=descriptor.description, + CLASS=descriptor.__class__)) + + b = bytes(descriptor) + notes = descriptor.notes() + i = 0 + + # This prints each subdescriptor on a separate line. + variable_name = StringIndex.index_to_variable[idx] + if not variable_name: + variable_name = "string_descriptor{}".format(idx) + + const = "const " + if variable_name == "usb_serial_number": + const = "" + c_file.write("""\ +{const}uint16_t {NAME}[] = {{ +""".format(const=const, NAME=variable_name)) + pointers_to_strings.append("{name}".format(name=variable_name)) + n = 0 + while i < len(b): + length = b[i] + for j in range(length // 2): + c_file.write("0x{:04x}, ".format(b[i + 2*j + 1] << 8 | b[i + 2*j])) + n += 1 + c_file.write("\n") + i += length + c_file.write("""\ +}; +""") c_file.write("""\ +// array of pointer to string descriptors +uint16_t const * const string_desc_arr [] = +{ +""") +c_file.write(""",\ + +""".join(pointers_to_strings)) + +c_file.write(""" }; """) +c_file.write("\n"); + +hid_descriptor_length = len(bytes(combined_hid_report_descriptor)) + # Now we values we need for the .h file. h_file.write("""\ #ifndef MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H #define MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H -#define SERIAL_NUMBER_OFFSET {SERIAL_NUMBER_OFFSET} -#define SERIAL_NUMBER_LENGTH {SERIAL_NUMBER_LENGTH} -uint8_t* serial_number; +#include <stdint.h> + +const uint8_t usb_desc_dev[{device_length}]; +// Make sure the control buffer is big enough to fit the descriptor. +#define CFG_TUD_ENUM_BUFFER_SIZE {max_configuration_length} +const uint8_t usb_desc_cfg[{configuration_length}]; +uint16_t usb_serial_number[{serial_number_length}]; +uint16_t const * const string_desc_arr [{string_descriptor_length}]; + +const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}]; + +// Vendor name included in Inquiry response, max 8 bytes +#define CFG_TUD_MSC_VENDOR "{msc_vendor}" -uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}]; -#define USB_HID_ENDPOINT_IN {HID_ENDPOINT_IN_ADDRESS} -#define USB_HID_ENDPOINT_OUT {HID_ENDPOINT_OUT_ADDRESS} +// Product name included in Inquiry response, max 16 bytes +#define CFG_TUD_MSC_PRODUCT "{msc_product}" """ -.format(SERIAL_NUMBER_OFFSET=serial_number_offset, - SERIAL_NUMBER_LENGTH=args.serial_number_length, +.format(serial_number_length=len(bytes(serial_number_descriptor)) // 2, + device_length=len(bytes(device)), + configuration_length=descriptor_length, + max_configuration_length=max(hid_descriptor_length, descriptor_length), + string_descriptor_length=len(pointers_to_strings), HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)), - HID_ENDPOINT_IN_ADDRESS=hex(hid_endpoint_in_descriptor.bEndpointAddress), - HID_ENDPOINT_OUT_ADDRESS=hex(hid_endpoint_out_descriptor.bEndpointAddress))) - -# Write out #define's that declare which endpoints are in use. -# These provide information for declaring cache sizes and perhaps other things at compile time -for interface in interfaces: - for subdescriptor in interface.subdescriptors: - if isinstance(subdescriptor, standard.EndpointDescriptor): - endpoint_num = subdescriptor.bEndpointAddress & standard.EndpointDescriptor.NUMBER_MASK - endpoint_in = ((subdescriptor.bEndpointAddress & standard.EndpointDescriptor.DIRECTION_MASK) == - standard.EndpointDescriptor.DIRECTION_IN) - h_file.write("""\ -#define USB_ENDPOINT_{NUMBER}_{DIRECTION}_USED 1 -""".format(NUMBER=endpoint_num, - DIRECTION="IN" if endpoint_in else "OUT")) - -h_file.write("\n") + msc_vendor=args.manufacturer[:8], + msc_product=args.product[:16])) # #define the report ID's used in the combined HID descriptor for name, id in hid_report_ids_dict.items(): h_file.write("""\ -#define USB_HID_REPORT_ID_{NAME} {ID} -""".format(NAME=name, - ID = id)) +#define USB_HID_REPORT_ID_{name} {id} +""".format(name=name, + id=id)) h_file.write("\n") # #define the report sizes used in the combined HID descriptor for name, length in hid_report_lengths_dict.items(): h_file.write("""\ -#define USB_HID_REPORT_LENGTH_{NAME} {LENGTH} -""".format(NAME=name, - LENGTH=length)) +#define USB_HID_REPORT_LENGTH_{name} {length} +""".format(name=name, + length=length)) h_file.write("\n") h_file.write("""\ -#define USB_HID_NUM_DEVICES {NUM_DEVICES} -#define USB_HID_MAX_REPORT_LENGTH {MAX_LENGTH} -""".format(NUM_DEVICES=len(hid_report_lengths_dict), - MAX_LENGTH=hid_max_report_length)) +#define USB_HID_NUM_DEVICES {num_devices} +#define USB_HID_MAX_REPORT_LENGTH {max_length} +""".format(num_devices=len(hid_report_lengths_dict), + max_length=hid_max_report_length)) # Write out the report descriptor and info c_file.write("""\ -uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{ -""".format(HID_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)))) +const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{ +""".format(HID_DESCRIPTOR_LENGTH=hid_descriptor_length)) for b in bytes(combined_hid_report_descriptor): c_file.write("0x{:02x}, ".format(b)) @@ -342,12 +469,6 @@ c_file.write(""" }; """) -c_file.write("""\ - -struct usbd_descriptors descriptor_bounds = {{usb_descriptors, usb_descriptors + sizeof(usb_descriptors)}}; -uint8_t* serial_number = usb_descriptors + {SERIAL_NUMBER_OFFSET}; -""".format(SERIAL_NUMBER_OFFSET=serial_number_offset)) - h_file.write("""\ #endif // MICROPY_INCLUDED_AUTOGEN_USB_DESCRIPTOR_H """) diff --git a/ports/atmel-samd/tools/hid_report_descriptors.py b/tools/hid_report_descriptors.py index f3b28ebcf..f3b28ebcf 100644 --- a/ports/atmel-samd/tools/hid_report_descriptors.py +++ b/tools/hid_report_descriptors.py diff --git a/tools/usb_descriptor b/tools/usb_descriptor -Subproject 2507847031a0395465956539253cbfa27f87511 +Subproject 57bf602dac9cba8c4226f764c286cbc60103d67 |
