Add support for onboard LEDs; Fix serial bug


git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@43 42af7a65-404d-4744-a932-0658087f49c3
diff --git a/arch/c5471/src/Makefile b/arch/c5471/src/Makefile
index a7867f0..ec91753 100644
--- a/arch/c5471/src/Makefile
+++ b/arch/c5471/src/Makefile
@@ -51,7 +51,7 @@
 		  up_exit.c up_assert.c up_blocktask.c up_unblocktask.c \
 		  up_releasepending.c up_reprioritizertr.c up_copystate.c \
 		  up_schedulesigaction.c up_sigdeliver.c up_serial.c \
-		  up_delay.c up_allocateheap.c
+		  up_delay.c up_allocateheap.c up_leds.c
 COBJS		= $(CSRCS:.c=.o)
 
 SRCS		= $(ASRCS) $(CSRCS)
diff --git a/arch/c5471/src/up_allocateheap.c b/arch/c5471/src/up_allocateheap.c
index 2d40857..3ee7a68 100644
--- a/arch/c5471/src/up_allocateheap.c
+++ b/arch/c5471/src/up_allocateheap.c
@@ -72,6 +72,7 @@
 
 void up_allocate_heap(FAR void **heap_start, size_t *heap_size)
 {
-  *heap_start = (FAR void*)g_heapstart;
-  *heap_size = CONFIG_DRAM_END - g_heapstart;
+  up_ledon(LED_HEAPALLOCATE);
+  *heap_start = (FAR void*)g_heapbase;
+  *heap_size = CONFIG_DRAM_END - g_heapbase;
 }
diff --git a/arch/c5471/src/up_assert.c b/arch/c5471/src/up_assert.c
index 4975408..679a01f 100644
--- a/arch/c5471/src/up_assert.c
+++ b/arch/c5471/src/up_assert.c
@@ -65,7 +65,15 @@
   if (current_regs || ((_TCB*)g_readytorun.head)->pid == 0)
     {
        (void)irqsave();
-        for(;;);
+        for(;;)
+          {
+#ifdef CONFIG_C5471_LEDS
+            up_ledon(LED_PANIC);
+            up_delay(250);
+            up_ledoff(LED_PANIC);
+            up_delay(250);
+#endif
+          }
     }
   else
     {
@@ -83,8 +91,9 @@
 
 void up_assert(const ubyte *filename, int lineno)
 {
+  up_ledon(LED_ASSERTION);
   dbg("Assertion failed at file:%s line: %d\n",
-      filename, lineno);
+        filename, lineno);
   _up_assert(EXIT_FAILURE);
 }
 
@@ -94,7 +103,8 @@
 
 void up_assert_code(const ubyte *filename, int lineno, int errorcode)
 {
+  up_ledon(LED_ASSERTION);
   dbg("Assertion failed at file:%s line: %d error code: %d\n",
-       filename, lineno, errorcode);
+        filename, lineno, errorcode);
   _up_assert(errorcode);
 }
diff --git a/arch/c5471/src/up_createstack.c b/arch/c5471/src/up_createstack.c
index 0e1f069..7903ee8 100644
--- a/arch/c5471/src/up_createstack.c
+++ b/arch/c5471/src/up_createstack.c
@@ -119,6 +119,7 @@
        tcb->adj_stack_ptr  = (uint32*)top_of_stack;
        tcb->adj_stack_size = size_of_stack;
 
+       up_ledon(LED_STACKCREATED);
        return OK;
      }
 
diff --git a/arch/c5471/src/up_doirq.c b/arch/c5471/src/up_doirq.c
index 48cbd3e..f4e0787 100644
--- a/arch/c5471/src/up_doirq.c
+++ b/arch/c5471/src/up_doirq.c
@@ -68,6 +68,7 @@
 
 void up_doirq(int irq, uint32* regs)
 {
+  up_ledon(LED_INIRQ);
 #ifdef CONFIG_SUPPRESS_INTERRUPTS
   PANIC(OSERR_ERREXCEPTION);
 #else
@@ -85,5 +86,6 @@
 
        up_enable_irq(irq);
     }
+  up_ledoff(LED_INIRQ);
 #endif
 }
diff --git a/arch/c5471/src/up_head.S b/arch/c5471/src/up_head.S
index dd59b98..770cadd 100644
--- a/arch/c5471/src/up_head.S
+++ b/arch/c5471/src/up_head.S
@@ -38,10 +38,11 @@
  ************************************************************/
 
 #include <nuttx/config.h>
