summaryrefslogtreecommitdiffstatshomepage
path: root/stmhal/uart.c
diff options
context:
space:
mode:
Diffstat (limited to 'stmhal/uart.c')
-rw-r--r--stmhal/uart.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/stmhal/uart.c b/stmhal/uart.c
index 272b207eb7..108236ca1a 100644
--- a/stmhal/uart.c
+++ b/stmhal/uart.c
@@ -150,7 +150,6 @@ STATIC bool uart_init2(pyb_uart_obj_t *uart_obj) {
#endif
#if defined(MICROPY_HW_UART2_PORT) && defined(MICROPY_HW_UART2_PINS)
- // USART2 is on PA2/PA3 (CTS,RTS,CK on PA0,PA1,PA4), PD5/PD6 (CK on PD7)
case PYB_UART_2:
UARTx = USART2;
irqn = USART2_IRQn;
@@ -320,10 +319,14 @@ int uart_rx_char(pyb_uart_obj_t *self) {
data = self->read_buf[self->read_buf_tail];
}
self->read_buf_tail = (self->read_buf_tail + 1) % self->read_buf_len;
+ if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
+ // UART was stalled by flow ctrl: re-enable IRQ now we have room in buffer
+ __HAL_UART_ENABLE_IT(&self->uart, UART_IT_RXNE);
+ }
return data;
} else {
// no buffering
- #if defined(MCU_SERIES_F7)
+ #if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
return self->uart.Instance->RDR & self->char_mask;
#else
return self->uart.Instance->DR & self->char_mask;
@@ -347,6 +350,11 @@ STATIC bool uart_tx_wait(pyb_uart_obj_t *self, uint32_t timeout) {
}
STATIC HAL_StatusTypeDef uart_tx_data(pyb_uart_obj_t *self, uint8_t *data, uint16_t len) {
+ if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
+ // CTS can hold off transmission for an arbitrarily long time. Apply
+ // the overall timeout rather than the character timeout.
+ return HAL_UART_Transmit(&self->uart, data, len, self->timeout);
+ }
// The timeout specified here is for waiting for the TX data register to
// become empty (ie between chars), as well as for the final char to be
// completely transferred. The default value for timeout_char is long
@@ -385,25 +393,25 @@ void uart_irq_handler(mp_uint_t uart_id) {
}
if (__HAL_UART_GET_FLAG(&self->uart, UART_FLAG_RXNE) != RESET) {
- #if defined(MCU_SERIES_F7)
- int data = self->uart.Instance->RDR; // clears UART_FLAG_RXNE
- #else
- int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE
- #endif
- data &= self->char_mask;
if (self->read_buf_len != 0) {
uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len;
if (next_head != self->read_buf_tail) {
- // only store data if room in buf
+ // only read data if room in buf
+ #if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
+ int data = self->uart.Instance->RDR; // clears UART_FLAG_RXNE
+ #else
+ int data = self->uart.Instance->DR; // clears UART_FLAG_RXNE
+ #endif
+ data &= self->char_mask;
if (self->char_width == CHAR_WIDTH_9BIT) {
((uint16_t*)self->read_buf)[self->read_buf_head] = data;
} else {
self->read_buf[self->read_buf_head] = data;
}
self->read_buf_head = next_head;
+ } else { // No room: leave char in buf, disable interrupt
+ __HAL_UART_DISABLE_IT(&self->uart, UART_IT_RXNE);
}
- } else {
- // TODO set flag for buffer overflow
}
}
}
@@ -427,6 +435,15 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
} else {
mp_printf(print, "%u", self->uart.Init.Parity == UART_PARITY_EVEN ? 0 : 1);
}
+ if (self->uart.Init.HwFlowCtl) {
+ mp_printf(print, ", flow=");
+ if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_RTS) {
+ mp_printf(print, "RTS%s", self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS ? "|" : "");
+ }
+ if (self->uart.Init.HwFlowCtl & UART_HWCONTROL_CTS) {
+ mp_printf(print, "CTS");
+ }
+ }
mp_printf(print, ", stop=%u, timeout=%u, timeout_char=%u, read_buf_len=%u)",
self->uart.Init.StopBits == UART_STOPBITS_1 ? 1 : 2,
self->timeout, self->timeout_char,
@@ -434,7 +451,7 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
}
}
-/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, read_buf_len=64)
+/// \method init(baudrate, bits=8, parity=None, stop=1, *, timeout=1000, timeout_char=0, flow=0, read_buf_len=64)
///
/// Initialise the UART bus with the given parameters:
///
@@ -444,6 +461,7 @@ STATIC void pyb_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_k
/// - `stop` is the number of stop bits, 1 or 2.
/// - `timeout` is the timeout in milliseconds to wait for the first character.
/// - `timeout_char` is the timeout in milliseconds to wait between characters.
+/// - `flow` is RTS | CTS where RTS == 256, CTS == 512
/// - `read_buf_len` is the character length of the read buffer (0 to disable).
STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
static const mp_arg_t allowed_args[] = {
@@ -552,12 +570,20 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con
// compute actual baudrate that was configured
// (this formula assumes UART_OVERSAMPLING_16)
uint32_t actual_baudrate;
- if (self->uart.Instance == USART1 || self->uart.Instance == USART6) {
+ if (self->uart.Instance == USART1
+ #if defined(USART6)
+ || self->uart.Instance == USART6
+ #endif
+ ) {
actual_baudrate = HAL_RCC_GetPCLK2Freq();
} else {
actual_baudrate = HAL_RCC_GetPCLK1Freq();
}
+ #if defined(MCU_SERIES_L4)
+ actual_baudrate = (actual_baudrate << 5) / (self->uart.Instance->BRR >> 3);
+ #else
actual_baudrate /= self->uart.Instance->BRR;
+ #endif
// check we could set the baudrate within 5%
uint32_t baudrate_diff;
@@ -697,11 +723,13 @@ STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
__UART5_RELEASE_RESET();
__UART5_CLK_DISABLE();
#endif
+ #if defined(UART6)
} else if (uart->Instance == USART6) {
HAL_NVIC_DisableIRQ(USART6_IRQn);
__USART6_FORCE_RESET();
__USART6_RELEASE_RESET();
__USART6_CLK_DISABLE();
+ #endif
}
return mp_const_none;
}
@@ -757,7 +785,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar);
// uart.sendbreak()
STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
- #if defined(MCU_SERIES_F7)
+ #if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
self->uart.Instance->RQR = USART_RQR_SBKRQ; // write-only register
#else
self->uart.Instance->CR1 |= USART_CR1_SBK;
@@ -847,7 +875,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
return MP_STREAM_ERROR;
}
- // wait to be able to write the first character
+ // wait to be able to write the first character. EAGAIN causes write to return None
if (!uart_tx_wait(self, self->timeout)) {
*errcode = EAGAIN;
return MP_STREAM_ERROR;
@@ -859,6 +887,17 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
if (status == HAL_OK) {
// return number of bytes written
return size;
+ } else if (status == HAL_TIMEOUT) { // UART_WaitOnFlagUntilTimeout() disables RXNE interrupt on timeout
+ if (self->read_buf_len > 0) {
+ __HAL_UART_ENABLE_IT(&self->uart, UART_IT_RXNE); // re-enable RXNE
+ }
+ // return number of bytes written
+ if (self->char_width == CHAR_WIDTH_8BIT) {
+ return size - self->uart.TxXferCount - 1;
+ } else {
+ int written = self->uart.TxXferCount * 2;
+ return size - written - 2;
+ }
} else {
*errcode = mp_hal_status_to_errno_table[status];
return MP_STREAM_ERROR;