arch/arm/src/samd2l2: Add RS485 support to SAMD2L2 serial

This commit is contained in:
Alan Carvalho de Assis
2019-01-20 12:43:42 -06:00
committed by Gregory Nutt
parent bb2391358c
commit a34c9733bc
5 changed files with 290 additions and 14 deletions
+126
View File
@@ -616,6 +616,27 @@ config SAMD2L2_SERCOM0_ISUSART
endchoice
if USART0_SERIALDRIVER
config USART0_RS485MODE
bool "RS-485 on USART0"
default n
---help---
Enable RS-485 interface on USART0. Your board config will have to
provide GPIO_USART0_RS485_DIR pin definition. Currently it cannot be
used with USART0_RXDMA.
config USART0_RS485_DIR_POLARITY
int "USART0 RS-485 DIR pin polarity"
default 1
range 0 1
depends on USART0_RS485MODE
---help---
Polarity of DIR pin for RS-485 on USART0. Set to state on DIR pin which
enables TX (0 - low / nTXEN, 1 - high / TXEN).
endif # USART0_SERIALDRIVER
choice
prompt "SERCOM1 mode"
default SAMD2L2_SERCOM1_ISUSART
@@ -636,6 +657,27 @@ config SAMD2L2_SERCOM1_ISUSART
endchoice
if USART1_SERIALDRIVER
config USART1_RS485MODE
bool "RS-485 on USART1"
default n
---help---
Enable RS-485 interface on USART1. Your board config will have to
provide GPIO_USART1_RS485_DIR pin definition. Currently it cannot be
used with USART1_RXDMA.
config USART1_RS485_DIR_POLARITY
int "USART1 RS-485 DIR pin polarity"
default 1
range 0 1
depends on USART1_RS485MODE
---help---
Polarity of DIR pin for RS-485 on USART1. Set to state on DIR pin which
enables TX (0 - low / nTXEN, 1 - high / TXEN).
endif # USART1_SERIALDRIVER
choice
prompt "SERCOM2 mode"
default SAMD2L2_SERCOM2_ISUSART
@@ -656,6 +698,27 @@ config SAMD2L2_SERCOM2_ISUSART
endchoice
if USART2_SERIALDRIVER
config USART2_RS485MODE
bool "RS-485 on USART2"
default n
---help---
Enable RS-485 interface on USART2. Your board config will have to
provide GPIO_USART2_RS485_DIR pin definition. Currently it cannot be
used with USART2_RXDMA.
config USART2_RS485_DIR_POLARITY
int "USART2 RS-485 DIR pin polarity"
default 1
range 0 1
depends on USART2_RS485MODE
---help---
Polarity of DIR pin for RS-485 on USART2. Set to state on DIR pin which
enables TX (0 - low / nTXEN, 1 - high / TXEN).
endif # USART2_SERIALDRIVER
choice
prompt "SERCOM3 mode"
default SAMD2L2_SERCOM3_ISUSART
@@ -676,6 +739,27 @@ config SAMD2L2_SERCOM3_ISUSART
endchoice
if USART3_SERIALDRIVER
config USART3_RS485MODE
bool "RS-485 on USART3"
default n
---help---
Enable RS-485 interface on USART3. Your board config will have to
provide GPIO_USART3_RS485_DIR pin definition. Currently it cannot be
used with USART3_RXDMA.
config USART3_RS485_DIR_POLARITY
int "USART3 RS-485 DIR pin polarity"
default 1
range 0 1
depends on USART3_RS485MODE
---help---
Polarity of DIR pin for RS-485 on USART3. Set to state on DIR pin which
enables TX (0 - low / nTXEN, 1 - high / TXEN).
endif # USART3_SERIALDRIVER
choice
prompt "SERCOM4 mode"
default SAMD2L2_SERCOM4_ISUSART
@@ -696,6 +780,27 @@ config SAMD2L2_SERCOM4_ISUSART
endchoice
if USART4_SERIALDRIVER
config USART4_RS485MODE
bool "RS-485 on USART4"
default n
---help---
Enable RS-485 interface on USART4. Your board config will have to
provide GPIO_USART4_RS485_DIR pin definition. Currently it cannot be
used with USART4_RXDMA.
config USART4_RS485_DIR_POLARITY
int "USART4 RS-485 DIR pin polarity"
default 1
range 0 1
depends on USART4_RS485MODE
---help---
Polarity of DIR pin for RS-485 on USART4. Set to state on DIR pin which
enables TX (0 - low / nTXEN, 1 - high / TXEN).
endif # USART4_SERIALDRIVER
choice
prompt "SERCOM5 mode"
default SAMD2L2_SERCOM5_ISUSART
@@ -716,6 +821,27 @@ config SAMD2L2_SERCOM5_ISUSART
endchoice
if USART5_SERIALDRIVER
config USART5_RS485MODE
bool "RS-485 on USART5"
default n
---help---
Enable RS-485 interface on USART5. Your board config will have to
provide GPIO_USART5_RS485_DIR pin definition. Currently it cannot be
used with USART5_RXDMA.
config USART5_RS485_DIR_POLARITY
int "USART5 RS-485 DIR pin polarity"
default 1
range 0 1
depends on USART5_RS485MODE
---help---
Polarity of DIR pin for RS-485 on USART5. Set to state on DIR pin which
enables TX (0 - low / nTXEN, 1 - high / TXEN).
endif # USART5_SERIALDRIVER
config SAMD2L2_HAVE_SPI
bool
select SPI
+50 -1
View File
@@ -1,7 +1,7 @@
/************************************************************************************
* arch/arm/src/samd2l2/sam_config.h
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Copyright (C) 2014, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -135,6 +135,14 @@
# undef CONFIG_USART4_SERIAL_CONSOLE
# undef CONFIG_USART5_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
# ifdef CONFIG_USART0_RS485MODE
# define SAM_CONSOLE_RS485_DIR GPIO_USART0_RS485_DIR
# if (CONFIG_USART0_RS485_DIR_POLARITY == 0)
# define SAM_CONSOLE_RS485_DIR_POLARITY false
# else
# define SAM_CONSOLE_RS485_DIR_POLARITY true
# endif
# endif
#elif defined(CONFIG_USART1_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART2_SERIAL_CONSOLE
@@ -142,6 +150,14 @@
# undef CONFIG_USART4_SERIAL_CONSOLE
# undef CONFIG_USART5_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
# ifdef CONFIG_USART1_RS485MODE
# define SAM_CONSOLE_RS485_DIR GPIO_USART1_RS485_DIR
# if (CONFIG_USART1_RS485_DIR_POLARITY == 0)
# define SAM_CONSOLE_RS485_DIR_POLARITY false
# else
# define SAM_CONSOLE_RS485_DIR_POLARITY true
# endif
# endif
#elif defined(CONFIG_USART2_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART1_SERIAL_CONSOLE
@@ -149,6 +165,14 @@
# undef CONFIG_USART4_SERIAL_CONSOLE
# undef CONFIG_USART5_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
# ifdef CONFIG_USART2_RS485MODE
# define SAM_CONSOLE_RS485_DIR GPIO_USART2_RS485_DIR
# if (CONFIG_USART2_RS485_DIR_POLARITY == 0)
# define SAM_CONSOLE_RS485_DIR_POLARITY false
# else
# define SAM_CONSOLE_RS485_DIR_POLARITY true
# endif
# endif
#elif defined(CONFIG_USART3_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART1_SERIAL_CONSOLE
@@ -156,6 +180,14 @@
# undef CONFIG_USART4_SERIAL_CONSOLE
# undef CONFIG_USART5_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
# ifdef CONFIG_USART3_RS485MODE
# define SAM_CONSOLE_RS485_DIR GPIO_USART3_RS485_DIR
# if (CONFIG_USART3_RS485_DIR_POLARITY == 0)
# define SAM_CONSOLE_RS485_DIR_POLARITY false
# else
# define SAM_CONSOLE_RS485_DIR_POLARITY true
# endif
# endif
#elif defined(CONFIG_USART4_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART1_SERIAL_CONSOLE
@@ -163,6 +195,14 @@
# undef CONFIG_USART3_SERIAL_CONSOLE
# undef CONFIG_USART5_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
# ifdef CONFIG_USART4_RS485MODE
# define SAM_CONSOLE_RS485_DIR GPIO_USART4_RS485_DIR
# if (CONFIG_USART4_RS485_DIR_POLARITY == 0)
# define SAM_CONSOLE_RS485_DIR_POLARITY false
# else
# define SAM_CONSOLE_RS485_DIR_POLARITY true
# endif
# endif
#elif defined(CONFIG_USART5_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART1_SERIAL_CONSOLE
@@ -170,6 +210,14 @@
# undef CONFIG_USART3_SERIAL_CONSOLE
# undef CONFIG_USART4_SERIAL_CONSOLE
# define HAVE_SERIAL_CONSOLE 1
# ifdef CONFIG_USART5_RS485MODE
# define SAM_CONSOLE_RS485_DIR GPIO_USART5_RS485_DIR
# if (CONFIG_USART5_RS485_DIR_POLARITY == 0)
# define SAM_CONSOLE_RS485_DIR_POLARITY false
# else
# define SAM_CONSOLE_RS485_DIR_POLARITY true
# endif
# endif
#else
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART1_SERIAL_CONSOLE
@@ -178,6 +226,7 @@
# undef CONFIG_USART4_SERIAL_CONSOLE
# undef CONFIG_USART5_SERIAL_CONSOLE
# undef HAVE_SERIAL_CONSOLE
# undef SAM_CONSOLE_RS485_DIR
#endif
/* Are any SERCOM peripherals are configured as SPI peripherals? */
+15 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/samd2l2/sam_lowputc.c
*
* Copyright (C) 2014-2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2014-2016, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* References:
@@ -467,7 +467,13 @@ void sam_lowputc(uint32_t ch)
/* Wait for the USART to be ready for new TX data */
while ((getreg8(intflag) & USART_INT_DRE) == 0);
while ((getreg8(intflag) & USART_INT_DRE) == 0)
{
}
#ifdef SAM_CONSOLE_RS485_DIR
sam_portwrite(SAM_CONSOLE_RS485_DIR, SAM_CONSOLE_RS485_DIR_POLARITY);
#endif
/* Wait until synchronization is complete */
@@ -479,6 +485,12 @@ void sam_lowputc(uint32_t ch)
/* Wait until data is sent */
while ((getreg8(intflag) & USART_INT_TXC) == 0);
while ((getreg8(intflag) & USART_INT_TXC) == 0)
{
}
#ifdef SAM_CONSOLE_RS485_DIR
sam_portwrite(SAM_CONSOLE_RS485_DIR, !SAM_CONSOLE_RS485_DIR_POLARITY);
#endif
}
#endif
+78 -3
View File
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/samd2l2/sam_serial.c
*
* Copyright (C) 2014-2015 Gregory Nutt. All rights reserved.
* Copyright (C) 2014-2015, 2019 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@@ -229,6 +229,11 @@ struct sam_dev_s
const struct sam_usart_config_s * const config;
/* Information unique to the serial driver */
#ifdef HAVE_RS485
const uint32_t rs485_dir_gpio; /* USART RS-485 DIR GPIO pin configuration */
const bool rs485_dir_polarity; /* USART RS-485 DIR pin state for TX enabled */
#endif
};
/****************************************************************************
@@ -320,6 +325,14 @@ static char g_usart5txbuffer[CONFIG_USART5_TXBUFSIZE];
static struct sam_dev_s g_usart0priv =
{
.config = &g_usart0config,
#ifdef CONFIG_USART0_RS485MODE
.rs485_dir_gpio = GPIO_USART0_RS485_DIR,
# if (CONFIG_USART0_RS485_DIR_POLARITY == 0)
.rs485_dir_polarity = false,
# else
.rs485_dir_polarity = true,
# endif
#endif
};
static uart_dev_t g_usart0port =
@@ -345,6 +358,14 @@ static uart_dev_t g_usart0port =
static struct sam_dev_s g_usart1priv =
{
.config = &g_usart1config,
#ifdef CONFIG_USART1_RS485MODE
.rs485_dir_gpio = GPIO_USART1_RS485_DIR,
# if (CONFIG_USART1_RS485_DIR_POLARITY == 0)
.rs485_dir_polarity = false,
# else
.rs485_dir_polarity = true,
# endif
#endif
};
static uart_dev_t g_usart1port =
@@ -370,6 +391,14 @@ static uart_dev_t g_usart1port =
static struct sam_dev_s g_usart2priv =
{
.config = &g_usart2config,
#ifdef CONFIG_USART2_RS485MODE
.rs485_dir_gpio = GPIO_USART2_RS485_DIR,
# if (CONFIG_USART2_RS485_DIR_POLARITY == 0)
.rs485_dir_polarity = false,
# else
.rs485_dir_polarity = true,
# endif
#endif
};
static uart_dev_t g_usart2port =
@@ -395,6 +424,14 @@ static uart_dev_t g_usart2port =
static struct sam_dev_s g_usart3priv =
{
.config = &g_usart3config,
#ifdef CONFIG_USART3_RS485MODE
.rs485_dir_gpio = GPIO_USART3_RS485_DIR,
# if (CONFIG_USART3_RS485_DIR_POLARITY == 0)
.rs485_dir_polarity = false,
# else
.rs485_dir_polarity = true,
# endif
#endif
};
static uart_dev_t g_usart3port =
@@ -420,6 +457,14 @@ static uart_dev_t g_usart3port =
static struct sam_dev_s g_usart4priv =
{
.config = &g_usart4config,
#ifdef CONFIG_USART4_RS485MODE
.rs485_dir_gpio = GPIO_USART4_RS485_DIR,
# if (CONFIG_USART4_RS485_DIR_POLARITY == 0)
.rs485_dir_polarity = false,
# else
.rs485_dir_polarity = true,
# endif
#endif
};
static uart_dev_t g_usart4port =
@@ -445,6 +490,14 @@ static uart_dev_t g_usart4port =
static struct sam_dev_s g_usart5priv =
{
.config = &g_usart5config,
#ifdef CONFIG_USART5_RS485MODE
.rs485_dir_gpio = GPIO_USART5_RS485_DIR,
# if (CONFIG_USART5_RS485_DIR_POLARITY == 0)
.rs485_dir_polarity = false,
# else
.rs485_dir_polarity = true,
# endif
#endif
};
static uart_dev_t g_usart5port =
@@ -548,6 +601,20 @@ static int sam_interrupt(int irq, void *context, FAR void *arg)
inten = sam_serialin8(priv, SAM_USART_INTENCLR_OFFSET);
pending = intflag & inten;
#ifdef HAVE_RS485
/* Transmission of whole buffer is over - TXC is set.
* Note - this should be first, to have the most recent TC bit value from
* SR register - sending data affects TXC, but without refresh we will not
* know that...
*/
if ((pending & USART_INT_TXC) != 0)
{
sam_portwrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
sam_serialout8(priv, SAM_USART_INTENCLR_OFFSET, USART_INT_TXC);
}
#endif
/* Handle an incoming, receive byte. The RXC flag is set when there is
* unread data in DATA register. This flag is cleared by reading the DATA
* register (or by disabling the receiver).
@@ -602,6 +669,14 @@ static int sam_setup(struct uart_dev_s *dev)
}
#endif
#ifdef HAVE_RS485
if (priv->rs485_dir_gpio != 0)
{
(void)sam_configport(priv->rs485_dir_gpio);
sam_portwrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
}
#endif
return ret;
}
@@ -831,7 +906,7 @@ static void sam_txint(struct uart_dev_s *dev, bool enable)
*/
#ifndef CONFIG_SUPPRESS_SERIAL_INTS
sam_serialout8(priv, SAM_USART_INTENSET_OFFSET, USART_INT_DRE);
sam_serialout8(priv, SAM_USART_INTENSET_OFFSET, USART_TX_INTS);
/* Fake a TX interrupt here by just calling uart_xmitchars() with
* interrupts disabled (note this may recurse).
@@ -843,7 +918,7 @@ static void sam_txint(struct uart_dev_s *dev, bool enable)
}
else
{
/* Disable the TX interrupt */
/* Disable the TX interrupt. Only disable DRE, TXC will disable itself! */
sam_serialout8(priv, SAM_USART_INTENCLR_OFFSET, USART_INT_DRE);
}
+14
View File
@@ -79,6 +79,20 @@
# undef g_consoleconfig
#endif
/* Is RS-485 used? */
#if defined(CONFIG_USART0_RS485MODE) || defined(CONFIG_USART1_RS485MODE) || \
defined(CONFIG_USART2_RS485MODE) || defined(CONFIG_USART3_RS485MODE) || \
defined(CONFIG_USART4_RS485MODE) || defined(CONFIG_USART5_RS485MODE)
# define HAVE_RS485 1
#endif
#ifdef HAVE_RS485
# define USART_TX_INTS (USART_INT_DRE | USART_INT_TXC)
#else
# define USART_TX_INTS (USART_INT_DRE)
#endif
/************************************************************************************
* Public Types
************************************************************************************/