summaryrefslogtreecommitdiff
path: root/nuttx/arch/sh/src
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-02-17 02:43:47 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2009-02-17 02:43:47 +0000
commit56d90dca78d332130f9872e06fa6d33512a0193e (patch)
tree8a262895417e263e4cd25ac280c4adbbad7f15d7 /nuttx/arch/sh/src
parent34f65599a3508531cd068f70b7e4350c9c72158e (diff)
downloadpx4-nuttx-56d90dca78d332130f9872e06fa6d33512a0193e.tar.gz
px4-nuttx-56d90dca78d332130f9872e06fa6d33512a0193e.tar.bz2
px4-nuttx-56d90dca78d332130f9872e06fa6d33512a0193e.zip
Add M16C serial driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@1509 42af7a65-404d-4744-a932-0658087f49c3
Diffstat (limited to 'nuttx/arch/sh/src')
-rw-r--r--nuttx/arch/sh/src/m16c/Make.defs4
-rw-r--r--nuttx/arch/sh/src/m16c/chip.h32
-rwxr-xr-xnuttx/arch/sh/src/m16c/m16c_dumpstate.c18
-rw-r--r--nuttx/arch/sh/src/m16c/m16c_lowputc.c4
-rw-r--r--nuttx/arch/sh/src/m16c/m16c_serial.c1186
5 files changed, 1223 insertions, 21 deletions
diff --git a/nuttx/arch/sh/src/m16c/Make.defs b/nuttx/arch/sh/src/m16c/Make.defs
index a9a1c21bf..5c4b2ea8a 100644
--- a/nuttx/arch/sh/src/m16c/Make.defs
+++ b/nuttx/arch/sh/src/m16c/Make.defs
@@ -43,10 +43,8 @@ CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c \
up_udelay.c up_unblocktask.c up_usestack.c
CHIP_ASRCS = m16c_vectors.S
-#CHIP_CSRCS = m16c_initialstate.c m16c_copystate.c m16c_lowputc.c m16c_irq.c \
-# m16c_timerisr.c m16c_serial.c m16c_dumpstate.c
CHIP_CSRCS = m16c_initialstate.c m16c_copystate.c m16c_lowputc.c m16c_irq.c \
- m16c_timerisr.c m16c_dumpstate.c
+ m16c_timerisr.c m16c_serial.c m16c_dumpstate.c
ifneq ($(CONFIG_DISABLE_SIGNALS),y)
CHIP_CSRCS += m16c_schedulesigaction.c m16c_sigdeliver.c
diff --git a/nuttx/arch/sh/src/m16c/chip.h b/nuttx/arch/sh/src/m16c/chip.h
index fccd771a5..095bb688c 100644
--- a/nuttx/arch/sh/src/m16c/chip.h
+++ b/nuttx/arch/sh/src/m16c/chip.h
@@ -251,20 +251,28 @@
#ifndef __ASSEMBLY__
-extern uint16 g_snbss; /* Start of near .bss */
-extern uint16 g_enbss; /* End+1 of near .bss */
-extern uint16 g_sndata; /* Start of near .data */
-extern uint16 g_endata; /* End+1 of near .data */
-extern uint32 g_enronly; /* Start of relocated read-only data in FLASH */
+extern uint16 g_snbss; /* Start of near .bss */
+extern uint16 g_enbss; /* End+1 of near .bss */
+extern uint16 g_sndata; /* Start of near .data */
+extern uint16 g_endata; /* End+1 of near .data */
+extern uint32 g_enronly; /* Start of relocated read-only data in FLASH */
#ifdef CONFIG_M16C_HAVEFARRAM
-extern uint32 g_sfbss; /* Start of far .bss */
-extern uint32 g_efbss; /* End+1 of far .bss */
-extern uint32 g_sfdata; /* Start of far .data */
-extern uint32 g_efdata; /* End_1 of far .data */
-extern uint32 g_efronly; /* Start of relocated read-only data in FLASH */
+ extern uint32 g_sfbss; /* Start of far .bss */
+ extern uint32 g_efbss; /* End+1 of far .bss */
+ extern uint32 g_sfdata; /* Start of far .data */
+ extern uint32 g_efdata; /* End_1 of far .data */
+ xtern uint32 g_efronly; /* Start of relocated read-only data in FLASH */
+#endif
+extern uint32 g_svarvect; /* Start of variable vectors */
+extern uint32 g_heapbase; /* Start of the heap */
+
+/* Address of the saved user stack pointer */
+
+#ifndef __ASSEMBLY__
+# if CONFIG_ARCH_INTERRUPTSTACK > 3
+ extern uint16 g_userstack;
+# endif
#endif
-extern uint32 g_svarvect; /* Start of variable vectors */
-extern uint32 g_heapbase; /* Start of the heap */
#endif /* __ASSEMBLY__ */
diff --git a/nuttx/arch/sh/src/m16c/m16c_dumpstate.c b/nuttx/arch/sh/src/m16c/m16c_dumpstate.c
index 6d70d8cee..11bd990cd 100755
--- a/nuttx/arch/sh/src/m16c/m16c_dumpstate.c
+++ b/nuttx/arch/sh/src/m16c/m16c_dumpstate.c
@@ -92,6 +92,18 @@ static inline uint16 m16c_getsp(void)
}
/****************************************************************************
+ * Name: m16c_getusersp
+ ****************************************************************************/
+
+#if CONFIG_ARCH_INTERRUPTSTACK > 3
+static inline uint16 m16c_getusersp(void)
+{
+ ubyte *ptr = (ubyte*) current_regs;
+ return (uint16)ptr[REG_SP] << 8 | ptr[REG_SP+1];
+}
+#endif
+
+/****************************************************************************
* Name: m16c_stackdump
****************************************************************************/
@@ -199,11 +211,9 @@ void up_dumpstate(void)
m16c_stackdump(sp, istackbase);
- /* Extract the user stack pointer which should lie
- * at the base of the interrupt stack.
- */
+ /* Extract the user stack pointer from the register area */
- sp = g_userstack;
+ sp = m16c_getusersp();
lldbg("sp: %04x\n", sp);
}
diff --git a/nuttx/arch/sh/src/m16c/m16c_lowputc.c b/nuttx/arch/sh/src/m16c/m16c_lowputc.c
index 78b2a68af..861623dc2 100644
--- a/nuttx/arch/sh/src/m16c/m16c_lowputc.c
+++ b/nuttx/arch/sh/src/m16c/m16c_lowputc.c
@@ -71,8 +71,8 @@
# undef CONFIG_UART2_SERIAL_CONSOLE
#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && !defined(CONFIG_UART2_DISABLE)
# define HAVE_CONSOLE 1
+# undef CONFIG_UART0_SERIAL_CONSOLE
# undef CONFIG_UART1_SERIAL_CONSOLE
-# undef CONFIG_UART2_SERIAL_CONSOLE
#else
# if defined(CONFIG_UART0_SERIAL_CONSOLE) || defined(CONFIG_UART1_SERIAL_CONSOLE)|| defined(CONFIG_UART2_SERIAL_CONSOLE)
# error "Serial console selected, but corresponding UART not enabled"
@@ -183,7 +183,7 @@
#ifdef HAVE_CONSOLE
static inline int up_txready(void)
{
- /* Check the TI bit in the CI register. 1=Transmit buffer emptyy */
+ /* Check the TI bit in the CI register. 1=Transmit buffer empty */
return ((getreg8(M16C_UART_BASE + M16C_UART_C1) & UART_C1_TI) != 0);
}
diff --git a/nuttx/arch/sh/src/m16c/m16c_serial.c b/nuttx/arch/sh/src/m16c/m16c_serial.c
new file mode 100644
index 000000000..12b614864
--- /dev/null
+++ b/nuttx/arch/sh/src/m16c/m16c_serial.c
@@ -0,0 +1,1186 @@
+/****************************************************************************
+ * arch/sh/src/m16c/m16c_serial.c
+ *
+ * Copyright (C) 2009 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <spudmonkey@racsa.co.cr>
+ *
+ * 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 <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.h>
+#include <arch/serial.h>
+
+#include "chip.h"
+#include "up_arch.h"
+#include "up_internal.h"
+#include "os_internal.h"
+#include "m16c_uart.h"
+
+/****************************************************************************
+ * Definitions
+ ****************************************************************************/
+
+/* Configuration **********************************************************/
+
+#ifndef M16C_XIN_PRESCALER
+# define M16C_XIN_PRESCALER 1
+#endif
+
+/* Make sure interrupt priorities are defined. If not, use a default of 5 */
+
+#ifndef M16C_S2T_PRIO
+# define M16C_S2T_PRIO 5 /* UART2 transmit interrupt priority */
+#endif
+#ifndef M16C_S2R_PRIO
+# define M16C_S2R_PRIO 5 /* UART2 receive interrupt priority */
+#endif
+#ifndef M16C_S0T_PRIO
+# define M16C_S0T_PRIO 5 /* UART0 transmit interrupt priority */
+#endif
+#ifndef M16C_S0R_PRIO
+# define M16C_S0R_PRIO 5 /* UART0 receive interrupt priority */
+#endif
+#ifndef M16C_S1T_PRIO
+# define M16C_S1T_PRIO 5 /* UART1 transmit interrupt priority */
+#endif
+#ifndef M16C_S1R_PRIO
+# define M16C_S1R_PRIO 5 /* UART1 receive interrupt priority */
+#endif
+
+/* Some sanity checks *******************************************************/
+
+/* Are there any UARTs? */
+
+#if defined(CONFIG_UART0_DISABLE) && defined(CONFIG_UART1_DISABLE) && defined(CONFIG_UART2_DISABLE)
+# ifdef CONFIG_USE_SERIALDRIVER
+# error "Serial driver selected, but UARTs not enabled"
+# undef CONFIG_USE_SERIALDRIVER
+# endif
+#endif
+
+/* Is there a serial console? */
+
+#if defined(CONFIG_UART0_SERIAL_CONSOLE) && !defined(CONFIG_UART0_DISABLE)
+# define HAVE_CONSOLE 1
+# undef CONFIG_UART1_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE) && !defined(CONFIG_UART1_DISABLE)
+# define HAVE_CONSOLE 1
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && !defined(CONFIG_UART2_DISABLE)
+# define HAVE_CONSOLE 1
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART1_SERIAL_CONSOLE
+#else
+# if defined(CONFIG_UART0_SERIAL_CONSOLE) || defined(CONFIG_UART1_SERIAL_CONSOLE)|| defined(CONFIG_UART2_SERIAL_CONSOLE)
+# error "Serial console selected, but corresponding UART not enabled"
+# endif
+# undef HAVE_CONSOLE
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART1_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+#endif
+
+#ifdef CONFIG_USE_SERIALDRIVER
+
+/* Which UART with be tty0/console and which tty1 and tty2? */
+
+/* CONFIG_UART0_SERIAL_CONSOLE (implies CONFIG_UART0_DISABLE also un-defined) */
+
+#if defined(CONFIG_UART0_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart0port /* UART0 is console */
+# define TTYS0_DEV g_uart0port /* UART0 is tty0 */
+# ifndef CONFIG_UART1_DISABLE
+# define TTYS1_DEV g_uart1port /* UART1 is tty1 */
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS2_DEV g_uart2port /* UART2 is tty2 */
+# endif
+# else
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS2_DEV g_uart2port /* UART2 is tty1 */
+# else
+# undef TTYS1_DEV /* No tty1 */
+# endif
+# undef TTYS2_DEV /* No tty2 */
+# endif
+
+/* CONFIG_UART1_SERIAL_CONSOLE (implies CONFIG_UART1_DISABLE also un-defined) */
+
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart1port /* UART1 is console */
+# define TTYS0_DEV g_uart1port /* UART1 is tty0 */
+# ifndef CONFIG_UART0_DISABLE
+# define TTYS1_DEV g_uart0port /* UART0 is tty1 */
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS2_DEV g_uart2port /* UART2 is tty2 */
+# endif
+# else
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS2_DEV g_uart2port /* UART2 is tty1 */
+# else
+# undef TTYS1_DEV /* No tty1 */
+# endif
+# undef TTYS2_DEV /* No tty2 */
+# endif
+
+/* CONFIG_UART2_SERIAL_CONSOLE (implies CONFIG_UART2_DISABLE also un-defined) */
+
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart2port /* UART2 is console */
+# define TTYS0_DEV g_uart2port /* UART2 is tty0 */
+# ifndef CONFIG_UART0_DISABLE
+# define TTYS1_DEV g_uart0port /* UART0 is tty1 */
+# ifndef CONFIG_UART1_DISABLE
+# define TTYS2_DEV g_uart1port /* UART1 is tty2 */
+# endif
+# else
+# ifndef CONFIG_UART1_DISABLE
+# define TTYS1_DEV g_uart1port /* UART1 is tty1 */
+# else
+# undef TTYS1_DEV /* No tty1 */
+# endif
+# undef TTYS2_DEV /* No tty2 */
+# endif
+
+/* No console, at least one of CONFIG_UART0/1/2_DISABLE defined */
+
+#elif !defined(CONFIG_UART0_DISABLE)
+# undef CONSOLE_DEV /* No console */
+# define TTYS0_DEV g_uart0port /* UART0 is tty0 */
+# ifndef CONFIG_UART1_DISABLE
+# define TTYS1_DEV g_uart1port /* UART1 is tty1 */
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS2_DEV g_uart2port /* UART2 is tty2 */
+# endif
+# else
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS1_DEV g_uart1port /* UART2 is tty1 */
+# else
+# undef TTYS1_DEV /* No tty1 */
+# endif
+# undef TTYS2_DEV /* No tty2 */
+# endif
+
+elif !defined(CONFIG_UART1_DISABLE)
+# undef CONSOLE_DEV /* No console */
+# undef TTYS2_DEV /* No tty2 */
+# define TTYS0_DEV g_uart1port /* UART1 is tty0 */
+# ifndef CONFIG_UART2_DISABLE
+# define TTYS1_DEV g_uart2port /* UART2 is tty1 */
+# else
+# undef TTYS1_DEV /* No tty1 */
+# endif
+
+/* Otherwise, there is no console and only CONFIG_UART2_DISABLE is un-defined */
+
+#else
+# undef CONSOLE_DEV /* No console */
+# define TTYS0_DEV g_uart2port /* UART2 is tty0 */
+# undef TTYS1_DEV /* No tty1 */
+# undef TTYS1_DEV /* No tty2 */
+#endif
+
+/* Definitions for the enable field of the device structure */
+
+#define M16C_RXENABLED 0x01
+#define M16C_TXENABLED 0x02
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct up_dev_s
+{
+ uint32 baud; /* Configured baud */
+ uint16 uartbase; /* Base address of UART registers */
+ ubyte uartno; /* UART number */
+ volatile ubyte ucon; /* Saved SCR value */
+ volatile ubyte ssr; /* Saved SR value (only used during interrupt processing) */
+ ubyte rcvirq; /* UART receive data available IRQ */
+ ubyte xmtirq; /* UART transmit complete IRQ */
+ ubyte enables; /* Bit 0: 1=RX enabled, Bit 1: 1=TX enabled */
+ ubyte parity; /* 0=none, 1=odd, 2=even */
+ ubyte bits; /* Number of bits (7 or 8) */
+ boolean stopbits2; /* TRUE: Configure with 2 stop bits instead of 1 */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int up_setup(struct uart_dev_s *dev);
+static void up_shutdown(struct uart_dev_s *dev);
+static int up_attach(struct uart_dev_s *dev);
+static void up_detach(struct uart_dev_s *dev);
+static int up_rcvinterrupt(int irq, void *context);
+static int up_receive(struct uart_dev_s *dev, unsigned int *status);
+static void m16c_rxint(struct up_dev_s *dev, boolean enable);
+static void up_rxint(struct uart_dev_s *dev, boolean enable);
+static boolean up_rxavailable(struct uart_dev_s *dev);
+static int up_xmtinterrupt(int irq, void *context);
+static void up_send(struct uart_dev_s *dev, int ch);
+static void m16c_txint(struct up_dev_s *dev, boolean enable);
+static void up_txint(struct uart_dev_s *dev, boolean enable);
+static boolean up_txready(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+struct uart_ops_s g_uart_ops =
+{
+ .setup = up_setup,
+ .shutdown = up_shutdown,
+ .attach = up_attach,
+ .detach = up_detach,
+ .receive = up_receive,
+ .rxint = up_rxint,
+ .rxavailable = up_rxavailable,
+ .send = up_send,
+ .txint = up_txint,
+ .txready = up_txready,
+ .txempty = up_txready,
+};
+
+/* I/O buffers */
+
+#ifndef CONFIG_UART0_DISABLE
+static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE];
+static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE];
+#endif
+#ifndef CONFIG_UART1_DISABLE
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifndef CONFIG_UART2_DISABLE
+static char g_uart2rxbuffer[CONFIG_UART2_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART2_TXBUFSIZE];
+#endif
+
+/* This describes the state of the M16C UART0 port. */
+
+#ifndef CONFIG_UART0_DISABLE
+static struct up_dev_s g_uart0priv =
+{
+ .baud = CONFIG_UART0_BAUD,
+ .uartbase = M16C_UART0_BASE,
+ .uartno = 0,
+ .rcvirq = M16C_UART0RCV_IRQ,
+ .xmtirq = M16C_UART0XMT_IRQ,
+ .parity = CONFIG_UART0_PARITY,
+ .bits = CONFIG_UART0_BITS,
+ .stopbits2 = CONFIG_UART0_2STOP,
+};
+
+static uart_dev_t g_uart0port =
+{
+ .recv =
+ {
+ .size = CONFIG_UART0_RXBUFSIZE,
+ .buffer = g_uart0rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART0_TXBUFSIZE,
+ .buffer = g_uart0txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_uart0priv,
+};
+#endif
+
+/* This describes the state of the M16C UART1 port. */
+
+#ifndef CONFIG_UART1_DISABLE
+static struct up_dev_s g_uart1priv =
+{
+ .baud = CONFIG_UART1_BAUD,
+ .uartbase = M16C_UART1_BASE,
+ .uartno = 1,
+ .rcvirq = M16C_UART1RCV_IRQ,
+ .xmtirq = M16C_UART1XMT_IRQ,
+ .parity = CONFIG_UART1_PARITY,
+ .bits = CONFIG_UART1_BITS,
+ .stopbits2 = CONFIG_UART1_2STOP,
+};
+
+static uart_dev_t g_uart1port =
+{
+ .recv =
+ {
+ .size = CONFIG_UART1_RXBUFSIZE,
+ .buffer = g_uart1rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART1_TXBUFSIZE,
+ .buffer = g_uart1txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_uart1priv,
+};
+#endif
+
+/* This describes the state of the M16C UART2 port. */
+
+#ifndef CONFIG_UART2_DISABLE
+static struct up_dev_s g_uart2priv =
+{
+ .baud = CONFIG_UART2_BAUD,
+ .uartbase = M16C_UART2_BASE,
+ .uartno = 2,
+ .rcvirq = M16C_UART2RCV_IRQ,
+ .xmtirq = M16C_UART2XMT_IRQ,
+ .parity = CONFIG_UART2_PARITY,
+ .bits = CONFIG_UART2_BITS,
+ .stopbits2 = CONFIG_UART2_2STOP,
+};
+
+static uart_dev_t g_uart2port =
+{
+ .recv =
+ {
+ .size = CONFIG_UART2_RXBUFSIZE,
+ .buffer = g_uart2rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART2_TXBUFSIZE,
+ .buffer = g_uart2txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_uart2priv,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialin
+ ****************************************************************************/
+
+static inline ubyte up_serialin(struct up_dev_s *priv, int offset)
+{
+ return getreg8(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialin16
+ ****************************************************************************/
+
+static inline uint16 up_serialin16(struct up_dev_s *priv, int offset)
+{
+ return getreg16(priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout
+ ****************************************************************************/
+
+static inline void up_serialout(struct up_dev_s *priv, int offset, ubyte value)
+{
+ putreg8(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_serialout16
+ ****************************************************************************/
+
+static inline void up_serialout16(struct up_dev_s *priv, int offset, uint16 value)
+{
+ putreg16(value, priv->uartbase + offset);
+}
+
+/****************************************************************************
+ * Name: up_disableuartint
+ ****************************************************************************/
+
+static inline void up_disableuartint(struct up_dev_s *priv, ubyte *penables)
+{
+ ubyte enables = priv->enables;
+ m16c_txint(priv, FALSE);
+ m16c_rxint(priv, FALSE);
+
+ if (enables)
+ {
+ *penables = enables;
+ }
+}
+
+/****************************************************************************
+ * Name: up_restoreuartint
+ ****************************************************************************/
+
+static inline void up_restoreuartint(struct up_dev_s *priv, ubyte enables)
+{
+ m16c_rxint(priv, (enables & M16C_RXENABLED) != 0);
+ m16c_txint(priv, (enables & M16C_TXENABLED) != 0);
+}
+
+/****************************************************************************
+ * Name: up_waittxready
+ ****************************************************************************/
+
+#ifdef HAVE_CONSOLE
+static inline void up_waittxready(struct up_dev_s *priv)
+{
+ int tmp;
+
+ /* Limit how long we will wait for the TDR empty condition */
+
+ for (tmp = 1000 ; tmp > 0 ; tmp--)
+ {
+ /* Check the TI bit in the CI register. 1=Transmit buffer empty */
+
+ if ((up_serialin(priv, M16C_UART_C1) & UART_C1_TI) != 0);
+ {
+ /* The transmit buffer is empty... return */
+ break;
+ }
+ }
+}
+#endif
+
+/****************************************************************************
+ * Name: ub_setbrg
+ *
+ * Description:
+ * Calculate the correct value for the BRG given the configured frequency
+ * and the desired BAUD settings.
+ *
+ ****************************************************************************/
+
+static inline void ub_setbrg(struct up_dev_s *priv, unsigned int baud)
+{
+ uint16 brg;
+
+ /* The Bit Rate Generator (BRG) value can be calculated by:
+ *
+ * BRG = source-frequency / prescaler / 16 / baud rate - 1
+ *
+ * Example:
+ * source-frequency = 20,000,000 (20MHz)
+ * prescaler = 1
+ * baud rate = 19200
+ * BRG = 20,000,000/1/16/19200 - 1 = 64
+ */
+
+ brg = (M16C_XIN_FREQ / (16L * M16C_XIN_PRESCALER * (uint32)baud)) - 1;
+ up_serialout(priv, M16C_UART_BRG, brg);
+}
+
+/****************************************************************************
+ * Name: up_setup
+ *
+ * Description:
+ * Configure the UART baud, bits, parity, fifos, etc. This
+ * method is called the first time that the serial port is
+ * opened.
+ *
+ ****************************************************************************/
+
+static int up_setup(struct uart_dev_s *dev)
+{
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ ubyte regval;
+
+ /* Set the baud rate generator */
+
+ ub_setbrg(priv, priv->baud);
+
+ /* Disable CTS/RTS */
+
+ up_serialout(priv, M16C_UART_C0, UART_C0_CRD);
+
+ /* Disable RX/TX interrupts */
+
+ m16c_rxint(priv, FALSE);
+ m16c_txint(priv, FALSE);
+
+/* Set interrupt cause=TX complete and continuous receive mode */
+
+#ifndef CONFIG_UART0_DISABLE
+ if (priv->uartno == 0)
+ {
+ regval = getreg8(M16C_UCON);
+ regval |= (UART_CON_U0IRS|UART_CON_U0RRM);
+ putreg8(regval, M16C_UCON);
+ }
+ else
+#endif
+#ifndef CONFIG_UART1_DISABLE
+ if (priv->uartno == 1)
+ {
+ regval = getreg8(M16C_UCON);
+ regval |= (UART_CON_U1IRS|UART_CON_U1RRM);
+ putreg8(regval, M16C_UCON);
+ }
+ else
+#endif
+#ifndef CONFIG_UART2_DISABLE
+ if (priv->uartno == 2)
+ {
+ regval = getreg8(M16C_U2C1);
+ regval |= ((UART_C1_U2IRS|UART_C1_U2RRM);
+ putreg8(regval, M16C_U2C1);
+ }
+ else
+#endif
+ {
+ dbg("Invalid UART #\n");
+ }
+
+ /* Set UART transmit/receive control register 1 to enable transmit and receive */
+
+ up_serialout(priv, M16C_UART_C1, UART_C1_TE|UART_C1_RE);
+
+ /* Set UART transmit/receive mode register data bits, stop bits, parity */
+
+ regval = 0;
+
+ if (priv->bits == 7)
+ {
+ regval |= UART_MR_SMD7BITS;
+ }
+ else if (priv->bits == 8)
+ {
+ regval |= UART_MR_SMD8BITS;
+ }
+ else if (priv->bits == 9)
+ {
+ regval |= UART_MR_SMD9BITS;
+ }
+ else
+ {
+ dbg("Invalid bits=%d\n", priv->bits);
+ }
+
+ if (priv->parity != 0)
+ {
+ regval |= UART_MR_PRYE;
+ if (priv->parity == 2)
+ {
+ regval |= UART_MR_PRY;
+ }
+ }
+
+ if (priv->stopbits2)
+ {
+ regval |= UART_MR_STPS;
+ }
+
+ up_serialout(priv, M16C_UART_MR, regval);
+
+ /* Set port direction registers for Rx/TX pins */
+
+#ifndef CONFIG_UART0_DISABLE
+ if (priv->uartno == 0)
+ {
+ regval = getreg8(M16C_PD6);
+ regval &= ~(1 << 2); /* PD6-2:RxD1 */
+ regval |= (1 << 3); /* PD6-3:TxD1 */
+ putreg8(regval, M16C_PD6);
+ }
+ else
+#endif
+#ifndef CONFIG_UART1_DISABLE
+ if (priv->uartno == 1)
+ {
+ regval = getreg8(M16C_PD6);
+ regval &= ~(1 << 6); /* PD6-6:RxD1 */
+ regval |= (1 << 7); /* PD6-7:TxD1 */
+ putreg8(regval, M16C_PD6);
+ }
+ else
+#endif
+#ifndef CONFIG_UART2_DISABLE
+ if (priv->uartno == 2)
+ {
+ regval = getreg8(M16C_PD7);
+ regval &= ~(1 << 1); /* PD7-1:RxD1 */
+ regval &= (1 << 0); /* PD7-0:TxD1 */
+ putreg8(regval, M16C_PD7);
+ }
+ else
+#endif
+ {
+ dbg("Invalid UART #\n");
+ }
+
+ /* Read any data left in the RX fifo */
+
+ regval = (ubyte)up_serialin16(priv, M16C_UART_RB);
+#endif
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_shutdown
+ *
+ * Description:
+ * Disable the UART. This method is called when the serial port is closed
+ *
+ ****************************************************************************/
+
+static void up_shutdown(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ up_disableuartint(priv, NULL);
+}
+
+/****************************************************************************
+ * Name: up_attach
+ *
+ * Description:
+ * Configure the UART to operation in interrupt driven mode. This method is
+ * called when the serial port is opened. Normally, this is just after the
+ * 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 up_attach(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ int ret;
+
+ /* Attach the UART receive data available IRQ */
+
+ ret = irq_attach(priv->rcvirq, up_rcvinterrupt);
+ if (ret == OK)
+ {
+ /* Attach the UART transmit complete IRQ */
+
+ ret = irq_attach(priv->xmtirq, up_xmtinterrupt);
+ if (ret != OK)
+ {
+ /* Detach the ERI interrupt on failure */
+
+ (void)irq_detach(priv->rcvirq);
+ }
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: up_detach
+ *
+ * Description:
+ * Detach UART 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 up_detach(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+
+ /* Disable all UART interrupts */
+
+ up_disableuartint(priv, NULL);
+
+ /* Detach the UART interrupts */
+
+ (void)irq_detach(priv->rcvirq);
+ (void)irq_detach(priv->xmtirq);
+}
+
+/****************************************************************************
+ * Name: up_recvinterrupt
+ *
+ * Description:
+ * This is the UART receive interrupt handler. It will be invoked when an
+ * interrupt received on the 'irq' It should call uart_receivechar to
+ * perform the appropriate data transfer. The interrupt handling logic
+ * must be able to map the 'irq' number into the approprite up_dev_s
+ * structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_rcvinterrupt(int irq, void *context)
+{
+ struct uart_dev_s *dev = NULL;
+
+#ifndef CONFIG_UART0_DISABLE
+ if (irq == g_uart0priv.rcvirq)
+ {
+ dev = &g_uart0port;
+ }
+ else
+#endif
+#ifndef CONFIG_UART1_DISABLE
+ if (irq == g_uart1priv.rcvirq)
+ {
+ dev = &g_uart1port;
+ }
+ else
+#endif
+#ifndef CONFIG_UART2_DISABLE
+ if (irq = g_uart2priv.rcvirq)
+ {
+ dev = &g_uart2port;
+ }
+ else
+#endif
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+
+ /* Handle incoming, receive bytes (RDRF: Receive Data Register Full) */
+
+ uart_recvchars(dev);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_receive
+ *
+ * Description:
+ * Called (usually) from the interrupt level to receive one character from
+ * the UART. Error bits associated with the receipt are provided in the
+ * return 'status'.
+ *
+ ****************************************************************************/
+
+static int up_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ uint16 rb;
+
+ /* Read the character from the readbuffer */
+
+ rb = up_serialin16(priv, M16C_UART_RB);
+
+ /* Return the received byte with the receive status */
+
+ *status = rb;
+
+ /* Return the received character (up to 9 bits) */
+
+ return (int)(rb & 0x01ff);
+}
+
+/****************************************************************************
+ * Name: m16c_rxint, up_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+static void m16c_rxint(struct up_dev_s *dev, boolean enable)
+{
+ irqstate_t flags;
+ uint16 regaddr;
+ ubyte regvalue;
+
+ /* Disable interrupts to prevent asynchronous accesses */
+
+ flags = irqsave();
+
+ /* Pick the SxTIC register and enable interrupt priority */
+
+#ifndef CONFIG_UART0_DISABLE
+ if (dev->uartno == 0)
+ {
+ regaddr = M16C_S0RIC;
+ regvalue = M16C_S0R_PRIO;
+ }
+ else
+#endif
+#ifndef CONFIG_UART1_DISABLE
+ if (dev->uartno == 1)
+ {
+ regaddr = M16C_S1RIC;
+ regvalue = M16C_S1R_PRIO;
+ }
+ else
+#endif
+#ifndef CONFIG_UART2_DISABLE
+ if (dev->uartno == 2)
+ {
+ regaddr = M16C_S2RIC;
+ regvalue = M16C_S2R_PRIO;
+ }
+ else
+#endif
+ {
+ dbg("Invalid UART #\n");
+ return;
+ }
+
+ /* Are we enabling or disabling? */
+
+ if (enable)
+ {
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ putreg8(regvalue, regaddr);
+#endif
+ dev->enables |= M16C_RXENABLED;
+ }
+ else
+ {
+ putreg8(0, regaddr);
+ dev->enables = ~M16C_RXENABLED;
+ }
+
+ asm ("\tnop\n\tnop\n\tnop"); /* Three NOPs -- probably not necessary here */
+ irqrestore(flags);
+}
+
+static void up_rxint(struct uart_dev_s *dev, boolean enable)
+{
+ m16c_rxint((struct up_dev_s*)dev->priv, enable);
+}
+
+/****************************************************************************
+ * Name: up_rxavailable
+ *
+ * Description:
+ * Return TRUE if the RDR is not empty
+ *
+ ****************************************************************************/
+
+static boolean up_rxavailable(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+
+ /* Return true if the there is data available in the read buffer */
+
+ return ((up_serialin(priv, M16C_UART_C1) & UART_C1_RI) != 0);
+}
+
+/****************************************************************************
+ * Name: up_xmtvinterrupt
+ *
+ * Description:
+ * This is the UART receive 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
+ * up_dev_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int up_xmtinterrupt(int irq, void *context)
+{
+ struct uart_dev_s *dev = NULL;
+
+#ifndef CONFIG_UART0_DISABLE
+ if (irq == g_uart0priv.xmtirq)
+ {
+ dev = &g_uart0port;
+ }
+ else
+#endif
+#ifndef CONFIG_UART1_DISABLE
+ if (irq == g_uart1priv.xmtirq)
+ {
+ dev = &g_uart1port;
+ }
+ else
+#endif
+#ifndef CONFIG_UART2_DISABLE
+ if (irq == g_uart2priv.xmtirq)
+ {
+ dev = &g_uart1port;
+ }
+ else
+#endif
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+
+ /* Handle outgoing, transmit bytes */
+
+ uart_xmitchars(dev);
+ return OK;
+}
+
+/****************************************************************************
+ * Name: up_send
+ *
+ * Description:
+ * This method will send one byte on the UART
+ *
+ ****************************************************************************/
+
+static void up_send(struct uart_dev_s *dev, int ch)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+
+ /* Write the data to the transmit buffer */
+
+ up_serialout16(priv, M16C_UART_TB, (uint16)ch);
+}
+
+/****************************************************************************
+ * Name: m16c_txint, up_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts
+ *
+ ****************************************************************************/
+
+static void m16c_txint(struct up_dev_s *dev, boolean enable)
+{
+ irqstate_t flags;
+ uint16 regaddr;
+ ubyte regvalue;
+
+ /* Disable interrupts to prevent asynchronous accesses */
+
+ flags = irqsave();
+
+ /* Pick the SxTIC register and enable interrupt priority */
+
+#ifndef CONFIG_UART0_DISABLE
+ if (dev->uartno == 0)
+ {
+ regaddr = M16C_S0TIC;
+ regvalue = M16C_S0T_PRIO;
+ }
+ else
+#endif
+#ifndef CONFIG_UART1_DISABLE
+ if (dev->uartno == 1)
+ {
+ regaddr = M16C_S1TIC;
+ regvalue = M16C_S1T_PRIO;
+ }
+ else
+#endif
+#ifndef CONFIG_UART2_DISABLE
+ if (dev->uartno == 2)
+ {
+ regaddr = M16C_S2TIC;
+ regvalue = M16C_S2T_PRIO;
+ }
+ else
+#endif
+ {
+ dbg("Invalid UART #\n");
+ return;
+ }
+
+ /* Are we enabling or disabling? */
+
+ if (enable)
+ {
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ putreg8(regvalue, regaddr);
+#endif
+ dev->enables |= M16C_TXENABLED;
+ }
+ else
+ {
+ putreg8(0, regaddr);
+ dev->enables = ~M16C_TXENABLED;
+ }
+
+ asm ("\tnop\n\tnop\n\tnop"); /* Three NOPs -- probably not necessary here */
+ irqrestore(flags);
+}
+
+static void up_txint(struct uart_dev_s *dev, boolean enable)
+{
+ m16c_txint((struct up_dev_s*)dev->priv, enable);
+}
+
+/****************************************************************************
+ * Name: up_txready
+ *
+ * Description:
+ * Return TRUE if the TDR is empty
+ *
+ ****************************************************************************/
+
+static boolean up_txready(struct uart_dev_s *dev)
+{
+ struct up_dev_s *priv = (struct up_dev_s*)dev->priv;
+ return ((up_serialin(priv, M16C_UART_C1) & UART_C1_TI) != 0);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_serialinit
+ *
+ * Description:
+ * Performs the low level UART initialization early in
+ * debug so that the serial console will be available
+ * during bootup. This must be called before up_serialinit.
+ *
+ ****************************************************************************/
+
+void up_earlyserialinit(void)
+{
+ /* NOTE: All GPIO configuration for the UARTs was performed in
+ * up_lowsetup
+ */
+
+ /* Disable all UARTs */
+
+#ifdef TTYS0_DEV
+ up_disableuartint(TTYS0_DEV.priv, NULL);
+#ifdef TTYS1_DEV
+ up_disableuartint(TTYS1_DEV.priv, NULL);
+#ifdef TTYS2_DEV
+ up_disableuartint(TTYS2_DEV.priv, NULL);
+#endif
+#endif
+#endif
+
+ /* Configuration whichever one is the console */
+
+#ifdef HAVE_CONSOLE
+ CONSOLE_DEV.isconsole = TRUE;
+ up_setup(&CONSOLE_DEV);
+#endif
+}
+
+/****************************************************************************
+ * Name: up_serialinit
+ *
+ * Description:
+ * Register serial console and serial ports. This assumes
+ * that up_earlyserialinit was called previously.
+ *
+ ****************************************************************************/
+
+void up_serialinit(void)
+{
+ /* Register the console */
+
+#ifdef HAVE_CONSOLE
+ (void)uart_register("/dev/console", &CONSOLE_DEV);
+#endif
+
+ /* Register all UARTs */
+
+#ifdef TTYS0_DEV
+ (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
+#ifdef TTYS1_DEV
+ (void)uart_register("/dev/ttyS1", &TTYS1_DEV);
+#ifdef TTYS2_DEV
+ (void)uart_register("/dev/ttyS2", &TTYS2_DEV);
+#endif
+#endif
+#endif
+}
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+#ifdef HAVE_CONSOLE
+ struct up_dev_s *priv = (struct up_dev_s*)CONSOLE_DEV.priv;
+ ubyte ucon;
+
+ up_disableuartint(priv, &ucon);
+
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ up_waittxready(priv);
+ up_serialout16(priv, M16C_UART_TB, (uint16)'\r');
+ }
+
+ up_waittxready(priv);
+ up_serialout16(priv, M16C_UART_TB, (uint16)ch);
+
+ up_waittxready(priv);
+ up_restoreuartint(priv, ucon);
+#endif
+ return ch;
+}
+
+#else /* CONFIG_USE_SERIALDRIVER */
+
+/****************************************************************************
+ * Name: up_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+int up_putc(int ch)
+{
+#ifdef HAVE_CONSOLE
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ up_lowputc('\r');
+ }
+
+ up_lowputc(ch);
+#endif
+ return ch;
+}
+
+#endif /* CONFIG_USE_SERIALDRIVER */