summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott@chickadee.tech>2016-08-31 00:11:56 -0700
committerScott Shawcroft <scott@chickadee.tech>2016-08-31 00:11:56 -0700
commiteff137a5f5a897fa6ce2734db29c6cce1d85e1f1 (patch)
treeccb6a22808cde7904dfd1e11a7c2a34dd523ae88
parentccb309bd5c0b283ea847b18621038bf5ef817f38 (diff)
atmel/samd: Support CTRL-C on USB. This won't escape native code but it will cause Python code to stop.
-rw-r--r--atmel-samd/Makefile38
-rw-r--r--atmel-samd/boards/arduino_zero/conf_usb.h3
-rw-r--r--atmel-samd/boards/feather_m0_ble/conf_usb.h3
-rw-r--r--atmel-samd/main.c6
-rw-r--r--atmel-samd/mpconfigport.h1
-rw-r--r--atmel-samd/mphalport.c97
-rw-r--r--atmel-samd/mphalport.h35
7 files changed, 173 insertions, 10 deletions
diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile
index 9e02d7f73..ebb196f5a 100644
--- a/atmel-samd/Makefile
+++ b/atmel-samd/Makefile
@@ -81,7 +81,43 @@ endif
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -ggdb
else
-CFLAGS += -Os -DNDEBUG
+# was -Os
+CFLAGS += -O1 -ggdb -DNDEBUG
+# CFLAGS += -O0 \
+# -ftree-ter \
+# -ftree-sra \
+# -ftree-slsr \
+# -ftree-sink \
+# -ftree-pta \
+# -ftree-fre \
+# -ftree-dse \
+# -ftree-dominator-opts \
+# -ftree-dce \
+# -ftree-copyrename \
+# -ftree-copy-prop \
+# -ftree-ch \
+# -ftree-ccp \
+# -ftree-bit-ccp \
+# -fsplit-wide-types \
+# -fshrink-wrap \
+# -fsection-anchors \
+# -fsched-pressure \
+# -fomit-frame-pointer \
+# -fmove-loop-invariants \
+# -fmerge-constants \
+# -fipa-reference \
+# -fipa-pure-const \
+# -fipa-profile \
+# -finline-functions-called-once \
+# -fif-conversion \
+# -fif-conversion2 \
+# -fguess-branch-probability \
+# -fforward-propagate \
+# -fdefer-pop \
+# -fcprop-registers \
+# -fcompare-elim \
+# -fcombine-stack-adjustments \
+# -fbranch-count-reg
endif
LIBS =
diff --git a/atmel-samd/boards/arduino_zero/conf_usb.h b/atmel-samd/boards/arduino_zero/conf_usb.h
index 5702b87c5..70035e64a 100644
--- a/atmel-samd/boards/arduino_zero/conf_usb.h
+++ b/atmel-samd/boards/arduino_zero/conf_usb.h
@@ -34,7 +34,8 @@ extern void mp_cdc_disable(uint8_t port);
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
#define UDI_CDC_DEFAULT_DATABITS 8
-#define UDI_CDC_RX_NOTIFY(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_DTR_EXT(port,set)
#define UDI_CDC_SET_RTS_EXT(port,set)
diff --git a/atmel-samd/boards/feather_m0_ble/conf_usb.h b/atmel-samd/boards/feather_m0_ble/conf_usb.h
index 5702b87c5..70035e64a 100644
--- a/atmel-samd/boards/feather_m0_ble/conf_usb.h
+++ b/atmel-samd/boards/feather_m0_ble/conf_usb.h
@@ -34,7 +34,8 @@ extern void mp_cdc_disable(uint8_t port);
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
#define UDI_CDC_DEFAULT_DATABITS 8
-#define UDI_CDC_RX_NOTIFY(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_DTR_EXT(port,set)
#define UDI_CDC_SET_RTS_EXT(port,set)
diff --git a/atmel-samd/main.c b/atmel-samd/main.c
index 5c9c75546..15b281cbc 100644
--- a/atmel-samd/main.c
+++ b/atmel-samd/main.c
@@ -59,6 +59,8 @@ int main(int argc, char **argv) {
#endif
mp_init();
+ MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
+
pin_init0();
#if MICROPY_REPL_EVENT_DRIVEN
@@ -101,6 +103,10 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
}
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
+void mp_keyboard_interrupt(void) {
+ MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
+}
+
void nlr_jump_fail(void *val) {
}
diff --git a/atmel-samd/mpconfigport.h b/atmel-samd/mpconfigport.h
index 7682997ad..4142767e2 100644
--- a/atmel-samd/mpconfigport.h
+++ b/atmel-samd/mpconfigport.h
@@ -114,6 +114,7 @@ extern const struct _mp_obj_module_t utime_module;
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
vstr_t *repl_line; \
+ mp_obj_t mp_kbd_exception; \
mp_obj_t pin_class_mapper; \
mp_obj_t pin_class_map_dict; \
diff --git a/atmel-samd/mphalport.c b/atmel-samd/mphalport.c
index 90ecbeef3..29f29ff1f 100644
--- a/atmel-samd/mphalport.c
+++ b/atmel-samd/mphalport.c
@@ -7,8 +7,29 @@
#include "py/mpstate.h"
#include "mpconfigboard.h"
+#include "mphalport.h"
+
+// Store received characters on our own so that we can filter control characters
+// and act immediately on CTRL-C for example.
+// This is adapted from asf/thirdparty/wireless/addons/sio2host
+
+// Receive buffer
+static uint8_t usb_rx_buf[USB_RX_BUF_SIZE];
+
+// Receive buffer head
+static uint8_t usb_rx_buf_head;
+
+// Receive buffer tail
+static uint8_t usb_rx_buf_tail;
+
+// Number of bytes in receive buffer
+static volatile uint8_t usb_rx_count;
static volatile bool mp_cdc_enabled = false;
+
+void mp_keyboard_interrupt(void);
+int interrupt_char;
+
extern struct usart_module usart_instance;
bool mp_cdc_enable(uint8_t port)
@@ -22,11 +43,71 @@ void mp_cdc_disable(uint8_t port)
mp_cdc_enabled = false;
}
+void usb_rx_notify(void)
+{
+ if (mp_cdc_enabled) {
+ while (udi_cdc_is_rx_ready()) {
+ uint8_t c;
+ c = udi_cdc_getc();
+
+ if (c == interrupt_char) {
+ mp_keyboard_interrupt();
+ // Don't put the interrupt into the buffer, just continue.
+ continue;
+ }
+
+ // Introducing critical section to avoid buffer corruption.
+ cpu_irq_disable();
+
+ // The count of characters present in receive buffer is
+ // incremented.
+ usb_rx_count++;
+ usb_rx_buf[usb_rx_buf_tail] = c;
+
+ 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++;
+ }
+
+ cpu_irq_enable();
+ }
+ }
+}
+
+int receive_usb() {
+ if (0 == usb_rx_count) {
+ return 0;
+ }
+
+ if (USB_RX_BUF_SIZE <= usb_rx_count) {
+ // Bytes between head and tail are overwritten by new data. The
+ // oldest data in buffer is the one to which the tail is pointing. So
+ // reading operation should start from the tail.
+ usb_rx_buf_head = usb_rx_buf_tail;
+
+ // This is a buffer overflow case.But still only the number of bytes
+ // equivalent to full buffer size are useful.
+ usb_rx_count = USB_RX_BUF_SIZE;
+ }
+
+ // Copy from head.
+ int data = usb_rx_buf[usb_rx_buf_head];
+ usb_rx_buf_head++;
+ usb_rx_count--;
+ if ((USB_RX_BUF_SIZE) == usb_rx_buf_head) {
+ usb_rx_buf_head = 0;
+ }
+ return data;
+}
+
int mp_hal_stdin_rx_chr(void) {
for (;;) {
#ifdef USB_REPL
- if (mp_cdc_enabled && udi_cdc_is_rx_ready()) {
- return udi_cdc_getc();
+ if (mp_cdc_enabled && usb_rx_count > 0) {
+ return receive_usb();
}
#endif
#ifdef UART_REPL
@@ -41,10 +122,6 @@ int mp_hal_stdin_rx_chr(void) {
}
}
-//void mp_hal_stdout_tx_str(const char *str) {
-// mp_hal_stdout_tx_strn(str, strlen(str));
-//}
-
void mp_hal_stdout_tx_strn(const char *str, size_t len) {
#ifdef UART_REPL
usart_write_buffer_wait(&usart_instance, (uint8_t*) str, len);
@@ -57,6 +134,14 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
#endif
}
+void mp_hal_set_interrupt_char(int c) {
+ if (c != -1) {
+ mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
+ }
+ extern int interrupt_char;
+ interrupt_char = c;
+}
+
void mp_hal_delay_ms(mp_uint_t delay) {
delay_ms(delay);
}
diff --git a/atmel-samd/mphalport.h b/atmel-samd/mphalport.h
index 60d68bd2d..982960646 100644
--- a/atmel-samd/mphalport.h
+++ b/atmel-samd/mphalport.h
@@ -1,2 +1,35 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
+#define __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
+
+#define USB_RX_BUF_SIZE 128
+
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
-static inline void mp_hal_set_interrupt_char(char c) {}
+void mp_hal_set_interrupt_char(int c);
+
+#endif // __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__