stm32/usbd_cdc_interface: Add CTS flow control option for USB VCP.
Enabled by default, but disabled when REPL is connected to the VCP (this is the existing behaviour). Can be configured at run-time with, eg: pyb.USB_VCP().init(flow=pyb.USB_VCP.RTS | pyb.USB_VCP.CTS)
This commit is contained in:
parent
6b4666f8cf
commit
2397b44062
|
@ -634,6 +634,12 @@ STATIC void pyb_usb_vcp_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
|
|||
|
||||
void usb_vcp_attach_to_repl(const pyb_usb_vcp_obj_t *self, bool attached) {
|
||||
self->cdc_itf->attached_to_repl = attached;
|
||||
if (attached) {
|
||||
// Default behavior is non-blocking when attached to repl
|
||||
self->cdc_itf->flow &= ~USBD_CDC_FLOWCONTROL_CTS;
|
||||
} else {
|
||||
self->cdc_itf->flow |= USBD_CDC_FLOWCONTROL_CTS;
|
||||
}
|
||||
}
|
||||
|
||||
/// \classmethod \constructor()
|
||||
|
@ -791,6 +797,7 @@ STATIC const mp_rom_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
|
|||
|
||||
// class constants
|
||||
{ MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(USBD_CDC_FLOWCONTROL_RTS) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(USBD_CDC_FLOWCONTROL_CTS) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table);
|
||||
|
@ -808,18 +815,13 @@ STATIC mp_uint_t pyb_usb_vcp_read(mp_obj_t self_in, void *buf, mp_uint_t size, i
|
|||
|
||||
STATIC mp_uint_t pyb_usb_vcp_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
pyb_usb_vcp_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
if (self->cdc_itf->attached_to_repl) {
|
||||
usbd_cdc_tx_always(self->cdc_itf, (const byte*)buf, size);
|
||||
return size;
|
||||
} else {
|
||||
int ret = usbd_cdc_tx(self->cdc_itf, (const byte*)buf, size, 0);
|
||||
if (ret == 0) {
|
||||
// return EAGAIN error to indicate non-blocking
|
||||
*errcode = MP_EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return ret;
|
||||
int ret = usbd_cdc_tx_flow(self->cdc_itf, (const byte*)buf, size);
|
||||
if (ret == 0) {
|
||||
// return EAGAIN error to indicate non-blocking
|
||||
*errcode = MP_EAGAIN;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t pyb_usb_vcp_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
|
||||
|
|
|
@ -74,6 +74,12 @@ uint8_t *usbd_cdc_init(usbd_cdc_state_t *cdc_in) {
|
|||
cdc->rx_buf_full = false;
|
||||
cdc->tx_need_empty_packet = 0;
|
||||
cdc->connect_state = USBD_CDC_CONNECT_STATE_DISCONNECTED;
|
||||
if (cdc->attached_to_repl) {
|
||||
// Default behavior is non-blocking when attached to repl
|
||||
cdc->flow &= ~USBD_CDC_FLOWCONTROL_CTS;
|
||||
} else {
|
||||
cdc->flow |= USBD_CDC_FLOWCONTROL_CTS;
|
||||
}
|
||||
|
||||
// Return the buffer to place the first USB OUT packet
|
||||
return cdc->rx_packet_buf;
|
||||
|
@ -292,6 +298,19 @@ int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc) {
|
|||
return tx_waiting <= USBD_CDC_TX_DATA_SIZE / 2;
|
||||
}
|
||||
|
||||
// Writes only the data that fits if flow & CTS, else writes all data
|
||||
// Returns number of bytes actually written to the device
|
||||
int usbd_cdc_tx_flow(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len) {
|
||||
if (cdc->flow & USBD_CDC_FLOWCONTROL_CTS) {
|
||||
// Only write as much as can fit in tx buffer
|
||||
return usbd_cdc_tx(cdc, buf, len, 0);
|
||||
} else {
|
||||
// Never block, keep most recent data in rolling buffer
|
||||
usbd_cdc_tx_always(cdc, buf, len);
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
// timout in milliseconds.
|
||||
// Returns number of bytes written to the device.
|
||||
int usbd_cdc_tx(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len, uint32_t timeout) {
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
// Flow control settings
|
||||
#define USBD_CDC_FLOWCONTROL_NONE (0)
|
||||
#define USBD_CDC_FLOWCONTROL_RTS (1)
|
||||
#define USBD_CDC_FLOWCONTROL_CTS (2)
|
||||
|
||||
typedef struct _usbd_cdc_itf_t {
|
||||
usbd_cdc_state_t base; // state for the base CDC layer
|
||||
|
@ -75,6 +76,7 @@ static inline int usbd_cdc_is_connected(usbd_cdc_itf_t *cdc) {
|
|||
}
|
||||
|
||||
int usbd_cdc_tx_half_empty(usbd_cdc_itf_t *cdc);
|
||||
int usbd_cdc_tx_flow(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len);
|
||||
int usbd_cdc_tx(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len, uint32_t timeout);
|
||||
void usbd_cdc_tx_always(usbd_cdc_itf_t *cdc, const uint8_t *buf, uint32_t len);
|
||||
|
||||
|
|
Loading…
Reference in New Issue