+#include "up_internal.h"
 #include "c5471.h"
 
 /************************************************************
- * Definitions
+ * Macros
  ************************************************************/
 
 	/* This macro will modify r0, r1, r2 and r14 */
@@ -114,6 +115,11 @@
 	mov	r0, #'\n'
 	bl	up_putc
 #endif
+	/* Initialize onboard LEDs */
+
+#ifdef CONFIG_C5471_LEDS
+	bl	up_ledinit
+#endif
 
 	/* Then jump to OS entry */
 
@@ -124,7 +130,7 @@
 	 * _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.  The heap continues
-	 * from there until the end of memory.  See g_heapstart
+	 * from there until the end of memory.  See g_heapbase
 	 * below.
 	 */
 
@@ -139,18 +145,18 @@
 #endif
 	.size	__start, .-__start
 
-	/* This global variable is unsigned long g_heapstart and is
+	/* This global variable is unsigned long g_heapbase and is
 	 * exported from here only because of its coupling to LCO
 	 * above.
 	 */
 
 	.data
 	.align	4
-	.globl	g_heapstart
-	.type	g_heapstart, object
-g_heapstart:
+	.globl	g_heapbase
+	.type	g_heapbase, object
+g_heapbase:
 	.long	_ebss+CONFIG_PROC_STACK_SIZE
-	.size	g_heapstart, .-g_heapstart
+	.size	g_heapbase, .-g_heapbase
 
 	.end
 
diff --git a/arch/c5471/src/up_initialize.c b/arch/c5471/src/up_initialize.c
index 86b6a9f..6ae3f0d 100644
--- a/arch/c5471/src/up_initialize.c
+++ b/arch/c5471/src/up_initialize.c
@@ -99,4 +99,5 @@
   /* Initialize the serial device driver */
 
   up_serialinit();
+  up_ledon(LED_IRQSENABLED);
 }
diff --git a/arch/c5471/src/up_internal.h b/arch/c5471/src/up_internal.h
index 0c03967..5f7e430 100644
--- a/arch/c5471/src/up_internal.h
+++ b/arch/c5471/src/up_internal.h
@@ -48,6 +48,18 @@
 
 #define CONFIG_SUPPRESS_INTERRUPTS  1 /* Do not enable interrupts */
 #undef  CONFIG_SUPPRESS_UART_CONFIG   /* Do not reconfig UART */
+#define CONFIG_C5471_LEDS           1 /* Use LEDs to show state */
+
+/* LED meanings */
+
+#define LED_STARTED                 0
+#define LED_HEAPALLOCATE            1
+#define LED_IRQSENABLED             2
+#define LED_STACKCREATED            3
+#define LED_INIRQ                   4
+#define LED_SIGNAL                  5
+#define LED_ASSERTION               6
+#define LED_PANIC                   7
 
 /************************************************************
  * Public Types
@@ -75,7 +87,7 @@
  * CONFIG_DRAM_END
  */
 
