Pārlūkot izejas kodu

update lpc2478 bsp

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@10 bbd45198-f89e-11dd-88c7-29a3b14d5316
bernard.xiong 16 gadi atpakaļ
vecāks
revīzija
53919ba500
4 mainītis faili ar 354 papildinājumiem un 153 dzēšanām
  1. 0 38
      bsp/lpc2478/board.c
  2. 3 0
      bsp/lpc2478/board.h
  3. 4 6
      bsp/lpc2478/rtconfig.h
  4. 347 109
      libcpu/arm/lpc24xx/serial.c

+ 0 - 38
bsp/lpc2478/board.c

@@ -58,44 +58,6 @@ void rt_hw_board_init()
 	T0TCR = 0x01; //enable timer0 counter
 }
 
-#ifdef RT_USING_FINSH
-extern void finsh_notify(void);
-void rt_serial_isr(int vector)
-{
-	rt_uint32_t iir;
-
-	if (U0LSR & 0x01)
-	{
-		rt_uint8_t ch;
-		
-		while (U0LSR & 0x01)
-		{
-			ch = U0RBR;
-			rt_serial_savechar(ch);
-		}
-
-		/* notify finsh shell thread */
-		finsh_notify();
-	}
-
-	/* clear interrupt source */
-	iir = U0IIR;
-
-	/* acknowledge Interrupt */
-	VICVectAddr = 0;
-}
-
-void rt_hw_finsh_init()
-{
-	/* init UART rx interrupt */
-	U0IER = 0x01;
-
-	/* install UART isr */
-	rt_hw_interrupt_install(UART0_INT, rt_serial_isr, RT_NULL);
-	rt_hw_interrupt_umask(UART0_INT);
-}
-#endif
-
 /******************************************************************************
 ** Function name:		TargetInit
 **

+ 3 - 0
bsp/lpc2478/board.h

@@ -98,6 +98,9 @@ void rt_hw_finsh_init(void);
 
 #define VECT_ADDR_INDEX	0x100
 #define VECT_CNTL_INDEX 0x200
+
+#define CCLK	60000000	/* Fosc = 12MHz, M = 5 */
+#define PCLK	15000000	/* CCLK/4, use default */
 
 /******************************************************************************
 ** Function name:		TargetInit

+ 4 - 6
bsp/lpc2478/rtconfig.h

@@ -9,7 +9,7 @@
 #define RT_ALIGN_SIZE	4
 
 /* PRIORITY_MAX*/
-#define RT_THREAD_PRIORITY_MAX	32
+#define RT_THREAD_PRIORITY_MAX	256
 
 /* Tick per Second*/
 #define RT_TICK_PER_SECOND	100
@@ -55,7 +55,9 @@
 
 /* SECTION: Device System */
 /* Using Device System*/
-/* #define RT_USING_DEVICE */
+#define RT_USING_DEVICE
+#define RT_USING_UART1
+#define RT_UART_RX_BUFFER_SIZE	64
 
 /* SECTION: Console options */
 /* the buffer size of console*/
@@ -68,10 +70,6 @@
 #define FINSH_USING_SYMTAB
 #define FINSH_USING_DESCRIPTION
 
-/* SECTION: emulator options */
-/* Using QEMU or SkyEye*/
-/* #define RT_USING_EMULATOR */
-
 /* SECTION: a mini libc */
 /* Using mini libc library*/
 /* #define RT_USING_MINILIBC */

+ 347 - 109
libcpu/arm/lpc24xx/serial.c

@@ -1,149 +1,387 @@
-/*
- * File      : serial.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://openlab.rt-thread.com/license/LICENSE
- *
- * Change Logs:
- * Date           Author       Notes
- * 2006-08-23     Bernard      first version
- */
-
-#include <rthw.h>
+/*
+ * File      : serial.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://openlab.rt-thread.com/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2006-08-23     Bernard      first version
+ */
+
+#include <rthw.h>
 #include <rtthread.h>
+
 #include "lpc214x.h"
 #include "board.h"
 
