Repository: raspberrypi/pico-sdk
File: src/rp2_common/hardware_uart/uart.c (C)

Code before:
    // Anything else would require API changes to permit a non-enabled UART
    // state after init() where settings can be changed safely.

    uint32_t cr_save = uart_get_hw(uart)->cr;
    hw_clear_bits(&uart_get_hw(uart)->cr,
        UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS);

    uint32_t current_ibrd = uart_get_hw(uart)->ibrd;
    uint32_t current_fbrd = uart_get_hw(uart)->fbrd;

    // Note: Maximise precision here. Show working, the compiler will mop this up.
    // Create a 16.6 fixed-point fractional division ratio; then scale to 32-bits.
    uint32_t brdiv_ratio = 64u * current_ibrd + current_fbrd;
    brdiv_ratio <<= 10;
    // 3662 is ~(15 * 244.14) where 244.14 is 16e6 / 2^16
    uint32_t scaled_freq = clock_get_hz(clk_peri) / 3662ul;
    uint32_t wait_time_us = brdiv_ratio / scaled_freq;
    busy_wait_us(wait_time_us);

    return cr_save;
}

static void uart_write_lcr_bits_masked(uart_inst_t *uart, uint32_t values, uint32_t write_mask) {
    invalid_params_if(UART, uart != uart0 && uart != uart1);
    uint32_t cr_save;
    bool enabled = uart_is_enabled(uart);

    if (enabled) {
        // Need to cleanly disable UART before touching LCR
        cr_save = uart_disable_before_lcr_write(uart);
    }

    hw_write_masked(&uart_get_hw(uart)->lcr_h, values, write_mask);

    // Re-enable using saved control register value
    if (enabled) {
        uart_get_hw(uart)->cr = cr_save;
    }
}

/// \tag::uart_set_baudrate[]
uint uart_set_baudrate(uart_inst_t *uart, uint baudrate) {
    invalid_params_if(UART, baudrate == 0);
    uint32_t baud_rate_div = (8 * clock_get_hz(clk_peri) / baudrate);
    uint32_t baud_ibrd = baud_rate_div >> 7;
    uint32_t baud_fbrd;

    if (baud_ibrd == 0) {
        baud_ibrd = 1;
        baud_fbrd = 0;
    } else if (baud_ibrd >= 65535) {

Review comment (suggestion):
I mentioned this in a previous review, but i would like to get rid of the `uart_is_enabled` checks in the caller, and just put it in the uart_disable_before_lcr_write (which can just do the delay if the UART was enabled based on its read of the CR).

it is then fine to unconditionally set the CR at the bottom of the callers too.

Code after:
    // Anything else would require API changes to permit a non-enabled UART
    // state after init() where settings can be changed safely.
    uint32_t cr_save = uart_get_hw(uart)->cr;

    if (cr_save & UART_UARTCR_UARTEN_BITS) {
        hw_clear_bits(&uart_get_hw(uart)->cr,
            UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS | UART_UARTCR_RXE_BITS);

        uint32_t current_ibrd = uart_get_hw(uart)->ibrd;
        uint32_t current_fbrd = uart_get_hw(uart)->fbrd;

        // Note: Maximise precision here. Show working, the compiler will mop this up.
        // Create a 16.6 fixed-point fractional division ratio; then scale to 32-bits.
        uint32_t brdiv_ratio = 64u * current_ibrd + current_fbrd;
        brdiv_ratio <<= 10;
        // 3662 is ~(15 * 244.14) where 244.14 is 16e6 / 2^16
        uint32_t scaled_freq = clock_get_hz(clk_peri) / 3662ul;
        uint32_t wait_time_us = brdiv_ratio / scaled_freq;
        busy_wait_us(wait_time_us);
    }

    return cr_save;
}

static void uart_write_lcr_bits_masked(uart_inst_t *uart, uint32_t values, uint32_t write_mask) {
    invalid_params_if(UART, uart != uart0 && uart != uart1);

    // (Potentially) Cleanly handle disabling the UART before touching LCR
    uint32_t cr_save = uart_disable_before_lcr_write(uart);

    hw_write_masked(&uart_get_hw(uart)->lcr_h, values, write_mask);

    uart_get_hw(uart)->cr = cr_save;
}

/// \tag::uart_set_baudrate[]
uint uart_set_baudrate(uart_inst_t *uart, uint baudrate) {
    invalid_params_if(UART, baudrate == 0);
    uint32_t baud_rate_div = (8 * clock_get_hz(clk_peri) / baudrate);
    uint32_t baud_ibrd = baud_rate_div >> 7;
    uint32_t baud_fbrd;

    if (baud_ibrd == 0) {
        baud_ibrd = 1;
        baud_fbrd = 0;
    } else if (baud_ibrd >= 65535) {
        baud_ibrd = 65535;
        baud_fbrd = 0;
    }  else {
        baud_fbrd = ((baud_rate_div & 0x7f) + 1) / 2;
    }