Still having problems with serial driver

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@10 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-02-20 12:52:27 +00:00
parent e3f52bbeb4
commit 808d6e3b33
4 changed files with 65 additions and 138 deletions

View file

@ -192,5 +192,5 @@ CONFIG_STACK_POINTER=
CONFIG_PROC_STACK_SIZE=4096 CONFIG_PROC_STACK_SIZE=4096
CONFIG_PTHREAD_STACK_MIN=256 CONFIG_PTHREAD_STACK_MIN=256
CONFIG_PTHREAD_STACK_DEFAULT=4096 CONFIG_PTHREAD_STACK_DEFAULT=4096
CONFIG_HEAP_BASE=(0x10300000+90*1024+4096) CONFIG_HEAP_BASE=(0x10300000+90*1024+CONFIG_PROC_STACK_SIZE)
CONFIG_HEAP_SIZE=(0x11000000-CONFIG_HEAP_BASE) CONFIG_HEAP_SIZE=(0x11000000-CONFIG_HEAP_BASE)

View file

@ -48,8 +48,7 @@
#define TIOCSBRK 0x5401 /* BSD compatibility */ #define TIOCSBRK 0x5401 /* BSD compatibility */
#define TIOCCBRK 0x5402 /* " " " " */ #define TIOCCBRK 0x5402 /* " " " " */
#define TIOCSERCONFIG 0x5403 /* Reconfigure the port */ #define TIOCSERGSTRUCT 0x5403 /* Get up_dev_t for port */
#define TIOCSERGSTRUCT 0x5458 /* Get up_dev_t for port */
/************************************************************ /************************************************************
* Private Data * Private Data

View file

@ -118,7 +118,12 @@ __start:
b os_start b os_start
/* Variables */ /* Variables:
* _sbss is the start of the BSS region (see ld.script)
* _ebss is the end of the BSS regsion (see ld.script)
* The idle task stack starts at the end of BSS and is
* of size CONFIG_PROC_STACK_SIZE
*/
LC0: .long _sbss LC0: .long _sbss
.long _ebss .long _ebss

View file