-void rt_serial_init(void);
+/* serial hardware register */
+#define REG8(d)			(*((volatile unsigned char *)(d)))
+#define REG32(d)		(*((volatile unsigned long *)(d)))
 
-#define PCLK		18000000
-#define BAUD_RATE	115200
-#define U0PINS  	0x00000005
+#define UART_RBR(base)  REG8(base + 0x00)
+#define UART_THR(base)  REG8(base + 0x00)
+#define UART_IER(base)  REG32(base + 0x04)
+#define UART_IIR(base)  REG32(base + 0x08)
+#define UART_FCR(base)  REG8(base + 0x08)
+#define UART_LCR(base)  REG8(base + 0x0C)
+#define UART_MCR(base)  REG8(base + 0x10)
+#define UART_LSR(base)  REG8(base + 0x14)
+#define UART_MSR(base)  REG8(base + 0x18)
+#define UART_SCR(base)  REG8(base + 0x1C)
+#define UART_DLL(base)  REG8(base + 0x00)
+#define UART_DLM(base)  REG8(base + 0x04)
+#define UART_ACR(base)  REG32(base + 0x20)
+#define UART_FDR(base)  REG32(base + 0x28)
+#define UART_TER(base)  REG8(base + 0x30)
 
-/**
- * @addtogroup LPC2100
- */
-/*@{*/
+/* LPC serial device */
+struct rt_lpcserial
+{
+	/* inherit from device */
+	struct rt_device parent;
+
+	rt_uint32_t hw_base;
+	rt_uint32_t irqno;
+	rt_uint32_t baudrate;
+
+	/* reception field */
+	rt_uint16_t save_index, read_index;
+	rt_uint8_t  rx_buffer[RT_UART_RX_BUFFER_SIZE];
+};
 
