diff --git a/ChangeLog b/ChangeLog
index 823a1c832cde4b4d02259d3eb74823dbc337141e..61b8970b0ed4714bb22bce0071e1082406cb006c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,3 +3,16 @@
 	* Initial Release
 	* Support for Linux user mode simulation and TI
 	  TMS320C5471 (Arm7) provided
+
+0.1.1 2007-xx-xx  Gregory Nutt <spudmonkey@racsa.co.cr>
+
+	* Corrected an error in interrupt level context switching
+	  for C5471
+	* Added fgets logic; verified console read.
+	* Corrected error in reading from serial port.  Improper
+	  use of semaphore can cause deadlock.
+	* Attempts to use C5471 console from interrupt handlers
+	  can casue errors. Added a special path for this case.
+	* Refuse callse to sem_wait and sem_trywait from interrupt
+	  handlers.
+	* Documentation updates
diff --git a/arch/c5471/src/up_blocktask.c b/arch/c5471/src/up_blocktask.c
index 6b42d4270256981dcfc5de42468bf313390c7b91..5e0693e2e37cb836c403e5136e728c2f7631bbc5 100644
--- a/arch/c5471/src/up_blocktask.c
+++ b/arch/c5471/src/up_blocktask.c
@@ -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
diff --git a/arch/c5471/src/up_doirq.c b/arch/c5471/src/up_doirq.c
index f4e07873cd37def5028f2b4e78cab1efc6fc7053..ab1b40d655612ba4a8f63190ef11e655c65d93eb 100644
--- a/arch/c5471/src/up_doirq.c
+++ b/arch/c5471/src/up_doirq.c
@@ -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);
diff --git a/arch/c5471/src/up_serial.c b/arch/c5471/src/up_serial.c
index c6d6dc58ef1095e55a9dde1734c52322f0f0ec06..022befd3805cfe45b6f751d43a3c2253e621f4bb 100644
--- a/arch/c5471/src/up_serial.c
+++ b/arch/c5471/src/up_serial.c
@@ -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;
 }
 
diff --git a/include/ctype.h b/include/ctype.h
index 9b62034ff714ee2bfa145e50ca56e3f8fdc850b8..fb30746de0dd5ad332175477cbfbf3624f4f34b5 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -64,31 +64,49 @@
  ************************************************************/
 
 #define isspace(c) \
-  (c == ' '  || c == '\t' || c == '\n' || \
-   c == '\r' || c == '\f' || c== '\v')
+  ((c) == ' '  || (c) == '\t' || (c) == '\n' || \
+   (c) == '\r' || (c) == '\f' || c== '\v')
 
 /************************************************************
- * Function:  isdigit
+ * Function:  isascii
  *
  * Description:
- *    ANSI standard isdigit implementation.
+ *  Checks whether c is a 7-bit unsigned char value that
+ *  fits into the ASCII character set.
  *
  ************************************************************/
 
-#define isdigit(c) \
-  (c >= '0' && c <= '9')
+#define isascii(c) ((c) >= 0 && (c) <= 0x7f);
 
 /************************************************************
- * Function:  isascii
+ * Function:  isprint
  *
  * Description:
- *  Checks whether c is a 7-bit unsigned char value that
- *  fits into the ASCII character set.
+ *  Checks for a printable character (including space)
+ *
+ ************************************************************/
+
+#define isprint(c) ((c) >= 0x20 && (c) < 0x7f)
+
+/************************************************************
+ * Function:  iscntrl
+ *
+ * Description:
+ *  Checks for control character.
+ *
+ ************************************************************/
+
+#define iscontrol(c) (!isprint(c))
+
+/************************************************************
+ * Function:  isdigit
+ *
+ * Description:
+ *    ANSI standard isdigit implementation.
  *
  ************************************************************/
 
-#define isascii(c) \
-  (c >= 0 && c <= 0177);
+#define isdigit(c)   ((c) >= '0' && (c) <= '9')
 
 /************************************************************
  * Function:  isxdigit
@@ -100,9 +118,9 @@
  ************************************************************/
 
 #define isxdigit(c) \
-  ((c >= '0' && c <= '9') || \
-   (c >= 'a' && c <= 'f') || \
-   (c >= 'A' && c <= 'F'))
+  (((c) >= '0' && (c) <= '9') || \
+   ((c) >= 'a' && (c) <= 'f') || \
+   ((c) >= 'A' && (c) <= 'F'))
 
 /************************************************************
  * Function:  toupper
@@ -113,7 +131,7 @@
  ************************************************************/
 
 #define toupper(c) \
-  ((c >= 'a' && c <= 'z') ? ((c) - 'a' + 'A') : (c))
+  (((c) >= 'a' && (c) <= 'z') ? ((c) - 'a' + 'A') : (c))
 
 /************************************************************
  * Function:  tolower
@@ -124,7 +142,7 @@
  ************************************************************/
 
 #define tolower(c) \
