You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2020/09/30 12:09:16 UTC

[incubator-nuttx] 01/03: nrf52: add serial termios support

This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 35a5036e32743da23f7dec2200beb9beeca161a6
Author: raiden00pl <ra...@railab.me>
AuthorDate: Wed Sep 16 10:18:36 2020 +0200

    nrf52: add serial termios support
---
 arch/arm/Kconfig                   |   1 +
 arch/arm/src/nrf52/nrf52_lowputc.c | 206 ++++++++++++++++++++++++++++++++++++-
 arch/arm/src/nrf52/nrf52_lowputc.h |  12 +++
 arch/arm/src/nrf52/nrf52_serial.c  | 135 +++++++++++++++++++++++-
 4 files changed, 348 insertions(+), 6 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1b2c671..90e15a3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -213,6 +213,7 @@ config ARCH_CHIP_NRF52
 	#select ARM_HAVE_MPU_UNIFIED
 	select ARCH_HAVE_FPU
 	select ARCH_HAVE_PWM_MULTICHAN
+	select ARCH_HAVE_SERIAL_TERMIOS
 	---help---
 		Nordic NRF52 architectures (ARM Cortex-M4).
 
diff --git a/arch/arm/src/nrf52/nrf52_lowputc.c b/arch/arm/src/nrf52/nrf52_lowputc.c
index ea40102..865090f 100644
--- a/arch/arm/src/nrf52/nrf52_lowputc.c
+++ b/arch/arm/src/nrf52/nrf52_lowputc.c
@@ -113,21 +113,187 @@ static const struct uart_config_s g_console_config =
  *
  ****************************************************************************/
 
-#ifdef HAVE_UART_DEVICE
 static void nrf52_setbaud(uintptr_t base, const struct uart_config_s *config)
 {
   uint32_t br = 0;
 
-  if (config->baud == 115200)
+  switch (config->baud)
     {
-      br = UART_BAUDRATE_115200;
+      case 1200:
+        {
+          br = UART_BAUDRATE_1200;
+          break;
+        }
+
+      case 2400:
+        {
+          br = UART_BAUDRATE_2400;
+          break;
+        }
+
+      case 4800:
+        {
+          br = UART_BAUDRATE_4800;
+          break;
+        }
+
+      case 9600:
+        {
+          br = UART_BAUDRATE_9600;
+          break;
+        }
+
+      case 14400:
+        {
+          br = UART_BAUDRATE_14400;
+          break;
+        }
+
+      case 19200:
+        {
+          br = UART_BAUDRATE_19200;
+          break;
+        }
+
+      case 28800:
+        {
+          br = UART_BAUDRATE_28800;
+          break;
+        }
+
+      case 31250:
+        {
+          br = UART_BAUDRATE_31250;
+          break;
+        }
+
+      case 38400:
+        {
+          br = UART_BAUDRATE_38400;
+          break;
+        }
+
+      case 56000:
+        {
+          br = UART_BAUDRATE_56000;
+          break;
+        }
+
+      case 57600:
+        {
+          br = UART_BAUDRATE_57600;
+          break;
+        }
+
+      case 76000:
+        {
+          br = UART_BAUDRATE_76000;
+          break;
+        }
+
+      case 115200:
+        {
+          br = UART_BAUDRATE_115200;
+          break;
+        }
+
+      case 230400:
+        {
+          br = UART_BAUDRATE_230400;
+          break;
+        }
+
+      case 250000:
+        {
+          br = UART_BAUDRATE_250000;
+          break;
+        }
+
+      case 460800:
+        {
+          br = UART_BAUDRATE_460800;
+          break;
+        }
+
+      case 921600:
+        {
+          br = UART_BAUDRATE_921600;
+          break;
+        }
+
+      default:
+        {
+          DEBUGASSERT(0);
+          break;
+        }
     }
 
   putreg32(br, base + NRF52_UART_BAUDRATE_OFFSET);
 }