-extern uint32 g_heapstart;
+extern uint32 g_heapbase;
 #endif
 
 /************************************************************
@@ -133,6 +145,18 @@
 
 extern void up_maskack_irq(int irq);
 
+/* Defined in up_leds.c */
+
+#ifdef CONFIG_C5471_LEDS
+extern void up_ledinit(void);
+extern void up_ledon(int led);
+extern void up_ledoff(int led);
+#else
+# define up_ledinit()
+# define up_ledon(led)
+# define up_ledoff(led)
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif  /* __UP_INTERNAL_H */
diff --git a/arch/c5471/src/up_leds.c b/arch/c5471/src/up_leds.c
new file mode 100644
index 0000000..ee1241e
--- /dev/null
+++ b/arch/c5471/src/up_leds.c
@@ -0,0 +1,107 @@
+/************************************************************
+ * up_leds.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.
+ *
+ ************************************************************/
+
+/************************************************************
+ * Included Files
+ ************************************************************/
+
+#include <nuttx/config.h>
+#include <sys/types.h>
+#include "up_internal.h"
+
+/************************************************************
+ * Definitions
+ ************************************************************/
+
+#define CS2  *(volatile uint32*)0xffff2e08
+#define LEDS *(volatile uint32*)0x01000000
+
+/************************************************************
+ * Private Data
+ ************************************************************/
+
+static uint32 g_ledstate;
+
+/************************************************************
+ * Private Functions
+ ************************************************************/
+
+/************************************************************
+ * Public Funtions
+ ************************************************************/
+
+/************************************************************
+ * Name: up_ledinit
+ ************************************************************/
+
+#ifdef CONFIG_C5471_LEDS
+void up_ledinit(void)
+{
+  /* Enable acces to LEDs */
+
+  CS2 = 0x000013db;
+
+  /* Turn LED 1-7 off; turn LED 0 on */
+
+  g_ledstate = 0x000000fe;
+  LEDS       = g_ledstate;
+}
+
+/************************************************************
+ * Name: up_ledon
+ ************************************************************/
+
+void up_ledon(int led)
+{
+  if (led < 8)
+    {
+      g_ledstate &= ~(1 << led);
+      LEDS        = g_ledstate;
+    }
+}
+
+/************************************************************
+ * Name: up_ledoff
+ ************************************************************/
+
+void up_ledoff(int led)
+{
+  if (led < 8)
+    {
+      g_ledstate |= (1 << led);
+      LEDS        = g_ledstate;
+    }
+}
+#endif /* CONFIG_C5471_LEDS */
diff --git a/arch/c5471/src/up_serial.c b/arch/c5471/src/up_serial.c
index faaf7ae..b51e48c 100644
--- a/arch/c5471/src/up_serial.c
+++ b/arch/c5471/src/up_serial.c
@@ -589,42 +589,51 @@
 static void up_putxmitchar(up_dev_t *dev, int ch)
 {
   int nexthead = dev->xmit.head + 1;
-  if (nexthead >= dev->xmit.size)
+
+  for(;;)
     {
-      nexthead = 0;
-    }
-
-  if (nexthead != dev->xmit.tail)
-    {
-      dev->xmit.buffer[dev->xmit.head] = ch;
-      dev->xmit.head = nexthead;
-    }
-  else
-    {
-      /* Transfer some characters with interrupts disabled */
-
-      up_xmitchars(dev);
-
-      /* If we unsuccessful in making room in the buffer.
-       * then transmit the characters with interrupts
-       * enabled and wait for result.
-       */
-
-      if (nexthead == dev->xmit.tail)
+      if (nexthead >= dev->xmit.size)
         {
-          /* Still no space */
+          nexthead = 0;
+        }
 
-          dev->xmitwaiting = TRUE;
+      if (nexthead != dev->xmit.tail)
+        {
+          dev->xmit.buffer[dev->xmit.head] = ch;
+          dev->xmit.head = nexthead;
+          return;
+        }
+      else
+        {
+          /* Transfer some characters with interrupts disabled */
 
-          /* Wait for some characters to be sent from the buffer
-           * with the TX interrupt disabled.
+          up_xmitchars(dev);
+
+          /* If we unsuccessful in making room in the buffer.
+           * then transmit the characters with interrupts
+           * enabled and wait for result.
            */
 
-         up_enabletxint(dev);
-         up_takesem(&dev->xmitsem);
-         up_disabletxint(dev);
-       }
-   }
+          if (nexthead == dev->xmit.tail)
+            {
+              /* Still no space */
+
+#ifdef CONFIG_SUPPRESS_INTERRUPTS
+              up_waittxfifonotfull(dev);
+#else
+              dev->xmitwaiting = TRUE;
+
+              /* Wait for some characters to be sent from the buffer
+               * with the TX interrupt disabled.
+               */
+
+              up_enabletxint(dev);
+              up_takesem(&dev->xmitsem);
+              up_disabletxint(dev);
+#endif
+            }
+        }
+    }
 }
 
 /************************************************************
diff --git a/arch/c5471/src/up_sigdeliver.c b/arch/c5471/src/up_sigdeliver.c
index 1ef77c1..df10403 100644
--- a/arch/c5471/src/up_sigdeliver.c
+++ b/arch/c5471/src/up_sigdeliver.c
@@ -80,6 +80,7 @@
   uint32 regs[XCPTCONTEST_REGS];
   sig_deliver_t sigdeliver;
 
+  up_ledon(LED_SIGNAL);
   ASSERT(rtcb->xcp.sigdeliver);
 
   /* Save the real return state on the stack. */
@@ -113,5 +114,6 @@
    * execution.
    */
 
+  up_ledoff(LED_SIGNAL);
   up_fullcontextrestore(regs);
 }