Skip to content

Commit 0e1fd9a

Browse files
committed
atmel-samd: Support ampy get and fix USB dropping characters.
Fixes #2.
1 parent 33b796e commit 0e1fd9a

File tree

3 files changed

+58
-30
lines changed

3 files changed

+58
-30
lines changed

atmel-samd/Makefile

+7-1
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,11 @@ SRC_C = \
160160
lib/libc/string0.c \
161161
lib/mp-readline/readline.c
162162

163+
STM_SRC_C = $(addprefix stmhal/,\
164+
pybstdio.c \
165+
input.c \
166+
)
167+
163168
# TODO(tannewt): Use this sed line to extract the RST docs from these sources:
164169
# sed': sed -n 's+^//|++p' ../api/machine.c
165170
#
@@ -176,9 +181,10 @@ SRC_AUTOGEN = \
176181
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
177182
OBJ += $(addprefix $(BUILD)/, $(SRC_ASF:.c=.o))
178183
OBJ += $(addprefix $(BUILD)/, $(SRC_AUTOGEN:.c=.o))
184+
OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o))
179185
OBJ += $(addprefix $(BUILD)/, $(SRC_BINDINGS_EXPANDED:.c=.o))
180186

181-
SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED)
187+
SRC_QSTR += $(SRC_C) $(SRC_BINDINGS_EXPANDED) $(STM_SRC_C)
182188

183189
all: $(BUILD)/firmware.bin
184190

atmel-samd/mpconfigport.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
#define MICROPY_HELPER_LEXER_UNIX (0)
2828
#define MICROPY_ENABLE_SOURCE_LINE (1)
2929
#define MICROPY_ENABLE_DOC_STRING (0)
30-
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
30+
//#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
31+
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_NORMAL)
3132
#define MICROPY_BUILTIN_METHOD_CHECK_SELF_ARG (0)
3233
#define MICROPY_PY_ASYNC_AWAIT (0)
3334
#define MICROPY_PY_BUILTINS_BYTEARRAY (1)
@@ -71,6 +72,8 @@
7172
#define MICROPY_HW_ENABLE_DAC (1)
7273
#define MICROPY_ENABLE_FINALISER (1)
7374
#define MICROPY_USE_INTERNAL_PRINTF (1)
75+
#define MICROPY_PY_SYS_STDFILES (1)
76+
#define MICROPY_PY_IO_FILEIO (1)
7477

7578
// type definitions for the specific machine
7679

atmel-samd/mphalport.c

+47-28
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@
1818
static uint8_t usb_rx_buf[USB_RX_BUF_SIZE];
1919

2020
// Receive buffer head
21-
static uint8_t usb_rx_buf_head;
21+
static volatile uint8_t usb_rx_buf_head;
2222

2323
// Receive buffer tail
24-
static uint8_t usb_rx_buf_tail;
24+
static volatile uint8_t usb_rx_buf_tail;
2525

2626
// Number of bytes in receive buffer
2727
static volatile uint8_t usb_rx_count;
@@ -46,61 +46,80 @@ void mp_cdc_disable(uint8_t port)
4646

4747
void usb_rx_notify(void)
4848
{
49+
irqflags_t flags;
4950
if (mp_cdc_enabled) {
5051
while (udi_cdc_is_rx_ready()) {
5152
uint8_t c;
52-
c = udi_cdc_getc();
5353

54-
if (c == interrupt_char) {
55-
mp_keyboard_interrupt();
56-
// Don't put the interrupt into the buffer, just continue.
57-
continue;
54+
// Introduce a critical section to avoid buffer corruption. We use
55+
// cpu_irq_save instead of cpu_irq_disable because we don't know the
56+
// current state of IRQs. They may have been turned off already and
57+
// we don't want to accidentally turn them back on.
58+
flags = cpu_irq_save();
59+
// If our buffer is full, then don't get another character otherwise
60+
// we'll lose a previous character.
61+
if (usb_rx_count >= USB_RX_BUF_SIZE) {
62+
cpu_irq_restore(flags);
63+
break;
5864
}
5965

60-
// Introducing critical section to avoid buffer corruption.
61-
cpu_irq_disable();
62-
63-
// The count of characters present in receive buffer is
64-
// incremented.
65-
usb_rx_count++;
66-
usb_rx_buf[usb_rx_buf_tail] = c;
67-
66+
uint8_t current_tail = usb_rx_buf_tail;
67+
// Pretend we've received a character so that any nested calls to
68+
// this function have to consider the spot we've reserved.
6869
if ((USB_RX_BUF_SIZE - 1) == usb_rx_buf_tail) {
6970
// Reached the end of buffer, revert back to beginning of
7071
// buffer.
7172
usb_rx_buf_tail = 0x00;
7273
} else {
7374
usb_rx_buf_tail++;
7475
}
76+
// The count of characters present in receive buffer is
77+
// incremented.
78+
usb_rx_count++;
79+
// WARNING(tannewt): This call can call us back with the next
80+
// character!
81+
c = udi_cdc_getc();
82+
83+
if (c == interrupt_char) {
84+
// We consumed a character rather than adding it to the rx
85+
// buffer so undo the modifications we made to count and the
86+
// tail.
87+
usb_rx_count--;
88+
usb_rx_buf_tail = current_tail;
89+
cpu_irq_restore(flags);
90+
mp_keyboard_interrupt();
91+
// Don't put the interrupt into the buffer, just continue.
92+
continue;
93+
}
7594

76-
cpu_irq_enable();
95+
// We put the next character where we expected regardless of whether
96+
// the next character was already loaded in the buffer.
97+
usb_rx_buf[current_tail] = c;
98+
99+
cpu_irq_restore(flags);
77100
}
78101
}
79102
}
80103

81104
int receive_usb() {
82-
if (0 == usb_rx_count) {
105+
if (usb_rx_count == 0) {
83106
return 0;
84107
}
85108

86-
if (USB_RX_BUF_SIZE <= usb_rx_count) {
87-
// Bytes between head and tail are overwritten by new data. The
88-
// oldest data in buffer is the one to which the tail is pointing. So
89-
// reading operation should start from the tail.
90-
usb_rx_buf_head = usb_rx_buf_tail;
91-
92-
// This is a buffer overflow case.But still only the number of bytes
93-
// equivalent to full buffer size are useful.
94-
usb_rx_count = USB_RX_BUF_SIZE;
95-
}
96-
97109
// Copy from head.
110+
cpu_irq_disable();
98111
int data = usb_rx_buf[usb_rx_buf_head];
99112
usb_rx_buf_head++;
100113
usb_rx_count--;
101114
if ((USB_RX_BUF_SIZE) == usb_rx_buf_head) {
102115
usb_rx_buf_head = 0;
103116
}
117+
cpu_irq_enable();
118+
119+
// Call usb_rx_notify if we just emptied a spot in the buffer.
120+
if (usb_rx_count == USB_RX_BUF_SIZE - 1) {
121+
usb_rx_notify();
122+
}
104123
return data;
105124
}
106125

0 commit comments

Comments
 (0)