Skip to content

Commit eff137a

Browse files
committed
atmel/samd: Support CTRL-C on USB. This won't escape native code but it will cause Python code to stop.
1 parent ccb309b commit eff137a

File tree

7 files changed

+173
-10
lines changed

7 files changed

+173
-10
lines changed

atmel-samd/Makefile

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,43 @@ endif
8181
ifeq ($(DEBUG), 1)
8282
CFLAGS += -O0 -ggdb
8383
else
84-
CFLAGS += -Os -DNDEBUG
84+
# was -Os
85+
CFLAGS += -O1 -ggdb -DNDEBUG
86+
# CFLAGS += -O0 \
87+
# -ftree-ter \
88+
# -ftree-sra \
89+
# -ftree-slsr \
90+
# -ftree-sink \
91+
# -ftree-pta \
92+
# -ftree-fre \
93+
# -ftree-dse \
94+
# -ftree-dominator-opts \
95+
# -ftree-dce \
96+
# -ftree-copyrename \
97+
# -ftree-copy-prop \
98+
# -ftree-ch \
99+
# -ftree-ccp \
100+
# -ftree-bit-ccp \
101+
# -fsplit-wide-types \
102+
# -fshrink-wrap \
103+
# -fsection-anchors \
104+
# -fsched-pressure \
105+
# -fomit-frame-pointer \
106+
# -fmove-loop-invariants \
107+
# -fmerge-constants \
108+
# -fipa-reference \
109+
# -fipa-pure-const \
110+
# -fipa-profile \
111+
# -finline-functions-called-once \
112+
# -fif-conversion \
113+
# -fif-conversion2 \
114+
# -fguess-branch-probability \
115+
# -fforward-propagate \
116+
# -fdefer-pop \
117+
# -fcprop-registers \
118+
# -fcompare-elim \
119+
# -fcombine-stack-adjustments \
120+
# -fbranch-count-reg
85121
endif
86122

87123
LIBS =

atmel-samd/boards/arduino_zero/conf_usb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ extern void mp_cdc_disable(uint8_t port);
3434
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
3535
#define UDI_CDC_DEFAULT_DATABITS 8
3636

37-
#define UDI_CDC_RX_NOTIFY(port)
37+
#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify()
38+
void usb_rx_notify(void);
3839
#define UDI_CDC_SET_CODING_EXT(port,cfg)
3940
#define UDI_CDC_SET_DTR_EXT(port,set)
4041
#define UDI_CDC_SET_RTS_EXT(port,set)

atmel-samd/boards/feather_m0_ble/conf_usb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ extern void mp_cdc_disable(uint8_t port);
3434
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
3535
#define UDI_CDC_DEFAULT_DATABITS 8
3636

37-
#define UDI_CDC_RX_NOTIFY(port)
37+
#define UDI_CDC_RX_NOTIFY(port) usb_rx_notify()
38+
void usb_rx_notify(void);
3839
#define UDI_CDC_SET_CODING_EXT(port,cfg)
3940
#define UDI_CDC_SET_DTR_EXT(port,set)
4041
#define UDI_CDC_SET_RTS_EXT(port,set)

atmel-samd/main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ int main(int argc, char **argv) {
5959
#endif
6060
mp_init();
6161

62+
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
63+
6264
pin_init0();
6365

6466
#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) {
101103
}
102104
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
103105

106+
void mp_keyboard_interrupt(void) {
107+
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
108+
}
109+
104110
void nlr_jump_fail(void *val) {
105111
}
106112

atmel-samd/mpconfigport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ extern const struct _mp_obj_module_t utime_module;
114114
#define MICROPY_PORT_ROOT_POINTERS \
115115
const char *readline_hist[8]; \
116116
vstr_t *repl_line; \
117+
mp_obj_t mp_kbd_exception; \
117118
mp_obj_t pin_class_mapper; \
118119
mp_obj_t pin_class_map_dict; \
119120

atmel-samd/mphalport.c

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,29 @@
77
#include "py/mpstate.h"
88

99
#include "mpconfigboard.h"
10+
#include "mphalport.h"
11+
12+
// Store received characters on our own so that we can filter control characters
13+
// and act immediately on CTRL-C for example.
14+
// This is adapted from asf/thirdparty/wireless/addons/sio2host
15+
16+
// Receive buffer
17+
static uint8_t usb_rx_buf[USB_RX_BUF_SIZE];
18+
19+
// Receive buffer head
20+
static uint8_t usb_rx_buf_head;
21+
22+
// Receive buffer tail
23+
static uint8_t usb_rx_buf_tail;
24+
25+
// Number of bytes in receive buffer
26+
static volatile uint8_t usb_rx_count;
1027

