Skip to content

Commit 533ad9a

Browse files
committed
Handle DTR changes on Serial lines.
1 parent cb45df1 commit 533ad9a

File tree

1 file changed

+69
-15
lines changed

1 file changed

+69
-15
lines changed

cdc_uart.c

Lines changed: 69 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ static struct uart_device
4545
uint8_t *rx_read_address;
4646
uint n_checks;
4747
uint is_connected;
48+
bool cdc_stopped;
4849
} uart_devices[2];
4950

5051
static void dma_handler();
@@ -136,7 +137,8 @@ void cdc_uart_init( int index, uart_inst_t *const uart_, int uart_rx_pin, int ua
136137
uart->rx_dma_channel = setup_usart_rx_dma(uart->inst, &uart->rx_buf[0], dma_handler, RX_BUFFER_SIZE);
137138
uart->tx_write_address = &uart->tx_buf[0];
138139
uart->rx_read_address = (uint8_t *)&uart->rx_buf[0];
139-
uart->n_checks = 0;
140+
uart->n_checks = 0;
141+
uart->cdc_stopped = false;
140142
}
141143

142144
void set_tx_dma(volatile uint8_t *l_tx_write_address, struct uart_device *uart)
@@ -182,17 +184,16 @@ static void dma_handler()
182184

183185

184186

185-
bool cdc_stopped = false;
186187
void cdc_uart_task(void)
187188
{
188-
if (cdc_stopped)
189-
return;
190189

191190
struct uart_device *uart;
192191

193192
for (size_t i = 0; i < CDC_UART_INTF_COUNT; i++)
194193
{
195194
uart = &uart_devices[i];
195+
if (uart->cdc_stopped)
196+
return;
196197
if (tud_cdc_n_connected(i))
197198
{
198199
uart->is_connected = 1;
@@ -262,26 +263,79 @@ void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* line_coding)
262263
uart = &uart_devices[i];
263264
if (i == itf)
264265
{
266+
uart->cdc_stopped = true;
267+
uart_parity_t parity;
268+
uint data_bits, stop_bits;
265269
uart_deinit(uart->inst);
266270
tud_cdc_n_write_clear(itf);
267271
tud_cdc_n_read_flush(itf);
268272
uart_init(uart->inst, line_coding->bit_rate);
273+
switch (line_coding->parity)
274+
{
275+
case CDC_LINE_CODING_PARITY_ODD:
276+
parity = UART_PARITY_ODD;
277+
break;
278+
case CDC_LINE_CODING_PARITY_EVEN:
279+
parity = UART_PARITY_EVEN;
280+
break;
281+
case CDC_LINE_CODING_PARITY_NONE:
282+
parity = UART_PARITY_NONE;
283+
break;
284+
default:
285+
parity = UART_PARITY_NONE;
286+
break;
287+
}
288+
289+
switch (line_coding->data_bits)
290+
{
291+
case 5:
292+
case 6:
293+
case 7:
294+
case 8:
295+
data_bits = line_coding->data_bits;
296+
break;
297+
default:
298+
data_bits = 8;
299+
break;
300+
}
301+
302+
/* The PL011 only supports 1 or 2 stop bits. 1.5 stop bits is translated to 2,
303+
* which is safer than the alternative. */
304+
switch (line_coding->stop_bits)
305+
{
306+
case CDC_LINE_CONDING_STOP_BITS_1_5:
307+
case CDC_LINE_CONDING_STOP_BITS_2:
308+
stop_bits = 2;
309+
break;
310+
case CDC_LINE_CONDING_STOP_BITS_1:
311+
stop_bits = 1;
312+
break;
313+
default:
314+
stop_bits = 1;
315+
break;
316+
}
317+
318+
uart_set_format(uart->inst, data_bits, stop_bits, parity);
319+
uart->cdc_stopped = false;
320+
}
269321
}
270-
271-
}
272322
}
273323

274324
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
275325
{
276-
//if (itf != UART_PORT_ITF)
277-
return;
278-
/* CDC drivers use linestate as a bodge to activate/deactivate the interface.
279-
* Resume our UART polling on activate, stop on deactivate */
280-
// DTR RTS not so
281-
// if (!dtr && !rts)
282-
// cdc_stopped = true;
283-
// else
284-
// cdc_stopped = false;
326+
for (size_t i = 0; i < CDC_UART_INTF_COUNT; i++)
327+
{
328+
struct uart_device *uart = &uart_devices[i];
329+
if (i == itf)
330+
{
331+
/* CDC drivers use linestate as a bodge to activate/deactivate the interface.
332+
* Resume our UART polling on activate, stop on deactivate */
333+
if (!dtr)
334+
uart->cdc_stopped = true;
335+
else
336+
uart->cdc_stopped = false;
337+
}
338+
}
285339
}
286340

287341
#endif // CDC_UART_INTF_COUNT

0 commit comments

Comments
 (0)