From a51fb298dc2cc7e909e47623f48bc8293364d140 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Mon, 26 Jul 2021 14:42:36 +0200 Subject: [PATCH] cpu/sam0_common: implement periph_uart_collision feature --- cpu/sam0_common/periph/uart.c | 76 +++++++++++++++++++++++++++++++++++ cpu/samd21/Kconfig | 3 ++ cpu/samd21/Makefile.features | 4 ++ cpu/samd5x/Kconfig | 1 + cpu/samd5x/Makefile.features | 1 + cpu/saml1x/Kconfig | 1 + cpu/saml1x/Makefile.features | 1 + cpu/saml21/Kconfig | 1 + cpu/saml21/Makefile.features | 1 + 9 files changed, 89 insertions(+) diff --git a/cpu/sam0_common/periph/uart.c b/cpu/sam0_common/periph/uart.c index dc8fb6a224..32b804998e 100644 --- a/cpu/sam0_common/periph/uart.c +++ b/cpu/sam0_common/periph/uart.c @@ -322,6 +322,82 @@ void uart_poweroff(uart_t uart) sercom_clk_dis(dev(uart)); } +#ifdef MODULE_PERIPH_UART_COLLISION +bool uart_collision_detected(uart_t uart) +{ + /* In case of collision, the CTRLB register + * will be in sync during disabling of TX, + * then the flag will be set. + */ + _syncbusy(dev(uart)); + + bool collision = dev(uart)->STATUS.bit.COLL; + dev(uart)->STATUS.reg = SERCOM_USART_STATUS_COLL; + return collision; +} + +void uart_collision_detect_enable(uart_t uart) +{ + /* CTRLB is enable protected */ + dev(uart)->CTRLA.bit.ENABLE = 0; + _syncbusy(dev(uart)); + + /* clear stale collision flag */ + dev(uart)->STATUS.reg = SERCOM_USART_STATUS_COLL; + + /* enable collision detection */ + dev(uart)->CTRLB.bit.COLDEN = 1; + + /* disable RX interrupt */ + dev(uart)->INTENCLR.bit.RXC = 1; + + /* re-enable UART */ + dev(uart)->CTRLA.bit.ENABLE = 1; + + /* wait for config to be applied */ + _syncbusy(dev(uart)); +} + +static void _drain_rxbuf(SercomUsart *dev) +{ + /* clear readback bytes from receive buffer */ + while (dev->INTFLAG.bit.RXC) { + dev->DATA.reg; + } +} + +void uart_collision_detect_disable(uart_t uart) +{ + uint32_t ctrlb = dev(uart)->CTRLB.reg; + + /* re-enable TX after collision */ + ctrlb |= SERCOM_USART_CTRLB_TXEN; + + /* disable collision detection */ + ctrlb &= ~SERCOM_USART_CTRLB_COLDEN; + + /* CTRLB is enable protected */ + dev(uart)->CTRLA.bit.ENABLE = 0; + _syncbusy(dev(uart)); + + dev(uart)->CTRLB.reg = ctrlb; + + /* re-enable UART */ + dev(uart)->CTRLA.bit.ENABLE = 1; + + /* wait for config to be applied */ + _syncbusy(dev(uart)); + + /* clear bytes from RX buffer */ + _drain_rxbuf(dev(uart)); + + /* re-enable RX complete IRQ */ + if (uart_ctx[uart].rx_cb) { + dev(uart)->INTENSET.bit.RXC = 1; + } +} +#endif + #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) diff --git a/cpu/samd21/Kconfig b/cpu/samd21/Kconfig index f90b970f71..718bb8f9a4 100644 --- a/cpu/samd21/Kconfig +++ b/cpu/samd21/Kconfig @@ -16,6 +16,7 @@ config CPU_FAM_SAMD10 bool select CPU_COMMON_SAMD21 select HAS_PERIPH_DMA + select HAS_PERIPH_UART_COLLISION config CPU_FAM_SAMD20 bool @@ -25,11 +26,13 @@ config CPU_FAM_SAMD21 bool select CPU_COMMON_SAMD21 select HAS_PERIPH_DMA + select HAS_PERIPH_UART_COLLISION config CPU_FAM_SAMR21 bool select CPU_COMMON_SAMD21 select HAS_PERIPH_DMA + select HAS_PERIPH_UART_COLLISION ## Definition of specific features config HAS_CPU_SAMD21 diff --git a/cpu/samd21/Makefile.features b/cpu/samd21/Makefile.features index 043d08dea3..f7e9895431 100644 --- a/cpu/samd21/Makefile.features +++ b/cpu/samd21/Makefile.features @@ -2,4 +2,8 @@ CPU_CORE = cortex-m0plus FEATURES_PROVIDED += periph_gpio_fast_read +ifeq (,$(filter samd20%,$(CPU_MODEL))) + FEATURES_PROVIDED += periph_uart_collision +endif + -include $(RIOTCPU)/sam0_common/Makefile.features diff --git a/cpu/samd5x/Kconfig b/cpu/samd5x/Kconfig index 0531548781..54339e8ca7 100644 --- a/cpu/samd5x/Kconfig +++ b/cpu/samd5x/Kconfig @@ -16,6 +16,7 @@ config CPU_COMMON_SAMD5X select HAS_PERIPH_GPIO_TAMPER_WAKE select HAS_PERIPH_HWRNG select HAS_PERIPH_RTC_MEM + select HAS_PERIPH_UART_COLLISION select HAS_PERIPH_SPI_ON_QSPI config CPU_FAM_SAMD51 diff --git a/cpu/samd5x/Makefile.features b/cpu/samd5x/Makefile.features index e024c5e1bc..7cba14d218 100644 --- a/cpu/samd5x/Makefile.features +++ b/cpu/samd5x/Makefile.features @@ -6,5 +6,6 @@ FEATURES_PROVIDED += cortexm_mpu FEATURES_PROVIDED += periph_gpio_tamper_wake FEATURES_PROVIDED += periph_rtc_mem FEATURES_PROVIDED += periph_spi_on_qspi +FEATURES_PROVIDED += periph_uart_collision include $(RIOTCPU)/sam0_common/Makefile.features diff --git a/cpu/saml1x/Kconfig b/cpu/saml1x/Kconfig index ca7fa9ad04..1fa2335c38 100644 --- a/cpu/saml1x/Kconfig +++ b/cpu/saml1x/Kconfig @@ -13,6 +13,7 @@ config CPU_COMMON_SAML1X select HAS_PERIPH_DMA select HAS_PERIPH_GPIO_FAST_READ select HAS_PERIPH_HWRNG + select HAS_PERIPH_UART_COLLISION config CPU_FAM_SAML10 bool diff --git a/cpu/saml1x/Makefile.features b/cpu/saml1x/Makefile.features index 267b8b7fee..b46af8aaba 100644 --- a/cpu/saml1x/Makefile.features +++ b/cpu/saml1x/Makefile.features @@ -5,5 +5,6 @@ CPU_CORE = cortex-m23 FEATURES_PROVIDED += periph_hwrng FEATURES_PROVIDED += periph_gpio_fast_read +FEATURES_PROVIDED += periph_uart_collision include $(RIOTCPU)/sam0_common/Makefile.features diff --git a/cpu/saml21/Kconfig b/cpu/saml21/Kconfig index 97c99c2540..dc8ca5f358 100644 --- a/cpu/saml21/Kconfig +++ b/cpu/saml21/Kconfig @@ -14,6 +14,7 @@ config CPU_COMMON_SAML21 select HAS_PERIPH_DMA select HAS_PERIPH_GPIO_FAST_READ select HAS_PERIPH_RTC_MEM + select HAS_PERIPH_UART_COLLISION config CPU_FAM_SAML21 bool diff --git a/cpu/saml21/Makefile.features b/cpu/saml21/Makefile.features index 85685fb27f..fe77d1c1df 100644 --- a/cpu/saml21/Makefile.features +++ b/cpu/saml21/Makefile.features @@ -4,6 +4,7 @@ CPU_CORE = cortex-m0plus CPU_MODELS_WITHOUT_HWRNG += samr30% FEATURES_PROVIDED += periph_gpio_fast_read +FEATURES_PROVIDED += periph_uart_collision # Low Power SRAM is *not* retained during Backup Sleep. # It therefore does not fulfill the requirements of the 'backup_ram' interface.