This is an automated email from the ASF dual-hosted git repository. pkarashchenko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 89a2b51b96980aaaa55700da4e09bac4bf8f66e3 Author: Michal Lenc <[email protected]> AuthorDate: Thu Jul 14 21:41:51 2022 +0200 samv7: add RS-485 mode support to USART driver This commit enhances SAMV7 serial driver with RS-485 mode available to USART peripherals. The hardware automatically sets RTS pin high when data are transfered and low then no transfer occurs. Only USART peripherals support this mode, UART peripherals do not. This mode can be enabled by configuration option SAMV7_USARTx_RS485MODE. Signed-off-by: Michal Lenc <[email protected]> --- arch/arm/src/samv7/Kconfig | 45 ++++++++++++++++++++++++++++--- arch/arm/src/samv7/sam_serial.c | 60 +++++++++++++++++++++++++++++++++++++++++ arch/arm/src/samv7/sam_serial.h | 51 +++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 3 deletions(-) diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig index 7f0c9f1dda..96f0126c22 100644 --- a/arch/arm/src/samv7/Kconfig +++ b/arch/arm/src/samv7/Kconfig @@ -797,27 +797,66 @@ config SAMV7_USBHOSTHS depends on SAMV7_HAVE_USBHS select USBHOST -config SAMV7_USART0 +menuconfig SAMV7_USART0 bool "USART 0" default n depends on SAMV7_HAVE_USART0 select USART0_SERIALDRIVER select ARCH_HAVE_SERIAL_TERMIOS -config SAMV7_USART1 +if SAMV7_USART0 + +config SAMV7_USART0_RS485MODE + bool "RS-485 on USART0" + default n + ---help--- + Enable RS-485 interface on USART0. Please note that the pin is set + to logical 1 before the serial driver is opened. Board specific + logic is required to set the pin to logical 0 before the driver is + opened for the first time. + +endif + +menuconfig SAMV7_USART1 bool "USART 1" default n depends on SAMV7_HAVE_USART1 select USART1_SERIALDRIVER select ARCH_HAVE_SERIAL_TERMIOS -config SAMV7_USART2 +if SAMV7_USART1 + +config SAMV7_USART1_RS485MODE + bool "RS-485 on USART1" + default n + ---help--- + Enable RS-485 interface on USART1. Please note that the pin is set + to logical 1 before the serial driver is opened. Board specific + logic is required to set the pin to logical 0 before the driver is + opened for the first time. + +endif + +menuconfig SAMV7_USART2 bool "USART 2" default n depends on SAMV7_HAVE_USART2 select USART2_SERIALDRIVER select ARCH_HAVE_SERIAL_TERMIOS +if SAMV7_USART2 + +config SAMV7_USART2_RS485MODE + bool "RS-485 on USART2" + default n + ---help--- + Enable RS-485 interface on USART2. Please note that the pin is set + to logical 1 before the serial driver is opened. Board specific + logic is required to set the pin to logical 0 before the driver is + opened for the first time. + +endif + config SAMV7_WDT bool "Watchdog Timer (WDT)" default n diff --git a/arch/arm/src/samv7/sam_serial.c b/arch/arm/src/samv7/sam_serial.c index a07bb524cf..762843f7d6 100644 --- a/arch/arm/src/samv7/sam_serial.c +++ b/arch/arm/src/samv7/sam_serial.c @@ -46,7 +46,11 @@ #include "arm_internal.h" #include "sam_config.h" + #include "hardware/sam_uart.h" +#include "hardware/sam_pinmap.h" +#include "sam_gpio.h" +#include "sam_serial.h" /**************************************************************************** * Pre-processor Definitions @@ -328,6 +332,12 @@ struct sam_dev_s #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) bool flowc; /* input flow control (RTS) enabled */ #endif + + bool has_rs485; /* True if RS-485 mode is enabled */ + +#ifdef SERIAL_HAVE_RS485 + uint32_t rs485_dir_gpio; /* RS-485 RTS pin */ +#endif }; /**************************************************************************** @@ -417,6 +427,7 @@ static struct sam_dev_s g_uart0priv = .parity = CONFIG_UART0_PARITY, .bits = CONFIG_UART0_BITS, .stopbits2 = CONFIG_UART0_2STOP, + .has_rs485 = false, }; static uart_dev_t g_uart0port = @@ -447,6 +458,7 @@ static struct sam_dev_s g_uart1priv = .parity = CONFIG_UART1_PARITY, .bits = CONFIG_UART1_BITS, .stopbits2 = CONFIG_UART1_2STOP, + .has_rs485 = false, }; static uart_dev_t g_uart1port = @@ -477,6 +489,7 @@ static struct sam_dev_s g_uart2priv = .parity = CONFIG_UART2_PARITY, .bits = CONFIG_UART2_BITS, .stopbits2 = CONFIG_UART2_2STOP, + .has_rs485 = false, }; static uart_dev_t g_uart2port = @@ -507,6 +520,7 @@ static struct sam_dev_s g_uart3priv = .parity = CONFIG_UART3_PARITY, .bits = CONFIG_UART3_BITS, .stopbits2 = CONFIG_UART3_2STOP, + .has_rs485 = false, }; static uart_dev_t g_uart3port = @@ -537,6 +551,7 @@ static struct sam_dev_s g_uart4priv = .parity = CONFIG_UART4_PARITY, .bits = CONFIG_UART4_BITS, .stopbits2 = CONFIG_UART4_2STOP, + .has_rs485 = false, }; static uart_dev_t g_uart4port = @@ -570,6 +585,12 @@ static struct sam_dev_s g_usart0priv = #if defined(CONFIG_USART0_OFLOWCONTROL) || defined(CONFIG_USART0_IFLOWCONTROL) .flowc = true, #endif +#ifdef CONFIG_SAMV7_USART0_RS485MODE + .has_rs485 = true, + .rs485_dir_gpio = GPIO_USART0_RTS, +#else + .has_rs485 = false, +#endif }; static uart_dev_t g_usart0port = @@ -603,6 +624,12 @@ static struct sam_dev_s g_usart1priv = #if defined(CONFIG_USART1_OFLOWCONTROL) || defined(CONFIG_USART1_IFLOWCONTROL) .flowc = true, #endif +#ifdef CONFIG_SAMV7_USART1_RS485MODE + .has_rs485 = true, + .rs485_dir_gpio = GPIO_USART1_RTS, +#else + .has_rs485 = false, +#endif }; static uart_dev_t g_usart1port = @@ -636,6 +663,12 @@ static struct sam_dev_s g_usart2priv = #if defined(CONFIG_USART2_OFLOWCONTROL) || defined(CONFIG_USART2_IFLOWCONTROL) .flowc = true, #endif +#ifdef CONFIG_SAMV7_USART2_RS485MODE + .has_rs485 = true, + .rs485_dir_gpio = GPIO_USART2_RTS, +#else + .has_rs485 = false, +#endif }; static uart_dev_t g_usart2port = @@ -879,6 +912,17 @@ static int sam_setup(struct uart_dev_s *dev) /* Enable receiver & transmitter */ sam_serialout(priv, SAM_UART_CR_OFFSET, (UART_CR_RXEN | UART_CR_TXEN)); + +#ifdef SERIAL_HAVE_RS485 + if (priv->has_rs485) + { + sam_configgpio(priv->rs485_dir_gpio); + + regval = sam_serialin(priv, SAM_UART_MR_OFFSET); + regval |= UART_MR_MODE_RS485; + sam_serialout(priv, SAM_UART_MR_OFFSET, regval); + } +#endif #endif return OK; @@ -896,6 +940,7 @@ static int sam_setup(struct uart_dev_s *dev) static void sam_shutdown(struct uart_dev_s *dev) { struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv; + uint32_t regval; /* Reset and disable receiver and transmitter */ @@ -903,6 +948,21 @@ static void sam_shutdown(struct uart_dev_s *dev) (UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS)); + /* Set mode back to normal */ + + regval = sam_serialin(priv, SAM_UART_MR_OFFSET); + regval &= ~(UART_MR_MODE_MASK); + sam_serialout(priv, SAM_UART_MR_OFFSET, regval); + +#ifdef SERIAL_HAVE_RS485 + if (priv->has_rs485) + { + /* Force RTS pin to get low if RS-485 mode is enabled */ + + sam_serialout(priv, SAM_UART_CR_OFFSET, UART_CR_RTSEN); + } +#endif + /* Disable all interrupts */ sam_disableallints(priv, NULL); diff --git a/arch/arm/src/samv7/sam_serial.h b/arch/arm/src/samv7/sam_serial.h new file mode 100644 index 0000000000..ffba73845a --- /dev/null +++ b/arch/arm/src/samv7/sam_serial.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * arch/arm/src/samv7/sam_serial.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __ARCH_ARM_SRC_SAMV7_SAM_SERIAL_H +#define __ARCH_ARM_SRC_SAMV7_SAM_SERIAL_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <stdint.h> + +#include "chip.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* Is RS-485 used? */ + +#undef SERIAL_HAVE_RS485 +#if defined(CONFIG_SAMV7_USART0_RS485MODE) || \ + defined(CONFIG_SAMV7_USART1_RS485MODE) || \ + defined(CONFIG_SAMV7_USART2_RS485MODE) +# define SERIAL_HAVE_RS485 1 +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#endif /* __ARCH_ARM_SRC_SAMV7_SAM_SERIAL_H */