+
+/****************************************************************************
+ * Name: nrf52_setparity
+ ****************************************************************************/
+
+static void nrf52_setparity(uintptr_t base,
+                            const struct uart_config_s *config)
+{
+  uint32_t regval = 0;
+
+  regval = getreg32(base + NRF52_UART_CONFIG_OFFSET);
+
+  if (config->parity == 2)
+    {
+      /* Include even parity */
+
+      regval |= UART_CONFIG_PARITY;
+    }
+  else
+    {
+      /* Exclude parity */
+
+      regval &= ~UART_CONFIG_PARITY;
+    }
+
+  putreg32(regval, base + NRF52_UART_CONFIG_OFFSET);
+}
+
+/****************************************************************************
+ * Name: nrf52_setstops
+ ****************************************************************************/
+
+#ifdef HAVE_UART_STOPBITS
+static void nrf52_setstops(uintptr_t base,
+                           const struct uart_config_s *config)
+{
+  uint32_t regval = 0;
+
+  regval = getreg32(base + NRF52_UART_CONFIG_OFFSET);
+
+  if (config->stopbits2 == true)
+    {
+      regval |= UART_CONFIG_STOP;
+    }
+  else
+    {
+      regval &= ~UART_CONFIG_STOP;
+    }
+
+  putreg32(regval, base + NRF52_UART_CONFIG_OFFSET);
+}
 #endif
 
 /****************************************************************************
+ * Name: nrf52_sethwflow
+ ****************************************************************************/
+
+static void nrf52_sethwflow(uintptr_t base,
+                            const struct uart_config_s *config)
+{
+  /* TODO */
+}
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -174,9 +340,9 @@ void nrf52_usart_configure(uintptr_t base,
   putreg32(1, base + NRF52_UART_TASKS_STOPTX_OFFSET);
   putreg32(NRF52_UART_ENABLE_DISABLE, base + NRF52_UART_ENABLE_OFFSET);
 
-  /* Configure baud */
+  /* Set UART format */
 
-  nrf52_setbaud(base, config);
+  nrf52_usart_setformat(base, config);
 
   /* Config GPIO pins for uart */
 
@@ -263,3 +429,33 @@ void arm_lowputc(char ch)
   putreg32(1, CONSOLE_BASE + NRF52_UART_TASKS_STOPTX_OFFSET);
 #endif
 }
+
+/****************************************************************************
+ * Name: nrf52_usart_setformat
+ *
+ * Description:
+ *   Set the USART line format and speed.
+ *
+ ****************************************************************************/
+
+void nrf52_usart_setformat(uintptr_t base,
+                           FAR const struct uart_config_s *config)
+{
+  /* Configure baud */
+
+  nrf52_setbaud(base, config);
+
+  /* Configure polarity */
+
+  nrf52_setparity(base, config);
+
+#ifdef HAVE_UART_STOPBITS
+  /* Configure STOP bits */
+
+  nrf52_setstops(base, config);
+#endif
+
+  /* Configure hardware flow control */
+
+  nrf52_sethwflow(base, config);
+}
diff --git a/arch/arm/src/nrf52/nrf52_lowputc.h b/arch/arm/src/nrf52/nrf52_lowputc.h
index 6fe445d..b708846 100644
--- a/arch/arm/src/nrf52/nrf52_lowputc.h
+++ b/arch/arm/src/nrf52/nrf52_lowputc.h
@@ -45,6 +45,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <nrf52_gpio.h>
+#include <nrf52_config.h>
 
 /****************************************************************************
  * Public Types
@@ -114,4 +115,15 @@ void nrf52_usart_disable(uintptr_t base,
                          FAR const struct uart_config_s *config);
 #endif
 
+/****************************************************************************
+ * Name: nrf52_usart_setformat
+ *
+ * Description:
+ *   Set the USART line format and speed.
+ *
+ ****************************************************************************/
+
+void nrf52_usart_setformat(uintptr_t base,
+                           FAR const struct uart_config_s *config);
+
 #endif /* __ARCH_ARM_SRC_NRF52_NRF52_LOWPUTC_H */
diff --git a/arch/arm/src/nrf52/nrf52_serial.c b/arch/arm/src/nrf52/nrf52_serial.c
index 5dd347f..70a1cc9 100644
--- a/arch/arm/src/nrf52/nrf52_serial.c
+++ b/arch/arm/src/nrf52/nrf52_serial.c
@@ -49,8 +49,13 @@
 
 #include <nuttx/irq.h>
 #include <nuttx/arch.h>
