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 */

Reply via email to