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