Skip to content
Snippets Groups Projects
Commit 158a8300 authored by Joakim Nohlgård's avatar Joakim Nohlgård
Browse files

kinetis: LPUART: Compute oversampling rate at init

By not forcing a fixed oversampling rate we can achieve better baud rate
accuracy than otherwise possible.
For example, when requesting 115200 with a module clock of 4 MHz,
picking an oversampling rate of 17 (instead of hardware
default 16) yields 117647 baud instead of 125000 baud as the best
matching rate. Better matching baud rate between receiver and
transmitter results in a lower probability of transmission errors.
parent 6d5af802
No related branches found
No related tags found
No related merge requests found
......@@ -58,9 +58,14 @@
#endif
#endif
#ifndef LPUART_OVERSAMPLING_RATE
/* Use 16x oversampling by default (hardware defaults) */
#define LPUART_OVERSAMPLING_RATE (16)
#ifndef LPUART_OVERSAMPLING_RATE_MIN
/* Use 10x oversampling at minimum, this will be iterated to achieve a better
* baud rate match than otherwise possible with a fixed oversampling rate */
/* Hardware reset default value is an oversampling rate of 16 */
#define LPUART_OVERSAMPLING_RATE_MIN (10)
#endif
#ifndef LPUART_OVERSAMPLING_RATE_MAX
#define LPUART_OVERSAMPLING_RATE_MAX (32)
#endif
/* Default LPUART clock setting to avoid compilation failures, define this in
......@@ -318,7 +323,6 @@ void UART_4_ISR(void)
static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
{
LPUART_Type *dev = uart_config[uart].dev;
uint32_t clk = uart_config[uart].freq;
/* Set LPUART clock source */
#ifdef SIM_SOPT2_LPUART0SRC
......@@ -339,10 +343,23 @@ static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
dev->CTRL = uart_config[uart].mode;
/* calculate baud rate divisor */
uint32_t div = clk / (baudrate * LPUART_OVERSAMPLING_RATE);
uint32_t clk = uart_config[uart].freq;
uint32_t best_err = baudrate;
uint32_t best_osr = LPUART_OVERSAMPLING_RATE_MIN;
/* Use the oversampling rate as a baud rate fine adjust tool */
for (uint32_t osr = LPUART_OVERSAMPLING_RATE_MIN; osr <= LPUART_OVERSAMPLING_RATE_MAX; ++osr) {
uint32_t div = clk / (osr * baudrate);
uint32_t actual_baud = clk / (osr * div);
uint32_t err = ((actual_baud > baudrate) ? actual_baud - baudrate : baudrate - actual_baud);
if (err < best_err) {
best_err = err;
best_osr = osr;
}
}
uint32_t sbr = clk / (best_osr * baudrate);
/* set baud rate */
dev->BAUD = LPUART_BAUD_OSR(LPUART_OVERSAMPLING_RATE - 1) | LPUART_BAUD_SBR(div);
dev->BAUD = LPUART_BAUD_OSR(best_osr - 1) | LPUART_BAUD_SBR(sbr);
/* enable transmitter and receiver + RX interrupt */
dev->CTRL |= LPUART_CTRL_TE_MASK | LPUART_CTRL_RE_MASK | LPUART_CTRL_RIE_MASK;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment