8000 stmhal: Make uart.write() function correctly for timeout=0. · micropython/micropython@0d9b450 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0d9b450

Browse files
committed
stmhal: Make uart.write() function correctly for timeout=0.
In non-blocking mode (timeout=0), uart.write() can now transmit all of its data without raising an exception. uart.read() also works correctly in this mode. As part of this patch, timout_char now has a minimum value which is long enough to transfer 1 character. Addresses issue #1533.
1 parent f99491c commit 0d9b450

File tree

3 files changed

+61
-8
lines changed

3 files changed

+61
-8
lines changed

stmhal/uart.c

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,37 @@ int uart_rx_char(pyb_uart_obj_t *self) {
331331
}
332332
}
333333

334+
// Waits at most timeout milliseconds for TX register to become empty.
335+
// Returns true if can write, false if can't.
336+
STATIC bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout) {
337+
uint32_t start = HAL_GetTick();
338+
for (;;) {
339+
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_TXE)) {
340+
return true; // tx register is empty
341+
}
342+
if (HAL_GetTick() - start >= timeout) {
343+
return false; // timeout
344+
}
345+
__WFI();
346+
}
347+
}
348+
349+
STATIC HAL_StatusTypeDef uart_tx_data(pyb_uart_obj_t *self, uint8_t *data, uint16_t len) {
350+
// The timeout specified here is for waiting for the TX data register to
351+
// become empty (ie between chars), as well as for the final char to be
352+
// completely transferred. The default value for timeout_char is long
353+
// enough for 1 char, but we need to double it to wait for the last char
354+
// to be transferred to the data register, and then to be transmitted.
355+
return HAL_UART_Transmit(&self->uart, data, len, 2 * self->timeout_char);
356+
}
357+
334358
STATIC void uart_tx_char(pyb_uart_obj_t *uart_obj, int c) {
335359
uint8_t ch = c;
336-
HAL_UART_Transmit(&uart_obj->uart, &ch, 1, uart_obj->timeout);
360+
uart_tx_data(uart_obj, &ch, 1);
337361
}
338362

339363
void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
340-
HAL_UART_Transmit(&uart_obj->uart, (uint8_t*)str, len, uart_obj->timeout);
364+
uart_tx_data(uart_obj, (uint8_t*)str, len);
341365
}
342366

343367
void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
@@ -480,9 +504,16 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
480504
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "UART(%d) does not exist", self->uart_id));
481505
}
482506

483-
// set timeouts
507+
// set timeout
484508
self->timeout = args[5].u_int;
509+
510+
// set timeout_char
511+
// make sure it is at least as long as a whole character (13 bits to be safe)
485512
self->timeout_char = args[6].u_int;
513+
uint32_t min_timeout_char = 13000 / init->BaudRate + 1;
514+
if (self->timeout_char < min_timeout_char) {
515+
self->timeout_char = min_timeout_char;
516+
}
486517

487518
// setup the read buffer
488519
m_del(byte, self->read_buf, self->read_buf_len << self->char_width);
@@ -689,8 +720,13 @@ STATIC mp_obj_t pyb_uart_writechar(mp_obj_t self_in, mp_obj_t char_in) {
689720
// get the character to write (might be 9 bits)
690721
uint16_t data = mp_obj_get_int(char_in);
691722

692-
// write the data
693-
HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, (uint8_t*)&data, 1, self->timeout);
723+
// write the character
724+
HAL_StatusTypeDef status;
725+
if (uart_tx_wait(self, self->timeout)) {
726+
status = uart_tx_data(self, (uint8_t*)&data, 1);
727+
} else {
728+
status = HAL_TIMEOUT;
729+
}
694730

695731
if (status != HAL_OK) {
696732
mp_hal_raise(status);
@@ -807,8 +843,14 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
807843
return MP_STREAM_ERROR;
808844
}
809845

846+
// wait to be able to write the first character
847+
if (!uart_tx_wait(self, self->timeout)) {
848+
*errcode = EAGAIN;
849+
return MP_STREAM_ERROR;
850+
}
851+
810852
// write the data
811-
HAL_StatusTypeDef status = HAL_UART_Transmit(&self->uart, (uint8_t*)buf, size >> self->char_width, self->timeout);
853+
HAL_StatusTypeDef status = uart_tx_data(self, (uint8_t*)buf, size >> self->char_width);
812854

813855
if (status == HAL_OK) {
814856
// return number of bytes written

tests/pyb/uart.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,10 @@
2323

2424
# make sure this method exists
2525
uart.sendbreak()
26+
27+
# non-blocking mode
28+
uart = UART(1, 9600, timeout=0)
29+
print(uart.write(b'1'))
30+
print(uart.write(b'abcd'))
31+
print(uart.writechar(1))
32+
print(uart.read(100))

tests/pyb/uart.py.exp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@ UART XB
1212
UART YA
1313
UART YB
1414
ValueError Z
15-
UART(1, baudrate=9600, bits=8, parity=None, stop=1, timeout=1000, timeout_char=0, read_buf_len=64)
16-
UART(1, baudrate=2400, bits=8, parity=None, stop=1, timeout=1000, timeout_char=0, read_buf_len=64)
15+
UART(1, baudrate=9600, bits=8, parity=None, stop=1, timeout=1000, timeout_char=2, read_buf_len=64)
16+
UART(1, baudrate=2400, bits=8, parity=None, stop=1, timeout=1000, timeout_char=6, read_buf_len=64)
1717
0
1818
3
1919
4
2020
None
21+
1
22+
4
23+
None
24+
None

0 commit comments

Comments
 (0)
0