9
0
Fork 0

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

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@51 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2007-03-10 00:17:29 +00:00
parent 132b1d0f43
commit 156791e5fb
11 changed files with 439 additions and 30 deletions

View File

@ -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

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;
}

View File

@ -64,19 +64,8 @@
************************************************************/
#define isspace(c) \
(c == ' ' || c == '\t' || c == '\n' || \
c == '\r' || c == '\f' || c== '\v')
/************************************************************
* Function: isdigit
*
* Description:
* ANSI standard isdigit implementation.
*
************************************************************/
#define isdigit(c) \
(c >= '0' && c <= '9')
((c) == ' ' || (c) == '\t' || (c) == '\n' || \
(c) == '\r' || (c) == '\f' || c== '\v')
/************************************************************
* Function: isascii
@ -87,8 +76,37 @@
*
************************************************************/
#define isascii(c) \
(c >= 0 && c <= 0177);
#define isascii(c) ((c) >= 0 && (c) <= 0x7f);
/************************************************************
* Function: isprint
*
* Description:
* 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 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

View File

@ -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);

View File

@ -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 \

306
nuttx/lib/lib_fgets.c Normal file
View File

@ -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 */

View File

@ -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)

View File

@ -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;

View File

@ -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;