@@ -105,6 +105,10 @@ struct cdc_acm_uart_data {
105
105
struct k_work irq_cb_work ;
106
106
struct cdc_acm_uart_fifo rx_fifo ;
107
107
struct cdc_acm_uart_fifo tx_fifo ;
108
+ /* When flow_ctrl is set, poll out is blocked when the buffer is full,
109
+ * roughly emulating flow control.
110
+ */
111
+ bool flow_ctrl ;
108
112
/* USBD CDC ACM TX fifo work */
109
113
struct k_work tx_fifo_work ;
110
114
/* USBD CDC ACM RX fifo work */
@@ -373,7 +377,8 @@ static void cdc_acm_update_uart_cfg(struct cdc_acm_uart_data *const data)
373
377
break ;
374
378
};
375
379
376
- cfg -> flow_ctrl = UART_CFG_FLOW_CTRL_NONE ;
380
+ cfg -> flow_ctrl = data -> flow_ctrl ? UART_CFG_FLOW_CTRL_RTS_CTS :
381
+ UART_CFG_FLOW_CTRL_NONE ;
377
382
}
378
383
379
384
static void cdc_acm_update_linestate (struct cdc_acm_uart_data * const data )
@@ -884,24 +889,27 @@ static int cdc_acm_poll_in(const struct device *dev, unsigned char *const c)
884
889
static void cdc_acm_poll_out (const struct device * dev , const unsigned char c )
885
890
{
886
891
struct cdc_acm_uart_data * const data = dev -> data ;
892
+ uint32_t wrote ;
887
893
888
894
if (atomic_test_and_set_bit (& data -> state , CDC_ACM_LOCK )) {
889
895
LOG_ERR ("IRQ callback is used" );
890
896
return ;
891
897
}
892
898
893
- if (ring_buf_put (data -> tx_fifo .rb , & c , 1 )) {
894
- goto poll_out_exit ;
895
- }
899
+ while (true) {
900
+ wrote = ring_buf_put (data -> tx_fifo .rb , & c , 1 );
901
+ if (wrote == 1 ) {
902
+ break ;
903
+ }
896
904
897
- LOG_DBG ("Ring buffer full, drain buffer" );
898
- if (!ring_buf_get (data -> tx_fifo .rb , NULL , 1 ) ||
899
- !ring_buf_put (data -> tx_fifo .rb , & c , 1 )) {
900
- LOG_ERR ("Failed to drain buffer" );
901
- __ASSERT_NO_MSG (false);
905
+ if (k_is_in_isr () || !data -> flow_ctrl ) {
906
+ LOG_WRN_ONCE ("Ring buffer full, discard data" );
907
+ break ;
908
+ }
909
+
910
+ k_msleep (1 );
902
911
}
903
912
904
- poll_out_exit :
905
913
atomic_clear_bit (& data -> state , CDC_ACM_LOCK );
906
914
cdc_acm_work_submit (& data -> tx_fifo_work );
907
915
}
@@ -976,17 +984,18 @@ static int cdc_acm_line_ctrl_get(const struct device *dev,
976
984
static int cdc_acm_configure (const struct device * dev ,
977
985
const struct uart_config * const cfg )
978
986
{
979
- ARG_UNUSED (dev );
980
- ARG_UNUSED (cfg );
981
- /*
982
- * We cannot implement configure API because there is
983
- * no notification of configuration changes provided
984
- * for the Abstract Control Model and the UART controller
985
- * is only emulated.
986
- * However, it allows us to use CDC ACM UART together with
987
- * subsystems like Modbus which require configure API for
988
- * real controllers.
989
- */
987
+ struct cdc_acm_uart_data * const data = dev -> data ;
988
+
989
+ switch (cfg -> flow_ctrl ) {
990
+ case UART_CFG_FLOW_CTRL_NONE :
991
+ data -> flow_ctrl = false;
992
+ break ;
993
+ case UART_CFG_FLOW_CTRL_RTS_CTS :
994
+ data -> flow_ctrl = true;
995
+ break ;
996
+ default :
997
+ return - ENOTSUP ;
998
+ }
990
999
991
1000
return 0 ;
992
1001
}
@@ -1240,6 +1249,7 @@ const static struct usb_desc_header *cdc_acm_hs_desc_##n[] = { \
1240
1249
.c_data = &cdc_acm_##n, \
1241
1250
.rx_fifo.rb = &cdc_acm_rb_rx_##n, \
1242
1251
.tx_fifo.rb = &cdc_acm_rb_tx_##n, \
1252
+ .flow_ctrl = DT_INST_PROP(n, hw_flow_control), \
1243
1253
.notif_sem = Z_SEM_INITIALIZER(uart_data_##n.notif_sem, 0, 1), \
1244
1254
.desc = &cdc_acm_desc_##n, \
1245
1255
.fs_desc = cdc_acm_fs_desc_##n, \
0 commit comments