Fix IRQ-related bugs, fix serial read logic, add fgets

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@51 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-03-10 00:17:29 +00:00
parent 43f4608432
commit 89b91918d9
3 changed files with 62 additions and 7 deletions

View File

@ -95,8 +95,6 @@ void up_block_task(_TCB *tcb, tstate_t task_state)
_TCB *rtcb = (_TCB*)g_readytorun.head;
boolean switch_needed;
dbg("Blocking TCB=%p\n", tcb);
/* Remove the tcb task from the ready-to-run list. If we
* are blocking the task at the head of the task list (the
* most likely case), then a context switch to the next

View File

@ -74,6 +74,13 @@ void up_doirq(int irq, uint32* regs)
#else
if ((unsigned)irq < NR_IRQS)
{
/* Current regs non-zero indicates that we are processing
* an interrupt; current_regs is also used to manage
* interrupt level context switches.
*/
current_regs = regs;
/* Mask and acknowledge the interrupt */
up_maskack_irq(irq);
@ -82,8 +89,15 @@ void up_doirq(int irq, uint32* regs)
irq_dispatch(irq, regs);
/* Then unmask it */
/* Indicate that we are no long in an interrupt handler */
current_regs = NULL;
/* Unmask the last interrupt (global interrupts are still
* disabled.
*/
current_regs = NULL;
up_enable_irq(irq);
}
up_ledoff(LED_INIRQ);

View File

@ -521,7 +521,7 @@ static inline void up_givesem(sem_t *sem)
* characters from the tail of the buffer.
*/
static inline void up_recvchars(up_dev_t *dev)
static void up_recvchars(up_dev_t *dev)
{
uint16 status;
int nexthead = dev->recv.head + 1;
@ -800,6 +800,32 @@ static void shutdown(up_dev_t * dev)
irqrestore(flags);
}
/************************************************************
* Name: up_irqwrite
************************************************************/
static ssize_t up_irqwrite(up_dev_t *dev, const char *buffer, size_t buflen)
{
ssize_t ret = buflen;
/* Force each character through the low level interface */
for (; buflen; buflen--)
{
int ch = *buffer++;
up_lowputc(ch);
/* If this is the console, then we should replace LF with LF-CR */
if (ch == '\n')
{
up_lowputc('\r');
}
}
return ret;
}
/************************************************************
* Name: up_write
************************************************************/
@ -810,6 +836,23 @@ static ssize_t up_write(struct file *filep, const char *buffer, size_t buflen)
up_dev_t *dev = inode->i_private;
ssize_t ret = buflen;
/* We may receive console writes through this path from
* interrupt handlers! In this case, we will need to do
* things a little differently.
*/
if (up_interrupt_context())
{
if (dev->isconsole)
{
return up_irqwrite(dev, buffer, buflen);
}
else
{
return ERROR;
}
}
/* Only one user can be accessing dev->xmit.head at once */
up_takesem(&dev->xmit.sem);
@ -827,10 +870,10 @@ static ssize_t up_write(struct file *filep, const char *buffer, size_t buflen)
/* Put the character into the transmit buffer */
up_putxmitchar(dev, ch);
/* If this is the console, then we should replace LF with LF-CR */
if (ch == '\n')
if (dev->isconsole && ch == '\n')
{
up_putxmitchar(dev, '\r');
}
@ -895,7 +938,7 @@ static ssize_t up_read(struct file *filep, char *buffer, size_t buflen)
}
up_enablerxint(dev);
up_takesem(&dev->recv.sem);
up_givesem(&dev->recv.sem);
return ret;
}