summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-10 00:58:10 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-03-10 00:58:10 +0000
commitc6ac5f39311cceded51db709503502a0fd2b1e60 (patch)
tree7cd1075ddfb75ed404424d1de42071e73f3baf8f
parented75882857639faaa26d47ff90aecee0b3213273 (diff)
downloadnuttx-c6ac5f39311cceded51db709503502a0fd2b1e60.tar.gz
nuttx-c6ac5f39311cceded51db709503502a0fd2b1e60.tar.bz2
nuttx-c6ac5f39311cceded51db709503502a0fd2b1e60.zip
Fix basic QEMU port
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3357 42af7a65-404d-4744-a932-0658087f49c3
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_serial.c23
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_uart.h2
-rw-r--r--nuttx/arch/x86/src/i486/i486_utils.S66
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_fullcontextrestore.S75
-rwxr-xr-xnuttx/arch/x86/src/qemu/qemu_head.S108
-rwxr-xr-xnuttx/arch/x86/src/qemu/qemu_irq.c7
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_lowsetup.c5
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_saveusercontext.S38
-rwxr-xr-xnuttx/arch/x86/src/qemu/qemu_vectors.S240
-rw-r--r--nuttx/configs/qemu-i486/ostest/defconfig6
-rwxr-xr-xnuttx/drivers/serial/uart_16550.c1092
-rw-r--r--nuttx/include/nuttx/ioctl.h6
-rwxr-xr-xnuttx/include/nuttx/uart_16550.h351
13 files changed, 1562 insertions, 457 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c b/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c
index dcee165c1..d58ce7c03 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_serial.c
@@ -74,7 +74,7 @@
#if defined(CONFIG_USE_SERIALDRIVER) && defined(HAVE_UART)
-/* Configuration *********************************************************************/
+/* Configuration ************************************************************/
/****************************************************************************
* Private Types
@@ -281,7 +281,7 @@ static uart_dev_t g_uart3port =
# ifdef CONFIG_LPC17_UART3
# define TTYS3_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2;UART3=ttyS3 */
# else
- undef TTYS3_DEV /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS;No ttyS3 */
+# undef TTYS3_DEV /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS;No ttyS3 */
# endif
# else
# ifdef CONFIG_LPC17_UART3
@@ -780,9 +780,8 @@ static inline uint32_t lpc17_uartdl(uint32_t baud, uint8_t divcode)
* 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.
+ * Configure the UART baud, bits, parity, fifos, etc. This method is
+ * called the first time that the serial port is opened.
*
****************************************************************************/
@@ -858,8 +857,7 @@ static int up_setup(struct uart_dev_s *dev)
* Name: up_shutdown
*
* Description:
- * Disable the UART. This method is called when the serial
- * port is closed
+ * Disable the UART. This method is called when the serial port is closed
*
****************************************************************************/
@@ -924,12 +922,11 @@ static void up_detach(struct uart_dev_s *dev)
* Name: up_interrupt
*
* Description:
- * This is the UART 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.
+ * This is the UART 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
+ * appropriate uart_dev_s structure in order to call these functions.
*
****************************************************************************/
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_uart.h b/nuttx/arch/arm/src/lpc17xx/lpc17_uart.h
index 36ede428b..830c3244d 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_uart.h
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_uart.h
@@ -184,7 +184,7 @@
#define UART_IIR_INTID_MASK (7 << UART_IIR_INTID_SHIFT)
# define UART_IIR_INTID_MSI (0 << UART_IIR_INTID_SHIFT) /* Modem Status (UART1 only) */
# define UART_IIR_INTID_THRE (1 << UART_IIR_INTID_SHIFT) /* THRE Interrupt */
-# define UART_IIR_INTID_RDA (2 << UART_IIR_INTID_SHIFT) /* 2a - Receive Data Available (RDA */
+# define UART_IIR_INTID_RDA (2 << UART_IIR_INTID_SHIFT) /* 2a - Receive Data Available (RDA) */
# define UART_IIR_INTID_RLS (3 << UART_IIR_INTID_SHIFT) /* 1 - Receive Line Status (RLS) */
# define UART_IIR_INTID_CTI (6 << UART_IIR_INTID_SHIFT) /* 2b - Character Time-out Indicator (CTI) */
/* Bits 4-5: Reserved */
diff --git a/nuttx/arch/x86/src/i486/i486_utils.S b/nuttx/arch/x86/src/i486/i486_utils.S
index d94024f78..ee89c0c68 100644
--- a/nuttx/arch/x86/src/i486/i486_utils.S
+++ b/nuttx/arch/x86/src/i486/i486_utils.S
@@ -42,6 +42,8 @@
#include <nuttx/config.h>
+ .file "i486_utils.S"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -49,73 +51,14 @@
#define KSEG 0x10
/****************************************************************************
- * Nasm
- ****************************************************************************/
-
-#ifdef CONFIG_X86_NASM
-
-/****************************************************************************
- * Nasm externals
- ****************************************************************************/
-
-global gdt_flush
-global idt_flush
-
-/****************************************************************************
- * Nasm macros
- ****************************************************************************/
-
-/****************************************************************************
- * Nasm .text
- ****************************************************************************/
-
-SECTION .text
-BITS 32
-
-/****************************************************************************
- * Name: gdt_flush
- ****************************************************************************/
-
-gdt_flush:
- mov eax, [esp+4] /* Get the pointer to the GDT, passed as a parameter */
- lgdt [eax] /* Load the new GDT pointer */
-
- mov $KSEG, ax /* KSEG is the offset in the GDT to our data segment */
- mov ax, ds /* Load all data segment selectors */
- mov ax, es
- mov ax, fs
- mov ax, gs
- mov ax, ss
- jmp 0x08:.gflush /* 0x08 is the offset to our code segment: Far jump! */
-.gflush:
- ret
-
-/****************************************************************************
- * Name: idt_flush
- ****************************************************************************/
-
-idt_flush:
- mov eax, [esp+4] /* Get the pointer to the IDT, passed as a parameter */
- lidt [eax] /* Load the IDT pointer */
- ret
-
-#else /* !CONFIG_X86_NASM (GAS) */
-
-/****************************************************************************
- * GAS
- ****************************************************************************/
-
- .file "i486_utils.S"
-
-/****************************************************************************
- * GAS Globals
+ * Globals
****************************************************************************/
.globl gdt_flush
.globl idt_flush
/****************************************************************************
- * GAS .text
+ * .text
****************************************************************************/
.text
@@ -151,4 +94,3 @@ idt_flush:
ret
.size idt_flush, . - idt_flush
.end
-#endif /* CONFIG_X86_NASM */
diff --git a/nuttx/arch/x86/src/qemu/qemu_fullcontextrestore.S b/nuttx/arch/x86/src/qemu/qemu_fullcontextrestore.S
index 6f15662dd..7d25e9072 100644
--- a/nuttx/arch/x86/src/qemu/qemu_fullcontextrestore.S
+++ b/nuttx/arch/x86/src/qemu/qemu_fullcontextrestore.S
@@ -45,34 +45,36 @@
#include <arch/irq.h>
#include "up_internal.h"
-/**************************************************************************
- * Pre-processor Definitions
- **************************************************************************/
-
-/**************************************************************************
- * Private Types
- **************************************************************************/
+ .file "qemu_fullcontextrestore.S"
/**************************************************************************
- * Private Function Prototypes
+ * Pre-processor Definitions
**************************************************************************/
/**************************************************************************
* Global Variables
**************************************************************************/
-/**************************************************************************
- * Private Variables
- **************************************************************************/
+/****************************************************************************
+ * Macros
+ ****************************************************************************/
-/**************************************************************************
- * Private Functions
- **************************************************************************/
+/* Trace macros, use like trace 'i' to print char to serial port. */
+
+ .macro trace, ch
+#ifdef CONFIG_DEBUG
+ mov $0x3f8, %dx
+ mov $\ch, %al
+ out %al, %dx
+#endif
+ .endm
/**************************************************************************
* Public Functions
**************************************************************************/
+ .text
+
/**************************************************************************
* Name: up_fullcontextrestore
*
@@ -81,11 +83,6 @@
*
**************************************************************************/
-#ifdef CONFIG_X86_NASM
-# warning "No Nasm support"
-#else
- .file "qemu_fullcontextrestore.S"
- .text
.globl up_fullcontextrestore
.type up_fullcontextrestore, @function
up_fullcontextrestore:
@@ -105,38 +102,54 @@ up_fullcontextrestore:
movl (4*REG_SP)(%eax), %esp
- /* Save the return address, EFLAGS, and the values as well the
- * values of EBX and EAC on the new stack.
+ /* Create an interrupt stack frame for the final iret.
+ *
+ * SP Before ->
+ * SS
+ * ESP
+ * EFLAGS
+ * CS
+ * SP After -> EIP
*/
- movl (4*REG_EIP)(%eax), %ebx
+ mov (4*REG_SS)(%eax), %ebx
+ push %ebx
+ movl (4*REG_SP)(%eax), %ebx
push %ebx
movl (4*REG_EFLAGS)(%eax), %ebx
push %ebx
+ mov (4*REG_CS)(%eax), %ebx
+ push %ebx
+ movl (4*REG_EIP)(%eax), %ebx
+ push %ebx
+
+ /* Save the value of EAX on the stack too */
+
movl (4*REG_EAX)(%eax), %ebx
push %ebx
/* Now restore the remaining registers */
- movl (4*REG_EDI)(%eax), %edi
movl (4*REG_ESI)(%eax), %esi
+ movl (4*REG_EDI)(%eax), %edi
movl (4*REG_EBP)(%eax), %ebp
+ movl (4*REG_EBX)(%eax), %ebx
movl (4*REG_EDX)(%eax), %edx
movl (4*REG_ECX)(%eax), %ecx
- movl (4*REG_EBX)(%eax), %ebx
- /* Restore the segment registers */
+ /* Restore the data segment register. I think there is an issue that will
+ * need to be address here at some time: If the register save area is in
+ * one data segment and the stack is in another, then the above would not
+ * work (and, conversely, if they are in the same data segment, the
+ * following is unnecessary and redundant).
+ */
mov (4*REG_DS)(%eax), %ds
- mov (4*REG_CS)(%eax), %cs
- mov (4*REG_SS)(%eax), %ss
- /* Restore the correct value of EAX, EBX, and the EFLAGS then return */
+ /* Restore the correct value of EAX and then return */
popl %eax
- popf
- ret
+ iret
.size up_fullcontextrestore, . - up_fullcontextrestore
.end
-#endif /* CONFIG_X86_NASM */
diff --git a/nuttx/arch/x86/src/qemu/qemu_head.S b/nuttx/arch/x86/src/qemu/qemu_head.S
index 096705f46..9933d91ff 100755
--- a/nuttx/arch/x86/src/qemu/qemu_head.S
+++ b/nuttx/arch/x86/src/qemu/qemu_head.S
@@ -39,6 +39,8 @@
#include <nuttx/config.h>
+ .file "qemu_head.S"
+
/****************************************************************************
* Pre-processor definitions
****************************************************************************/
@@ -56,94 +58,35 @@
#define HEAP_BASE (STACKBASE+CONFIG_IDLETHREAD_STACKSIZE)
/****************************************************************************
- * Nasm .text
+ * Macros
****************************************************************************/
-#ifdef CONFIG_X86_NASM
-global __start /* Making entry point visible to linker */
-global g_heapbase /* The start of the heap */
-extern os_start /* os_start is defined elsewhere */
-extern up_lowsetup /* up_lowsetup is defined elsewhere */
-
-/* Setting up the Multiboot header - see GRUB docs for details */
-
-MODULEALIGN equ 1<<0 /* Align loaded modules on page boundaries */
-MEMINFO equ 1<<1 /* Provide memory map */
-FLAGS equ MODULEALIGN | MEMINFO /* This is the Multiboot 'flag' field */
-MAGIC equ 0x1badb002 /* 'magic number' lets bootloader find the header */
-CHECKSUM equ -(MAGIC + FLAGS) /* Checksum required */
-
-section .text
-align 4
-MultiBootHeader:
- dd MAGIC
- dd FLAGS
- dd CHECKSUM
-
-__start:
- /* Set up the stack */
-
- mov esp, idle_stack + CONFIG_IDLETHREAD_STACKSIZE
-
- /* Multiboot setup */
+/* Trace macros, use like trace 'i' to print char to serial port. */
- push eax /* Pass Multiboot magic number */
- push ebx /* Pass Multiboot info structure */
+ .macro trace, ch
+#ifdef CONFIG_DEBUG
+ mov $0x3f8, %dx
+ mov $\ch, %al
+ out %al, %dx
+#endif
+ .endm
- /* Initialize and start NuttX */
-
- call up_lowsetup /* Low-level, pre-OS initialization */
- call os_start /* Start NuttX */
-
- /* NuttX will not return */
-
- cli
-hang:
- hlt /* Halt machine should NuttX return */
- jmp hang
-
/****************************************************************************
- * .bss
+ * Global Symbols
****************************************************************************/
-/* The stack for the IDLE task thread is declared in .bss. NuttX boots and
- * initializes on the IDLE thread, then at the completion of OS startup, this
- * thread becomes the thread that executes when there is nothing else to
- * do in the system (see up_idle()).
- */
-
-section .bss
-align 4
-idle_stack:
- resb CONFIG_IDLETHREAD_STACKSIZE
+ .global __start /* Making entry point visible to linker */
+ .global os_start /* os_start is defined elsewhere */
+ .global up_lowsetup /* up_lowsetup is defined elsewhere */
+ .global g_heapbase /* The start of the heap */
/****************************************************************************
- * .rodata
+ * .text
****************************************************************************/
-
-section .rodata
-
-/* HEAP BASE: _sbss is the start of the BSS region (see ld.script) _ebss is
- * the end of the BSS region (see ld.script). The heap continues from there
- * until the end of memory.
- */
-
-align 4
-g_heapbase:
- dd _ebss
-
-#else /* !CONFIG_X86_NASM (GAS) */
-
/****************************************************************************
- * GAS .text
+ * Multiboot Header
****************************************************************************/
- .file "qemu_head.S"
- .global __start /* Making entry point visible to linker */
- .global os_start /* os_start is defined elsewhere */
- .global up_lowsetup /* up_lowsetup is defined elsewhere */
- .global g_heapbase /* The start of the heap */
-
/* Setting up the Multiboot header - see GRUB docs for details */
.set ALIGN, 1<<0 /* Align loaded modules on page boundaries */
@@ -158,28 +101,24 @@ g_heapbase:
.long FLAGS
.long CHECKSUM
+/****************************************************************************
+ * Name: Start
+ ****************************************************************************/
+
.type __start, @function
__start:
/* Set up the stack */
- mov $'a', %ax
- mov $0x3f8, %dx
- outb %al, %dx
+
mov $(idle_stack + CONFIG_IDLETHREAD_STACKSIZE), %esp
/* Multiboot setup */
push %eax /* Multiboot magic number */
push %ebx /* Multiboot data structure */
- mov $'b', %ax
- mov $0x3f8, %dx
- outb %al, %dx
/* Initialize and start NuttX */
call up_lowsetup /* Low-level, pre-OS initialization */
- mov $'c', %ax
- mov $0x3f8, %dx
- outb %al, %dx
call os_start /* Start NuttX */
/* NuttX will not return */
@@ -220,4 +159,3 @@ g_heapbase:
.long _ebss
.size g_heapbase, . - g_heapbase
.end
-#endif /* CONFIG_X86_NASM */
diff --git a/nuttx/arch/x86/src/qemu/qemu_irq.c b/nuttx/arch/x86/src/qemu/qemu_irq.c
index f266f6714..b92db7882 100755
--- a/nuttx/arch/x86/src/qemu/qemu_irq.c
+++ b/nuttx/arch/x86/src/qemu/qemu_irq.c
@@ -78,6 +78,8 @@ uint32_t *current_regs;
* Private Data
****************************************************************************/
+static struct idt_entry_s idt_entries[256];
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -171,10 +173,7 @@ static void up_idtentry(struct idt_entry_s *entry, uint32_t base,
static inline void up_idtinit(void)
{
- /* This uses a ton of stack! */
-
- struct idt_entry_s idt_entries[256];
- struct idt_ptr_s idt_ptr;
+ struct idt_ptr_s idt_ptr;
idt_ptr.limit = sizeof(struct idt_entry_s) * 256 - 1;
idt_ptr.base = (uint32_t)&idt_entries;
diff --git a/nuttx/arch/x86/src/qemu/qemu_lowsetup.c b/nuttx/arch/x86/src/qemu/qemu_lowsetup.c
index bbc7f1229..bc5aa52e7 100644
--- a/nuttx/arch/x86/src/qemu/qemu_lowsetup.c
+++ b/nuttx/arch/x86/src/qemu/qemu_lowsetup.c
@@ -52,6 +52,8 @@
* Private Data
****************************************************************************/
+static struct gdt_entry_s gdt_entries[5];
+
/****************************************************************************
* Private Functions
****************************************************************************/
@@ -93,8 +95,7 @@ static void up_gdtentry(struct gdt_entry_s *entry, uint32_t base,
static void up_gdtinit(void)
{
- struct gdt_entry_s gdt_entries[5];
- struct gdt_ptr_s gdt_ptr;
+ struct gdt_ptr_s gdt_ptr;
up_gdtentry(&gdt_entries[0], 0, 0, 0, 0); /* Null segment */
up_gdtentry(&gdt_entries[1], 0, 0xffffffff, 0x9a, 0xcf); /* Code segment */
diff --git a/nuttx/arch/x86/src/qemu/qemu_saveusercontext.S b/nuttx/arch/x86/src/qemu/qemu_saveusercontext.S
index 4e38784a4..ffa1cf7f6 100644
--- a/nuttx/arch/x86/src/qemu/qemu_saveusercontext.S
+++ b/nuttx/arch/x86/src/qemu/qemu_saveusercontext.S
@@ -45,33 +45,31 @@
#include <arch/irq.h>
#include "up_internal.h"
-/**************************************************************************
- * Private Definitions
- **************************************************************************/
+ .file "qemu_saveusercontext.S"
/**************************************************************************
- * Private Types
+ * Pre-processor Definitions
**************************************************************************/
-/**************************************************************************
- * Private Function Prototypes
- **************************************************************************/
+/****************************************************************************
+ * Macros
+ ****************************************************************************/
-/**************************************************************************
- * Global Variables
- **************************************************************************/
+/* Trace macros, use like trace 'i' to print char to serial port. */
-/**************************************************************************
- * Private Variables
- **************************************************************************/
+ .macro trace, ch
+#ifdef CONFIG_DEBUG
+ mov $0x3f8, %dx
+ mov $\ch, %al
+ out %al, %dx
+#endif
+ .endm
/**************************************************************************
- * Private Functions
+ * .text
**************************************************************************/
-/**************************************************************************
- * Public Functions
- **************************************************************************/
+ .text
/**************************************************************************
* Name: up_saveusercontext
@@ -95,11 +93,6 @@
*
**************************************************************************/
-#ifdef CONFIG_X86_NASM
-# warning "No Nasm support"
-#else
- .file "qemu_saveusercontext.S"
- .text
.globl up_saveusercontext
.type up_saveusercontext, @function
up_saveusercontext:
@@ -151,4 +144,3 @@ up_saveusercontext:
ret
.size up_saveusercontext, . - up_saveusercontext
.end
-#endif
diff --git a/nuttx/arch/x86/src/qemu/qemu_vectors.S b/nuttx/arch/x86/src/qemu/qemu_vectors.S
index 068ce00c2..a512e1f95 100755
--- a/nuttx/arch/x86/src/qemu/qemu_vectors.S
+++ b/nuttx/arch/x86/src/qemu/qemu_vectors.S
@@ -1,5 +1,5 @@
/****************************************************************************
- * arch/x86/src/qemu/qemu_head.S
+ * arch/x86/src/qemu/qemu_head.S
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
@@ -43,6 +43,8 @@
#include <nuttx/config.h>
#include <arch/irq.h>
+ .file "qemu_vectors.S"
+
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
@@ -50,242 +52,20 @@
#define KSEG 0x10
/****************************************************************************
- * Nasm .text
- ****************************************************************************/
-
-#ifdef CONFIG_X86_NASM
-
-/****************************************************************************
- * Nasm externals
- ****************************************************************************/
-
-extern irq_handler
-extern isr_handler
-
-/****************************************************************************
- * Nasm macros
+ * .text
****************************************************************************/
-/* Trace macros, use like trace 'i' to print char to serial port. */
-
-%macro io_outb 2
- mov dx, %1 /* param1 = address, param2 = data. */
- mov al, %2
- out dx, al
-%endmacro
-
-%macro trace 1
- io_outb 0x3f8, %1 /* diagnostic character */
-%endmacro
-
-/* This macro creates a stub for an ISR which does NOT pass it's own
- * error code (adds a dummy errcode byte).
- */
-
-%macro ISR_NOERRCODE 1
- global vector_isr%1
- vector_isr%1:
- cli /* Disable interrupts firstly. */
- push byte 0 /* Push a dummy error code. */
- push byte %1 /* Push the interrupt number. */
- jmp isr_common /* Go to our common handler code. */
-%endmacro
-
-/* This macro creates a stub for an ISR which passes it's own
- * error code.
- */
-
-%macro ISR_ERRCODE 1
- global vector_isr%1
- vector_isr%1:
- cli /* Disable interrupts. */
- push byte %1 /* Push the interrupt number */
- jmp isr_common
-%endmacro
-
-/* This macro creates a stub for an IRQ - the first parameter is
- * the IRQ number, the second is the ISR number it is remapped to.
- */
+ .text
-%macro IRQ 2
- global vector_irq%1
- vector_irq%1:
- cli
- push byte 0
- push byte %2
- jmp irq_common
-%endmacro
-
/****************************************************************************
- * Nasm vectors
- ****************************************************************************/
-
-/* The following will be the vector address programmed into the IDT */
-
-ISR_NOERRCODE ISR0
-ISR_NOERRCODE ISR1
-ISR_NOERRCODE ISR2
-ISR_NOERRCODE ISR3
-ISR_NOERRCODE ISR4
-ISR_NOERRCODE ISR5
-ISR_NOERRCODE ISR6
-ISR_NOERRCODE ISR7
-ISR_ERRCODE ISR8
-ISR_NOERRCODE ISR9
-ISR_ERRCODE ISR10
-ISR_ERRCODE ISR11
-ISR_ERRCODE ISR12
-ISR_ERRCODE ISR13
-ISR_ERRCODE ISR14
-ISR_NOERRCODE ISR15
-ISR_NOERRCODE ISR16
-ISR_NOERRCODE ISR17
-ISR_NOERRCODE ISR18
-ISR_NOERRCODE ISR19
-ISR_NOERRCODE ISR20
-ISR_NOERRCODE ISR21
-ISR_NOERRCODE ISR22
-ISR_NOERRCODE ISR23
-ISR_NOERRCODE ISR24
-ISR_NOERRCODE ISR25
-ISR_NOERRCODE ISR26
-ISR_NOERRCODE ISR27
-ISR_NOERRCODE ISR28
-ISR_NOERRCODE ISR29
-ISR_NOERRCODE ISR30
-ISR_NOERRCODE ISR31
-IRQ 0, IRQ0
-IRQ 1, IRQ1
-IRQ 2, IRQ2
-IRQ 3, IRQ3
-IRQ 4, IRQ4
-IRQ 5, IRQ5
-IRQ 6, IRQ6
-IRQ 7, IRQ7
-IRQ 8, IRQ8
-IRQ 9, IRQ9
-IRQ 10, IRQ10
-IRQ 11, IRQ11
-IRQ 12, IRQ12
-IRQ 13, IRQ13
-IRQ 14, IRQ14
-IRQ 15, IRQ15
-
-/****************************************************************************
- * Name: isr_common
- *
- * Description:
- * This is the common ISR logic. It saves the processor state, sets up for
- * kernel mode segments, calls the C-level fault handler, and finally
- * restores the stack frame.
- *
- ****************************************************************************/
-
-isr_common:
-/* trace 'S' */
- pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
-
- mov ax, ds /* Lower 16-bits of eax = ds. */
- push eax /* Save the data segment descriptor */
-
- mov ax, KSEG /* Load the kernel data segment descriptor */
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- /* The current value of the SP points to the beginning of the state save
- * structure. Save that on the stack as the input parameter to isr_handler.
- */
-
- mov esp, eax
- push eax
- call isr_handler
- jmp .Lreturn
-
-/****************************************************************************
- * Name: irq_common
- *
- * Description:
- * This is the common IRQ logic. It saves the processor state, sets up for
- * kernel mode segments, calls the C-level fault handler, and finally
- * restores the stack frame.
- *
- ****************************************************************************/
-
-irq_common:
-/* trace 'R' */
- pusha /* Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax */
-
- mov ax, ds /* Lower 16-bits of eax = ds. */
- push eax /* Save the data segment descriptor */
-
- mov ax, KSEG /* Load the kernel data segment descriptor */
- mov ds, ax
- mov es, ax
- mov fs, ax
- mov gs, ax
-
- /* The current value of the SP points to the beginning of the state save
- * structure. Save that on the stack as the input parameter to irq_handler.
- */
-
- mov esp, eax
- push eax
- call irq_handler
-
- /* The common return point for both isr_handler and irq_handler */
-
-.Lreturn:
- add 4, esp
-
- /* EAX may possibly hold a pointer to a different regiser save area on
- * return. Are we switching to a new context?
- */
-
- cmp eax, esp
- je .Lnoswitch
-
- /* A context swith will be performed. EAX holds the address of the new
- * register save structure.
- *
- * 'Jump' to up_fullcontextrestore(). We perform a call here, but that function
- * never returns. The address of the new register save block is the argument
- * to the up_fullcontextrestore().
- */
-
- push eax
- jmp up_fullcontext
-
-.Lnoswitch:
- pop ebx /* Reload the original data segment descriptor */
- mov ds, bx
- mov es, bx
- mov fs, bx
- mov gs, bx
-
- popa /* Pops edi,esi,ebp... */
- add esp, 8 /* Cleans up the pushed error code and pushed ISR number */
- sti
- iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
-
-#else /* !CONFIG_X86_NASM (GAS) */
-
-/****************************************************************************
- * GAS .text
- ****************************************************************************/
-
- .file "qemu_vectors.S"
-
-/****************************************************************************
- * GAS globals
+ * Globals
****************************************************************************/
.globl irq_handler
.globl isr_handler
/****************************************************************************
- * GAS macros
+ * Macros
****************************************************************************/
/* Trace macros, use like trace 'i' to print char to serial port. */
@@ -334,7 +114,10 @@ vector_irq\irqno:
jmp isr_common /* Go to the common handler code. */
.endm
- /* The following will be the vector address programmed into the IDT */
+/****************************************************************************
+ * IDT Vectors
+ ****************************************************************************/
+/* The following will be the vector addresses programmed into the IDT */
ISR_NOERRCODE ISR0
ISR_NOERRCODE ISR1
@@ -487,4 +270,3 @@ irq_common:
iret /* Pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP */
.size irq_common, . - irq_common
.end
-#endif /* CONFIG_X86_NASM */
diff --git a/nuttx/configs/qemu-i486/ostest/defconfig b/nuttx/configs/qemu-i486/ostest/defconfig
index e7541be17..f0e558d4a 100644
--- a/nuttx/configs/qemu-i486/ostest/defconfig
+++ b/nuttx/configs/qemu-i486/ostest/defconfig
@@ -68,7 +68,6 @@
# the 100 second delay then adjust CONFIG_BOARD_LOOPSPERMSEC until
# the delay actually is 100 seconds.
# CONFIG_ARCH_DMA - Support DMA initialization
-# CONFIG_X86_NASM - Using Nasm instead of GAS
#
CONFIG_ARCH=x86
CONFIG_ARCH_X86=y
@@ -87,7 +86,6 @@ CONFIG_ARCH_LEDS=n
CONFIG_ARCH_BUTTONS=n
CONFIG_ARCH_CALIBRATION=n
CONFIG_ARCH_DMA=n
-CONFIG_X86_NASM=n
#
# General OS setup
@@ -149,8 +147,8 @@ CONFIG_X86_NASM=n
# to be closed in the new task.
#
CONFIG_APP_DIR=examples/ostest
-CONFIG_DEBUG=y
-CONFIG_DEBUG_VERBOSE=y
+CONFIG_DEBUG=n
+CONFIG_DEBUG_VERBOSE=n
CONFIG_DEBUG_SYMBOLS=n
CONFIG_MM_REGIONS=1
CONFIG_ARCH_LOWPUTC=y
diff --git a/nuttx/drivers/serial/uart_16550.c b/nuttx/drivers/serial/uart_16550.c
new file mode 100755
index 000000000..e65d5cced
--- /dev/null
+++ b/nuttx/drivers/serial/uart_16550.c
@@ -0,0 +1,1092 @@
+/****************************************************************************
+ * drivers/serial/uart_16550.c
+ * Serial driver for 16550 UART
+ *
+ * Copyright (C) 2011 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 <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.h>
+#include <nuttx/uart_16550.h>
+
+#include <arch/board/board.h>
+
+#ifdef CONFIG_UART_16550
+
+/****************************************************************************
+ * Pre-processor definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct uart_16550_s
+{
+ uart_addrwidth_t uartbase; /* Base address of UART registers */
+ uint32_t baud; /* Configured baud */
+ uint32_t uartclk; /* UART clock frequency */
+ uart_datawidth_t ier; /* Saved IER value */
+ uint8_t irq; /* IRQ associated with this UART */
+ uint8_t parity; /* 0=none, 1=odd, 2=even */
+ uint8_t bits; /* Number of bits (7 or 8) */
+ bool stopbits2; /* true: Configure with 2 stop bits instead of 1 */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int uart_setup(struct uart_dev_s *dev);
+static void uart_shutdown(struct uart_dev_s *dev);
+static int uart_attach(struct uart_dev_s *dev);
+static void uart_detach(struct uart_dev_s *dev);
+static int uart_interrupt(int irq, void *context);
+static int uart_ioctl(struct file *filep, int cmd, unsigned long arg);
+static int uart_receive(struct uart_dev_s *dev, uint32_t *status);
+static void uart_rxint(struct uart_dev_s *dev, bool enable);
+static bool uart_rxavailable(struct uart_dev_s *dev);
+static void uart_send(struct uart_dev_s *dev, int ch);
+static void uart_txint(struct uart_dev_s *dev, bool enable);
+static bool uart_txready(struct uart_dev_s *dev);
+static bool uart_txempty(struct uart_dev_s *dev);
+
+/****************************************************************************
+ * Private Variables
+ ****************************************************************************/
+
+struct uart_ops_s g_uart_ops =
+{
+ .setup = uart_setup,
+ .shutdown = uart_shutdown,
+ .attach = uart_attach,
+ .detach = uart_detach,
+ .ioctl = uart_ioctl,
+ .receive = uart_receive,
+ .rxint = uart_rxint,
+ .rxavailable = uart_rxavailable,
+ .send = uart_send,
+ .txint = uart_txint,
+ .txready = uart_txready,
+ .txempty = uart_txempty,
+};
+
+/* I/O buffers */
+
+#ifdef CONFIG_16550_UART0
+static char g_uart0rxbuffer[CONFIG_UART0_RXBUFSIZE];
+static char g_uart0txbuffer[CONFIG_UART0_TXBUFSIZE];
+#endif
+#ifdef CONFIG_16550_UART1
+static char g_uart1rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart1txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifdef CONFIG_16550_UART2
+static char g_uart2rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart2txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+#ifdef CONFIG_16550_UART3
+static char g_uart3rxbuffer[CONFIG_UART1_RXBUFSIZE];
+static char g_uart3txbuffer[CONFIG_UART1_TXBUFSIZE];
+#endif
+
+/* This describes the state of the LPC17xx uart0 port. */
+
+#ifdef CONFIG_16550_UART0
+static struct uart_16550_s g_uart0priv =
+{
+ .uartbase = CONFIG_16550_UART0_BASE,
+ .baud = CONFIG_UART0_BAUD,
+ .uartclk = CONFIG_16550_UART0_CLOCK,
+ .irq = CONFIG_16550_UART0_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 LPC17xx uart1 port. */
+
+#ifdef CONFIG_16550_UART1
+static struct uart_16550_s g_uart1priv =
+{
+ .uartbase = CONFIG_16550_UART1_BASE,
+ .baud = CONFIG_UART1_BAUD,
+ .uartclk = CONFIG_16550_UART1_CLOCK,
+ .irq = CONFIG_16550_UART1_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 LPC17xx uart1 port. */
+
+#ifdef CONFIG_16550_UART2
+static struct uart_16550_s g_uart2priv =
+{
+ .uartbase = CONFIG_16550_UART2_BASE,
+ .baud = CONFIG_UART2_BAUD,
+ .uartclk = CONFIG_16550_UART2_CLOCK,
+ .irq = CONFIG_16550_UART2_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
+
+/* This describes the state of the LPC17xx uart1 port. */
+
+#ifdef CONFIG_16550_UART3
+static struct uart_16550_s g_uart3priv =
+{
+ .uartbase = CONFIG_16550_UART3_BASE,
+ .baud = CONFIG_UART3_BAUD,
+ .uartclk = CONFIG_16550_UART3_CLOCK,
+ .irq = CONFIG_16550_UART3_IRQ,
+ .parity = CONFIG_UART3_PARITY,
+ .bits = CONFIG_UART3_BITS,
+ .stopbits2 = CONFIG_UART3_2STOP,
+};
+
+static uart_dev_t g_uart3port =
+{
+ .recv =
+ {
+ .size = CONFIG_UART3_RXBUFSIZE,
+ .buffer = g_uart3rxbuffer,
+ },
+ .xmit =
+ {
+ .size = CONFIG_UART3_TXBUFSIZE,
+ .buffer = g_uart3txbuffer,
+ },
+ .ops = &g_uart_ops,
+ .priv = &g_uart3priv,
+};
+#endif
+
+/* Which UART with be tty0/console and which tty1? tty2? tty3? */
+
+#if defined(CONFIG_UART0_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart0port /* UART0=console */
+# define TTYS0_DEV g_uart0port /* UART0=ttyS0 */
+# ifdef CONFIG_16550_UART1
+# define TTYS1_DEV g_uart1port /* UART0=ttyS0;UART1=ttyS1 */
+# ifdef CONFIG_16550_UART2
+# define TTYS2_DEV g_uart2port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2 */
+# ifdef CONFIG_16550_UART3
+# define TTYS3_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS2;UART3=ttyS3 */
+# else
+# undef TTYS3_DEV /* UART0=ttyS0;UART1=ttyS1;UART2=ttyS;No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART3
+# define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART1=ttyS1;UART3=ttys2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART0=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART2
+# define TTYS1_DEV g_uart2port /* UART0=ttyS0;UART2=ttyS1;No ttyS3 */
+# ifdef CONFIG_16550_UART3
+# define TTYS2_DEV g_uart3port /* UART0=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART0=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# else
+# ifdef CONFIG_16550_UART3
+# define TTYS1_DEV g_uart3port /* UART0=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */
+# else
+# undef TTYS1_DEV /* UART0=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS2_DEV /* No ttyS2 */
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# endif
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart1port /* UART1=console */
+# define TTYS0_DEV g_uart1port /* UART1=ttyS0 */
+# ifdef CONFIG_16550_UART
+# define TTYS1_DEV g_uart0port /* UART1=ttyS0;UART0=ttyS1 */
+# ifdef CONFIG_16550_UART2
+# define TTYS2_DEV g_uart2port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2 */
+# ifdef CONFIG_16550_UART3
+# define TTYS3_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS2;UART3=ttyS3 */
+# else
+# undef TTYS3_DEV /* UART1=ttyS0;UART0=ttyS1;UART2=ttyS;No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART3
+# define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART1=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART2
+# define TTYS1_DEV g_uart2port /* UART1=ttyS0;UART2=ttyS1 */
+# ifdef CONFIG_16550_UART3
+# define TTYS2_DEV g_uart3port /* UART1=ttyS0;UART2=ttyS1;UART3=ttyS2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART1=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# else
+# ifdef CONFIG_16550_UART3
+# define TTYS1_DEV g_uart3port /* UART1=ttyS0;UART3=ttyS1;No ttyS2;No ttyS3 */
+# else
+# undef TTYS1_DEV /* UART1=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS2_DEV /* No ttyS2 */
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# endif
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart2port /* UART2=console */
+# define TTYS0_DEV g_uart2port /* UART2=ttyS0 */
+# ifdef CONFIG_16550_UART
+# define TTYS1_DEV g_uart0port /* UART2=ttyS0;UART0=ttyS1 */
+# ifdef CONFIG_16550_UART1
+# define TTYS2_DEV g_uart1port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2 */
+# ifdef CONFIG_16550_UART3
+# define TTYS3_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS2;UART3=ttyS3 */
+# else
+# undef TTYS3_DEV /* UART2=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART3
+# define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART0=ttyS1;UART3=ttys2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART2=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART1
+# define TTYS1_DEV g_uart1port /* UART2=ttyS0;UART1=ttyS1 */
+# ifdef CONFIG_16550_UART3
+# define TTYS2_DEV g_uart3port /* UART2=ttyS0;UART1=ttyS1;UART3=ttyS2 */
+# else
+# undef TTYS2_DEV /* UART2=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# else
+# ifdef CONFIG_16550_UART3
+# define TTYS1_DEV g_uart3port /* UART2=ttyS0;UART3=ttyS1;No ttyS3 */
+# else
+# undef TTYS1_DEV /* UART2=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS2_DEV /* No ttyS2 */
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# endif
+#elif defined(CONFIG_UART3_SERIAL_CONSOLE)
+# define CONSOLE_DEV g_uart3port /* UART3=console */
+# define TTYS0_DEV g_uart3port /* UART3=ttyS0 */
+# ifdef CONFIG_16550_UART
+# define TTYS1_DEV g_uart0port /* UART3=ttyS0;UART0=ttyS1 */
+# ifdef CONFIG_16550_UART1
+# define TTYS2_DEV g_uart1port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2 */
+# ifdef CONFIG_16550_UART2
+# define TTYS3_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS2;UART2=ttyS3 */
+# else
+# undef TTYS3_DEV /* UART3=ttyS0;UART0=ttyS1;UART1=ttyS;No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART2
+# define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART0=ttyS1;UART2=ttys2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART3=ttyS0;UART0=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# else
+# ifdef CONFIG_16550_UART1
+# define TTYS1_DEV g_uart1port /* UART3=ttyS0;UART1=ttyS1 */
+# ifdef CONFIG_16550_UART2
+# define TTYS2_DEV g_uart2port /* UART3=ttyS0;UART1=ttyS1;UART2=ttyS2;No ttyS3 */
+# else
+# undef TTYS2_DEV /* UART3=ttyS0;UART1=ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS3_DEV /* No ttyS3 */
+# else
+# ifdef CONFIG_16550_UART2
+# define TTYS1_DEV g_uart2port /* UART3=ttyS0;UART2=ttyS1;No ttyS3;No ttyS3 */
+# undef TTYS3_DEV /* UART3=ttyS0;UART2=ttyS1;No ttyS2;No ttyS3 */
+# else
+# undef TTYS1_DEV /* UART3=ttyS0;No ttyS1;No ttyS2;No ttyS3 */
+# endif
+# undef TTYS2_DEV /* No ttyS2 */
+# undef TTYS3_DEV /* No ttyS3 */
+# endif
+# endif
+#endif
+
+/************************************************************************************
+ * Inline Functions
+ ************************************************************************************/
+
+/****************************************************************************
+ * Name: uart_serialin
+ ****************************************************************************/
+
+static inline uart_datawidth_t uart_serialin(struct uart_16550_s *priv, int offset)
+{
+ return uart_getreg(priv->uartbase, offset);
+}
+
+/****************************************************************************
+ * Name: uart_serialout
+ ****************************************************************************/
+
+static inline void uart_serialout(struct uart_16550_s *priv, int offset, uart_datawidth_t value)
+{
+ uart_putreg(priv->uartbase, offset, value);
+}
+
+/****************************************************************************
+ * Name: uart_disableuartint
+ ****************************************************************************/
+
+static inline void uart_disableuartint(struct uart_16550_s *priv, uart_datawidth_t *ier)
+{
+ if (ier)
+ {
+ *ier = priv->ier & UART_IER_ALLIE;
+ }
+
+ priv->ier &= ~UART_IER_ALLIE;
+ uart_serialout(priv, UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: uart_restoreuartint
+ ****************************************************************************/
+
+static inline void uart_restoreuartint(struct uart_16550_s *priv, uint32_t ier)
+{
+ priv->ier |= ier & UART_IER_ALLIE;
+ uart_serialout(priv, UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: uart_enablebreaks
+ ****************************************************************************/
+
+static inline void uart_enablebreaks(struct uart_16550_s *priv, bool enable)
+{
+ uint32_t lcr = uart_serialin(priv, UART_LCR_OFFSET);
+ if (enable)
+ {
+ lcr |= UART_LCR_BRK;
+ }
+ else
+ {
+ lcr &= ~UART_LCR_BRK;
+ }
+ uart_serialout(priv, UART_LCR_OFFSET, lcr);
+}
+
+/************************************************************************************
+ * Name: uart_divisor
+ *
+ * Descrption:
+ * Select a divider to produce the BAUD from the UART_CLK.
+ *
+ * BAUD = UART_CLK / (16 * DL), or
+ * DIV = UART_CLK / BAUD / 16
+ *
+ * Ignoring the fractional divider for now.
+ *
+ ************************************************************************************/
+
+static inline uint32_t uart_divisor(struct uart_16550_s *priv)
+{
+ return (priv->uartclk + (priv->baud << 3)) / (priv->baurd << 4);
+}
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uart_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 uart_setup(struct uart_dev_s *dev)
+{
+#ifndef CONFIG_16550_SUPRESS_CONFIG
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ uint16_t div;
+ uint32_t lcr;
+
+ /* Clear fifos */
+
+ uart_serialout(priv, UART_FCR_OFFSET, (UART_FCR_RXRST|UART_FCR_TXRST));
+
+ /* Set trigger */
+
+ uart_serialout(priv, UART_FCR_OFFSET, (UART_FCR_FIFOEN|UART_FCR_RXTRIGGER_8));
+
+ /* Set up the IER */
+
+ priv->ier = uart_serialin(priv, UART_IER_OFFSET);
+
+ /* Set up the LCR */
+
+ lcr = 0;
+ switch (priv->bits)
+ {
+ case 5 :
+ lcr |= UART_LCR_WLS_7BIT;
+ break;
+
+ case 6 :
+ lcr |= UART_LCR_WLS_7BIT;
+ break;
+
+ case 7 :
+ lcr |= UART_LCR_WLS_7BIT;
+ break;
+
+ default:
+ case 8 :
+ lcr |= UART_LCR_WLS_7BIT;
+ break;
+ }
+
+ if (priv->stopbits2)
+ {
+ lcr |= UART_LCR_STB;
+ }
+
+ if (priv->parity == 1)
+ {
+ lcr |= UART_LCR_PEN;
+ }
+ else if (priv->parity == 2)
+ {
+ lcr |= (UART_LCR_PEN|UART_LCR_EPS);
+ }
+
+ /* Enter DLAB=1 */
+
+ uart_serialout(priv, UART_LCR_OFFSET, (lcr | UART_LCR_DLAB));
+
+ /* Set the BAUD divisor */
+
+ div = uart_divisor(priv);
+ uart_serialout(priv, UART_DLM_OFFSET, div >> 8);
+ uart_serialout(priv, UART_DLL_OFFSET, div & 0xff);
+
+ /* Clear DLAB */
+
+ uart_serialout(priv, UART_LCR_OFFSET, lcr);
+
+ /* Configure the FIFOs */
+
+ uart_serialout(priv, UART_FCR_OFFSET,
+ (UART_FCR_RXTRIGGER_8|UART_FCR_TXRST|UART_FCR_RXRST|UART_FCR_FIFOEN));
+#endif
+ return OK;
+}
+
+/****************************************************************************
+ * Name: uart_shutdown
+ *
+ * Description:
+ * Disable the UART. This method is called when the serial
+ * port is closed
+ *
+ ****************************************************************************/
+
+static void uart_shutdown(struct uart_dev_s *dev)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ uart_disableuartint(priv, NULL);
+}
+
+/****************************************************************************
+ * Name: uart_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 uart_attach(struct uart_dev_s *dev)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ int ret;
+
+ /* Attach and enable the IRQ */
+
+ ret = irq_attach(priv->irq, uart_interrupt);
+#ifndef CONFIG_ARCH_NOINTC
+ if (ret == OK)
+ {
+ /* Enable the interrupt (RX and TX interrupts are still disabled
+ * in the UART
+ */
+
+ uart_enable_irq(priv->irq);
+ }
+endif
+ return ret;
+}
+
+/****************************************************************************
+ * Name: uart_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 uart_detach(struct uart_dev_s *dev)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+#ifndef CONFIG_ARCH_NOINTC
+ uart_disable_irq(priv->irq);
+#endif
+ irq_detach(priv->irq);
+}
+
+/****************************************************************************
+ * Name: uart_interrupt
+ *
+ * Description:
+ * This is the UART 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
+ * appropriate uart_16550_s structure in order to call these functions.
+ *
+ ****************************************************************************/
+
+static int uart_interrupt(int irq, void *context)
+{
+ struct uart_dev_s *dev = NULL;
+ struct uart_16550_s *priv;
+ uint32_t status;
+ int passes;
+
+#ifdef CONFIG_16550_UART0
+ if (g_uart0priv.irq == irq)
+ {
+ dev = &g_uart0port;
+ }
+ else
+#endif
+#ifdef CONFIG_16550_UART1
+ if (g_uart1priv.irq == irq)
+ {
+ dev = &g_uart1port;
+ }
+ else
+#endif
+#ifdef CONFIG_16550_UART2
+ if (g_uart2priv.irq == irq)
+ {
+ dev = &g_uart2port;
+ }
+ else
+#endif
+#ifdef CONFIG_16550_UART3
+ if (g_uart3priv.irq == irq)
+ {
+ dev = &g_uart3port;
+ }
+ else
+#endif
+ {
+ PANIC(OSERR_INTERNAL);
+ }
+ priv = (struct uart_16550_s*)dev->priv;
+
+ /* Loop until there are no characters to be transferred or,
+ * until we have been looping for a long time.
+ */
+
+ for (passes = 0; passes < 256; passes++)
+ {
+ /* Get the current UART status and check for loop
+ * termination conditions
+ */
+
+ status = uart_serialin(priv, UART_IIR_OFFSET);
+
+ /* The UART_IIR_INTSTATUS bit should be zero if there are pending
+ * interrupts
+ */
+
+ if ((status & UART_IIR_INTSTATUS) != 0)
+ {
+ /* Break out of the loop when there is no longer a
+ * pending interrupt
+ */
+
+ break;
+ }
+
+ /* Handle the interrupt by its interrupt ID field */
+
+ switch (status & UART_IIR_INTID_MASK)
+ {
+ /* Handle incoming, receive bytes (with or without timeout) */
+
+ case UART_IIR_INTID_RDA:
+ case UART_IIR_INTID_CTI:
+ {
+ uart_recvchars(dev);
+ break;
+ }
+
+ /* Handle outgoing, transmit bytes */
+
+ case UART_IIR_INTID_THRE:
+ {
+ uart_xmitchars(dev);
+ break;
+ }
+
+ /* Just clear modem status interrupts (UART1 only) */
+
+ case UART_IIR_INTID_MSI:
+ {
+ /* Read the modem status register (MSR) to clear */
+
+ status = uart_serialin(priv, UART_MSR_OFFSET);
+ vdbg("MSR: %02x\n", status);
+ break;
+ }
+
+ /* Just clear any line status interrupts */
+
+ case UART_IIR_INTID_RLS:
+ {
+ /* Read the line status register (LSR) to clear */
+
+ status = uart_serialin(priv, UART_LSR_OFFSET);
+ vdbg("LSR: %02x\n", status);
+ break;
+ }
+
+ /* There should be no other values */
+
+ default:
+ {
+ dbg("Unexpected IIR: %02x\n", status);
+ break;
+ }
+ }
+ }
+ return OK;
+}
+
+/****************************************************************************
+ * Name: uart_ioctl
+ *
+ * Description:
+ * All ioctl calls will be routed through this method
+ *
+ ****************************************************************************/
+
+static int uart_ioctl(struct file *filep, int cmd, unsigned long arg)
+{
+ struct inode *inode = filep->f_inode;
+ struct uart_dev_s *dev = inode->i_private;
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ int ret = OK;
+
+ switch (cmd)
+ {
+ case TIOCSERGSTRUCT:
+ {
+ struct uart_16550_s *user = (struct uart_16550_s*)arg;
+ if (!user)
+ {
+ *get_errno_ptr() = EINVAL;
+ ret = ERROR;
+ }
+ else
+ {
+ memcpy(user, dev, sizeof(struct uart_16550_s));
+ }
+ }
+ break;
+
+ case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
+ {
+ irqstate_t flags = irqsave();
+ uart_enablebreaks(priv, true);
+ irqrestore(flags);
+ }
+ break;
+
+ case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
+ {
+ irqstate_t flags;
+ flags = irqsave();
+ uart_enablebreaks(priv, false);
+ irqrestore(flags);
+ }
+ break;
+
+ default:
+ *get_errno_ptr() = ENOTTY;
+ ret = ERROR;
+ break;
+ }
+
+ return ret;
+}
+
+/****************************************************************************
+ * Name: uart_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 uart_receive(struct uart_dev_s *dev, uint32_t *status)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ uint32_t rbr;
+
+ *status = uart_serialin(priv, UART_LSR_OFFSET);
+ rbr = uart_serialin(priv, UART_RBR_OFFSET);
+ return rbr;
+}
+
+/****************************************************************************
+ * Name: uart_rxint
+ *
+ * Description:
+ * Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+static void uart_rxint(struct uart_dev_s *dev, bool enable)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ if (enable)
+ {
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ priv->ier |= UART_IER_ERBFI;
+#endif
+ }
+ else
+ {
+ priv->ier &= ~UART_IER_ERBFI;
+ }
+ uart_serialout(priv, UART_IER_OFFSET, priv->ier);
+}
+
+/****************************************************************************
+ * Name: uart_rxavailable
+ *
+ * Description:
+ * Return true if the receive fifo is not empty
+ *
+ ****************************************************************************/
+
+static bool uart_rxavailable(struct uart_dev_s *dev)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ return ((uart_serialin(priv, UART_LSR_OFFSET) & UART_LSR_RDR) != 0);
+}
+
+/****************************************************************************
+ * Name: uart_send
+ *
+ * Description:
+ * This method will send one byte on the UART
+ *
+ ****************************************************************************/
+
+static void uart_send(struct uart_dev_s *dev, int ch)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ uart_serialout(priv, UART_THR_OFFSET, (uint32_t)ch);
+}
+
+/****************************************************************************
+ * Name: uart_txint
+ *
+ * Description:
+ * Call to enable or disable TX interrupts
+ *
+ ****************************************************************************/
+
+static void uart_txint(struct uart_dev_s *dev, bool enable)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ irqstate_t flags;
+
+ flags = irqsave();
+ if (enable)
+ {
+#ifndef CONFIG_SUPPRESS_SERIAL_INTS
+ priv->ier |= UART_IER_ETBEI;
+ uart_serialout(priv, UART_IER_OFFSET, priv->ier);
+
+ /* Fake a TX interrupt here by just calling uart_xmitchars() with
+ * interrupts disabled (note this may recurse).
+ */
+
+ uart_xmitchars(dev);
+#endif
+ }
+ else
+ {
+ priv->ier &= ~UART_IER_ETBEI;
+ uart_serialout(priv, UART_IER_OFFSET, priv->ier);
+ }
+ irqrestore(flags);
+}
+
+/****************************************************************************
+ * Name: uart_txready
+ *
+ * Description:
+ * Return true if the tranmsit fifo is not full
+ *
+ ****************************************************************************/
+
+static bool uart_txready(struct uart_dev_s *dev)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ return ((uart_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0);
+}
+
+/****************************************************************************
+ * Name: uart_txempty
+ *
+ * Description:
+ * Return true if the transmit fifo is empty
+ *
+ ****************************************************************************/
+
+static bool uart_txempty(struct uart_dev_s *dev)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)dev->priv;
+ return ((uart_serialin(priv, UART_LSR_OFFSET) & UART_LSR_THRE) != 0);
+}
+
+/****************************************************************************
+ * Public Funtions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: uart_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 uart_serialinit.
+ *
+ * NOTE: Configuration of the CONSOLE UART was performed by uart_lowsetup()
+ * very early in the boot sequence.
+ *
+ ****************************************************************************/
+
+void uart_earlyserialinit(void)
+{
+ /* Configure all UARTs (except the CONSOLE UART) and disable interrupts */
+
+#ifdef CONFIG_16550_UART0
+ uart_disableuartint(&g_uart0priv, NULL);
+#endif
+#ifdef CONFIG_16550_UART1
+ uart_disableuartint(&g_uart1priv, NULL);
+#endif
+ uart_disableuartint(&g_uart2priv, NULL);
+#endif
+ uart_disableuartint(&g_uart3priv, NULL);
+#endif
+
+ /* Configuration whichever one is the console */
+
+#ifdef CONSOLE_DEV
+ CONSOLE_DEV.isconsole = true;
+ uart_setup(&CONSOLE_DEV);
+#endif
+}
+
+/****************************************************************************
+ * Name: uart_serialinit
+ *
+ * Description:
+ * Register serial console and serial ports. This assumes that
+ * uart_earlyserialinit was called previously.
+ *
+ ****************************************************************************/
+
+void uart_serialinit(void)
+{
+#ifdef CONSOLE_DEV
+ (void)uart_register("/dev/console", &CONSOLE_DEV);
+#endif
+#ifdef TTYS0_DEV
+ (void)uart_register("/dev/ttyS0", &TTYS0_DEV);
+#endif
+#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
+}
+
+/****************************************************************************
+ * Name: uart_putc
+ *
+ * Description:
+ * Provide priority, low-level access to support OS debug writes
+ *
+ ****************************************************************************/
+
+#ifdef HAVE_16550_CONSOLE
+int uart_putc(int ch)
+{
+ struct uart_16550_s *priv = (struct uart_16550_s*)CONSOLE_DEV.priv;
+ uart_datawidth_t ier;
+
+ uart_disableuartint(priv, &ier);
+
+ /* Check for LF */
+
+ if (ch == '\n')
+ {
+ /* Add CR */
+
+ uart_lowputc('\r');
+ }
+
+ uart_lowputc(ch);
+ uart_restoreuartint(priv, ier);
+ return ch;
+}
+#endif
+
+#endif /* CONFIG_UART_16550 */
diff --git a/nuttx/include/nuttx/ioctl.h b/nuttx/include/nuttx/ioctl.h
index c3b83cf04..5eaf886c8 100644
--- a/nuttx/include/nuttx/ioctl.h
+++ b/nuttx/include/nuttx/ioctl.h
@@ -52,13 +52,13 @@
*/
#define _TIOCBASE (0x5400) /* Terminal I/O ioctl commands */
-#define _WDIOCBASE (0x5400) /* Watchdog driver ioctl commands */
+#define _WDIOCBASE (0x5500) /* Watchdog driver ioctl commands */
#define _FIOCBASE (0x8700) /* File system ioctl commands */
#define _DIOCBASE (0x8800) /* Character driver ioctl commands */
#define _BIOCBASE (0x8900) /* Block driver ioctl commands */
#define _MTDIOCBASE (0x8a00) /* MTD ioctl commands */
-#define _SIOCBASE (0x8b00) /* Socket ioctl commandss */
-#define _ARPBASE (0x8c00) /* ARP ioctl commandss */
+#define _SIOCBASE (0x8b00) /* Socket ioctl commands */
+#define _ARPBASE (0x8c00) /* ARP ioctl commands */
/* Macros used to manage ioctl commands */
diff --git a/nuttx/include/nuttx/uart_16550.h b/nuttx/include/nuttx/uart_16550.h
new file mode 100755
index 000000000..cdad637e0
--- /dev/null
+++ b/nuttx/include/nuttx/uart_16550.h
@@ -0,0 +1,351 @@
+/************************************************************************************
+ * include/nuttx/uart_16550.h
+ * Serial driver for 16550 UART
+ *
+ * Copyright (C) 2011 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.
+ *
+ ************************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_UART_16550_H
+#define __INCLUDE_NUTTX_UART_16550_H
+
+/************************************************************************************
+ * Included Files
+ ************************************************************************************/
+
+#include <nuttx/config.h>
+
+#ifdef CONFIG_UART_16550
+
+/************************************************************************************
+ * Pre-processor Definitions
+ ************************************************************************************/
+
+/* CONFIGURATION ********************************************************************/
+
+/* Are any UARTs enabled? */
+
+#undef HAVE_UART
+#if defined(CONFIG_16550_UART0) || defined(CONFIG_16550_UART1) || \
+ defined(CONFIG_16550_UART2) || defined(CONFIG_16550_UART3)
+# define HAVE_UART 1
+#endif
+
+/* We need to be told the address increment between registers and the register bit
+ * width.
+ */
+
+#ifndef CONFIG_16550_REGINCR
+# error "CONFIG_16550_REGINCR not defined"
+#endif
+
+#if CONFIG_16550_REGINCR != 1 && CONFIG_16550_REGINCR != 2 && CONFIG_16550_REGINCR != 4
+# error "CONFIG_16550_REGINCR not supported"
+#endif
+
+#ifndef CONFIG_16550_REGWIDTH
+# error "CONFIG_16550_REGWIDTH not defined"
+#endif
+
+#if CONFIG_16550_REGWIDTH != 1 && CONFIG_16550_REGWIDTH != 2 && CONFIG_16550_REGWIDTH != 4
+# error "CONFIG_16550_REGWIDTH not supported"
+#endif
+
+#ifndef CONFIG_16550_ADDRWIDTH
+# error "CONFIG_16550_ADDRWIDTH not defined"
+#endif
+
+#if CONFIG_16550_ADDRWIDTH != 1 && CONFIG_16550_ADDRWIDTH != 2 && CONFIG_16550_ADDRWIDTH != 4
+# error "CONFIG_16550_ADDRWIDTH not supported"
+#endif
+
+/* If a UART is enabled, then its base address, clock, and IRQ must also be provided */
+
+#ifdef CONFIG_16550_UART0
+# ifndef CONFIG_16550_UART0_BASE
+# error "CONFIG_16550_UART0_BASE not provided"
+# undef CONFIG_16550_UART0
+# endif
+# ifndef CONFIG_16550_UART0_CLOCK
+# error "CONFIG_16550_UART0_CLOCK not provided"
+# undef CONFIG_16550_UART0
+# endif
+# ifndef CONFIG_16550_UART0_IRQ
+# error "CONFIG_16550_UART0_IRQ not provided"
+# undef CONFIG_16550_UART0
+# endif
+#endif
+
+#ifdef CONFIG_16550_UART1
+# ifndef CONFIG_16550_UART1_BASE
+# error "CONFIG_16550_UART1_BASE not provided"
+# undef CONFIG_16550_UART1
+# endif
+# ifndef CONFIG_16550_UART1_CLOCK
+# error "CONFIG_16550_UART1_CLOCK not provided"
+# undef CONFIG_16550_UART1
+# endif
+# ifndef CONFIG_16550_UART1_IRQ
+# error "CONFIG_16550_UART1_IRQ not provided"
+# undef CONFIG_16550_UART1
+# endif
+#endif
+
+#ifdef CONFIG_16550_UART2
+# ifndef CONFIG_16550_UART2_BASE
+# error "CONFIG_16550_UART2_BASE not provided"
+# undef CONFIG_16550_UART2
+# endif
+# ifndef CONFIG_16550_UART2_CLOCK
+# error "CONFIG_16550_UART2_CLOCK not provided"
+# undef CONFIG_16550_UART2
+# endif
+# ifndef CONFIG_16550_UART2_IRQ
+# error "CONFIG_16550_UART2_IRQ not provided"
+# undef CONFIG_16550_UART2
+# endif
+#endif
+
+#ifdef CONFIG_16550_UART3
+# ifndef CONFIG_16550_UART3_BASE
+# error "CONFIG_16550_UART3_BASE not provided"
+# undef CONFIG_16550_UART3
+# endif
+# ifndef CONFIG_16550_UART3_CLOCK
+# error "CONFIG_16550_UART3_CLOCK not provided"
+# undef CONFIG_16550_UART3
+# endif
+# ifndef CONFIG_16550_UART3_IRQ
+# error "CONFIG_16550_UART3_IRQ not provided"
+# undef CONFIG_16550_UART3
+# endif
+#endif
+
+/* Is there a serial console? There should be at most one defined. It could be on
+ * any UARTn, n=0,1,2,3
+ */
+
+#if defined(CONFIG_UART0_SERIAL_CONSOLE) && defined(CONFIG_16550_UART0)
+# undef CONFIG_UART1_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+# undef CONFIG_UART3_SERIAL_CONSOLE
+# define HAVE_16550_CONSOLE 1
+#elif defined(CONFIG_UART1_SERIAL_CONSOLE) && defined(CONFIG_16550_UART1)
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+# undef CONFIG_UART3_SERIAL_CONSOLE
+# define HAVE_16550_CONSOLE 1
+#elif defined(CONFIG_UART2_SERIAL_CONSOLE) && defined(CONFIG_16550_UART2)
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART1_SERIAL_CONSOLE
+# undef CONFIG_UART3_SERIAL_CONSOLE
+# define HAVE_16550_CONSOLE 1
+#elif defined(CONFIG_UART3_SERIAL_CONSOLE) && defined(CONFIG_16550_UART3)
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART1_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+# define HAVE_16550_CONSOLE 1
+#else
+# undef CONFIG_UART0_SERIAL_CONSOLE
+# undef CONFIG_UART1_SERIAL_CONSOLE
+# undef CONFIG_UART2_SERIAL_CONSOLE
+# undef CONFIG_UART3_SERIAL_CONSOLE
+# undef HAVE_16550_CONSOLE
+#endif
+
+/* Register offsets *****************************************************************/
+
+#define UART_RBR_INCR 0 /* (DLAB =0) Receiver Buffer Register */
+#define UART_THR_INCR 0 /* (DLAB =0) Transmit Holding Register */
+#define UART_DLL_INCR 0 /* (DLAB =1) Divisor Latch LSB */
+#define UART_DLM_INCR 1 /* (DLAB =1) Divisor Latch MSB */
+#define UART_IER_INCR 1 /* (DLAB =0) Interrupt Enable Register */
+#define UART_IIR_INCR 2 /* Interrupt ID Register */
+#define UART_FCR_INCR 2 /* FIFO Control Register */
+#define UART_LCR_INCR 3 /* Line Control Register */
+#define UART_MCR_INCR 4 /* Modem Control Register */
+#define UART_LSR_INCR 5 /* Line Status Register */
+#define UART_MSR_INCR 6 /* Modem Status Register */
+#define UART_SCR_INCR 7 /* Scratch Pad Register */
+
+#define UART_RBR_OFFSET (CONFIG_16550_REGINCR*UART_RBR_INCR)
+#define UART_THR_OFFSET (CONFIG_16550_REGINCR*UART_THR_INCR)
+#define UART_DLL_OFFSET (CONFIG_16550_REGINCR*UART_DLL_INCR)
+#define UART_DLM_OFFSET (CONFIG_16550_REGINCR*UART_DLM_INCR)
+#define UART_IER_OFFSET (CONFIG_16550_REGINCR*UART_IER_INCR)
+#define UART_IIR_OFFSET (CONFIG_16550_REGINCR*UART_IIR_INCR)
+#define UART_FCR_OFFSET (CONFIG_16550_REGINCR*UART_FCR_INCR)
+#define UART_LCR_OFFSET (CONFIG_16550_REGINCR*UART_LCR_INCR)
+#define UART_MCR_OFFSET (CONFIG_16550_REGINCR*UART_MCR_INCR)
+#define UART_LSR_OFFSET (CONFIG_16550_REGINCR*UART_LSR_INCR)
+#define UART_MSR_OFFSET (CONFIG_16550_REGINCR*UART_MSR_INCR)
+#define UART_SCR_OFFSET (CONFIG_16550_REGINCR*UART_SCR_INCR)
+
+/* Register bit definitions *********************************************************/
+
+/* RBR (DLAB =0) Receiver Buffer Register */
+
+#define UART_RBR_MASK (0xff) /* Bits 0-7: Oldest received byte in RX FIFO */
+ /* Bits 8-31: Reserved */
+
+/* THR (DLAB =0) Transmit Holding Register */
+
+#define UART_THR_MASK (0xff) /* Bits 0-7: Adds byte to TX FIFO */
+ /* Bits 8-31: Reserved */
+
+/* DLL (DLAB =1) Divisor Latch LSB */
+
+#define UART_DLL_MASK (0xff) /* Bits 0-7: DLL */
+ /* Bits 8-31: Reserved */
+
+/* DLM (DLAB =1) Divisor Latch MSB */
+
+#define UART_DLM_MASK (0xff) /* Bits 0-7: DLM */
+ /* Bits 8-31: Reserved */
+
+/* IER (DLAB =0) Interrupt Enable Register */
+
+#define UART_IER_ERBFI (1 << 0) /* Bit 0: Enable received data available interrupt */
+#define UART_IER_ETBEI (1 << 1) /* Bit 1: Enable THR empty interrupt */
+#define UART_IER_ELSI (1 << 2) /* Bit 2: Enable receiver line status interrupt */
+#define UART_IER_EDSSI (1 << 3) /* Bit 3: Enable MODEM status interrupt */
+ /* Bits 4-7: Reserved */
+#define UART_IER_ALLIE (0x0f)
+
+/* IIR Interrupt ID Register */
+
+#define UART_IIR_INTSTATUS (1 << 0) /* Bit 0: Interrupt status (active low) */
+#define UART_IIR_INTID_SHIFT (1) /* Bits 1-3: Interrupt identification */
+#define UART_IIR_INTID_MASK (7 << UART_IIR_INTID_SHIFT)
+# define UART_IIR_INTID_MSI (0 << UART_IIR_INTID_SHIFT) /* Modem Status */
+# define UART_IIR_INTID_THRE (1 << UART_IIR_INTID_SHIFT) /* THR Empty Interrupt */
+# define UART_IIR_INTID_RDA (2 << UART_IIR_INTID_SHIFT) /* Receive Data Available (RDA) */
+# define UART_IIR_INTID_RLS (3 << UART_IIR_INTID_SHIFT) /* Receiver Line Status (RLS) */
+# define UART_IIR_INTID_CTI (6 << UART_IIR_INTID_SHIFT) /* Character Time-out Indicator (CTI) */
+ /* Bits 4-5: Reserved */
+#define UART_IIR_FIFOEN_SHIFT (6) /* Bits 6-7: RCVR FIFO interrupt */
+#define UART_IIR_FIFOEN_MASK (3 << UART_IIR_FIFOEN_SHIFT)
+
+/* FCR FIFO Control Register */
+
+#define UART_FCR_FIFOEN (1 << 0) /* Bit 0: Enable FIFOs */
+#define UART_FCR_RXRST (1 << 1) /* Bit 1: RX FIFO Reset */
+#define UART_FCR_TXRST (1 << 2) /* Bit 2: TX FIFO Reset */
+#define UART_FCR_DMAMODE (1 << 3) /* Bit 3: DMA Mode Select */
+ /* Bits 4-5: Reserved */
+#define UART_FCR_RXTRIGGER_SHIFT (6) /* Bits 6-7: RX Trigger Level */
+#define UART_FCR_RXTRIGGER_MASK (3 << UART_FCR_RXTRIGGER_SHIFT)
+# define UART_FCR_RXTRIGGER_1 (0 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 0 (1 character) */
+# define UART_FCR_RXTRIGGER_4 (1 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 1 (4 characters) */
+# define UART_FCR_RXTRIGGER_8 (2 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 2 (8 characters) */
+# define UART_FCR_RXTRIGGER_14 (3 << UART_FCR_RXTRIGGER_SHIFT) /* Trigger level 3 (14 characters) */
+
+/* LCR Line Control Register */
+
+#define UART_LCR_WLS_SHIFT (0) /* Bit 0-1: Word Length Select */
+#define UART_LCR_WLS_MASK (3 << UART_LCR_WLS_SHIFT)
+# define UART_LCR_WLS_5BIT (0 << UART_LCR_WLS_SHIFT)
+# define UART_LCR_WLS_6BIT (1 << UART_LCR_WLS_SHIFT)
+# define UART_LCR_WLS_7BIT (2 << UART_LCR_WLS_SHIFT)
+# define UART_LCR_WLS_8BIT (3 << UART_LCR_WLS_SHIFT)
+#define UART_LCR_STB (1 << 2) /* Bit 2: Number of Stop Bits */
+#define UART_LCR_PEN (1 << 3) /* Bit 3: Parity Enable */
+#define UART_LCR_EPS (1 << 4) /* Bit 4: Even Parity Select */
+#define UART_LCR_STICKY (1 << 5) /* Bit 5: Stick Parity */
+#define UART_LCR_BRK (1 << 6) /* Bit 6: Break Control */
+#define UART_LCR_DLAB (1 << 7) /* Bit 7: Divisor Latch Access Bit (DLAB) */
+
+/* MCR Modem Control Register */
+
+#define UART_MCR_DTR (1 << 0) /* Bit 0: DTR Control Source for DTR output */
+#define UART_MCR_RTS (1 << 1) /* Bit 1: Control Source for RTS output */
+#define UART_MCR_OUT1 (1 << 2) /* Bit 2: Auxiliary user-defined output 1 */
+#define UART_MCR_OUT2 (1 << 3) /* Bit 3: Auxiliary user-defined output 2 */
+#define UART_MCR_LPBK (1 << 4) /* Bit 4: Loopback Mode Select */
+ /* Bit 5-7: Reserved */
+
+/* LSR Line Status Register */
+
+#define UART_LSR_DR (1 << 0) /* Bit 0: Data Ready */
+#define UART_LSR_OE (1 << 1) /* Bit 1: Overrun Error */
+#define UART_LSR_PE (1 << 2) /* Bit 2: Parity Error */
+#define UART_LSR_FE (1 << 3) /* Bit 3: Framing Error */
+#define UART_LSR_BI (1 << 4) /* Bit 4: Break Interrupt */
+#define UART_LSR_THRE (1 << 5) /* Bit 5: Transmitter Holding Register Empty */
+#define UART_LSR_TEMT (1 << 6) /* Bit 6: Transmitter Empty */
+#define UART_LSR_RXFE (1 << 7) /* Bit 7: Error in RX FIFO (RXFE) */
+
+/* SCR Scratch Pad Register */
+
+#define UART_SCR_MASK (0xff) /* Bits 0-7: SCR data */
+
+/************************************************************************************
+ * Public Types
+ ************************************************************************************/
+
+#if CONFIG_16550_REGWIDTH == 1
+typedef uint8_t uart_datawidth_t;
+#elif CONFIG_16550_REGWIDTH == 2
+typedef uint16_t uart_datawidth_t;
+#elif CONFIG_16550_REGWIDTH == 4
+typedef uint32_t uart_datawidth_t;
+#endif
+
+#if CONFIG_16550_REGWIDTH == 1
+typedef uint8_t uart_addrwidth_t;
+#elif CONFIG_16550_REGWIDTH == 2
+typedef uint16_t uart_addrwidth_t;
+#elif CONFIG_16550_REGWIDTH == 4
+typedef uint32_t uart_addrwidth_t;
+#endif
+
+/************************************************************************************
+ * Public Data
+ ************************************************************************************/
+
+/************************************************************************************
+ * Public Functions
+ ************************************************************************************/
+
+/************************************************************************************
+ * Name: uart_getreg(), uart_putreg()
+ *
+ * Description:
+ * These functions must be provided by the processor-specific code in order to
+ * correctly access 16550 registers
+ *
+ ************************************************************************************/
+
+extern uart_datawidth_t uart_getreg(uart_addrwidth_t base, unsigned int offset);
+extern void uart_putreg(uart_addrwidth_t base, unsigned int offset, uart_datawidth_t value);
+
+#endif /* CONFIG_UART_16550 */
+#endif /* __INCLUDE_NUTTX_UART_16550_H */