1128
static volatile bool mp_cdc_enabled = false;
29+
30+
void mp_keyboard_interrupt(void);
31+
int interrupt_char;
32+
1233
extern struct usart_module usart_instance;
1334

1435
bool mp_cdc_enable(uint8_t port)
@@ -22,11 +43,71 @@ void mp_cdc_disable(uint8_t port)
2243
mp_cdc_enabled = false;
2344
}
2445

46+
void usb_rx_notify(void)
47+
{
48+
if (mp_cdc_enabled) {
49+
while (udi_cdc_is_rx_ready()) {
50+
uint8_t c;
51+
c = udi_cdc_getc();
52+
53+
if (c == interrupt_char) {
54+
mp_keyboard_interrupt();
55+
// Don't put the interrupt into the buffer, just continue.
56+
continue;
57+
}
58+
59+
// Introducing critical section to avoid buffer corruption.
60+
cpu_irq_disable();
61+
62+
// The count of characters present in receive buffer is
63+
// incremented.
64+
usb_rx_count++;
65+
usb_rx_buf[usb_rx_buf_tail] = c;
66+
67+
if ((USB_RX_BUF_SIZE - 1) == usb_rx_buf_tail) {
68+
// Reached the end of buffer, revert back to beginning of
69+
// buffer.
70+
usb_rx_buf_tail = 0x00;
71+
} else {
72+
usb_rx_buf_tail++;
73+
}
74+
75+
cpu_irq_enable();
76+
}
77+
}
78+
}
79+
80+
int receive_usb() {
81+
if (0 == usb_rx_count) {
82+
return 0;
83+
}
84+
85+
if (USB_RX_BUF_SIZE <= usb_rx_count) {
86+
// Bytes between head and tail are overwritten by new data. The
87+
// oldest data in buffer is the one to which the tail is pointing. So
88+
// reading operation should start from the tail.
89+
usb_rx_buf_head = usb_rx_buf_tail;
90+
91+
// This is a buffer overflow case.But still only the number of bytes
92+
// equivalent to full buffer size are useful.
93+
usb_rx_count = USB_RX_BUF_SIZE;
94+
}
95+
96+
// Copy from head.
97+
int data = usb_rx_buf[usb_rx_buf_head];
98+
usb_rx_buf_head++;
99+
usb_rx_count--;
100+
if ((USB_RX_BUF_SIZE) == usb_rx_buf_head) {
101+
usb_rx_buf_head = 0;
102+
}
103+
return data;
104+
}
105+
25106
int mp_hal_stdin_rx_chr(void) {
26107
for (;;) {
27108
#ifdef USB_REPL
28-
if (mp_cdc_enabled && udi_cdc_is_rx_ready()) {
29-
return udi_cdc_getc();
109+
if (mp_cdc_enabled && usb_rx_count > 0) {
110+
return receive_usb();
30111
}
31112
#endif
32113
#ifdef UART_REPL
@@ -41,10 +122,6 @@ int mp_hal_stdin_rx_chr(void) {
41122
}
42123
}
43124

44-
//void mp_hal_stdout_tx_str(const char *str) {
45-
// mp_hal_stdout_tx_strn(str, strlen(str));
46-
//}
47-
48125
void mp_hal_stdout_tx_strn(const char *str, size_t len) {
49126
#ifdef UART_REPL
50127
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) {
57134
#endif
58135
}
59136

137+
void mp_hal_set_interrupt_char(int c) {
138+
if (c != -1) {
139+
mp_obj_exception_clear_traceback(MP_STATE_PORT(mp_kbd_exception));
140+
}
141+
extern int interrupt_char;
142+
interrupt_char = c;
143+
}
144+
60145
void mp_hal_delay_ms(mp_uint_t delay) {
61146
delay_ms(delay);
62147
}

atmel-samd/mphalport.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,35 @@
1+
/*
2+
* This file is part of the Micro Python project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2016 Scott Shawcroft
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
28+
#define __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__
29+
30+
#define USB_RX_BUF_SIZE 128
31+
132
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
2-
static inline void mp_hal_set_interrupt_char(char c) {}
33+
void mp_hal_set_interrupt_char(int c);
34+
35+
#endif // __MICROPY_INCLUDED_ATMEL_SAMD_MPHALPORT_H__

0 commit comments

Comments
 (0)