diff options
| author | Scott Shawcroft <scott@chickadee.tech> | 2016-08-31 00:11:56 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott@chickadee.tech> | 2016-08-31 00:11:56 -0700 |
| commit | eff137a5f5a897fa6ce2734db29c6cce1d85e1f1 (patch) | |
| tree | ccb6a22808cde7904dfd1e11a7c2a34dd523ae88 | |
| parent | ccb309bd5c0b283ea847b18621038bf5ef817f38 (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/Makefile | 38 | ||||
| -rw-r--r-- | atmel-samd/boards/arduino_zero/conf_usb.h | 3 | ||||
| -rw-r--r-- | atmel-samd/boards/feather_m0_ble/conf_usb.h | 3 | ||||
| -rw-r--r-- | atmel-samd/main.c | 6 | ||||
| -rw-r--r-- | atmel-samd/mpconfigport.h | 1 | ||||
| -rw-r--r-- | atmel-samd/mphalport.c | 97 | ||||
| -rw-r--r-- | atmel-samd/mphalport.h | 35 |
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__ |
