diff --git a/docs/library/pyb.UART.rst b/docs/library/pyb.UART.rst
index 257a9f281bafca5afd823b4f92dd1ed539908ad5..509ca40803e32bcce768e9ee3b8fd9ff1c588e4c 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 <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 d888358b36fb037d859aa0f102d71662dab866ad..4821da95fd4d54745be4c08446af49cb70437970 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;
 }