summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--atmel-samd/Makefile3
-rw-r--r--atmel-samd/access_vfs.c4
-rw-r--r--atmel-samd/autoreset.c87
-rw-r--r--atmel-samd/autoreset.h39
-rw-r--r--atmel-samd/boards/arduino_zero/mpconfigboard.h2
-rw-r--r--atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h2
-rw-r--r--atmel-samd/boards/feather_m0_basic/mpconfigboard.h2
-rw-r--r--atmel-samd/boards/metro_m0_flash/mpconfigboard.h2
-rw-r--r--atmel-samd/internal_flash.c3
-rw-r--r--atmel-samd/main.c22
-rw-r--r--atmel-samd/mphalport.c38
-rw-r--r--lib/mp-readline/readline.h2
-rw-r--r--lib/utils/pyexec.c1
-rw-r--r--py/misc.h2
14 files changed, 207 insertions, 2 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile
index fbdfa3f93..2cd917beb 100644
--- a/atmel-samd/Makefile
+++ b/atmel-samd/Makefile
@@ -101,6 +101,7 @@ CFLAGS_CORTEX_M0 = \
-DEXTINT_CALLBACK_MODE=true \
-DUDD_ENABLE \
-DUSART_CALLBACK_MODE=true \
+ -DTC_ASYNC=true \
-DUSB_DEVICE_LPM_SUPPORT
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT)
@@ -135,6 +136,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
drivers/system/interrupt/system_interrupt.c \
drivers/system/pinmux/pinmux.c \
drivers/system/system.c \
+ drivers/tc/tc_interrupt.c \
drivers/tc/tc_sam_d_r/tc.c \
drivers/tcc/tcc.c \
drivers/usb/stack_interface/usb_device_udd.c \
@@ -144,6 +146,7 @@ SRC_ASF = $(addprefix asf/sam0/,\
SRC_C = \
access_vfs.c \
+ autoreset.c \
builtin_open.c \
fatfs_port.c \
main.c \
diff --git a/atmel-samd/access_vfs.c b/atmel-samd/access_vfs.c
index cfd5dfe54..a8cb33e9c 100644
--- a/atmel-samd/access_vfs.c
+++ b/atmel-samd/access_vfs.c
@@ -27,11 +27,13 @@
#include <string.h>
#include "access_vfs.h"
+#include "autoreset.h"
#include "asf/common/services/usb/class/msc/device/udi_msc.h"
#include "extmod/fsusermount.h"
#include "lib/fatfs/diskio.h"
#include "py/mpconfig.h"
+#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/misc.h"
@@ -140,7 +142,6 @@ Ctrl_status vfs_usb_read_10(uint32_t addr, volatile uint16_t nb_sector)
return CTRL_GOOD;
}
-
//! This function transfers the USB MSC data to the memory
//!
//! @param addr Sector address to start write
@@ -183,5 +184,6 @@ Ctrl_status vfs_usb_write_10(uint32_t addr, volatile uint16_t nb_sector)
}
}
}
+ autoreset_start();
return CTRL_GOOD;
}
diff --git a/atmel-samd/autoreset.c b/atmel-samd/autoreset.c
new file mode 100644
index 000000000..ef7ca62a5
--- /dev/null
+++ b/atmel-samd/autoreset.c
@@ -0,0 +1,87 @@
+/*
+ * This file is part of the Micro Python 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 "autoreset.h"
+
+#include "asf/sam0/drivers/tc/tc_interrupt.h"
+#include "lib/mp-readline/readline.h"
+#include "py/mphal.h"
+
+struct tc_module autoreset_timer;
+
+static bool autoreset_initialized = false;
+
+static bool autoreset_enabled = false;
+
+extern void inject_character(char);
+void mp_keyboard_interrupt(void);
+
+void autoreset_callback(struct tc_module *const module_inst) {
+ if (autoreset_enabled) {
+ mp_keyboard_interrupt();
+ inject_character(CHAR_CTRL_D);
+ }
+
+ tc_stop_counter(&autoreset_timer);
+}
+
+void autoreset_init() {
+ #ifdef AUTORESET_TIMER
+ struct tc_config config_tc;
+ tc_get_config_defaults(&config_tc);
+ config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
+ config_tc.clock_prescaler = TC_CLOCK_PRESCALER_DIV256;
+ config_tc.counter_16_bit.compare_capture_channel[0] = 0xFFFF;
+ tc_init(&autoreset_timer, AUTORESET_TIMER, &config_tc);
+ tc_enable(&autoreset_timer);
+ tc_register_callback(&autoreset_timer, autoreset_callback, TC_CALLBACK_CC_CHANNEL0);
+ tc_enable_callback(&autoreset_timer, TC_CALLBACK_CC_CHANNEL0);
+ tc_stop_counter(&autoreset_timer);
+
+ autoreset_initialized = true;
+ #endif
+}
+
+void autoreset_enable() {
+ autoreset_enabled = true;
+}
+
+void autoreset_disable() {
+ autoreset_enabled = false;
+}
+
+void autoreset_start() {
+ if (!autoreset_initialized) return;
+
+ tc_stop_counter(&autoreset_timer);
+ tc_start_counter(&autoreset_timer);
+}
+
+void autoreset_stop() {
+ if (!autoreset_initialized) return;
+
+ tc_stop_counter(&autoreset_timer);
+}
diff --git a/atmel-samd/autoreset.h b/atmel-samd/autoreset.h
new file mode 100644
index 000000000..da9803fde
--- /dev/null
+++ b/atmel-samd/autoreset.h
@@ -0,0 +1,39 @@
+/*
+ * This file is part of the Micro Python 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.
+ */
+
+#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__
+#define __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__
+
+#include "asf/sam0/drivers/tc/tc.h"
+
+void autoreset_callback(struct tc_module *const module_inst);
+void autoreset_init();
+void autoreset_start();
+void autoreset_stop();
+void autoreset_enable();
+void autoreset_disable();
+
+#endif // __MICROPY_INCLUDED_ATMEL_SAMD_AUTORESET_H__
diff --git a/atmel-samd/boards/arduino_zero/mpconfigboard.h b/atmel-samd/boards/arduino_zero/mpconfigboard.h
index fbebaed2d..42b4e7635 100644
--- a/atmel-samd/boards/arduino_zero/mpconfigboard.h
+++ b/atmel-samd/boards/arduino_zero/mpconfigboard.h
@@ -8,3 +8,5 @@
#define MICROPY_HW_LED_TX PIN_PA27
#define MICROPY_HW_LED_RX PIN_PB03
+
+#define AUTORESET_TIMER TC5
diff --git a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h
index f820ce4a5..8af47af1e 100644
--- a/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h
+++ b/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.h
@@ -5,3 +5,5 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Adalogger"
#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define AUTORESET_TIMER TC5
diff --git a/atmel-samd/boards/feather_m0_basic/mpconfigboard.h b/atmel-samd/boards/feather_m0_basic/mpconfigboard.h
index a5b3ef063..29027c0b8 100644
--- a/atmel-samd/boards/feather_m0_basic/mpconfigboard.h
+++ b/atmel-samd/boards/feather_m0_basic/mpconfigboard.h
@@ -5,3 +5,5 @@
#define MICROPY_HW_BOARD_NAME "Adafruit Feather M0 Basic"
#define MICROPY_HW_MCU_NAME "samd21g18"
+
+#define AUTORESET_TIMER TC5
diff --git a/atmel-samd/boards/metro_m0_flash/mpconfigboard.h b/atmel-samd/boards/metro_m0_flash/mpconfigboard.h
index a4e1e3fc5..3cbd0a641 100644
--- a/atmel-samd/boards/metro_m0_flash/mpconfigboard.h
+++ b/atmel-samd/boards/metro_m0_flash/mpconfigboard.h
@@ -29,3 +29,5 @@
#define SPI_FLASH_PAD3_PINMUX PINMUX_PB11D_SERCOM4_PAD3 // SCK
#define SPI_FLASH_CS PIN_PA13
#define SPI_FLASH_SERCOM SERCOM4
+
+#define AUTORESET_TIMER TC5
diff --git a/atmel-samd/internal_flash.c b/atmel-samd/internal_flash.c
index 68a3100c5..1bbbd23e8 100644
--- a/atmel-samd/internal_flash.c
+++ b/atmel-samd/internal_flash.c
@@ -27,6 +27,7 @@
#include <stdint.h>
#include <string.h>
+#include "py/mphal.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
@@ -40,7 +41,7 @@
#define TOTAL_INTERNAL_FLASH_SIZE 0x010000
#define INTERNAL_FLASH_MEM_SEG1_START_ADDR (0x00040000 - TOTAL_INTERNAL_FLASH_SIZE)
-#define INTERNAL_FLASH_PART1_START_BLOCK (0x100)
+#define INTERNAL_FLASH_PART1_START_BLOCK (0x1)
#define INTERNAL_FLASH_PART1_NUM_BLOCKS (TOTAL_INTERNAL_FLASH_SIZE / INTERNAL_FLASH_BLOCK_SIZE)
static bool internal_flash_is_initialised = false;
diff --git a/atmel-samd/main.c b/atmel-samd/main.c
index df259d9c4..2a0dff851 100644
--- a/atmel-samd/main.c
+++ b/atmel-samd/main.c
@@ -22,6 +22,7 @@
#include "asf/sam0/drivers/system/system.h"
#include <board.h>
+#include "autoreset.h"
#include "mpconfigboard.h"
#include "modmachine_pin.h"
@@ -172,6 +173,9 @@ static char *stack_top;
static char heap[16384];
void reset_mp() {
+ autoreset_stop();
+ autoreset_enable();
+
// Sync the file systems in case any used RAM from the GC to cache. As soon
// as we re-init the GC all bets are off on the cache.
disk_ioctl(0, CTRL_SYNC, NULL);
@@ -191,8 +195,18 @@ void reset_mp() {
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
pin_init0();
+}
+
+void start_mp() {
+ #ifdef AUTORESET_TIMER
+ mp_hal_stdout_tx_str("\r\n");
+ mp_hal_stdout_tx_str("Auto-soft reset is on. Simply save files over USB to run them.\r\n");
+ mp_hal_stdout_tx_str("Type anything into the REPL to disable and manually reset (CTRL-D) to re-enable.\r\n");
+ #endif
+ mp_hal_stdout_tx_str("boot.py output:\r\n");
pyexec_file("boot.py");
+ mp_hal_stdout_tx_str("\r\nmain.py output:\r\n");
pyexec_file("main.py");
}
@@ -216,11 +230,18 @@ int main(int argc, char **argv) {
// as current dir.
init_flash_fs();
+ // Initialize the autoreset timer. It will automatically reset the repl
+ // after a burst of writes to the FS.
+ autoreset_init();
+
// Start USB after getting everything going.
#ifdef USB_REPL
udc_start();
#endif
+ // Run boot and main.
+ start_mp();
+
// Main script is finished, so now go into REPL mode.
// The REPL mode can change, or it can request a soft reset.
int exit_code = 0;
@@ -233,6 +254,7 @@ int main(int argc, char **argv) {
if (exit_code == PYEXEC_FORCED_EXIT) {
mp_hal_stdout_tx_str("soft reboot\r\n");
reset_mp();
+ start_mp();
} else if (exit_code != 0) {
break;
}
diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c
index 7102bf220..c84640fd5 100644
--- a/atmel-samd/mphalport.c
+++ b/atmel-samd/mphalport.c
@@ -1,5 +1,6 @@
#include <string.h>
+#include "autoreset.h"
#include "compiler.h"
#include "asf/common/services/sleepmgr/sleepmgr.h"
#include "asf/common/services/usb/class/cdc/device/udi_cdc.h"
@@ -67,6 +68,40 @@ void usb_rts_notify(uint8_t port, bool set) {
return;
}
+void inject_character(char c) {
+ // Introduce a critical section to avoid buffer corruption. We use
+ // cpu_irq_save instead of cpu_irq_disable because we don't know the
+ // current state of IRQs. They may have been turned off already and
+ // we don't want to accidentally turn them back on.
+ irqflags_t flags = cpu_irq_save();
+ // If our buffer is full, then don't get another character otherwise
+ // we'll lose a previous character.
+ if (usb_rx_count >= USB_RX_BUF_SIZE) {
+ cpu_irq_restore(flags);
+ return;
+ }
+
+ uint8_t current_tail = usb_rx_buf_tail;
+ // Pretend we've received a character so that any nested calls to
+ // this function have to consider the spot we've reserved.
+ if ((USB_RX_BUF_SIZE - 1) == usb_rx_buf_tail) {
+ // Reached the end of buffer, revert back to beginning of
+ // buffer.
+ usb_rx_buf_tail = 0x00;
+ } else {
+ usb_rx_buf_tail++;
+ }
+ // The count of characters present in receive buffer is
+ // incremented.
+ usb_rx_count++;
+
+ // We put the next character where we expected regardless of whether
+ // the next character was already loaded in the buffer.
+ usb_rx_buf[current_tail] = c;
+
+ cpu_irq_restore(flags);
+}
+
void usb_rx_notify(void)
{
irqflags_t flags;
@@ -129,6 +164,9 @@ int receive_usb() {
return 0;
}
+ // Disable autoreset if someone is using the repl.
+ autoreset_disable();
+
// Copy from head.
cpu_irq_disable();
int data = usb_rx_buf[usb_rx_buf_head];
diff --git a/lib/mp-readline/readline.h b/lib/mp-readline/readline.h
index f73934d23..ffb0d0e1c 100644
--- a/lib/mp-readline/readline.h
+++ b/lib/mp-readline/readline.h
@@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
+#include "py/misc.h"
+
#define CHAR_CTRL_A (1)
#define CHAR_CTRL_B (2)
#define CHAR_CTRL_C (3)
diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c
index f9bbf68a1..ce68e40b3 100644
--- a/lib/utils/pyexec.c
+++ b/lib/utils/pyexec.c
@@ -226,6 +226,7 @@ STATIC int pyexec_friendly_repl_process_char(int c) {
} else if (ret == CHAR_CTRL_B) {
// reset friendly REPL
mp_hal_stdout_tx_str("\r\n");
+ mp_hal_stdout_tx_str("\r\n");
mp_hal_stdout_tx_str("Adafruit MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE "; " MICROPY_HW_BOARD_NAME " with " MICROPY_HW_MCU_NAME "\r\n");
// mp_hal_stdout_tx_str("Type \"help()\" for more information.\r\n");
goto input_restart;
diff --git a/py/misc.h b/py/misc.h
index e60665e59..b68f9cccb 100644
--- a/py/misc.h
+++ b/py/misc.h
@@ -34,6 +34,8 @@
#include <stdint.h>
#include <stddef.h>
+#include "mpconfig.h"
+
typedef unsigned char byte;
typedef unsigned int uint;