diff --git a/arch/arm/src/samv7/Kconfig b/arch/arm/src/samv7/Kconfig index 7f0c9f1dda2..96f0126c221 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 a07bb524cfe..762843f7d60 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 00000000000..ffba73845a1 --- /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 + +#include + +#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 */