@@ -61,8 +61,10 @@ uintptr_t mp_usbd_cdc_poll_interfaces(uintptr_t poll_flags) {
61
61
if ((poll_flags & MP_STREAM_POLL_RD ) && ringbuf_peek (& stdin_ringbuf ) != -1 ) {
62
62
ret |= MP_STREAM_POLL_RD ;
63
63
}
64
- if ((poll_flags & MP_STREAM_POLL_WR ) && tud_cdc_connected () && tud_cdc_write_available () > 0 ) {
65
- // When connected operate as blocking, only allow if space is available.
64
+ if ((poll_flags & MP_STREAM_POLL_WR ) &&
65
+ (!tud_cdc_connected () || (tud_cdc_connected () && tud_cdc_write_available () > 0 ))) {
66
+ // Always allow write when not connected, fifo will retain latest.
67
+ // When connected operate as blocking, only allow if space is available
66
68
ret |= MP_STREAM_POLL_WR ;
67
69
}
68
70
return ret ;
@@ -96,40 +98,55 @@ void tud_cdc_rx_cb(uint8_t itf) {
96
98
97
99
mp_uint_t mp_usbd_cdc_tx_strn (const char * str , mp_uint_t len ) {
98
100
size_t i = 0 ;
99
- if (tud_cdc_connected ()) {
100
- while (i < len ) {
101
- uint32_t n = len - i ;
102
- if (n > CFG_TUD_CDC_EP_BUFSIZE ) {
103
- n = CFG_TUD_CDC_EP_BUFSIZE ;
104
- }
105
- int timeout = 0 ;
106
- // Wait with a max of USC_CDC_TIMEOUT ms
107
- while (n > tud_cdc_write_available () && timeout ++ < MICROPY_HW_USB_CDC_TX_TIMEOUT ) {
101
+ while (i < len ) {
102
+ uint32_t n = len - i ;
103
+ if (n > CFG_TUD_CDC_EP_BUFSIZE ) {
104
+ n = CFG_TUD_CDC_EP_BUFSIZE ;
105
+ }
106
+ int timeout = 0 ;
107
+ if (tud_cdc_connected ()) {
108
+ // If cdc port is connected but the buffer is full,
109
+ // wait for up to USC_CDC_TIMEOUT ms
110
+ while (n > tud_cdc_write_available ()
111
+ && timeout ++ < MICROPY_HW_USB_CDC_TX_TIMEOUT ) {
108
112
mp_event_wait_ms (1 );
109
113
110
114
// Explicitly run the USB stack as the scheduler may be locked (eg we
111
115
// are in an interrupt handler), while there is data pending.
112
116
mp_usbd_task ();
113
117
}
114
- if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT ) {
118
+ // Limit write to available space in tx buffer when connected.
119
+ n = MIN (n , tud_cdc_write_available ());
120
+ if (n == 0 ) {
115
121
break ;
116
122
}
117
- uint32_t n2 = tud_cdc_write (str + i , n );
118
- tud_cdc_write_flush ();
119
- i += n2 ;
120
123
}
124
+ // When not connected we always write to usb fifo, ensuring it has latest data.
125
+ uint32_t n2 = tud_cdc_write (str + i , n );
126
+ tud_cdc_write_flush ();
127
+ i += n2 ;
121
128
}
122
129
return i ;
123
130
}
124
131
125
- #if MICROPY_HW_USB_CDC_1200BPS_TOUCH && MICROPY_HW_ENABLE_USBDEV
132
+ static int8_t cdc_connected_flush_delay = 0 ;
133
+
134
+ void tud_sof_cb (uint32_t frame_count ) {
135
+ if (-- cdc_connected_flush_delay < 0 ) {
136
+ // Finished on-connection delat, disable SOF interrupt again.
137
+ tud_sof_cb_enable (false);
138
+ tud_cdc_write_flush ();
139
+ }
140
+ }
126
141
142
+ #if MICROPY_HW_USB_CDC_1200BPS_TOUCH
127
143
static mp_sched_node_t mp_bootloader_sched_node ;
128
144
129
145
static void usbd_cdc_run_bootloader_task (mp_sched_node_t * node ) {
130
146
mp_hal_delay_ms (250 );
131
147
machine_bootloader (0 , NULL );
132
148
}
149
+ #endif
133
150
134
151
void
135
152
#if MICROPY_HW_USB_EXTERNAL_TINYUSB
@@ -138,6 +155,15 @@ mp_usbd_line_state_cb
138
155
tud_cdc_line_state_cb
139
156
#endif
140
157
(uint8_t itf , bool dtr , bool rts ) {
158
+
159
+ if (dtr ) {
160
+ // A host application has started to open the cdc serial port.
161
+ // Wait a few ms for host to be ready then send tx buffer.
162
+ // High speed connection SOF fires at 125us, full speed at 1ms.
163
+ cdc_connected_flush_delay = (tud_speed_get () == TUSB_SPEED_HIGH ) ? 128 : 16 ;
164
+ tud_sof_cb_enable (true);
165
+ }
166
+ #if MICROPY_HW_USB_CDC_1200BPS_TOUCH
141
167
if (dtr == false && rts == false) {
142
168
// Device is disconnected.
143
169
cdc_line_coding_t line_coding ;
@@ -147,7 +173,7 @@ tud_cdc_line_state_cb
147
173
mp_sched_schedule_node (& mp_bootloader_sched_node , usbd_cdc_run_bootloader_task );
148
174
}
149
175
}
176
+ #endif
150
177
}
151
178
152
179
#endif
153
- #endif
0 commit comments