summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-03-10 00:17:29 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2007-03-10 00:17:29 +0000
commitaf447e106c50246185a2b666900022043636d418 (patch)
tree3da31331ea2df513646279912b4e4b1b4d22fdb0
parent713a462159cc5bb7e4574be4494d4e88024f010f (diff)
downloadnuttx-af447e106c50246185a2b666900022043636d418.tar.gz
nuttx-af447e106c50246185a2b666900022043636d418.tar.bz2
nuttx-af447e106c50246185a2b666900022043636d418.zip
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
-rw-r--r--nuttx/ChangeLog13
-rw-r--r--nuttx/arch/c5471/src/up_blocktask.c2
-rw-r--r--nuttx/arch/c5471/src/up_doirq.c16
-rw-r--r--nuttx/arch/c5471/src/up_serial.c51
-rw-r--r--nuttx/include/ctype.h50
-rw-r--r--nuttx/include/stdio.h1
-rw-r--r--nuttx/lib/Makefile4
-rw-r--r--nuttx/lib/lib_fgets.c306
-rw-r--r--nuttx/sched/sem_post.c2
-rw-r--r--nuttx/sched/sem_trywait.c7
-rw-r--r--nuttx/sched/sem_wait.c9
11 files changed, 435 insertions, 26 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 823a1c832..61b8970b0 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/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/nuttx/arch/c5471/src/up_blocktask.c b/nuttx/arch/c5471/src/up_blocktask.c
index 6b42d4270..5e0693e2e 100644
--- a/nuttx/arch/c5471/src/up_blocktask.c
+++ b/nuttx/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/nuttx/arch/c5471/src/up_doirq.c b/nuttx/arch/c5471/src/up_doirq.c
index f4e07873c..ab1b40d65 100644
--- a/nuttx/arch/c5471/src/up_doirq.c
+++ b/nuttx/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/nuttx/arch/c5471/src/up_serial.c b/nuttx/arch/c5471/src/up_serial.c
index c6d6dc58e..022befd38 100644
--- a/nuttx/arch/c5471/src/up_serial.c
+++ b/nuttx/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;
@@ -801,6 +801,32 @@ static void shutdown(up_dev_t * dev)
}
/************************************************************
+ * 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/nuttx/include/ctype.h b/nuttx/include/ctype.h
index 9b62034ff..fb30746de 100644
--- a/nuttx/include/ctype.h
+++ b/nuttx/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/nuttx/include/stdio.h b/nuttx/include/stdio.h
index f234a861c..426b23714 100644
--- a/nuttx/include/stdio.h
+++ b/nuttx/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/nuttx/lib/Makefile b/nuttx/lib/Makefile
index 2189db7a5..cb77499c8 100644
--- a/nuttx/lib/Makefile
+++ b/nuttx/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/nuttx/lib/lib_fgets.c b/nuttx/lib/lib_fgets.c
new file mode 100644
index 000000000..df18c239a
--- /dev/null
+++ b/nuttx/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/nuttx/sched/sem_post.c b/nuttx/sched/sem_post.c
index 3b4fac368..857b20def 100644
--- a/nuttx/sched/sem_post.c
+++ b/nuttx/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/nuttx/sched/sem_trywait.c b/nuttx/sched/sem_trywait.c
index 384eff0a0..dc65f8f58 100644
--- a/nuttx/sched/sem_trywait.c
+++ b/nuttx/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/nuttx/sched/sem_wait.c b/nuttx/sched/sem_wait.c
index 7893b39ba..4d82dd41a 100644
--- a/nuttx/sched/sem_wait.c
+++ b/nuttx/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;