+#include <nuttx/fs/ioctl.h>
 #include <nuttx/serial/serial.h>
 
+#ifdef CONFIG_SERIAL_TERMIOS
+#  include <termios.h>
+#endif
+
 #include <arch/board/board.h>
 
 #include "arm_arch.h"
@@ -423,6 +428,23 @@ static int nrf52_interrupt(int irq, void *context, FAR void *arg)
 }
 
 /****************************************************************************
+ * Name: nrf52_set_format
+ *
+ * Description:
+ *   Set the serial line format and speed.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SERIAL_TERMIOS
+void nrf52_set_format(struct uart_dev_s *dev)
+{
+  struct nrf52_dev_s *priv = (struct nrf52_dev_s *)dev->priv;
+
+  nrf52_usart_setformat(priv->uartbase, &priv->config);
+}
+#endif
+
+/****************************************************************************
  * Name: nrf52_ioctl
  *
  * Description:
@@ -432,7 +454,118 @@ static int nrf52_interrupt(int irq, void *context, FAR void *arg)
 
 static int nrf52_ioctl(struct file *filep, int cmd, unsigned long arg)
 {
-  return -ENOTTY;
+  struct inode         *inode  = filep->f_inode;
+  struct uart_dev_s    *dev    = inode->i_private;
+  struct nrf52_dev_s   *priv   = (struct nrf52_dev_s *)dev->priv;
+  struct uart_config_s *config = &priv->config;
+  int                   ret    = OK;
+
+  switch (cmd)
+    {
+#ifdef CONFIG_SERIAL_TERMIOS
+      case TCGETS:
+        {
+          struct termios *termiosp = (struct termios *)arg;
+
+          if (!termiosp)
+            {
+              ret = -EINVAL;
+              break;
+            }
+
+          /* Get baud */
+
+          cfsetispeed(termiosp, config->baud);
+
+          /* Get flags */
+
+          termiosp->c_cflag = ((config->parity != 0) ? PARENB : 0)
+                              | ((config->parity == 1) ? PARODD : 0)
+                              | ((config->stopbits2) ? CSTOPB : 0) |
+#ifdef CONFIG_SERIAL_OFLOWCONTROL
+                              ((config->oflow) ? CCTS_OFLOW : 0) |
+#endif
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+                              ((config->iflow) ? CRTS_IFLOW : 0) |
+#endif
+                              CS8;
+
+          break;
+        }
+
+      case TCSETS:
+        {
+          struct termios *termiosp = (struct termios *)arg;
+
+          if (!termiosp)
+            {
+              ret = -EINVAL;
+              break;
+            }
+
+          /* Perform some sanity checks before accepting any changes */
+
+          if ((termiosp->c_cflag & CSIZE) != CS8)
+            {
+              ret = -EINVAL;
+              break;
+            }
+
+#ifndef HAVE_UART_STOPBITS
+          if ((termiosp->c_cflag & CSTOPB) != 0)
+            {
+              ret = -EINVAL;
+              break;
+            }
+#endif
+
+          if (termiosp->c_cflag & PARODD)
+            {
+              ret = -EINVAL;
+              break;
+            }
+
+          /* TODO: CCTS_OFLOW and CRTS_IFLOW */
+
+          /* Parity */
+
+          if (termiosp->c_cflag & PARENB)
+            {
+              config->parity = (termiosp->c_cflag & PARODD) ? 1 : 2;
+            }
+          else
+            {
+              config->parity = 0;
+            }
+
+#ifdef HAVE_UART_STOPBITS
+          /* Stop bits */
+
+          config->stopbits2 = (termiosp->c_cflag & CSTOPB) != 0;
+#endif
+
+          /* Note that only cfgetispeed is used because we have knowledge
+           * that only one speed is supported.
+           */
+
+          config->baud = cfgetispeed(termiosp);
+
+          /* Effect the changes */
+
+          nrf52_set_format(dev);
+
+          break;
+        }
+#endif
+
+      default:
+        {
+          ret = -ENOTTY;
+          break;
+        }
+    }
+
+  return ret;
 }
 
 /****************************************************************************