diff options
-rwxr-xr-x | nuttx/arch/arm/src/lpc17xx/lpc17_serial.c | 23 | ||||
-rwxr-xr-x | nuttx/arch/arm/src/lpc17xx/lpc17_uart.h | 2 | ||||
-rw-r--r-- | nuttx/arch/x86/src/i486/i486_utils.S | 66 | ||||
-rw-r--r-- | nuttx/arch/x86/src/qemu/qemu_fullcontextrestore.S | 75 | ||||
-rwxr-xr-x | nuttx/arch/x86/src/qemu/qemu_head.S | 108 | ||||
-rwxr-xr-x | nuttx/arch/x86/src/qemu/qemu_irq.c | 7 | ||||
-rw-r--r-- | nuttx/arch/x86/src/qemu/qemu_lowsetup.c | 5 | ||||
-rw-r--r-- | nuttx/arch/x86/src/qemu/qemu_saveusercontext.S | 38 | ||||
-rwxr-xr-x | nuttx/arch/x86/src/qemu/qemu_vectors.S | 240 | ||||
-rw-r--r-- | nuttx/configs/qemu-i486/ostest/defconfig | 6 | ||||
-rwxr-xr-x | nuttx/drivers/serial/uart_16550.c | 1092 | ||||
-rw-r--r-- | nuttx/include/nuttx/ioctl.h | 6 | ||||
-rwxr-xr-x | nuttx/include/nuttx/uart_16550.h | 351 |
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 */
|