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