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:
parent
132b1d0f43
commit
156791e5fb
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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 */
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue