Merge pull request #17186 from benpicco/cpu/sam0_common/uart-frac
cpu/sam0_common: uart: set oversampling based on baud rate
This commit is contained in:
commit
8f4ef1eb75
@ -95,14 +95,16 @@ static inline void _reset(SercomUsart *dev)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _set_baud(uart_t uart, uint32_t baudrate)
|
static void _set_baud(uart_t uart, uint32_t baudrate, uint32_t f_src)
|
||||||
{
|
{
|
||||||
const uint32_t f_src = sam0_gclk_freq(uart_config[uart].gclk_src);
|
|
||||||
#if IS_ACTIVE(CONFIG_SAM0_UART_BAUD_FRAC)
|
#if IS_ACTIVE(CONFIG_SAM0_UART_BAUD_FRAC)
|
||||||
/* Asynchronous Fractional */
|
/* Asynchronous Fractional */
|
||||||
uint32_t baud = (((f_src * 8) / baudrate) / 16);
|
/* BAUD + FP / 8 = f_src / (S * f_baud) */
|
||||||
dev(uart)->BAUD.FRAC.FP = (baud % 8);
|
/* BAUD * 8 + FP = (8 * f_src) / (S * f_baud) */
|
||||||
dev(uart)->BAUD.FRAC.BAUD = (baud / 8);
|
/* S * (BAUD + 8 * FP) = (8 * f_src) / f_baud */
|
||||||
|
uint32_t baud = (f_src * 8) / baudrate;
|
||||||
|
dev(uart)->BAUD.FRAC.FP = (baud >> 4) & 0x7; /* baud / 16 */
|
||||||
|
dev(uart)->BAUD.FRAC.BAUD = baud >> 7; /* baud / (8 * 16) */
|
||||||
#else
|
#else
|
||||||
/* Asynchronous Arithmetic */
|
/* Asynchronous Arithmetic */
|
||||||
/* BAUD = 2^16 * (2^0 - 2^4 * f_baud / f_src) */
|
/* BAUD = 2^16 * (2^0 - 2^4 * f_baud / f_src) */
|
||||||
@ -180,12 +182,27 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
|||||||
/* configure clock generator */
|
/* configure clock generator */
|
||||||
sercom_set_gen(dev(uart), uart_config[uart].gclk_src);
|
sercom_set_gen(dev(uart), uart_config[uart].gclk_src);
|
||||||
|
|
||||||
|
uint32_t f_src = sam0_gclk_freq(uart_config[uart].gclk_src);
|
||||||
|
|
||||||
|
#if IS_ACTIVE(CONFIG_SAM0_UART_BAUD_FRAC)
|
||||||
|
uint32_t sampr;
|
||||||
|
/* constraint: f_baud ≤ f_src / S */
|
||||||
|
if (baudrate * 16 > f_src) {
|
||||||
|
/* 8x oversampling */
|
||||||
|
sampr = SERCOM_USART_CTRLA_SAMPR(0x3);
|
||||||
|
f_src <<= 1;
|
||||||
|
} else {
|
||||||
|
/* 16x oversampling */
|
||||||
|
sampr = SERCOM_USART_CTRLA_SAMPR(0x1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* set asynchronous mode w/o parity, LSB first, TX and RX pad as specified
|
/* set asynchronous mode w/o parity, LSB first, TX and RX pad as specified
|
||||||
* by the board in the periph_conf.h, x16 sampling and use internal clock */
|
* by the board in the periph_conf.h, x16 sampling and use internal clock */
|
||||||
dev(uart)->CTRLA.reg = SERCOM_USART_CTRLA_DORD
|
dev(uart)->CTRLA.reg = SERCOM_USART_CTRLA_DORD
|
||||||
#if IS_ACTIVE(CONFIG_SAM0_UART_BAUD_FRAC)
|
#if IS_ACTIVE(CONFIG_SAM0_UART_BAUD_FRAC)
|
||||||
/* enable Asynchronous Fractional mode */
|
/* enable Asynchronous Fractional mode */
|
||||||
| SERCOM_USART_CTRLA_SAMPR(0x1)
|
| sampr
|
||||||
#endif
|
#endif
|
||||||
| SERCOM_USART_CTRLA_TXPO(uart_config[uart].tx_pad)
|
| SERCOM_USART_CTRLA_TXPO(uart_config[uart].tx_pad)
|
||||||
| SERCOM_USART_CTRLA_RXPO(uart_config[uart].rx_pad)
|
| SERCOM_USART_CTRLA_RXPO(uart_config[uart].rx_pad)
|
||||||
@ -197,7 +214,7 @@ int uart_init(uart_t uart, uint32_t baudrate, uart_rx_cb_t rx_cb, void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* calculate and set baudrate */
|
/* calculate and set baudrate */
|
||||||
_set_baud(uart, baudrate);
|
_set_baud(uart, baudrate, f_src);
|
||||||
|
|
||||||
/* enable transmitter, and configure 8N1 mode */
|
/* enable transmitter, and configure 8N1 mode */
|
||||||
if (uart_config[uart].tx_pin != GPIO_UNDEF) {
|
if (uart_config[uart].tx_pin != GPIO_UNDEF) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user