diff --git a/cpu/sam0_common/Makefile.features b/cpu/sam0_common/Makefile.features index a8147a397f..f5cf9a55e3 100644 --- a/cpu/sam0_common/Makefile.features +++ b/cpu/sam0_common/Makefile.features @@ -3,5 +3,6 @@ FEATURES_PROVIDED += periph_flashpage FEATURES_PROVIDED += periph_flashpage_raw FEATURES_PROVIDED += periph_flashpage_rwee FEATURES_PROVIDED += periph_gpio periph_gpio_irq +FEATURES_PROVIDED += periph_uart_modecfg -include $(RIOTCPU)/cortexm_common/Makefile.features diff --git a/cpu/sam0_common/include/periph_cpu_common.h b/cpu/sam0_common/include/periph_cpu_common.h index d47bf93021..2056dbf942 100644 --- a/cpu/sam0_common/include/periph_cpu_common.h +++ b/cpu/sam0_common/include/periph_cpu_common.h @@ -178,6 +178,22 @@ typedef enum { UART_FLAG_WAKEUP = 0x2, /**< wake from sleep on receive */ } uart_flag_t; +/** + * @brief Available SERCOM UART data size selections + * + * 9 bit UART mode is currently unavailable as it is not supported by the common + * RIOT UART peripheral API. + * @{ + */ +#define HAVE_UART_DATA_BITS_T +typedef enum { + UART_DATA_BITS_5 = 0x5, /**< 5 data bits */ + UART_DATA_BITS_6 = 0x6, /**< 6 data bits */ + UART_DATA_BITS_7 = 0x7, /**< 7 data bits */ + UART_DATA_BITS_8 = 0x0, /**< 8 data bits */ +} uart_data_bits_t; +/** @} */ + /** * @brief UART device configuration */ diff --git a/cpu/sam0_common/periph/uart.c b/cpu/sam0_common/periph/uart.c index 68de304485..b89493dd8f 100644 --- a/cpu/sam0_common/periph/uart.c +++ b/cpu/sam0_common/periph/uart.c @@ -140,6 +140,47 @@ void uart_poweroff(uart_t uart) sercom_clk_dis(dev(uart)); } +#ifdef MODULE_PERIPH_UART_MODECFG +int uart_mode(uart_t uart, uart_data_bits_t data_bits, uart_parity_t parity, + uart_stop_bits_t stop_bits) +{ + if (uart >= UART_NUMOF) { + return UART_NODEV; + } + + if (stop_bits != UART_STOP_BITS_1 && stop_bits != UART_STOP_BITS_2) { + return UART_NOMODE; + } + + if (parity != UART_PARITY_NONE && parity != UART_PARITY_EVEN && + parity != UART_PARITY_ODD) { + return UART_NOMODE; + } + + /* Disable UART first to remove write protect */ + dev(uart)->CTRLA.bit.ENABLE = 0; + while (dev(uart)->SYNCBUSY.bit.ENABLE) {} + + dev(uart)->CTRLB.bit.CHSIZE = data_bits; + + if (parity == UART_PARITY_NONE) { + dev(uart)->CTRLA.bit.FORM = 0x0; + } + else { + dev(uart)->CTRLA.bit.FORM = 0x1; + dev(uart)->CTRLB.bit.PMODE = (parity == UART_PARITY_ODD) ? 1 : 0; + } + + dev(uart)->CTRLB.bit.SBMODE = (stop_bits == UART_STOP_BITS_1) ? 0 : 1; + + /* Enable UART again */ + dev(uart)->CTRLA.bit.ENABLE = 1; + while (dev(uart)->SYNCBUSY.bit.ENABLE) {} + + return UART_OK; +} +#endif + static inline void irq_handler(unsigned uartnum) { if (dev(uartnum)->INTFLAG.bit.RXC) {