From 5d732f45bb05f52251aae892d765658c7bc9173d Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Thu, 6 Jul 2017 13:41:13 -0700 Subject: [PATCH] atmel-samd: Reboot to bootloader when a 1200 baud serial connection is closed. This is how Arduino triggers the bootloader. --- atmel-samd/Makefile | 1 + atmel-samd/boards/arduino_zero/conf_usb.h | 5 ++- .../circuitplayground_express/conf_usb.h | 5 ++- .../boards/feather_m0_adalogger/conf_usb.h | 5 ++- atmel-samd/boards/feather_m0_basic/conf_usb.h | 5 ++- .../boards/feather_m0_express/conf_usb.h | 5 ++- atmel-samd/boards/gemma_m0/conf_usb.h | 5 ++- atmel-samd/boards/metro_m0_express/conf_usb.h | 7 +++- atmel-samd/boards/trinket_m0/conf_usb.h | 6 ++- atmel-samd/mphalport.c | 38 ++++++++++-------- atmel-samd/reset.c | 40 +++++++++++++++++++ atmel-samd/reset.h | 31 ++++++++++++++ 12 files changed, 127 insertions(+), 26 deletions(-) create mode 100644 atmel-samd/reset.c create mode 100644 atmel-samd/reset.h diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index fbd89cc5ad..d77ccdb745 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -190,6 +190,7 @@ SRC_C = \ main.c \ moduos.c \ mphalport.c \ + reset.c \ samd21_pins.c \ shared_dma.c \ rgb_led_status.c \ diff --git a/atmel-samd/boards/arduino_zero/conf_usb.h b/atmel-samd/boards/arduino_zero/conf_usb.h index 9ef8dd836d..98c9abe892 100644 --- a/atmel-samd/boards/arduino_zero/conf_usb.h +++ b/atmel-samd/boards/arduino_zero/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/circuitplayground_express/conf_usb.h b/atmel-samd/boards/circuitplayground_express/conf_usb.h index 5f95708626..971bee331f 100644 --- a/atmel-samd/boards/circuitplayground_express/conf_usb.h +++ b/atmel-samd/boards/circuitplayground_express/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/feather_m0_adalogger/conf_usb.h b/atmel-samd/boards/feather_m0_adalogger/conf_usb.h index 5a65ed6e64..8ec6f99dc5 100644 --- a/atmel-samd/boards/feather_m0_adalogger/conf_usb.h +++ b/atmel-samd/boards/feather_m0_adalogger/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/feather_m0_basic/conf_usb.h b/atmel-samd/boards/feather_m0_basic/conf_usb.h index 93abf17b76..940fc26bd4 100644 --- a/atmel-samd/boards/feather_m0_basic/conf_usb.h +++ b/atmel-samd/boards/feather_m0_basic/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/feather_m0_express/conf_usb.h b/atmel-samd/boards/feather_m0_express/conf_usb.h index 8453b48fd9..54313030cb 100644 --- a/atmel-samd/boards/feather_m0_express/conf_usb.h +++ b/atmel-samd/boards/feather_m0_express/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/gemma_m0/conf_usb.h b/atmel-samd/boards/gemma_m0/conf_usb.h index c020ebf4ea..dd5316b8fe 100644 --- a/atmel-samd/boards/gemma_m0/conf_usb.h +++ b/atmel-samd/boards/gemma_m0/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/metro_m0_express/conf_usb.h b/atmel-samd/boards/metro_m0_express/conf_usb.h index 1bbf0b7eee..0a623fa06f 100644 --- a/atmel-samd/boards/metro_m0_express/conf_usb.h +++ b/atmel-samd/boards/metro_m0_express/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -19,7 +21,7 @@ #endif #ifndef USB_DEVICE_PRODUCT_NAME -# define USB_DEVICE_PRODUCT_NAME "Metro M0 with Flash (Experimental)" +# define USB_DEVICE_PRODUCT_NAME "Metro M0 Express" #endif // #define USB_DEVICE_SERIAL_NAME "12...EF" #define USB_DEVICE_GET_SERIAL_NAME_POINTER serial_number @@ -55,7 +57,8 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/boards/trinket_m0/conf_usb.h b/atmel-samd/boards/trinket_m0/conf_usb.h index 4d8d368a8a..2e6cee1bc4 100644 --- a/atmel-samd/boards/trinket_m0/conf_usb.h +++ b/atmel-samd/boards/trinket_m0/conf_usb.h @@ -2,6 +2,8 @@ #include #include +#include "asf/common/services/usb/class/cdc/usb_protocol_cdc.h" + #ifndef CONF_USB_H_INCLUDED #define CONF_USB_H_INCLUDED @@ -55,7 +57,9 @@ extern void mp_cdc_disable(uint8_t port); #define UDI_CDC_RX_NOTIFY(port) usb_rx_notify() void usb_rx_notify(void); -#define UDI_CDC_SET_CODING_EXT(port,cfg) + +#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_coding_notify(port, cfg) +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding); #define UDI_CDC_SET_DTR_EXT(port,set) usb_dtr_notify(port, set) void usb_dtr_notify(uint8_t port, bool set); #define UDI_CDC_SET_RTS_EXT(port,set) usb_rts_notify(port, set) diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c index ed64c55293..34eecc9baa 100644 --- a/atmel-samd/mphalport.c +++ b/atmel-samd/mphalport.c @@ -39,38 +39,42 @@ extern struct usart_module usart_instance; // Read by main to know when USB is connected. volatile bool mp_msc_enabled = false; -bool mp_msc_enable() -{ - mp_msc_enabled = true; - return true; +bool mp_msc_enable() { + mp_msc_enabled = true; + return true; } -void mp_msc_disable() -{ - mp_msc_enabled = false; +void mp_msc_disable() { + mp_msc_enabled = false; } -bool mp_cdc_enable(uint8_t port) -{ - mp_cdc_enabled = false; - return true; +bool mp_cdc_enable(uint8_t port) { + mp_cdc_enabled = false; + return true; } -void mp_cdc_disable(uint8_t port) -{ - mp_cdc_enabled = false; +void mp_cdc_disable(uint8_t port) { + mp_cdc_enabled = false; } +volatile bool reset_on_disconnect = false; + void usb_dtr_notify(uint8_t port, bool set) { - mp_cdc_enabled = set; + mp_cdc_enabled = set; + if (!set && reset_on_disconnect) { + reset_to_bootloader(); + } } void usb_rts_notify(uint8_t port, bool set) { return; } -void usb_rx_notify(void) -{ +void usb_coding_notify(uint8_t port, usb_cdc_line_coding_t* coding) { + reset_on_disconnect = coding->dwDTERate == 1200; +} + +void usb_rx_notify(void) { irqflags_t flags; if (mp_cdc_enabled) { while (udi_cdc_is_rx_ready()) { diff --git a/atmel-samd/reset.c b/atmel-samd/reset.c new file mode 100644 index 0000000000..85090c7e8c --- /dev/null +++ b/atmel-samd/reset.c @@ -0,0 +1,40 @@ +/* + * 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 "flash_api.h" +#include "reset.h" + +#include "asf/sam0/utils/cmsis/samd21/include/samd21.h" + +// Copied from inc/uf2.h in https://github.com/Microsoft/uf2-samd21 +#define DBL_TAP_PTR ((volatile uint32_t *)(HMCRAMC0_ADDR + HMCRAMC0_SIZE - 4)) +#define DBL_TAP_MAGIC 0xf01669ef // Randomly selected, adjusted to have first and last bit set + +void reset_to_bootloader(void) { + flash_flush(); + *DBL_TAP_PTR = DBL_TAP_MAGIC; + NVIC_SystemReset(); +} diff --git a/atmel-samd/reset.h b/atmel-samd/reset.h new file mode 100644 index 0000000000..5ed2e01408 --- /dev/null +++ b/atmel-samd/reset.h @@ -0,0 +1,31 @@ +/* + * 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. + */ +#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_RESET_H__ +#define __MICROPY_INCLUDED_ATMEL_SAMD_RESET_H__ + +void reset_to_bootloader(void); + +#endif // __MICROPY_INCLUDED_ATMEL_SAMD_RESET_H__