diff options
Diffstat (limited to 'stmhal/uart.c')
-rw-r--r-- | stmhal/uart.c | 69 |
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; |