diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst index 257a9f281b..509ca40803 100644 --- a/docs/library/pyb.UART.rst +++ b/docs/library/pyb.UART.rst @@ -75,6 +75,13 @@ Methods - ``timeout_char`` is the timeout in milliseconds to wait between characters. - ``read_buf_len`` is the character length of the read buffer (0 to disable). + This method will raise an exception if the baudrate could not be set within + 5% of the desired value. The minimum baudrate is dictated by the frequency + of the bus that the UART is on; UART(1) and UART(6) are APB2, the rest are on + APB1. The default bus frequencies give a minimum baudrate of 1300 for + UART(1) and UART(6) and 650 for the others. Use :func:`pyb.freq ` + to reduce the bus frequencies to get lower baudrates. + *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits are supported. diff --git a/stmhal/uart.c b/stmhal/uart.c index d888358b36..4821da95fd 100644 --- a/stmhal/uart.c +++ b/stmhal/uart.c @@ -457,6 +457,28 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, mp_uint_t n_args, con HAL_NVIC_EnableIRQ(self->irqn); } + // 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) { + actual_baudrate = HAL_RCC_GetPCLK2Freq(); + } else { + actual_baudrate = HAL_RCC_GetPCLK1Freq(); + } + actual_baudrate /= self->uart.Instance->BRR; + + // check we could set the baudrate within 5% + uint32_t baudrate_diff; + if (actual_baudrate > init->BaudRate) { + baudrate_diff = actual_baudrate - init->BaudRate; + } else { + baudrate_diff = init->BaudRate - actual_baudrate; + } + init->BaudRate = actual_baudrate; // remember actual baudrate for printing + if (20 * baudrate_diff > init->BaudRate) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "set baudrate %d is not within 5%% of desired value", actual_baudrate)); + } + return mp_const_none; }