summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src/samd
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-02-16 11:34:32 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-02-16 11:34:32 -0600
commitee9ba3e6297786891e01eff8dcb9793f8347b0f5 (patch)
tree473a6d77b5e1021d35db03113f4b56105b0def06 /nuttx/arch/arm/src/samd
parentf8461f63db16041fe03271b5c1944e79c10f89a2 (diff)
downloadnuttx-ee9ba3e6297786891e01eff8dcb9793f8347b0f5.tar.gz
nuttx-ee9ba3e6297786891e01eff8dcb9793f8347b0f5.tar.bz2
nuttx-ee9ba3e6297786891e01eff8dcb9793f8347b0f5.zip
SAMD20: The basic port is complete but still untested
Diffstat (limited to 'nuttx/arch/arm/src/samd')
-rw-r--r--nuttx/arch/arm/src/samd/Make.defs2
-rw-r--r--nuttx/arch/arm/src/samd/chip/sam_sercom.h84
-rw-r--r--nuttx/arch/arm/src/samd/chip/sam_usart.h1
-rw-r--r--nuttx/arch/arm/src/samd/sam_lowputc.c37
-rw-r--r--nuttx/arch/arm/src/samd/sam_lowputc.h14
-rw-r--r--nuttx/arch/arm/src/samd/sam_serial.c1067
-rw-r--r--nuttx/arch/arm/src/samd/sam_serial.h1
-rw-r--r--nuttx/arch/arm/src/samd/sam_start.c2
-rw-r--r--nuttx/arch/arm/src/samd/sam_usart.h1
9 files changed, 1204 insertions, 5 deletions
diff --git a/nuttx/arch/arm/src/samd/Make.defs b/nuttx/arch/arm/src/samd/Make.defs
index 029433fb7..ae7ed8964 100644
--- a/nuttx/arch/arm/src/samd/Make.defs
+++ b/nuttx/arch/arm/src/samd/Make.defs
@@ -69,7 +69,7 @@ endif
CHIP_ASRCS =
CHIP_CSRCS = sam_clockconfig.c sam_idle.c sam_irq.c sam_lowputc.c
-CHIP_CSRCS += sam_port.c sam_start.c sam_timerisr.c sam_usart.c
+CHIP_CSRCS += sam_port.c sam_serial.c sam_start.c sam_timerisr.c sam_usart.c
ifeq ($(CONFIG_NUTTX_KERNEL),y)
CHIP_CSRCS += sam_userspace.c
diff --git a/nuttx/arch/arm/src/samd/chip/sam_sercom.h b/nuttx/arch/arm/src/samd/chip/sam_sercom.h
new file mode 100644
index 000000000..7e097589c
--- /dev/null
+++ b/nuttx/arch/arm/src/samd/chip/sam_sercom.h
@@ -0,0 +1,84 @@
+/********************************************************************************************
+ * arch/arm/src/samd/chip/sam_sercom.h
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * References:
+ * "Atmel SAM D20J / SAM D20G / SAM D20E ARM-Based Microcontroller
+ * Datasheet", 42129J–SAM–12/2013
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ********************************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_SAMD_CHIP_SAM_SERCOM_H
+#define __ARCH_ARM_SRC_SAMD_CHIP_SAM_SERCOM_H
+
+/********************************************************************************************
+ * Included Files
+ ********************************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+/********************************************************************************************
+ * Pre-processor Definitions
+ ********************************************************************************************/
+/* Two generic clocks are used by the SERCOM: GCLK_SERCOMx_CORE and GCLK_SERCOMx_SLOW. The
+ * core clock (GCLK_SERCOMx_CORE) is required to clock the SERCOM while operating as a
+ * master, while the slow clock (GCLK_SERCOMx_SLOW) is only required for certain functions.
+ * SERCOM modules must share the same slow GCLK channel ID.
+ *
+ * The baud-rate generator runs off the GCLK_SERCOMx_CORE clock (or, optionally, external
+ * clock).
+ */
+
+#define SERCOM_GCLK_ID_SLOW 12
+#define SERCOM_GCLK_ID_CORE(n) (13+(n))
+# define SERCOM0_GCLK_ID_CORE 13
+# define SERCOM1_GCLK_ID_CORE 14
+# define SERCOM2_GCLK_ID_CORE 15
+# define SERCOM3_GCLK_ID_CORE 16
+# define SERCOM4_GCLK_ID_CORE 17
+# define SERCOM5_GCLK_ID_CORE 18
+
+/********************************************************************************************
+ * Public Types
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Public Data
+ ********************************************************************************************/
+
+/********************************************************************************************
+ * Public Functions
+ ********************************************************************************************/
+
+#endif /* __ARCH_ARM_SRC_SAMD_CHIP_SAM_SERCOM_H */
diff --git a/nuttx/arch/arm/src/samd/chip/sam_usart.h b/nuttx/arch/arm/src/samd/chip/sam_usart.h
index c202c6f8f..03539d0dc 100644
--- a/nuttx/arch/arm/src/samd/chip/sam_usart.h
+++ b/nuttx/arch/arm/src/samd/chip/sam_usart.h
@@ -130,6 +130,7 @@
/* Control A register */
+#define USART_CTRLA_SWRST (1 << 0) /* Bit 0: Software reset */
#define USART_CTRLA_ENABLE (1 << 1) /* Bit 1: Enable */
#define USART_CTRLA_MODE_SHIFT (2) /* Bits 2-4: Operating Mode */
#define USART_CTRLA_MODE_MASK (7 << USART_CTRLA_MODE_SHIFT)
diff --git a/nuttx/arch/arm/src/samd/sam_lowputc.c b/nuttx/arch/arm/src/samd/sam_lowputc.c
index b98088df9..f998d19e0 100644
--- a/nuttx/arch/arm/src/samd/sam_lowputc.c
+++ b/nuttx/arch/arm/src/samd/sam_lowputc.c
@@ -61,6 +61,7 @@
#include "chip/sam_usart.h"
#include "sam_usart.h"
+#include "sam_lowputc.h"
/****************************************************************************
* Pre-processor Definitions
@@ -455,11 +456,15 @@ int sam_usart_initialize(const struct sam_usart_config_s * const config)
irqstate_t flags;
int ret;
+ /* Reset the SERCOM so that we know that it is in its initial state */
+
+ flags = irqsave();
+ sam_usart_reset(config);
+
/* Just invoke the internal implementation, but with interrupts disabled
* so that the operation is atomic.
*/
- flags = irqsave();
ret = sam_usart_internal(config);
irqrestore(flags);
return ret;
@@ -467,6 +472,36 @@ int sam_usart_initialize(const struct sam_usart_config_s * const config)
#endif
/****************************************************************************
+ * Name: sam_usart_reset
+ *
+ * Description:
+ * Reset the USART SERCOM. This restores all SERCOM register to the
+ * initial state and disables the SERCOM.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_USART
+void sam_usart_reset(const struct sam_usart_config_s * const config)
+{
+ uintptr_t regaddr = config->base + SAM_USART_CTRLA_OFFSET;
+ uint32_t regval;
+
+ /* Reset the SERCOM by setting the SWRST bit in the CTRLA register. When
+ * the reset completes, the SERCOM will registers will be restored to there
+ * initial state and the SERCOM will be disabled.
+ */
+
+ regval = getreg32(regaddr);
+ regval |= USART_CTRLA_SWRST;
+ putreg32(regval, regaddr);
+
+ /* Wait for the reset to complete */
+
+ while ((getreg32(regaddr) & USART_CTRLA_SWRST) != 0);
+}
+#endif
+
+/****************************************************************************
* Name: sam_lowputc
*
* Description:
diff --git a/nuttx/arch/arm/src/samd/sam_lowputc.h b/nuttx/arch/arm/src/samd/sam_lowputc.h
index cefd3ea03..6b7036ed9 100644
--- a/nuttx/arch/arm/src/samd/sam_lowputc.h
+++ b/nuttx/arch/arm/src/samd/sam_lowputc.h
@@ -96,6 +96,20 @@ int sam_usart_initialize(const struct sam_usart_config_s * const config);
#endif
/****************************************************************************
+ * Name: sam_usart_reset
+ *
+ * Description:
+ * Reset the USART SERCOM. This restores all SERCOM register to the
+ * initial state and disables the SERCOM.
+ *
+ *****************************************************************************/
+
+#ifdef HAVE_USART
+struct sam_usart_config_s;
+void sam_usart_reset(const struct sam_usart_config_s * const config);
+#endif
+
+/****************************************************************************
* Name: sam_lowputc
*
* Description:
diff --git a/nuttx/arch/arm/src/samd/sam_serial.c b/nuttx/arch/arm/src/samd/sam_serial.c
new file mode 100644
index 000000000..8ed18db04
--- /dev/null
+++ b/nuttx/arch/arm/src/samd/sam_serial.c
@@ -0,0 +1,1067 @@
+/****************************************************************************
+ * arch/arm/src/samd/sam_serial.c
+ *
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <semaphore.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/serial/serial.h>
+
+#include <arch/serial.h>
+#include <arch/board/board.h>
+
+#include "up_arch.h"
+#include "up_internal.h"
+#include "os_internal.h"
+
+#include "chip.h"
+#include "sam_config.h"
+#include "chip/sam_usart.h"
+#include "sam_usart.h"
+#include "sam_lowputc.h"
+#include "sam_serial.h"
+
+#ifdef HAVE_USART
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+/* If we are not using the serial driver for the console, then we still must
+ * provide some minimal implementation of up_putc.
+ */
+
+#ifdef USE_SERIALDRIVER
+
+/* Which USART with be tty0/console and which tty1? tty2? tty3? tty4? tty5? */
+
+/* First pick the console and ttys0. This could be any of USART0-5 */
+
+#if defined(CONFIG_USART0_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_usart0port /* USART0 is console */
+# define TTYS0_DEV g_usart0port /* USART0 is ttyS0 */
+# define USART0_ASSIGNED 1
+#elif defined(CONFIG_USART1_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_usart1port /* USART1 is console */
+# define TTYS0_DEV g_usart1port /* USART1 is ttyS0 */
+# define USART1_ASSIGNED 1
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_usart2port /* USART2 is console */
+# define TTYS0_DEV g_usart2port /* USART2 is ttyS0 */
+# define USART2_ASSIGNED 1
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_usart3port /* USART3 is console */
+# define TTYS0_DEV g_usart3port /* USART3 is ttyS0 */
+# define USART3_ASSIGNED 1
+#elif defined(CONFIG_USART4_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_usart4port /* USART4 is console */
+# define TTYS0_DEV g_usart4port /* USART4 is ttyS0 */
+# define USART4_ASSIGNED 1
+#elif defined(CONFIG_USART5_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_usart5port /* USART5 is console */
+# define TTYS5_DEV g_usart5port /* USART5 is ttyS0 */
+#else
+# undef CONSOLE_DEV /* No console */
+# if defined(SAMD_HAVE_USART0)
+# define TTYS0_DEV g_usart0port /* USART0 is ttyS0 */
+# define USART0_ASSIGNED 1
+# elif defined(SAMD_HAVE_USART1)
+# define TTYS0_DEV g_usart1port /* USART1 is ttyS0 */
+# define USART1_ASSIGNED 1
+# elif defined(SAMD_HAVE_USART2)
+# define TTYS0_DEV g_usart2port /* USART2 is ttyS0 */
+# define USART2_ASSIGNED 1
+# elif defined(SAMD_HAVE_USART3)
+# define TTYS0_DEV g_usart3port /* USART3 is ttyS0 */
+# define USART3_ASSIGNED 1
+# elif defined(SAMD_HAVE_USART4)
+# define TTYS0_DEV g_usart4port /* USART4 is ttyS0 */
+# define USART4_ASSIGNED 1
+# elif defined(SAMD_HAVE_USART5)
+# define TTYS0_DEV g_usart5port /* USART5 is ttyS0 */
+# define USART5_ASSIGNED 1
+# endif
+#endif
+
+/* Pick ttys1. This could be any of USART0-5 excluding the console USART. */
+
+#if defined(SAMD_HAVE_USART0) && !defined(USART0_ASSIGNED)
+# define TTYS1_DEV g_usart0port /* USART0 is ttyS1 */
+# define USART0_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART1) && !defined(USART1_ASSIGNED)
+# define TTYS1_DEV g_usart1port /* USART1 is ttyS1 */
+# define USART1_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART2) && !defined(USART2_ASSIGNED)
+# define TTYS1_DEV g_usart2port /* USART2 is ttyS1 */
+# define USART2_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART3) && !defined(USART3_ASSIGNED)
+# define TTYS1_DEV g_usart3port /* USART3 is ttyS1 */
+# define USART3_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART4) && !defined(USART4_ASSIGNED)
+# define TTYS1_DEV g_usart4port /* USART4 is ttyS1 */
+# define USART4_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART5) && !defined(USART5_ASSIGNED)
+# define TTYS1_DEV g_usart5port /* USART5 is ttyS1 */
+# define USART5_ASSIGNED 1
+#endif
+
+/* Pick ttys2. This could be one of USART1-5. It can't be USART0
+ * because that was either assigned as ttyS0 or ttys1. One of these
+ * could also be the console.
+ */
+
+#if defined(SAMD_HAVE_USART1) && !defined(USART1_ASSIGNED)
+# define TTYS2_DEV g_usart1port /* USART1 is ttyS2 */
+# define USART1_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART2) && !defined(USART2_ASSIGNED)
+# define TTYS2_DEV g_usart2port /* USART2 is ttyS2 */
+# define USART2_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART3) && !defined(USART3_ASSIGNED)
+# define TTYS2_DEV g_usart3port /* USART3 is ttyS2 */
+# define USART3_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART4) && !defined(USART4_ASSIGNED)
+# define TTYS2_DEV g_usart4port /* USART4 is ttyS2 */
+# define USART4_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART5) && !defined(USART5_ASSIGNED)
+# define TTYS2_DEV g_usart5port /* USART5 is ttyS2 */
+# define USART5_ASSIGNED 1
+#endif
+
+/* Pick ttys3. This could be one of USART2-5. It can't be USART0-1 because
+ * those have already been assigned to ttsyS0, 1, or 2. One of
+ * USART2-5 could also be the console.
+ */
+
+#if defined(SAMD_HAVE_USART2) && !defined(USART2_ASSIGNED)
+# define TTYS3_DEV g_usart2port /* USART2 is ttyS3 */
+# define USART2_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART3) && !defined(USART3_ASSIGNED)
+# define TTYS3_DEV g_usart3port /* USART3 is ttyS3 */
+# define USART3_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART4) && !defined(USART4_ASSIGNED)
+# define TTYS3_DEV g_usart4port /* USART4 is ttyS3 */
+# define USART4_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART5) && !defined(USART5_ASSIGNED)
+# define TTYS3_DEV g_usart5port /* USART5 is ttyS3 */
+# define USART5_ASSIGNED 1
+#endif
+
+/* Pick ttys4. This could be one of USART3-5. It can't be USART0-2
+ * because those have already been assigned to ttsyS0, 1, 2 or 3. One of
+ * USART3-5 could also be the console.
+ */
+
+#if defined(SAMD_HAVE_USART3) && !defined(USART3_ASSIGNED)
+# define TTYS4_DEV g_usart3port /* USART3 is ttyS4 */
+# define USART3_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART4) && !defined(USART4_ASSIGNED)
+# define TTYS4_DEV g_usart4port /* USART4 is ttyS4 */
+# define USART4_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART5) && !defined(USART5_ASSIGNED)
+# define TTYS4_DEV g_usart5port /* USART5 is ttyS4 */
+# define USART5_ASSIGNED 1
+#endif
+
+/* Pick ttys5. This could be one of USART4-5. It can't be USART0-3
+ * because those have already been assigned to ttsyS0, 1, 2, 3 or 4.
+ * One of USART4-5 could also be the console.
+ */
+
+#if defined(SAMD_HAVE_USART4) && !defined(USART4_ASSIGNED)
+# define TTYS5_DEV g_usart4port /* USART4 is ttyS5 */
+# define USART4_ASSIGNED 1
+#elif defined(SAMD_HAVE_USART5) && !defined(USART5_ASSIGNED)
+# define TTYS5_DEV g_usart5port /* USART5 is ttyS5 */
+# define USART5_ASSIGNED 1
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct sam_dev_s
+{
+ /* Common USART configuration */
+
+ const struct sam_usart_config_s * const config;
+
+ /* Information unique to the serial driver */
+
+ xcpt_t handler; /* Interrupt handler */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* Support functions */
+
+static inline uint8_t
+ sam_serialin8(struct sam_dev_s *priv, int offset);
+static inline void
+ sam_serialout8(struct sam_dev_s *priv, int offset,
+ uint8_t regval);
+static inline uint16_t
+ sam_serialin16(struct sam_dev_s *priv, int offset);
+static inline void
+ sam_serialout16(struct sam_dev_s *priv, int offset,
+ uint16_t regval);
+static void sam_disableallints(struct sam_dev_s *priv);
+static int sam_interrupt(struct uart_dev_s *dev);
+
+#ifdef SAMD_HAVE_USART0
+static int sam_usart0_interrupt(int irq, void *context);
+#endif
+#ifdef SAMD_HAVE_USART1
+static int sam_usart1_interrupt(int irq, void *context);
+#endif
+#ifdef SAMD_HAVE_USART2
+static int sam_usart2_interrupt(int irq, void *context);
+#endif
+#ifdef SAMD_HAVE_USART3
+static int sam_usart3_interrupt(int irq, void *context);
+#endif
+#ifdef SAMD_HAVE_USART4
+static int sam_usart4_interrupt(int irq, void *context);
+#endif
+#ifdef SAMD_HAVE_USART5
+static int sam_usart5_interrupt(int irq, void *context);
+#endif
+
+/* UART methods */
+
+static int sam_setup(struct uart_dev_s *dev);
+static void sam_shutdown(struct uart_dev_s *dev);
+static int sam_attach(struct uart_dev_s *dev);
+static void sam_detach(struct uart_dev_s *dev);
+static int sam_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int sam_receive(struct uart_dev_s *dev, uint32_t *status);
+static void sam_rxint(struct uart_dev_s *dev, bool enable);
+static bool sam_rxavailable(struct uart_dev_s *dev);
+static void sam_send(struct uart_dev_s *dev, int ch);
+static void sam_txint(struct uart_dev_s *dev, bool enable);
+static bool sam_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+static const struct uart_ops_s g_uart_ops =
+{
+ .setup = sam_setup,
+ .shutdown = sam_shutdown,
+ .attach = sam_attach,
+ .detach = sam_detach,
+ .ioctl = sam_ioctl,
+ .receive = sam_receive,
+ .rxint = sam_rxint,
+ .rxavailable = sam_rxavailable,
+ .send = sam_send,
+ .txint = sam_txint,
+ .txready = sam_txempty,
+ .txempty = sam_txempty,
+};
+
+/* I/O buffers */
+
+#ifdef SAMD_HAVE_USART0
+static char g_usart0rxbuffer[CONFIG_USART0_RXBUFSIZE];
+static char g_usart0txbuffer[CONFIG_USART0_TXBUFSIZE];
+#endif
+#ifdef SAMD_HAVE_USART1
+static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE];
+static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE];
+#endif
+#ifdef SAMD_HAVE_USART2
+static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE];
+static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE];
+#endif
+#ifdef SAMD_HAVE_USART3
+static char g_usart3rxbuffer[CONFIG_USART3_RXBUFSIZE];
+static char g_usart3txbuffer[CONFIG_USART3_TXBUFSIZE];
+#endif
+#ifdef SAMD_HAVE_USART4
+static char g_usart4rxbuffer[CONFIG_USART4_RXBUFSIZE];
+static char g_usart4txbuffer[CONFIG_USART4_TXBUFSIZE];
+#endif
+#ifdef SAMD_HAVE_USART5
+static char g_usart5rxbuffer[CONFIG_USART5_RXBUFSIZE];
+static char g_usart5txbuffer[CONFIG_USART5_TXBUFSIZE];
+#endif
+
+/* This describes the state of the USART0 port. */
+
+#ifdef SAMD_HAVE_USART0
+static struct sam_dev_s g_usart0priv =
+{
+ .config = &g_usart0config,
+ .handler = sam_usart0_interrupt,
+};
+
+static uart_dev_t g_usart0port =
+{
+ .recv =
+ {
+ .size = CONFIG_USART0_RXBUFSIZE,
+ .buffer = g_usart0rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART0_TXBUFSIZE,
+ .buffer = g_usart0txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart0priv,
+};
+#endif
+
+/* This describes the state of the USART1 port. */
+
+#ifdef SAMD_HAVE_USART1
+static struct sam_dev_s g_usart1priv =
+{
+ .config = &g_usart1config,
+ .handler = sam_usart1_interrupt,
+};
+
+static uart_dev_t g_usart1port =
+{
+ .recv =
+ {
+ .size = CONFIG_USART1_RXBUFSIZE,
+ .buffer = g_usart1rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART1_TXBUFSIZE,
+ .buffer = g_usart1txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart1priv,
+};
+#endif
+
+/* This describes the state of the USART2 port. */
+
+#ifdef SAMD_HAVE_USART2
+static struct sam_dev_s g_usart2priv =
+{
+ .config = &g_usart2config,
+ .handler = sam_usart2_interrupt,
+};
+
+static uart_dev_t g_usart2port =
+{
+ .recv =
+ {
+ .size = CONFIG_USART2_RXBUFSIZE,
+ .buffer = g_usart2rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART2_TXBUFSIZE,
+ .buffer = g_usart2txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart2priv,
+};
+#endif
+
+/* This describes the state of the USART3 port. */
+
+#ifdef SAMD_HAVE_USART3
+static struct sam_dev_s g_usart3priv =
+{
+ .config = &g_usart3config,
+ .handler = sam_usart3_interrupt,
+};
+
+static uart_dev_t g_usart3port =
+{
+ .recv =
+ {
+ .size = CONFIG_USART3_RXBUFSIZE,
+ .buffer = g_usart3rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART3_TXBUFSIZE,
+ .buffer = g_usart3txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart3priv,
+};
+#endif
+
+/* This describes the state of the USART4 port. */
+
+#ifdef SAMD_HAVE_USART4
+static struct sam_dev_s g_usart4priv =
+{
+ .config = &g_usart4config,
+ .handler = sam_usart4_interrupt,
+};
+
+static uart_dev_t g_usart4port =
+{
+ .recv =
+ {
+ .size = CONFIG_USART4_RXBUFSIZE,
+ .buffer = g_usart4rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART4_TXBUFSIZE,
+ .buffer = g_usart4txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart4priv,
+};
+#endif
+
+/* This describes the state of the USART5 port. */
+
+#ifdef SAMD_HAVE_USART5
+static struct sam_dev_s g_usart5priv =
+{
+ .config = &g_usart5config,
+ .handler = sam_usart5_interrupt,
+};
+
+static uart_dev_t g_usart5port =
+{
+ .recv =
+ {
+ .size = CONFIG_USART5_RXBUFSIZE,
+ .buffer = g_usart5rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_USART5_TXBUFSIZE,
+ .buffer = g_usart5txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_usart5priv,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sam_serialin8
+ ****************************************************************************/
+
+static inline uint8_t sam_serialin8(struct sam_dev_s *priv, int offset)
+{
+ return getreg8(priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: sam_serialout8
+ ****************************************************************************/
+
+static inline void sam_serialout8(struct sam_dev_s *priv, int offset,
+ uint8_t regval)
+{
+ putreg8(regval, priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: sam_serialin16
+ ****************************************************************************/
+
+static inline uint16_t sam_serialin16(struct sam_dev_s *priv, int offset)
+{
+ return getreg16(priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: sam_serialout16
+ ****************************************************************************/
+
+static inline void sam_serialout16(struct sam_dev_s *priv, int offset,
+ uint16_t regval)
+{
+ putreg16(regval, priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: sam_disableallints
+ ****************************************************************************/
+
+static void sam_disableallints(struct sam_dev_s *priv)
+{
+ /* Disable all interrupts */
+
+ sam_serialout8(priv, SAM_USART_INTENCLR_OFFSET, USART_INT_ALL);
+}
+
+/****************************************************************************
+ * Name: sam_interrupt
+ *
+ * Description:
+ * This is the USART interrupt handler. It will be invoked when an
+ * interrupt received on the 'irq' It should call uart_transmitchars or
+ * uart_receivechar to perform the appropriate data transfers. The
+ * interrupt handling logic must be able to map the 'irq' number into the
+ * approprite uart_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int sam_interrupt(struct uart_dev_s *dev)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;;
+ uint8_t pending;
+ uint8_t intflag;
+ uint8_t inten;
+
+ /* Get the set of pending USART usarts (we are only interested in the
+ * unmasked interrupts).
+ */
+
+ intflag = sam_serialin8(priv, SAM_USART_INTFLAG_OFFSET);
+ inten = sam_serialin8(priv, SAM_USART_INTENCLR_OFFSET);
+ pending = intflag & inten;
+
+ /* Handle an incoming, receive byte. The RXC flag is set when there is
+ * unread data in DATA register. This flag is cleared by reading the DATA
+ * register (or by disabling the receiver).
+ */
+
+ if ((pending & USART_INT_RXC) != 0)
+ {
+ /* Received data ready... process incoming bytes */
+
+ uart_recvchars(dev);
+ }
+
+ /* Handle outgoing, transmit bytes. The DRE flag is set when the DATA
+ * register is empty and ready to be written. This flag is cleared by
+ * writing new data to the DATA register. If there is no further data to
+ * be transmitted, the serial driver will disable TX interrupts, prohibit
+ * further interrupts until TX interrupts are re-enabled.
+ */
+
+ if ((pending & USART_INT_DRE) != 0)
+ {
+ /* Transmit data register empty ... process outgoing bytes */
+
+ uart_xmitchars(dev);
+ }
+
+ return OK;
+}
+
+/****************************************************************************
+ * Name: sam_usartN_interrupt
+ *
+ * Description:
+ * Handle each SERCOM USART interrupt by calling the common interrupt
+ * handling logic with the USART-specific state.
+ *
+ ****************************************************************************/
+
+#ifdef SAMD_HAVE_USART0
+static int sam_usart0_interrupt(int irq, void *context)
+{
+ return sam_interrupt(&g_usart0port);
+}
+#endif
+
+#ifdef SAMD_HAVE_USART1
+static int sam_usart1_interrupt(int irq, void *context)
+{
+ return sam_interrupt(&g_usart1port);
+}
+#endif
+
+#ifdef SAMD_HAVE_USART2
+static int sam_usart2_interrupt(int irq, void *context)
+{
+ return sam_interrupt(&g_usart2port);
+}
+#endif
+
+#ifdef SAMD_HAVE_USART3
+static int sam_usart3_interrupt(int irq, void *context)
+{
+ return sam_interrupt(&g_usart3port);
+}
+#endif
+
+#ifdef SAMD_HAVE_USART4
+static int sam_usart4_interrupt(int irq, void *context)
+{
+ return sam_interrupt(&g_usart4port);
+}
+#endif
+
+#ifdef SAMD_HAVE_USART5
+static int sam_usart5_interrupt(int irq, void *context)
+{
+ return sam_interrupt(&g_usart5port);
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_setup
+ *
+ * Description:
+ * Configure the USART baud, bits, parity, etc. This method is called the
+ * first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+static int sam_setup(struct uart_dev_s *dev)
+{
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+
+ /* Configure the SERCOM as a USART */
+
+ return sam_usart_initialize(priv->config);
+#else
+ return OK;
+#endif
+}
+
+/****************************************************************************
+ * Name: sam_shutdown
+ *
+ * Description:
+ * Disable the USART. This method is called when the serial port is
+ * closed
+ *
+ ****************************************************************************/
+
+static void sam_shutdown(struct uart_dev_s *dev)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+
+ /* Resetting the SERCOM restores all registers to the reget state and
+ * disables the SERCOM.
+ */
+
+ sam_usart_reset(priv->config);
+}
+
+/****************************************************************************
+ * Name: sam_attach
+ *
+ * Description:
+ * Configure the USART to operation in interrupt driven mode. This method
+ * is called when the serial port is opened. Normally, this is just after
+ * the setup() method is called, however, the serial console may operate in
+ * a non-interrupt driven mode during the boot phase.
+ *
+ * RX and TX interrupts are not enabled when by the attach method (unless
+ * the hardware supports multiple levels of interrupt enabling). The RX
+ * and TX interrupts are not enabled until the txint() and rxint() methods
+ * are called.
+ *
+ ****************************************************************************/
+
+static int sam_attach(struct uart_dev_s *dev)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+ const struct sam_usart_config_s * const config = priv->config;
+ int ret;
+
+ /* Attach and enable the IRQ */
+
+ ret = irq_attach(config->irq, priv->handler);
+ if (ret == OK)
+ {
+ /* Enable the interrupt (RX and TX interrupts are still disabled
+ * in the USART
+ */
+
+ up_enable_irq(config->irq);
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: sam_detach
+ *
+ * Description:
+ * Detach USART interrupts. This method is called when the serial port is
+ * closed normally just before the shutdown method is called. The
+ * exception is the serial console which is never shutdown.
+ *
+ ****************************************************************************/
+
+static void sam_detach(struct uart_dev_s *dev)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+ const struct sam_usart_config_s * const config = priv->config;
+
+ up_disable_irq(config->irq);
+ irq_detach(config->irq);
+}
+
+/****************************************************************************
+ * Name: sam_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method
+ *
+ ****************************************************************************/
+
+static int sam_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
+ struct inode *inode = filep->f_inode;
+ struct uart_dev_s *dev = inode->i_private;
+#endif
+ int ret = OK;
+
+ switch (cmd)
+ {
+#ifdef CONFIG_SERIAL_TIOCSERGSTRUCT
+ case TIOCSERGSTRUCT:
+ {
+ struct sam_dev_s *user = (struct sam_dev_s*)arg;
+ if (!user)
+ {
+ ret = -EINVAL;
+ }
+ else
+ {
+ memcpy(user, dev, sizeof(struct sam_dev_s));
+ }
+ }
+ break;
+#endif
+
+ default:
+ ret = -ENOTTY;
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: sam_receive
+ *
+ * Description:
+ * Called (usually) from the interrupt level to receive one
+ * character from the USART. Error bits associated with the
+ * receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+static int sam_receive(struct uart_dev_s *dev, uint32_t *status)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+
+ /* Return read status */
+
+ *status = (uint32_t)sam_serialin16(priv, SAM_USART_STATUS_OFFSET);
+
+ /* Then return the actual received byte */
+
+ return (int)sam_serialin16(priv, SAM_USART_DATA_OFFSET);
+}
+
+/****************************************************************************
+ * Name: sam_rxint
+ *
+ * Description:
+ * Call to enable or disable RXRDY interrupts
+ *
+ ****************************************************************************/
+
+static void sam_rxint(struct uart_dev_s *dev, bool enable)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+
+ if (enable)
+ {
+ /* Receive an interrupt when their is anything in the Rx data register */
+
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ sam_serialout8(priv, SAM_USART_INTENSET_OFFSET, USART_INT_RXC);
+#endif
+ }
+ else
+ {
+ sam_serialout8(priv, SAM_USART_INTENCLR_OFFSET, USART_INT_RXC);
+ }
+}
+
+/****************************************************************************
+ * Name: sam_rxavailable
+ *
+ * Description:
+ * Return true if the receive holding register is not empty
+ *
+ ****************************************************************************/
+
+static bool sam_rxavailable(struct uart_dev_s *dev)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+ return ((sam_serialin8(priv, SAM_USART_INTFLAG_OFFSET) & USART_INT_RXC) != 0);
+}
+
+/****************************************************************************
+ * Name: sam_send
+ *
+ * Description:
+ * This method will send one byte on the USART
+ *
+ ****************************************************************************/
+
+static void sam_send(struct uart_dev_s *dev, int ch)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+ sam_serialout16(priv, SAM_USART_DATA_OFFSET, (uint16_t)ch);
+}
+
+/****************************************************************************
+ * Name: sam_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts
+ *
+ ****************************************************************************/
+
+static void sam_txint(struct uart_dev_s *dev, bool enable)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+ irqstate_t flags;
+
+ flags = irqsave();
+ if (enable)
+ {
+ /* Set to receive an interrupt when the TX holding register register
+ * is empty
+ */
+
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ sam_serialout8(priv, SAM_USART_INTENSET_OFFSET, USART_INT_DRE);
+
+ /* Fake a TX interrupt here by just calling uart_xmitchars() with
+ * interrupts disabled (note this may recurse).
+ */
+
+ uart_xmitchars(dev);
+
+#endif
+ }
+ else
+ {
+ /* Disable the TX interrupt */
+
+ sam_serialout8(priv, SAM_USART_INTENCLR_OFFSET, USART_INT_DRE);
+ }
+
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: sam_txempty
+ *
+ * Description:
+ * Return true if the transmit holding and shift registers are empty
+ *
+ ****************************************************************************/
+
+static bool sam_txempty(struct uart_dev_s *dev)
+{
+ struct sam_dev_s *priv = (struct sam_dev_s*)dev->priv;
+ return ((sam_serialin8(priv, SAM_USART_INTFLAG_OFFSET) & USART_INT_DRE) != 0);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_earlyserialinit
+ *
+ * Description:
+ * Performs the low level USART initialization early in debug so that the
+ * serial console will be available during bootup. This must be called
+ * before sam_serialinit.
+ *
+ ****************************************************************************/
+
+void up_earlyserialinit(void)
+{
+ /* Disable all USARTS */
+
+ sam_disableallints(TTYS0_DEV.priv);
+#ifdef TTYS1_DEV
+ sam_disableallints(TTYS1_DEV.priv);
+#endif
+#ifdef TTYS2_DEV
+ sam_disableallints(TTYS2_DEV.priv);
+#endif
+#ifdef TTYS3_DEV
+ sam_disableallints(TTYS3_DEV.priv);
+#endif
+#ifdef TTYS4_DEV
+ sam_disableallints(TTYS4_DEV.priv);
+#endif
+#ifdef TTYS5_DEV
+ sam_disableallints(TTYS5_DEV.priv);
+#endif
+
+ /* Configuration whichever one is the console */
+
+#ifdef HAVE_SERIAL_CONSOLE
+ CONSOLE_DEV.isconsole = true;
+ sam_setup(&CONSOLE_DEV);
+#endif
+}
+
+/****************************************************************************
+ * Name: up_serialinit
+ *
+ * Description:
+ * Register serial console and serial ports. This assumes
+ * that sam_earlyserialinit was called previously.
+ *
+ ****************************************************************************/
+
+void up_serialinit(void)
+{
+ /* Register the console */
+
+#ifdef HAVE_SERIAL_CONSOLE
+ (void)uart_register("/dev/console", &CONSOLE_DEV);
+#endif
+
+ /* Register all USARTs */
+
+ (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
+#ifdef TTYS1_DEV
+ (void)uart_register("/dev/ttyS1", &TTYS1_DEV);
+#endif
+#ifdef TTYS2_DEV
+ (void)uart_register("/dev/ttyS2", &TTYS2_DEV);
+#endif
+#ifdef TTYS3_DEV
+ (void)uart_register("/dev/ttyS3", &TTYS3_DEV);
+#endif
+#ifdef TTYS4_DEV
+ (void)uart_register("/dev/ttyS4", &TTYS4_DEV);
+#endif
+#ifdef TTYS5_DEV
+ (void)uart_register("/dev/ttyS5", &TTYS5_DEV);
+#endif
+}
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+#ifdef HAVE_SERIAL_CONSOLE
+ irqstate_t flags;
+
+ /* All interrupts must be disabled to prevent re-entrancy and to prevent
+ * interrupts from firing in the serial driver code.
+ */
+
+ flags = irqsave();
+
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ sam_lowputc('\r');
+ }
+
+ sam_lowputc(ch);
+ irqrestore(flags);
+#endif
+ return ch;
+}
+
+#else /* USE_SERIALDRIVER */
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+#ifdef HAVE_SERIAL_CONSOLE
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ sam_lowputc('\r');
+ }
+
+ sam_lowputc(ch);
+#endif
+ return ch;
+}
+
+#endif /* USE_SERIALDRIVER */
+#endif /* HAVE_USART */
+
diff --git a/nuttx/arch/arm/src/samd/sam_serial.h b/nuttx/arch/arm/src/samd/sam_serial.h
index 0afd1b249..182ae064a 100644
--- a/nuttx/arch/arm/src/samd/sam_serial.h
+++ b/nuttx/arch/arm/src/samd/sam_serial.h
@@ -43,7 +43,6 @@
#include <nuttx/config.h>
#include "sam_config.h"
-#include "chip/sam_sercom.h"
/************************************************************************************
* Pre-processor Definitions
diff --git a/nuttx/arch/arm/src/samd/sam_start.c b/nuttx/arch/arm/src/samd/sam_start.c
index 81e4cf0c2..8f749339b 100644
--- a/nuttx/arch/arm/src/samd/sam_start.c
+++ b/nuttx/arch/arm/src/samd/sam_start.c
@@ -1,7 +1,7 @@
/****************************************************************************
* arch/arm/src/samd/sam_start.c
*
- * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
diff --git a/nuttx/arch/arm/src/samd/sam_usart.h b/nuttx/arch/arm/src/samd/sam_usart.h
index 7ea7ada2a..acd245052 100644
--- a/nuttx/arch/arm/src/samd/sam_usart.h
+++ b/nuttx/arch/arm/src/samd/sam_usart.h
@@ -83,7 +83,6 @@ struct sam_usart_config_s
uint8_t bits; /* Number of bits (5-9) */
uint8_t irq; /* SERCOM IRQ number */
uint8_t gclkgen; /* Source GCLK generator */
- bool isconsole; /* True: The USART is the console device */
bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */
uint32_t baud; /* Configured baud */
port_pinset_t pad0; /* Pin configuration for PAD0 */