-  ((c >= 'A' && c <= 'Z') ? ((c) - 'A' + 'a') : (c))
+  (((c) >= 'A' && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
 
 /************************************************************
  * Public Type Definitions
diff --git a/include/stdio.h b/include/stdio.h
index f234a861c2ad7ccaa1952550ab4b7564fea7c6e4..426b237147d5b86e1a24c2fd5b30c75c088d6113 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -224,6 +224,7 @@ EXTERN size_t fread(void *ptr, size_t size, size_t n_items,
 EXTERN int    fseek(FILE *stream, long int offset, int whence);
 EXTERN size_t fwrite(const void *ptr, size_t size,
 		     size_t n_items, FILE *stream);
+
 EXTERN int    printf(const char *format, ...);
 EXTERN int    puts(const char *s);
 EXTERN int    rename(const char *source, const char *target);
diff --git a/lib/Makefile b/lib/Makefile
index 2189db7a5c382a37739ced108c8329eba0252232..cb77499c82f752e80b7190d58d2f9becd8409323 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -46,8 +46,8 @@ STRING_SRCS	= lib_memset.c lib_memcpy.c lib_memcmp.c lib_memmove.c \
 		  lib_strlen.c lib_strdup.c lib_strtol.c lib_strchr.c
 CTYPE_SRCS	= 
 STDIO_SRCS	= lib_fopen.c lib_fclose.c \
-		  lib_fread.c lib_libfread.c lib_fgetc.c\
-		  lib_fwrite.c lib_libfwrite.c lib_fflush.c\
+		  lib_fread.c lib_libfread.c lib_fgetc.c lib_fgets.c \
+		  lib_fwrite.c lib_libfwrite.c lib_fflush.c \
 		  lib_fputc.c lib_puts.c lib_fputs.c \
 		  lib_ungetc.c \
 		  lib_printf.c lib_vprintf.c lib_fprintf.c  lib_rawprintf.c lib_lowprintf.c \
diff --git a/lib/lib_fgets.c b/lib/lib_fgets.c
new file mode 100644
index 0000000000000000000000000000000000000000..df18c239ad5d98958949225662fc8946a42b35d4
--- /dev/null
+++ b/lib/lib_fgets.c
@@ -0,0 +1,306 @@
+/************************************************************
+ * lib_fgets.c
+ *
+ *   Copyright (C) 2007 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 Gregory Nutt 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.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Compilation Switches
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <debug.h>
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+/************************************************************
+ * Private Type Declarations
+ ************************************************************/
+
+/************************************************************
+ * Private Function Prototypes
+ ************************************************************/
+
+/************************************************************
+ * Global Function Prototypes
+ ************************************************************/
+
+/************************************************************
+ * Global Constant Data
+ ************************************************************/
+
+/************************************************************
+ * Global Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Constant Data
+ ************************************************************/
+
+/************************************************************
+ * Private Variables
+ ************************************************************/
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: _lib_rawgetc
+ ************************************************************/
+
+static inline int _lib_rawgetc(int fd)
+{
+  char buffer;
+  (void)read(fd, &buffer, 1);
+  return buffer;
+}
+
+/************************************************************
+ * Name: _lib_consoleputc
+ ************************************************************/
+
+static inline void _lib_consoleputc(int ch)
+{
+  char buffer = ch;
+  (void)write(1, &buffer, 1);
+}
+
+/************************************************************
+ * Name: _lib_consoleputs
+ ************************************************************/
+
+static inline void _lib_consoleputs(char *s)
+{
+  (void)write(1, s, strlen(s));
+}
+
+/************************************************************
+ * Global Functions
+ ************************************************************/
+
+/************************************************************
+ * Name: fgets
+ *
+ * Description:
+ *   fgets() reads in at most one less than 'n' characters
+ *   from stream and stores them into the buffer pointed to
+ *   by 's'. Reading stops after an EOF or a newline.  If a
+ *   newline is read, it is stored into the buffer.  A null
+ *   terminator is stored after the last character in the
+ *   buffer.
+ *
+ * Assumptions:
+ *   If the stream corresponds to stdin (fd=0) this version
+ *   will assume that we are reading characters from a
+ *   VT100 console and that stdout (fd=1) is also available.
+ *   This will not work well if fd=0 corresponds to a raw
+ *   byte steam.
+ *
+ **********************************************************/
+
+char *fgets(FAR char *s, int n, FILE *stream)
+{
+  int     escape = 0;
+  boolean console;
+  int     nch = 0;
+
+  /* Sanity checks */
+
+  if (!stream || !s || n < 1 || stream->fs_filedes < 0)
+    {
+      return NULL;
+    }
+
+  if (n < 2)
+    {
+      *s = '\0';
+      return s;
+    }
+
+  /* Check if the stream is stdin */
+
+  console = (stream->fs_filedes == 0);
+
+  /* <esc>[K is the VT100 command that erases to the end of the line. */
+
+  if (console)
+    {
+      _lib_consoleputs("\033[K");
+    }
+
+  /* Read characters until we have a full line. On each
+   * the loop we must be assured that there are two free bytes
+   * in the line buffer:  One for the next character and one for
+   * the null terminator.
+   */
+
+  for(;;)
+    {
+      /* Get the next character */
+
+      int ch = _lib_rawgetc(stream->fs_filedes);
+
+      /* Are we processing a VT100 escape sequence */
+
+      if (escape)
+        {
+          /* Yes, is it an <esc>[, 3 byte sequence */
+
+          if (ch != 0x5b || escape == 2)
+            {
+              /* We are finished with the escape sequence */
+
+              escape = 0;
+              ch = 'a';
+            }
+          else
+            {
+              /* The next character is the end of a 3-byte sequence.
+               * NOTE:  Some of the <esc>[ sequences are longer than
+               * 3-bytes, but I have not encountered any in normal use
+               * yet and, so, have not provided the decoding logic.
+               */
+
+              escape = 2;
+            }
+        }
+
+      /* Check for backspace */
+
+      else if (ch == 0x08)
+        {
+          /* Eliminate that last character in the buffer. */
+
+          if (nch > 0)
+            {
+              nch--;
+
+              if (console)
+                {
+                  /* Echo the backspace character on the console */
+
+                  _lib_consoleputc(ch);
+                }
+            }
+        }
+
+      /* Check for the beginning of a VT100 escape sequence */
+
+      else if (console && ch == 0x1b)
+        {
+          /* The next character is escaped */
+
+          escape = 1;
+        }
+
+      /* Check for end-of-line or end-of-file */
+
+      else if (ch == 0x0d)
+        {
+          /* The newline is stored in the buffer along
+           * with the null terminator.
+           */
+
+          s[nch++] = '\n';
+          s[nch]   = '\0';
+
+          if (console)
+            {
+              /* Echo the newline to the console */
+
+              _lib_consoleputc('\n');
+            }
+
+          return s;
+        }
+
+      /* Check for end-of-line or end-of-file */
+
+      else if (ch == EOF)
+        {
+          /* Terminate the line */
+
+          s[nch]   = '\0';
+          return s;
+        }
+
+      /* Otherwise, check if the character is printable and,
+       * if so, put the character in the line buffer
+       */
+
+      else if (isprint(ch))
+        {
+          s[nch++] = ch;
+
+          if (console)
+            {
+              /* Echo the character to the console */
+
+              _lib_consoleputc(ch);
+            }
+
+          /* Check if there is room for another character
+           * and the line's null terminator.  If not then
+           * we have to end the line now.
+           */
+
+          if (nch + 1 >= n)
+            {
+              s[nch] = '\0';
+              return s;
+            }
+        }
+    }
+
+}
+
+/************************************************************
+ * Name: gets
+ *
+ * Description:
+ *   gets() reads a line from stdin into the buffer pointed
+ *   to by s until either a terminating newline or EOF,
+ *   which it replaces with '\0'.  No check for buffer
+ *   overrun is performed
+ *
+ **********************************************************/
+
+/* gets() is not supported because it is inherently un-safe */
diff --git a/sched/sem_post.c b/sched/sem_post.c
index 3b4fac368443ffdebf1f9042baaeae7cbe75fc6e..857b20def04c4f3f80f39b35bae61d72ffd73470 100644
--- a/sched/sem_post.c
+++ b/sched/sem_post.c
@@ -139,7 +139,7 @@ int sem_post(sem_t *sem)
            */
 
           for (stcb = (FAR _TCB*)g_waitingforsemaphore.head;
-               ((stcb) && (stcb->waitsem != sem));
+               (stcb && stcb->waitsem != sem);
                stcb = stcb->flink);
 
           if (stcb)
diff --git a/sched/sem_trywait.c b/sched/sem_trywait.c
index 384eff0a0c990a957c6ead79137565d5dd47333c..dc65f8f58e7247b1b2bcbdd78972c7fae09a2261 100644
--- a/sched/sem_trywait.c
+++ b/sched/sem_trywait.c
@@ -102,6 +102,13 @@ int sem_trywait(sem_t *sem)
   irqstate_t saved_state;
   int        ret = ERROR;
 
+  if (up_interrupt_context())
+    {
+      /* We do not want to set the errno in this case */
+
+      return ERROR;
+    }
+
   /* Assume any errors reported are due to invalid arguments. */
 
   *get_errno_ptr() = EINVAL;
diff --git a/sched/sem_wait.c b/sched/sem_wait.c
index 7893b39ba04e01c9273cbc5b3eaf5deaf45444f5..4d82dd41a11f5602c7bac3dbb6a69c064abf36c5 100644
--- a/sched/sem_wait.c
+++ b/sched/sem_wait.c
@@ -103,6 +103,15 @@ int sem_wait(sem_t *sem)
   int        ret = ERROR;
   irqstate_t saved_state;
 
+  /* This API should not be called from interrupt handlers */
+
+  if (up_interrupt_context())
+    {
+      /* We do not want to set the errno in this case */
+
+      return ERROR;
+    }
+
   /* Assume any errors reported are due to invalid arguments. */
 
   *get_errno_ptr() = EINVAL;