/*
* console driver for RTL22xx UARTs
*
* If you want the driver to be interrupt driven, you
* need to write the ISR, and in the ISR insert the
* chars into termios's queue.
*/
/*
* Copyright (c) By ray <rayx.cn@gmail.com>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/
#include <bsp.h> /* Must be before libio.h */
#include <rtems/libio.h>
#include <termios.h>
#include <rtems/bspIo.h>
/* Put the CPU (or UART) specific header file #include here */
#include <lpc22xx.h>
#include "lpc22xx_uart.h"
#include <libchip/serial.h>
#include <libchip/sersupp.h>
/* How many serial ports? */
#define NUM_DEVS 1
int dbg_dly;
/* static function prototypes */
static int uart_first_open(int major, int minor, void *arg);
static int uart_last_close(int major, int minor, void *arg);
static int uart_read(int minor);
static ssize_t uart_write(int minor, const char *buf, size_t len);
static void uart_init(int minor);
static void uart_write_polled(int minor, char c);
static int uart_set_attributes(int minor, const struct termios *t);
/* These are used by code in console.c */
unsigned long Console_Configuration_Count = NUM_DEVS;
/* Pointers to functions for handling the UART. */
const console_fns uart_fns = {
libchip_serial_default_probe,
uart_first_open,
uart_last_close,
uart_read,
uart_write,
uart_init,
uart_write_polled, /* not used in this driver */
uart_set_attributes,
FALSE /* TRUE if interrupt driven, FALSE if not. */
};
/*
* There's one item in array for each UART.
*
* Some of these fields are marked "NOT USED". They are not used
* by console.c, but may be used by drivers in libchip
*/
console_tbl Console_Configuration_Ports[] = {
{
"/dev/com0", /* sDeviceName */
SERIAL_CUSTOM, /* deviceType */
&uart_fns, /* pDeviceFns */
NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
0, /* ulMargin - NOT USED */
0, /* ulHysteresis - NOT USED */
NULL, /* pDeviceParams */
0, /* ulCtrlPort1 - NOT USED */
0, /* ulCtrlPort2 - NOT USED */
0, /* ulDataPort - NOT USED */
NULL, /* getRegister - NOT USED */
NULL, /* setRegister - NOT USED */
NULL, /* getData - NOT USED */
NULL, /* setData - NOT USED */
0, /* ulClock - NOT USED */
0 /* ulIntVector - NOT USED */
}
#if 0
{
"/dev/com1", /* sDeviceName */
SERIAL_CUSTOM, /* deviceType */
&uart_fns, /* pDeviceFns */
NULL, /* deviceProbe */
NULL, /* pDeviceFlow */
0, /* ulMargin - NOT USED */
0, /* ulHysteresis - NOT USED */
NULL, /* pDeviceParams */
0, /* ulCtrlPort1 - NOT USED */
0, /* ulCtrlPort2 - NOT USED */
0, /* ulDataPort - NOT USED */
NULL, /* getRegister - NOT USED */
NULL, /* setRegister - NOT USED */
NULL, /* getData - NOT USED */
NULL, /* setData - NOT USED */
0, /* ulClock - NOT USED */
0 /* ulIntVector - NOT USED */
}
#endif
};
/*
* This is called the first time each device is opened. If the driver
* is interrupt driven, you should enable interrupts here. Otherwise,
* it's probably safe to do nothing.
*
* Since micromonitor already set up the UART, we do nothing.
*/
static int uart_first_open(int major, int minor, void *arg)
{
return 0;
}
/*
* This is called the last time each device is closed. If the driver
* is interrupt driven, you should disable interrupts here. Otherwise,
* it's probably safe to do nothing.
*/
static int uart_last_close(int major, int minor, void *arg)
{
return 0;
}
/*
* Read one character from UART.
*
* Return -1 if there's no data, otherwise return
* the character in lowest 8 bits of returned int.
*/
static int uart_read(int minor)
{
char c;
switch (minor) {
case 0:
if (U0LSR & ULSR_RDR) {
c = U0RBR;
return c;
}
return -1;
case 1:
if (U1LSR & ULSR_RDR) {
c = U1RBR;
return c;
}
return -1;
default:
break;
}
printk("Unknown console minor number %d\n", minor);
return -1;
}
/*
* Write buffer to UART
*
* return 1 on success, -1 on error
*/
static ssize_t uart_write(int minor, const char *buf, size_t len)
{
size_t i;
switch (minor) {
case 0:
for (i = 0; i < len; i++) {
while (!(U0LSR & ULSR_THRE)) /* wait for TX buffer to empty*/
continue; /* also either WDOG() or swap()*/
U0THR = (char) buf[i];
}
break;
case 1:
for (i = 0; i < len; i++) {
while (!(U0LSR & ULSR_THRE)) /* wait for TX buffer to empty*/
continue; /* also either WDOG() or swap()*/
U0THR = (char) buf[i];
}
break;
default:
printk("Unknown console minor number %d\n", minor);
return -1;
}
return len;
}
/* Set up the UART. */
static void uart_init(int minor)
{
#if 0 //init will be done in bspstart.c
int baud=6;
int mode =0x03;
if(minor==0){
// set port pins for UART0
PINSEL0 = (PINSEL0 & ~U0_PINMASK) | U0_PINSEL;
U0IER = 0x00; // disable all interrupts
// set the baudrate
U0LCR = 1<<7; // select divisor latches
U0DLL = (uint8_t)baud; // set for baud low byte
U0DLM = (uint8_t)(baud >> 8); // set for baud high byte
// set the number of characters and other
// user specified operating parameters
U0LCR = (mode & ~ULCR_DLAB_ENABLE);
U0FCR = mode>>8; /*fifo mode*/
// set port pins for UART1
PINSEL0 = (PINSEL0 & ~U1_PINMASK) | U1_PINSEL;
U1IER = 0x00; // disable all interrupts
}else if(minor==1){
// set the baudrate
U1LCR = ULCR_DLAB_ENABLE; // select divisor latches
U1DLL = (uint8_t)baud; // set for baud low byte
U1DLM = (uint8_t)(baud >> 8); // set for baud high byte
// set the number of characters and other
// user specified operating parameters
U1LCR = (mode & ~ULCR_DLAB_ENABLE);
U1FCR = mode>>8;/*fifo mode*/
}
#endif
}
/* I'm not sure this is needed for the shared console driver. */
static void uart_write_polled(int minor, char c)
{
uart_write(minor, &c, 1);
}
/* This is for setting baud rate, bits, etc. */
static int uart_set_attributes(int minor, const struct termios *t)
{
return 0;
}
/*
* Write a character to the console. This is used by printk() and
* maybe other low level functions. It should not use interrupts or any
* RTEMS system calls. It needs to be very simple
*/
static void _BSP_put_char( char c )
{
uart_write_polled(0, c);
if (c == '\n') {
uart_write_polled(0, '\r');
}
}
BSP_output_char_function_type BSP_output_char = _BSP_put_char;
static int _BSP_get_char(void)
{
return uart_read(0);
}
BSP_polling_getchar_function_type BSP_poll_char = _BSP_get_char;
/*
* init USART 0¡£8 bit, 1 Stop,No checkout, BPS115200
*/
void UART0_Ini(void)
{
long Fdiv;
int i;
PINSEL0 = 0x00000005; // I/O to UART0
U0LCR = 0x83; // DLAB = 1
Fdiv = (Fpclk >>4) / UART_BPS; // configure BPS
U0DLM = Fdiv/256;
U0DLL = Fdiv%256;
U0LCR = 0x03;
for(i=0;i<10;i++){
U0THR = 67; //send a C to see if is OK
while ( (U0LSR&0x40)==0 );
}
}