-/**
- * This function is used to display a string on console, normally, it's
- * invoked by rt_kprintf
- *
- * @param str the displayed string
- */
-void rt_console_puts(const char* str)
+#ifdef RT_USING_UART1
+struct rt_lpcserial serial1;
+#endif
+#ifdef RT_USING_UART2
+struct rt_lpcserial serial2;
+#endif
+
+void rt_hw_serial_init(void);
+
+#define U0PINS  	0x00000005
+
+void rt_hw_uart_isr(struct rt_lpcserial* lpc_serial)
 {
-	while (*str)
-	{
-		rt_serial_putc (*str++);
+	UNUSED rt_uint32_t iir;
+
+	RT_ASSERT(lpc_serial != RT_NULL)
+		
+	if (UART_LSR(lpc_serial->hw_base) & 0x01)
+	{
+		rt_base_t level;
+
+		while (UART_LSR(lpc_serial->hw_base) & 0x01)
+		{
+			/* disable interrupt */
+			level = rt_hw_interrupt_disable();
+
+			/* read character */
+			lpc_serial->rx_buffer[lpc_serial->save_index] = 
+				UART_RBR(lpc_serial->hw_base);
+			lpc_serial->save_index ++;
+			if (lpc_serial->save_index >= RT_UART_RX_BUFFER_SIZE)
+				lpc_serial->save_index = 0;
+			
+			/* if the next position is read index, discard this 'read char' */
+			if (lpc_serial->save_index == lpc_serial->read_index)
+			{
+				lpc_serial->read_index ++;
+				if (lpc_serial->read_index >= RT_UART_RX_BUFFER_SIZE)
+					lpc_serial->read_index = 0;
+			}
+
+			/* enable interrupt */
+			rt_hw_interrupt_enable(level);
+		}
+
+		/* invoke callback */
+		if(lpc_serial->parent.rx_indicate != RT_NULL)
+		{
+		  lpc_serial->parent.rx_indicate(&lpc_serial->parent, 1);
+		}
 	}
+
+	/* clear interrupt source */
+	iir = UART_IIR(lpc_serial->hw_base);
+
+	/* acknowledge Interrupt */
+	VICVectAddr = 0;
 }
 
-#define UART_RX_BUFFER_SIZE	64
-static rt_uint8_t  uart_rx_buffer[UART_RX_BUFFER_SIZE];
-static rt_uint32_t uart_read_index, uart_save_index;
+#ifdef RT_USING_UART1
+void rt_hw_uart_isr_1(int irqno)
+{
+	/* get lpc serial device */
+	rt_hw_uart_isr(&serial1);
+}	
+#endif
 
-/**
- * This function initializes serial
- */
-void rt_serial_init()
+#ifdef RT_USING_UART2
+void rt_hw_uart_isr_2(int irqno)
+{
+	/* get lpc serial device */
+	rt_hw_uart_isr(&serial2);
+}	
+#endif
+
+/**
+ * @addtogroup LPC214x
+ */
+/*@{*/
+
+static rt_err_t rt_serial_init (rt_device_t dev)
 {
-	unsigned long Fdiv;
+	return RT_EOK;
+}
+
+static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
+{
+	struct rt_lpcserial* lpc_serial;
+	lpc_serial = (struct rt_lpcserial*) dev;
+	
+	RT_ASSERT(lpc_serial != RT_NULL);
+	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
+	{
+	    /* init UART rx interrupt */
+    	UART_IER(lpc_serial->hw_base) = 0x01;
 
-	PINSEL0 = 0x00000050;       /* RxD0 and TxD0 */
+		/* install ISR */
+		if (lpc_serial->irqno == UART0_INT)
+		{
+#ifdef RT_USING_UART1
+		    rt_hw_interrupt_install(lpc_serial->irqno, rt_hw_uart_isr_1, RT_NULL);
+#endif
+		}
+		else
+		{
+#ifdef RT_USING_UART2
+		    rt_hw_interrupt_install(lpc_serial->irqno, rt_hw_uart_isr_2, RT_NULL);
+#endif
+		}
 
-	rt_memset(uart_rx_buffer, 0, sizeof(uart_rx_buffer));
-	uart_read_index = uart_save_index = 0;
+	    rt_hw_interrupt_umask(lpc_serial->irqno);
+	}
 
-	U0LCR = 0x83;		/* 8 bits, no Parity, 1 Stop bit */
-	/*PCLK select is 00,so /4*/
-	Fdiv = ( PCLK / 16 ) / BAUD_RATE ;	/*baud rate */
-	U0DLM = Fdiv / 256;							
-	U0DLL = Fdiv % 256;
-	U0FCR = 0x00;		/* Enable and reset TX and RX FIFO. */
-	U0LCR = 0x03;		/* DLAB = 0 */
+	return RT_EOK;
 }
 
-/* save a char to serial buffer */
-void rt_serial_savechar(char ch)
+static rt_err_t rt_serial_close(rt_device_t dev)
 {
-	rt_base_t level;
+	struct rt_lpcserial* lpc_serial;
+	lpc_serial = (struct rt_lpcserial*) dev;
 	
-	/* disable interrupt */
-	level = rt_hw_interrupt_disable();
+	RT_ASSERT(lpc_serial != RT_NULL);
 
-	uart_rx_buffer[uart_save_index] = ch;
-	uart_save_index ++;
-	if (uart_save_index >= UART_RX_BUFFER_SIZE)
-		uart_save_index = 0;
-	
-	/* if the next position is read index, discard this 'read char' */
-	if (uart_save_index == uart_read_index)
+	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
 	{
-		uart_read_index ++;
-		if (uart_read_index >= UART_RX_BUFFER_SIZE)
-			uart_read_index = 0;
+		/* disable UART rx interrupt */
+		UART_IER(lpc_serial->hw_base) = 0x00;
 	}
 
-	/* enable interrupt */
-	rt_hw_interrupt_enable(level);
+	return RT_EOK;
 }
 
-/**
- * This function read a character from serial without interrupt enable mode
- *
- * @return the read char
- */
-char rt_serial_getc()
+static rt_err_t rt_serial_control(rt_device_t dev, rt_uint8_t cmd, void *args)
 {
-	char ch;
-	rt_base_t level;
-	
-	/* disable interrupt */
-	level = rt_hw_interrupt_disable();
-	
-	if (uart_read_index != uart_save_index)
+	return RT_EOK;
+}
+
+static rt_size_t rt_serial_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
+{
+	rt_uint8_t* ptr;
+	struct rt_lpcserial *lpc_serial = (struct rt_lpcserial*)dev;
+	RT_ASSERT(lpc_serial != RT_NULL);
+
+	/* point to buffer */
+	ptr = (rt_uint8_t*) buffer;
+
+	if (dev->flag & RT_DEVICE_FLAG_INT_RX)
 	{
-		ch = uart_rx_buffer[uart_read_index];
+		while (size)
+		{
+			/* interrupt receive */
+			rt_base_t level;
 
-		uart_read_index ++;
-		if (uart_read_index >= UART_RX_BUFFER_SIZE)
-			uart_read_index = 0;
-		
-		/* enable interrupt */
-		rt_hw_interrupt_enable(level);
-		
-		return ch;
+			/* disable interrupt */
+			level = rt_hw_interrupt_disable();
+			if (lpc_serial->read_index != lpc_serial->save_index)
+			{
+				*ptr = lpc_serial->rx_buffer[lpc_serial->read_index];
+
+				lpc_serial->read_index ++;
+				if (lpc_serial->read_index >= RT_UART_RX_BUFFER_SIZE)
+					lpc_serial->read_index = 0;
+			}
+			else
+			{
+				/* no data in rx buffer */
+
+				/* enable interrupt */
+				rt_hw_interrupt_enable(level);
+				break;
+			}
+
+			/* enable interrupt */
+			rt_hw_interrupt_enable(level);
+
+			ptr ++; size --;
+		}
+
+		return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
+	}
+	else if (dev->flag & RT_DEVICE_FLAG_DMA_RX)
+	{
+		/* not support right now */
+		RT_ASSERT(0);
 	}
 
-	/* enable interrupt */
-	rt_hw_interrupt_enable(level);
+	/* polling mode */
+	while (size && (UART_LSR(lpc_serial->hw_base) & 0x01))
+	{
+		/* Read Character */
+		*ptr = UART_RBR(lpc_serial->hw_base);
+		
+		ptr  ++;
+		size --;
+	}
 
-	return 0;
+	return (rt_size_t)ptr - (rt_size_t)buffer;
 }
 
-/**
- * This function will write a character to serial without interrupt enable mode
- *
- * @param c the char to write
- */
-void rt_serial_putc(const char c)
+static rt_size_t rt_serial_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
 {
-	/*
-		to be polite with serial console add a line feed
-		to the carriage return character
-	*/
-	if (c=='\n')
+	struct rt_lpcserial* lpc_serial;
+	char *ptr;
+
+	lpc_serial = (struct rt_lpcserial*) dev;
+	if (dev->flag & RT_DEVICE_FLAG_INT_TX)
 	{
-		while (!(U0LSR & 0x20));
-		U0THR = '\r';
+		/* not support */
+		RT_ASSERT(0);
+	}
+	else if (dev->flag & RT_DEVICE_FLAG_DMA_TX)
+	{
+		/* not support */
+		RT_ASSERT(0);
 	}
 
-	while (!(U0LSR & 0x20));
-	U0THR = c;
+	/* polling write */
+	ptr = (char *)buffer;
+	
+	if (dev->flag & RT_DEVICE_FLAG_STREAM)
+	{
+		/* stream mode */
+		while (size)
+		{
+			if (*ptr == '\n')
+			{
+				while (!(UART_LSR(lpc_serial->hw_base) & 0x20));
+				UART_THR(lpc_serial->hw_base) = '\r';
+			}
+
+			while (!(UART_LSR(lpc_serial->hw_base) & 0x20));
+			UART_THR(lpc_serial->hw_base) = *ptr;
+			
+			ptr ++;
+			size --;
+		}
+	}
+	else
+	{
+		while (size)
+		{
+			while (!(UART_LSR(lpc_serial->hw_base) & 0x20));
+			UART_THR(lpc_serial->hw_base) = *ptr;
+			
+			ptr ++;
+			size --;
+		}
+	}
+	
+	return (rt_size_t) ptr - (rt_size_t) buffer;
 }
 
-/*@}*/
+void rt_hw_serial_init(void)
+{
+	struct rt_lpcserial* lpc_serial;
+	
+#ifdef RT_USING_UART1
+	lpc_serial = &serial1;
+	
+	lpc_serial->parent.type = RT_Device_Class_Char;
+	
+	lpc_serial->hw_base = 0xE000C000;
+	lpc_serial->baudrate = 115200;
+	lpc_serial->irqno = UART0_INT;
+	
+	rt_memset(lpc_serial->rx_buffer, 0, sizeof(lpc_serial->rx_buffer));
+	lpc_serial->read_index = lpc_serial->save_index = 0;
+
+	/* Enable UART0 RxD and TxD pins */
+  	PINSEL0 |= 0x05;
+
+	/* 8 bits, no Parity, 1 Stop bit */
+	UART_LCR(lpc_serial->hw_base) = 0x83;
+	
+	/* Setup Baudrate */
+	UART_DLL(lpc_serial->hw_base) = (PCLK/16/lpc_serial->baudrate) & 0xFF;
+	UART_DLM(lpc_serial->hw_base) = ((PCLK/16/lpc_serial->baudrate) >> 8) & 0xFF;
+
+	/* DLAB = 0 */
+	UART_LCR(lpc_serial->hw_base) = 0x03;
+
+	lpc_serial->parent.init 	= rt_serial_init;
+	lpc_serial->parent.open 	= rt_serial_open;
+	lpc_serial->parent.close    = rt_serial_close;
+	lpc_serial->parent.read 	= rt_serial_read;
+	lpc_serial->parent.write    = rt_serial_write;
+	lpc_serial->parent.control  = rt_serial_control;
+	lpc_serial->parent.private  = RT_NULL;
+
+	rt_device_register(&lpc_serial->parent, 
+		"uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
+#endif
+
+#ifdef RT_USING_UART2
+	lpc_serial = &serial2;
+	
+	lpc_serial->parent.type = RT_Device_Class_Char;
+
+	lpc_serial->hw_base = 0xE0010000;
+	lpc_serial->baudrate = 115200;
+	lpc_serial->irqno = UART1_INT;
+
+	rt_memset(lpc_serial->rx_buffer, 0, sizeof(lpc_serial->rx_buffer));
+	lpc_serial->read_index = lpc_serial->save_index = 0;
+
+	/* Enable UART1 RxD and TxD pins */
+  	PINSEL0 |= 0x05 << 16;
+
+	/* 8 bits, no Parity, 1 Stop bit */
+	UART_LCR(lpc_serial->hw_base) = 0x83;
+	
+	/* Setup Baudrate */
+	UART_DLL(lpc_serial->hw_base) = (PCLK/16/lpc_serial->baudrate) & 0xFF;
+	UART_DLM(lpc_serial->hw_base) = ((PCLK/16/lpc_serial->baudrate) >> 8) & 0xFF;
+
+	/* DLAB = 0 */
+	UART_LCR(lpc_serial->hw_base) = 0x03;
+
+	lpc_serial->parent.init 	= rt_serial_init;
+	lpc_serial->parent.open 	= rt_serial_open;
+	lpc_serial->parent.close    = rt_serial_close;
+	lpc_serial->parent.read 	= rt_serial_read;
+	lpc_serial->parent.write    = rt_serial_write;
+	lpc_serial->parent.control  = rt_serial_control;
+	lpc_serial->parent.private  = RT_NULL;
+
+	rt_device_register(&lpc_serial->parent, 
+		"uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
+#endif
+}
+
+/*@}*/