summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-07-20 18:32:16 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-07-20 18:32:16 +0000
commitec9c693a8fbabde333c2a022c12476a12ca5f9b8 (patch)
tree2482d9d86be5c9caab9e456430706c269688baaf
parentaaab49d3299b2f2ebbbbb35bcfc5a027da8ed4a6 (diff)
downloadnuttx-ec9c693a8fbabde333c2a022c12476a12ca5f9b8.tar.gz
nuttx-ec9c693a8fbabde333c2a022c12476a12ca5f9b8.tar.bz2
nuttx-ec9c693a8fbabde333c2a022c12476a12ca5f9b8.zip
Add completed but untested support for RS-485 on the LPC43xx
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4959 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/arch/arm/src/lpc43xx/lpc43_config.h41
-rw-r--r--nuttx/arch/arm/src/lpc43xx/lpc43_serial.c169
-rw-r--r--nuttx/arch/arm/src/lpc43xx/lpc43_uart.c51
-rw-r--r--nuttx/configs/lpc4330-xplorer/README.txt2
-rw-r--r--nuttx/configs/lpc4330-xplorer/include/board.h1
-rw-r--r--nuttx/configs/lpc4330-xplorer/nsh/defconfig6
-rw-r--r--nuttx/configs/lpc4330-xplorer/ostest/defconfig6
-rw-r--r--nuttx/include/nuttx/serial/tioctl.h2
8 files changed, 254 insertions, 24 deletions
diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_config.h b/nuttx/arch/arm/src/lpc43xx/lpc43_config.h
index c969553cb..fb5773682 100644
--- a/nuttx/arch/arm/src/lpc43xx/lpc43_config.h
+++ b/nuttx/arch/arm/src/lpc43xx/lpc43_config.h
@@ -66,26 +66,49 @@
# define HAVE_UART 1
#endif
+/* Make sure all features are disabled for diabled U[S]ARTs. This simplifies
+ * checking later.
+ */
+
+#ifndef CONFIG_LPC43_USART0
+# undef CONFIG_USART0_SERIAL_CONSOLE
+# undef CONFIG_USART0_RS485MODE
+#endif
+
+#ifndef CONFIG_LPC43_UART1
+# undef CONFIG_UART1_SERIAL_CONSOLE
+#endif
+
+#ifndef CONFIG_LPC43_USART2
+# undef CONFIG_USART2_SERIAL_CONSOLE
+# undef CONFIG_USART2_RS485MODE
+#endif
+
+#ifndef CONFIG_LPC43_USART3
+# undef CONFIG_USART3_SERIAL_CONSOLE
+# undef CONFIG_USART3_RS485MODE
+#endif
+
/* Is there a serial console? There should be at most one defined. It could be on
- * any UARTn, n=0,1,2,3
+ * any UARTn, n=0,1,2,3 - OR - there might not be any serial console at all.
*/
-#if defined(CONFIG_USART0_SERIAL_CONSOLE) && defined(CONFIG_LPC43_USART0)
+#if defined(CONFIG_USART0_SERIAL_CONSOLE)
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_USART2_SERIAL_CONSOLE
# undef CONFIG_USART3_SERIAL_CONSOLE
# define HAVE_CONSOLE 1
-#elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_LPC43_UART1)
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_USART2_SERIAL_CONSOLE
# undef CONFIG_USART3_SERIAL_CONSOLE
# define HAVE_CONSOLE 1
-#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_LPC43_USART2)
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_USART3_SERIAL_CONSOLE
# define HAVE_CONSOLE 1
-#elif defined(CONFIG_USART3_SERIAL_CONSOLE) && defined(CONFIG_LPC43_USART3)
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE)
# undef CONFIG_USART0_SERIAL_CONSOLE
# undef CONFIG_UART1_SERIAL_CONSOLE
# undef CONFIG_USART2_SERIAL_CONSOLE
@@ -107,6 +130,14 @@
# undef CONFIG_UART1_FLOWCONTROL
#endif
+/* Check for RS-485 support (USART0,2,3 only) */
+
+#undef HAVE_RS485
+#if defined(CONFIG_USART0_RS485MODE) || defined(CONFIG_USART2_RS485MODE) || \
+ defined(CONFIG_USART3_RS485MODE)
+# define HAVE_RS485 1
+#endif
+
/************************************************************************************
* Public Types
************************************************************************************/
diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_serial.c b/nuttx/arch/arm/src/lpc43xx/lpc43_serial.c
index bfee7a222..9d678b125 100644
--- a/nuttx/arch/arm/src/lpc43xx/lpc43_serial.c
+++ b/nuttx/arch/arm/src/lpc43xx/lpc43_serial.c
@@ -864,18 +864,137 @@ static int up_interrupt(int irq, void *context)
* Handle LPC43xx USART0,2,3 RS485 mode set ioctl (TIOCSRS485) to enable
* and disable RS-485 mode. This is part of the serial ioctl logic.
*
+ * Supported and un-supported LPC43 RS-485 features:
+ *
+ * RS-485/EIA-485 Normal Multidrop Mode (NMM) -- NOT suppored
+ *
+ * In this mode, an address is detected when a received byte causes the
+ * USART to set the parity error and generate an interrupt. When the
+ * parity error interrupt will be generated and the processor can decide
+ * whether or not to disable the receiver.
+ *
+ * RS-485/EIA-485 Auto Address Detection (AAD) mode -- NOT supported
+ *
+ * In this mode, the receiver will compare any address byte received
+ * (parity = ‘1’) to the 8-bit value programmed into the RS485ADRMATCH
+ * register. When a matching address character is detected it will be
+ * pushed onto the RXFIFO along with the parity bit, and the receiver
+ * will be automatically enabled.
+ *
+ * When an address byte which does not match the RS485ADRMATCH value
+ * is received, the receiver will be automatically disabled in hardware.
+ *
+ * RS-485/EIA-485 Auto Direction Control -- Supported
+ *
+ * Allow the transmitter to automatically control the state of the DIR
+ * pin as a direction control output signal. The DIR pin will be asserted
+ * (driven LOW) when the CPU writes data into the TXFIFO. The pin will be
+ * de-asserted (driven HIGH) once the last bit of data has been transmitted.
+ *
+ * RS485/EIA-485 driver delay time -- Supported
+ *
+ * The driver delay time is the delay between the last stop bit leaving
+ * the TXFIFO and the de-assertion of the DIR pin. This delay time can be
+ * programmed in the 8-bit RS485DLY register. The delay time is in periods
+ * of the baud clock.
+ *
+ * RS485/EIA-485 output inversion -- Supported
+ *
+ * The polarity of the direction control signal on the DIR pin can be
+ * reversed by programming bit 5 in the RS485CTRL register.
+ *
****************************************************************************/
-#ifdef CONFIG_USART_RS485MODE
+#ifdef HAVE_RS485
static inline int up_set_rs485_mode(struct up_dev_s *priv,
const struct serial_rs485 *mode)
{
irqstate_t flags;
+ uint32_t regval;
+ uint64_t tmp;
DEBUGASSERT(priv && mode);
flags = irqsave();
-#warning "Missing logic"
+
+ /* Are we enabling or disabling RS-485 support? */
+
+ if ((mode->flags && SER_RS485_RTS_ON_SEND) != 0)
+ {
+ /* Disable all RS-485 features */
+
+ up_serialout(priv, LPC43_UART_RS485CTRL_OFFSET, 0);
+ }
+ else
+ {
+ /* Set the RS-485/EIA-485 Control register:
+ *
+ * NMMEN 0 = Normal Multidrop Mode (NMM) disabled
+ * RXDIS 0 = Receiver is not disabled
+ * AADEN 0 = Auto Address Detect (ADD) is disabled
+ * DCTRL 1 = Auto Direction Control is enabled
+ * OINV ? = Value control by user mode settings
+ */
+
+ regval = UART_RS485CTRL_DCTRL;
+
+ /* Logic levels are controlled by the SER_RS485_RTS_ON_SEND and
+ * SER_RS485_RTS_AFTER_SEND bits in the mode flags.
+ * SER_RS485_RTS_AFTER_SEND is ignored.
+ *
+ * By default, DIR will go logic low on send, but this can
+ * be inverted.
+ */
+
+ if ((mode->flags && SER_RS485_RTS_ON_SEND) != 0)
+ {
+ regval |= UART_RS485CTRL_OINV;
+ }
+
+ up_serialout(priv, LPC43_UART_RS485CTRL_OFFSET, regval);
+
+ /* We only have control of the delay after send. Time provided
+ * is in milliseconds; this must be converted to the baud clock.
+ * The baud clock should be 16 times the currently selected BAUD.
+ *
+ * Eg. Given BAUD=115,200, then a delay of n milliseconds would be:
+ *
+ * 115,200 * n / 1000 = 11525 clocks.
+ *
+ * n=1: 115 (OK)
+ * n=2: 230 (OK)
+ * n>2: Out of range
+ *
+ * The valid range is 0 to 255 bit times.
+ *
+ * REVISIT: Is this time in bit time or in terms of the baud clock?
+ * The text says either interchange-ably. Baud clock is 16 x BAUD
+ * and a bit time is 1/BAUD. The value range of values 0-255 suggests
+ * BAUD bit times, not the baud clock.
+ */
+
+ if (mode->delay_rts_after_send > 0)
+ {
+ regval = 0;
+ }
+ else
+ {
+ tmp = ((priv->baud << 4) * mode->delay_rts_after_send) / 1000;
+ if (tmp > 255)
+ {
+ regval = 255;
+ }
+ else
+ {
+ regval = (uint32_t)tmp;
+ }
+ }
+
+
+ up_serialout(priv, LPC43_UART_RS485DLY_OFFSET, regval);
+ }
+
irqrestore(flags);
+ return OK;
}
#endif
@@ -888,16 +1007,55 @@ static inline int up_set_rs485_mode(struct up_dev_s *priv,
*
****************************************************************************/
-#ifdef CONFIG_USART_RS485MODE
+#ifdef HAVE_RS485
static inline int up_get_rs485_mode(struct up_dev_s *priv,
struct serial_rs485 *mode)
{
irqstate_t flags;
+ uint32_t regval;
DEBUGASSERT(priv && mode);
flags = irqsave();
-#warning "Missing logic"
+
+ /* Assume disabled */
+
+ memset(mode, 0, sizeof(struct serial_rs485));
+
+ /* If RS-485 mode is enabled, then the DCTRL will be set in the RS485CTRL
+ * register.
+ */
+
+ regval = up_serialin(priv, LPC43_UART_RS485CTRL_OFFSET);
+ if ((regval & UART_RS485CTRL_DCTRL) != 0)
+ {
+ /* RS-485 mode is enabled */
+
+ mode->flags = SER_RS485_ENABLED;
+
+ /* Check if DIR is inverted */
+
+ if ((regval & UART_RS485CTRL_OINV) != 0)
+ {
+ mode->flags = (SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND);
+ }
+ else
+ {
+ mode->flags = SER_RS485_ENABLED;
+ }
+
+ /* We only have control of the delay after send. Time must be
+ * returned in milliseconds; this must be converted from the baud clock.
+ * (The baud clock should be 16 times the currently selected BAUD.)
+ *
+ * msec = 1000 * dly / baud
+ */
+
+ regval = up_serialin(priv, LPC43_UART_RS485DLY_OFFSET);
+ mode->delay_rts_after_send = (1000 * regval) / priv->baud;
+ }
+
irqrestore(flags);
+ return OK;
}
#endif
@@ -950,7 +1108,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
}
break;
-#ifdef CONFIG_USART_RS485MODE
+#ifdef HAVE_RS485
case TIOCSRS485: /* Set RS485 mode, arg: pointer to struct serial_rs485 */
{
ret = up_set_rs485_mode(priv,
@@ -1016,6 +1174,7 @@ static void up_rxint(struct uart_dev_s *dev, bool enable)
{
priv->ier &= ~UART_IER_RBRIE;
}
+
up_serialout(priv, LPC43_UART_IER_OFFSET, priv->ier);
}
diff --git a/nuttx/arch/arm/src/lpc43xx/lpc43_uart.c b/nuttx/arch/arm/src/lpc43xx/lpc43_uart.c
index e5f49bdf3..f03054695 100644
--- a/nuttx/arch/arm/src/lpc43xx/lpc43_uart.c
+++ b/nuttx/arch/arm/src/lpc43xx/lpc43_uart.c
@@ -338,11 +338,24 @@ void lpc43_usart0_setup(void)
regval |= (BOARD_USART0_CLKSRC | BASE_USART0_CLK_AUTOBLOCK);
putreg32(regval, LPC43_BASE_USART0_CLK);
- /* Configure I/O pins */
+ /* Configure I/O pins. NOTE that multiple pin configuration options must
+ * be disambiguated by defining the pin configuration in the board.h
+ * header file.
+ */
lpc43_pin_config(PINCONF_U0_TXD);
lpc43_pin_config(PINCONF_U0_RXD);
+ /* If USART RS-485 mode is selected, then configure the DIR pin as well.
+ * NOTE, again, that multiple pin configuration options must be
+ * disambiguated by defining the pin configuration in the board.h header
+ * file.
+ */
+
+#ifdef CONFIG_USART0_RS485MODE
+ lpc43_pin_config(PINCONF_U0_DIR);
+#endif
+
irqrestore(flags);
};
#endif
@@ -362,8 +375,9 @@ void lpc43_uart1_setup(void)
regval |= (BOARD_UART1_CLKSRC | BASE_UART1_CLK_AUTOBLOCK);
putreg32(regval, LPC43_BASE_UART1_CLK);
- /* Configure I/O pins (resolution of mulitple pins alternatvies
- * must be provided in the board.h file).
+ /* Configure I/O pins. NOTE that multiple pin configuration options must
+ * be disambiguated by defining the pin configuration in the board.h
+ * header file.
*/
lpc43_pin_config(PINCONF_U1_TXD);
@@ -398,13 +412,24 @@ void lpc43_usart2_setup(void)
regval |= (BOARD_USART2_CLKSRC | BASE_USART2_CLK_AUTOBLOCK);
putreg32(regval, LPC43_BASE_USART2_CLK);
- /* Configure I/O pins (resolution of mulitple pins alternatvies
- * must be provided in the board.h file).
+ /* Configure I/O pins. NOTE that multiple pin configuration options must
+ * be disambiguated by defining the pin configuration in the board.h
+ * header file.
*/
lpc43_pin_config(PINCONF_U2_TXD);
lpc43_pin_config(PINCONF_U2_RXD);
+ /* If USART RS-485 mode is selected, then configure the DIR pin as well.
+ * NOTE, again, that multiple pin configuration options must be
+ * disambiguated by defining the pin configuration in the board.h header
+ * file.
+ */
+
+#ifdef CONFIG_USART2_RS485MODE
+ lpc43_pin_config(PINCONF_U2_DIR);
+#endif
+
irqrestore(flags);
};
#endif
@@ -424,13 +449,24 @@ void lpc43_usart3_setup(void)
regval |= (BOARD_USART3_CLKSRC | BASE_USART3_CLK_AUTOBLOCK);
putreg32(regval, LPC43_BASE_USART3_CLK);
- /* Configure I/O pins (resolution of mulitple pins alternatvies
- * must be provided in the board.h file).
+ /* Configure I/O pins. NOTE that multiple pin configuration options must
+ * be disambiguated by defining the pin configuration in the board.h
+ * header file.
*/
lpc43_pin_config(PINCONF_U3_TXD);
lpc43_pin_config(PINCONF_U3_RXD);
+ /* If USART RS-485 mode is selected, then configure the DIR pin as well.
+ * NOTE, again, that multiple pin configuration options must be
+ * disambiguated by defining the pin configuration in the board.h header
+ * file.
+ */
+
+#ifdef CONFIG_USART3_RS485MODE
+ lpc43_pin_config(PINCONF_U3_DIR);
+#endif
+
irqrestore(flags);
};
#endif
@@ -562,4 +598,3 @@ void lpc43_setbaud(uintptr_t uartbase, uint32_t basefreq, uint32_t baud)
putreg32((mul << UART_FDR_MULVAL_SHIFT) | (divadd << UART_FDR_DIVADDVAL_SHIFT),
uartbase + LPC43_UART_FDR_OFFSET);
}
-
diff --git a/nuttx/configs/lpc4330-xplorer/README.txt b/nuttx/configs/lpc4330-xplorer/README.txt
index 3e89b478f..bbe954bea 100644
--- a/nuttx/configs/lpc4330-xplorer/README.txt
+++ b/nuttx/configs/lpc4330-xplorer/README.txt
@@ -729,7 +729,7 @@ LPC4330-Xplorer Configuration Options
CONFIG_U[S]ARTn_PARTIY - 0=no parity, 1=odd parity, 2=even parity
CONFIG_U[S]ARTn_2STOP - Two stop bits
- CONFIG_USART_RS485MODE - Support LPC43xx USART0,2,3 RS485 mode
+ CONFIG_USARTn_RS485MODE - Support LPC43xx USART0,2,3 RS485 mode
ioctls (TIOCSRS485 and TIOCGRS485) to enable and disable
RS-485 mode.
diff --git a/nuttx/configs/lpc4330-xplorer/include/board.h b/nuttx/configs/lpc4330-xplorer/include/board.h
index d98da7329..be59b40da 100644
--- a/nuttx/configs/lpc4330-xplorer/include/board.h
+++ b/nuttx/configs/lpc4330-xplorer/include/board.h
@@ -261,6 +261,7 @@
#define PINCONF_U0_TXD PINCONF_U0_TXD_3
#define PINCONF_U0_RXD PINCONF_U0_RXD_3
+#define PINCONF_U0_DIR PINCONF_U0_DIR_3
#define PINCONF_U1_TXD PINCONF_U1_TXD_1
#define PINCONF_U1_RXD PINCONF_U1_RXD_1
diff --git a/nuttx/configs/lpc4330-xplorer/nsh/defconfig b/nuttx/configs/lpc4330-xplorer/nsh/defconfig
index 8f6660ede..5547bca15 100644
--- a/nuttx/configs/lpc4330-xplorer/nsh/defconfig
+++ b/nuttx/configs/lpc4330-xplorer/nsh/defconfig
@@ -228,11 +228,13 @@ CONFIG_USART2_2STOP=0
CONFIG_USART3_2STOP=0
#
-# CONFIG_USART_RS485MODE - Support LPC43xx USART0,2,3 RS485 mode
+# CONFIG_USARTn_RS485MODE - Support LPC43xx USART0,2,3 RS485 mode
# ioctls (TIOCSRS485 and TIOCGRS485) to enable and disable
# RS-485 mode.
#
-CONFIG_USART_RS485MODE=n
+CONFIG_USART0_RS485MODE=n
+CONFIG_USART2_RS485MODE=n
+CONFIG_USART3_RS485MODE=n
#
# LPC43xx specific PHY/Ethernet device driver settings
diff --git a/nuttx/configs/lpc4330-xplorer/ostest/defconfig b/nuttx/configs/lpc4330-xplorer/ostest/defconfig
index 202192635..037a33daf 100644
--- a/nuttx/configs/lpc4330-xplorer/ostest/defconfig
+++ b/nuttx/configs/lpc4330-xplorer/ostest/defconfig
@@ -228,11 +228,13 @@ CONFIG_USART2_2STOP=0
CONFIG_USART3_2STOP=0
#
-# CONFIG_USART_RS485MODE - Support LPC43xx USART0,2,3 RS485 mode
+# CONFIG_USARTn_RS485MODE - Support LPC43xx USART0,2,3 RS485 mode
# ioctls (TIOCSRS485 and TIOCGRS485) to enable and disable
# RS-485 mode.
#
-CONFIG_USART_RS485MODE=n
+CONFIG_USART0_RS485MODE=n
+CONFIG_USART2_RS485MODE=n
+CONFIG_USART3_RS485MODE=n
#
# LPC43xx specific PHY/Ethernet device driver settings
diff --git a/nuttx/include/nuttx/serial/tioctl.h b/nuttx/include/nuttx/serial/tioctl.h
index a923fa324..bae2f2c8d 100644
--- a/nuttx/include/nuttx/serial/tioctl.h
+++ b/nuttx/include/nuttx/serial/tioctl.h
@@ -194,7 +194,7 @@ struct winsize
struct serial_rs485
{
- uint32_t flags /* See SER_RS485_* definitions */
+ uint32_t flags; /* See SER_RS485_* definitions */
uint32_t delay_rts_before_send; /* Delay before send (milliseconds) */
uint32_t delay_rts_after_send; /* Delay after send (milliseconds) */
};