nrf52: add serial termios support

This commit is contained in:
raiden00pl 2020-09-16 10:18:36 +02:00 committed by Alan Carvalho de Assis
parent b422f49fa7
commit 35a5036e32
4 changed files with 348 additions and 6 deletions

View File

@ -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).

View File

@ -113,20 +113,186 @@ 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);
}

View File

@ -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 */

View File

@ -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"
@ -422,6 +427,23 @@ static int nrf52_interrupt(int irq, void *context, FAR void *arg)
return OK;
}
/****************************************************************************
* 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
*
@ -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;
}
/****************************************************************************