@ -88,7 +88,6 @@ struct up_dev_s
* registers */ * registers */
unsigned int baud_base; /* Base baud for conversions */ unsigned int baud_base; /* Base baud for conversions */
unsigned int baud; /* Configured baud */ unsigned int baud; /* Configured baud */
int quotient; /* Quotient for configured baud */
ubyte xmit_fifo_size; /* Size of transmit FIFO */ ubyte xmit_fifo_size; /* Size of transmit FIFO */
ubyte irq; /* IRQ associated with ubyte irq; /* IRQ associated with
* this UART */ * this UART */
@ -102,6 +101,7 @@ struct up_dev_s
* for space in xmit.buffer */ * for space in xmit.buffer */
boolean recvwaiting; /* TRUE: User is waiting boolean recvwaiting; /* TRUE: User is waiting
* for space in recv.buffer */ * for space in recv.buffer */
boolean isconsole; /* TRUE: This is the serila console */
sem_t closesem; /* Looks out new opens while sem_t closesem; /* Looks out new opens while
* close is in progress */ * close is in progress */
sem_t xmitsem; /* Used to wakeup user waiting sem_t xmitsem; /* Used to wakeup user waiting
@ -214,9 +214,7 @@ static inline uint32 up_inserial(up_dev_t *dev, uint32 offset)
return getreg32(dev->uartbase + offset); return getreg32(dev->uartbase + offset);
} }
static inline void up_serialout(up_dev_t *dev, static inline void up_serialout(up_dev_t *dev, uint32 offset, uint32 value)
uint32 offset,
uint32 value)
{ {
putreg32(value, dev->uartbase + offset); putreg32(value, dev->uartbase + offset);
} }
@ -255,16 +253,16 @@ static inline void up_enablerxint(up_dev_t *dev)
up_serialout(dev, UART_IER_OFFS, dev->regs.ier); up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
} }
static inline void up_disableuartint(up_dev_t *dev, uint16 *msr) static inline void up_disableuartint(up_dev_t *dev, uint16 *ier)
{ {
*msr = dev->regs.ier & UART_IER_AllInts; *ier = dev->regs.ier & UART_IER_AllInts;
dev->regs.ier &= ~UART_IER_AllInts; dev->regs.ier &= ~UART_IER_AllInts;
up_serialout(dev, UART_IER_OFFS, dev->regs.ier); up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
} }
static inline void up_restoreuartint(up_dev_t *dev, uint16 msr) static inline void up_restoreuartint(up_dev_t *dev, uint16 ier)
{ {
dev->regs.ier |= msr & (UART_IER_RecvInt|UART_IER_XmitInt); dev->regs.ier |= ier & (UART_IER_RecvInt|UART_IER_XmitInt);
up_serialout(dev, UART_IER_OFFS, dev->regs.ier); up_serialout(dev, UART_IER_OFFS, dev->regs.ier);
} }
@ -423,7 +421,7 @@ static inline ubyte up_txfifonotfull(up_dev_t *dev)
return (up_inserial(dev, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0; return (up_inserial(dev, UART_SSR_OFFS) & UART_SSR_TXFULL) == 0;
} }
static inline void up_waitforxmtr(up_dev_t *dev) static inline void up_waittxfifonotfull(up_dev_t *dev)
{ {
int tmp; int tmp;
for (tmp = 1000 ; tmp > 0 ; tmp--) for (tmp = 1000 ; tmp > 0 ; tmp--)
@ -554,7 +552,7 @@ static inline void up_recvchars(up_dev_t *dev)
* up_write adds data to the head of the xmit buffer. * up_write adds data to the head of the xmit buffer.
*/ */
static inline void up_xmitchars(up_dev_t *dev) static void up_xmitchars(up_dev_t *dev)
{ {
/* Send while we still have data & room in the fifo */ /* Send while we still have data & room in the fifo */
@ -667,29 +665,9 @@ static int up_interrupt(int irq, struct xcptcontext *xcp)
************************************************************/ ************************************************************/
static void up_uartsetup(up_dev_t *dev) static void up_uartsetup(up_dev_t *dev)
{
uint32 flags;
uint16 mrs;
flags = irqsave();
up_saveregisters(dev);
up_disableuartint(dev, &mrs);
up_clearfifos(dev);
up_disablebreaks(dev);
up_settxtrigger(dev, UART_FCR_FTL);
up_setrxtrigger(dev, UART_FCR_FTL);
irqrestore(flags);
}
/************************************************************
* up_cval
************************************************************/
static unsigned int up_cval(up_dev_t *dev)
{ {
unsigned int cval; unsigned int cval;
uint16 mrs;
if (dev->bits == 7) if (dev->bits == 7)
{ {
@ -714,67 +692,13 @@ static unsigned int up_cval(up_dev_t *dev)
cval |= (UART_LCR_ParEn|UART_LCR_ParEven); cval |= (UART_LCR_ParEn|UART_LCR_ParEven);
} }
return cval; up_serialreset(dev);
}
/************************************************************
* Name: up_portstartup
************************************************************/
static int up_portstartup(up_dev_t *dev)
{
uint32 flags;
unsigned cval = up_cval(dev);
int quotient = 0;
uint16 ier;
int ret = OK;
flags = irqsave();
up_saveregisters(dev); up_saveregisters(dev);
up_disableuartint(dev, &ier); up_disableuartint(dev, &mrs);
up_clearfifos(dev); up_clearfifos(dev);
up_disablebreaks(dev); up_disablebreaks(dev);
up_settxtrigger(dev, UART_FCR_FTL);
/* Attache and enabled the IRQ */ up_setrxtrigger(dev, UART_FCR_FTL);
ret = irq_attach(dev->irq, up_interrupt);
if (ret != OK)
{
goto errout;
}
/* Mark the io buffers empty */
dev->xmit.head = 0;
dev->xmit.tail = 0;
dev->recv.head = 0;
dev->recv.tail = 0;
/* And set the speed of the serial port */
/* Determine divisor based on baud rate */
if (dev->baud == 134)
{
/* Special case since 134 is really 134.5 */
quotient = (2*dev->baud_base / 269);
}
else if (dev->baud)
{
quotient = (dev->baud_base / dev->baud) - 1;
}
/* If the quotient is zero, default to 9600 bps */
if (!quotient && dev->baud_base != dev->baud)
{
quotient = (dev->baud_base / 9600) - 1;
}
/* Set up parity check flag */
up_setrate(dev, dev->baud); up_setrate(dev, dev->baud);
up_setmode(dev, cval); up_setmode(dev, cval);
@ -786,16 +710,6 @@ static int up_portstartup(up_dev_t *dev)
{ {
serial_disable_hw_flow_control(dev); serial_disable_hw_flow_control(dev);
} }
/* Finally, enable interrupts */
up_enable_irq(dev->irq);
up_enablerxint(dev);
ret = 0;
errout:
irqrestore(flags);
return ret;
} }
/************************************************************ /************************************************************
@ -881,7 +795,10 @@ static ssize_t up_write(struct file *filep, const char *buffer, size_t buflen)
if (dev->xmit.head != dev->xmit.tail) if (dev->xmit.head != dev->xmit.tail)
{ {
up_xmitchars(dev); up_xmitchars(dev);
up_enabletxint(dev); if (dev->xmit.head != dev->xmit.tail)
{
up_enabletxint(dev);
}
} }
return ret; return ret;
@ -945,14 +862,6 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
switch (cmd) switch (cmd)
{ {
case TIOCSERCONFIG:
{
shutdown(dev);
up_uartsetup(dev);
ret = up_portstartup(dev);
}
break;
case TIOCSERGSTRUCT: case TIOCSERGSTRUCT:
{ {
up_dev_t *user = (up_dev_t*)arg; up_dev_t *user = (up_dev_t*)arg;
@ -1038,6 +947,7 @@ static int up_close(struct file *filep)
shutdown(dev); shutdown(dev);
up_givesem(&dev->closesem); up_givesem(&dev->closesem);
return OK;
} }
/************************************************************ /************************************************************
@ -1064,8 +974,39 @@ static int up_open(struct file *filep)
if (++dev->open_count == 1) if (++dev->open_count == 1)
{ {
up_uartsetup(dev); int flags = irqsave();
ret = up_portstartup(dev);
/* If this is the console, then the UART has already
* been initialized.
*/
if (!dev->isconsole)
{
up_uartsetup(dev);
}
/* But, in any event, we do have to configure for
* interrupt driven mode of operation.
*/
/* Attache and enabled the IRQ */
ret = irq_attach(dev->irq, up_interrupt);
if (ret == OK)
{
/* Mark the io buffers empty */
dev->xmit.head = 0;
dev->xmit.tail = 0;
dev->recv.head = 0;
dev->recv.tail = 0;
/* Finally, enable interrupts */
up_enable_irq(dev->irq);
up_enablerxint(dev);
}
irqrestore(flags);
} }
up_givesem(&dev->closesem); up_givesem(&dev->closesem);
@ -1094,26 +1035,6 @@ static void up_devinit(up_dev_t *dev,
sem_init(&dev->recvsem, 0, 0); sem_init(&dev->recvsem, 0, 0);
} }
/************************************************************
* Name: up_consoleinit
************************************************************/
static void up_consoleinit(up_dev_t *dev)
{
unsigned cval = up_cval(dev);
uint16 ier;
up_serialreset(dev);
up_saveregisters(dev);
up_disableuartint(dev, &ier);
up_clearfifos(dev);
up_setrate(dev, dev->baud);
up_setmode(dev, cval);
up_delay(5);
dev->open_count = 1;
}
/************************************************************ /************************************************************
* Public Funtions * Public Funtions
************************************************************/ ************************************************************/
@ -1141,7 +1062,8 @@ void up_earlyserialinit(void)
/* Configure the console for use now */ /* Configure the console for use now */
up_consoleinit(&CONSOLE_DEV); CONSOLE_DEV.isconsole = TRUE;
up_uartsetup(&CONSOLE_DEV);
} }
/************************************************************ /************************************************************
@ -1174,7 +1096,7 @@ int up_putc(int ch)
uint16 ier; uint16 ier;
up_disableuartint(&CONSOLE_DEV, &ier); up_disableuartint(&CONSOLE_DEV, &ier);
up_waitforxmtr(&CONSOLE_DEV); up_waittxfifonotfull(&CONSOLE_DEV);
up_outserialchar(&CONSOLE_DEV, ch); up_outserialchar(&CONSOLE_DEV, ch);
/* Check for LF */ /* Check for LF */
@ -1183,10 +1105,11 @@ int up_putc(int ch)
{ {
/* Add CR */ /* Add CR */
up_waitforxmtr(&CONSOLE_DEV); up_waittxfifonotfull(&CONSOLE_DEV);
up_outserialchar(&CONSOLE_DEV, 13); up_outserialchar(&CONSOLE_DEV, 13);
} }
up_waitforxmtr(&CONSOLE_DEV); up_waittxfifonotfull(&CONSOLE_DEV);
up_restoreuartint(&CONSOLE_DEV, ier); up_restoreuartint(&CONSOLE_DEV, ier);
return ch;
} }