arch/sim/src/: Reimplement sim uart on top of serial driver framework

The benefits include:

1. Simplify the implementation
2. Support Ctrl+C automatically
3. Support poll automatically
4. Call pm_activity automatically
5. Save one polling thread
This commit is contained in:
Xiang Xiao 2020-02-08 07:52:26 -06:00 committed by Gregory Nutt
parent 6d69439f58
commit fa3e66fe82
6 changed files with 274 additions and 392 deletions

View File

@ -84,6 +84,7 @@ ifeq ($(CONFIG_SMP),y)
CSRCS += up_smpsignal.c up_smphook.c up_cpuidlestack.c
HOSTCFLAGS += -DCONFIG_SMP=1 -DCONFIG_SMP_NCPUS=$(CONFIG_SMP_NCPUS)
HOSTSRCS += up_simsmp.c
STDLIBS += -lpthread
endif
ifeq ($(CONFIG_SCHED_INSTRUMENTATION),y)
@ -94,7 +95,7 @@ endif
ifeq ($(CONFIG_DEV_CONSOLE),y)
ifneq ($(CONFIG_SYSLOG_RPMSG),y)
CSRCS += up_devconsole.c up_uartwait.c
CSRCS += up_devconsole.c
HOSTSRCS += up_simuart.c
endif
endif
@ -135,6 +136,7 @@ endif
ifeq ($(CONFIG_FS_FAT),y)
CSRCS += up_blockdevice.c up_deviceimage.c
STDLIBS += -lz
endif
ifeq ($(CONFIG_ARCH_ROMGETC),y)
@ -208,13 +210,6 @@ endif
EXTRA_LIBS ?=
EXTRA_LIBPATHS ?=
ifeq ($(CONFIG_FS_FAT),y)
STDLIBS += -lz
endif
STDLIBS += -lc
STDLIBS += -lpthread
# Determine which objects are required in the link. The
# up_head object normally draws in all that is needed, but
# there are a fews that must be included because they
@ -223,12 +218,6 @@ STDLIBS += -lpthread
LINKOBJS = up_head$(OBJEXT)
REQUIREDOBJS = $(LINKOBJS)
ifeq ($(CONFIG_DEV_CONSOLE),y)
ifneq ($(CONFIG_SYSLOG_RPMSG),y)
REQUIREDOBJS += up_uartwait$(OBJEXT)
endif
endif
ifeq ($(CONFIG_SIM_X11FB),y)
ifeq ($(CONFIG_SIM_TOUCHSCREEN),y)
REQUIREDOBJS += up_touchscreen$(OBJEXT)

View File

@ -38,37 +38,70 @@
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdbool.h>
#include <sched.h>
#include <errno.h>
#include <fcntl.h>
#include <nuttx/fs/fs.h>
#include <nuttx/serial/serial.h>
#include "up_internal.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define DEVCONSOLE_BUFSIZE 256
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static ssize_t devconsole_read(FAR struct file *filep, FAR char *buffer,
size_t buflen);
static ssize_t devconsole_write(FAR struct file *filep,
FAR const char *buffer, size_t buflen);
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup);
static int devconsole_setup(FAR struct uart_dev_s *dev);
static void devconsole_shutdown(FAR struct uart_dev_s *dev);
static int devconsole_attach(FAR struct uart_dev_s *dev);
static void devconsole_detach(FAR struct uart_dev_s *dev);
static int devconsole_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
static int devconsole_receive(FAR struct uart_dev_s *dev, uint32_t *status);
static void devconsole_rxint(FAR struct uart_dev_s *dev, bool enable);
static bool devconsole_rxavailable(FAR struct uart_dev_s *dev);
static void devconsole_send(FAR struct uart_dev_s *dev, int ch);
static void devconsole_txint(FAR struct uart_dev_s *dev, bool enable);
static bool devconsole_txready(FAR struct uart_dev_s *dev);
static bool devconsole_txempty(FAR struct uart_dev_s *dev);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct file_operations devconsole_fops =
static const struct uart_ops_s g_devconsole_ops =
{
.read = devconsole_read,
.write = devconsole_write,
.poll = devconsole_poll,
.setup = devconsole_setup,
.shutdown = devconsole_shutdown,
.attach = devconsole_attach,
.detach = devconsole_detach,
.ioctl = devconsole_ioctl,
.receive = devconsole_receive,
.rxint = devconsole_rxint,
.rxavailable = devconsole_rxavailable,
.send = devconsole_send,
.txint = devconsole_txint,
.txready = devconsole_txready,
.txempty = devconsole_txempty,
};
static char g_devconsole_rxbuf[DEVCONSOLE_BUFSIZE];
static char g_devconsole_txbuf[DEVCONSOLE_BUFSIZE];
static struct uart_dev_s g_devconsole_dev =
{
.isconsole = true,
.ops = &g_devconsole_ops,
.xmit =
{
.size = DEVCONSOLE_BUFSIZE,
.buffer = g_devconsole_txbuf,
},
.recv =
{
.size = DEVCONSOLE_BUFSIZE,
.buffer = g_devconsole_rxbuf,
},
};
/****************************************************************************
@ -76,83 +109,176 @@ static const struct file_operations devconsole_fops =
****************************************************************************/
/****************************************************************************
* Name: devconsole_read
* Name: devconsole_setup
*
* Description:
* Configure the UART baud, bits, parity, fifos, etc. This
* method is called the first time that the serial port is
* opened.
*
****************************************************************************/
static ssize_t devconsole_read(struct file *filep, char *buffer, size_t len)
{
size_t remaining = len;
ssize_t nread;
int ch;
/* Loop until all requested bytes have been read. No error checking */
sched_lock();
for (remaining = len, nread = 0; remaining > 0; remaining--)
{
/* Read the next character from the console, we should only wait
* on the first read.
*/
ch = simuart_getc(!(filep->f_oflags & O_NONBLOCK));
if (ch < 0)
{
/* errno is set in upper layer according to returned value */
sched_unlock();
return ch;
}
*buffer++ = ch;
nread++;
/* We have at least one character. Return now if no further
* characters are available without waiting.
*/
if (!simuart_checkc())
{
break;
}
}
sched_unlock();
return nread;
}
/****************************************************************************
* Name: devconsole_write
****************************************************************************/
static ssize_t devconsole_write(struct file *filep, const char *buffer, size_t len)
{
int remaining;
int ret = OK;
for (remaining = len; remaining > 0 && ret >= 0; remaining--)
{
unsigned char ch = *buffer++;
ret = simuart_putc((int)ch);
}
if (ret < 0)
{
return -ret;
}
return len;
}
/****************************************************************************
* Name: devconsole_poll
****************************************************************************/
static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds,
bool setup)
static int devconsole_setup(FAR struct uart_dev_s *dev)
{
return OK;
}
/****************************************************************************
* Name: devconsole_shutdown
*
* Description:
* Disable the UART. This method is called when the serial
* port is closed
*
****************************************************************************/
static void devconsole_shutdown(struct uart_dev_s *dev)
{
}
/****************************************************************************
* Name: devconsole_attach
*
* Description:
* Configure the UART to operation in interrupt driven mode. This method is
* called when the serial port is opened. Normally, this is just after the
* the setup() method is called, however, the serial console may operate in
* a non-interrupt driven mode during the boot phase.
*
* RX and TX interrupts are not enabled when by the attach method (unless the
* hardware supports multiple levels of interrupt enabling). The RX and TX
* interrupts are not enabled until the txint() and rxint() methods are called.
*
****************************************************************************/
static int devconsole_attach(struct uart_dev_s *dev)
{
return OK;
}
/****************************************************************************
* Name: devconsole_detach
*
* Description:
* Detach UART interrupts. This method is called when the serial port is
* closed normally just before the shutdown method is called. The exception is
* the serial console which is never shutdown.
*
****************************************************************************/
static void devconsole_detach(FAR struct uart_dev_s *dev)
{
}
/****************************************************************************
* Name: devconsole_ioctl
*
* Description:
* All ioctl calls will be routed through this method
*
****************************************************************************/
static int devconsole_ioctl(struct file *filep, int cmd, unsigned long arg)
{
return -ENOTTY;
}
/****************************************************************************
* Name: devconsole_receive
*
* Description:
* Called (usually) from the interrupt level to receive one
* character from the UART. Error bits associated with the
* receipt are provided in the return 'status'.
*
****************************************************************************/
static int devconsole_receive(struct uart_dev_s *dev, uint32_t *status)
{
*status = 0;
return simuart_getc();
}
/****************************************************************************
* Name: devconsole_rxint
*
* Description:
* Call to enable or disable RX interrupts
*
****************************************************************************/
static void devconsole_rxint(struct uart_dev_s *dev, bool enable)
{
}
/****************************************************************************
* Name: devconsole_rxavailable
*
* Description:
* Return true if the receive fifo is not empty
*
****************************************************************************/
static bool devconsole_rxavailable(struct uart_dev_s *dev)
{
return simuart_checkc();
}
/****************************************************************************
* Name: devconsole_send
*
* Description:
* This method will send one byte on the UART
*
****************************************************************************/
static void devconsole_send(struct uart_dev_s *dev, int ch)
{
simuart_putc(ch);
}
/****************************************************************************
* Name: devconsole_txint
*
* Description:
* Call to enable or disable TX interrupts
*
****************************************************************************/
static void devconsole_txint(struct uart_dev_s *dev, bool enable)
{
if (enable)
{
uart_xmitchars(&g_devconsole_dev);
}
}
/****************************************************************************
* Name: devconsole_txready
*
* Description:
* Return true if the tranmsit fifo is not full
*
****************************************************************************/
static bool devconsole_txready(struct uart_dev_s *dev)
{
return true;
}
/****************************************************************************
* Name: devconsole_txempty
*
* Description:
* Return true if the transmit fifo is empty
*
****************************************************************************/
static bool devconsole_txempty(struct uart_dev_s *dev)
{
return true;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -163,7 +289,20 @@ static int devconsole_poll(FAR struct file *filep, FAR struct pollfd *fds,
void up_devconsole(void)
{
register_driver("/dev/console", &devconsole_fops, 0666, NULL);
uart_register("/dev/console", &g_devconsole_dev);
uart_register("/dev/ttyS0", &g_devconsole_dev);
}
/****************************************************************************
* Name: up_devconloop
****************************************************************************/
void up_devconloop(void)
{
if (simuart_checkc())
{
uart_recvchars(&g_devconsole_dev);
}
}
/****************************************************************************

View File

@ -1,7 +1,8 @@
/****************************************************************************
* arch/sim/src/sim/up_idle.c
*
* Copyright (C) 2007-2009, 2011-2012, 2014, 2016 Gregory Nutt. All rights reserved.
* Copyright (C) 2007-2009, 2011-2012, 2014, 2016, 2020 Gregory Nutt. All
* rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
@ -44,10 +45,6 @@
#include <nuttx/arch.h>
#ifdef CONFIG_PM
# include <nuttx/power/pm.h>
#endif
#ifdef CONFIG_SMP
# include <nuttx/spinlock.h>
#endif
@ -132,14 +129,7 @@ void up_idle(void)
#ifdef USE_DEVCONSOLE
/* Handle UART data availability */
if (g_uart_data_available)
{
#ifdef CONFIG_PM
pm_activity(PM_IDLE_DOMAIN, 100); /* Report important activity to PM */
#endif
g_uart_data_available = 0;
simuart_post();
}
up_devconloop();
#endif
#if defined(CONFIG_NET_ETHERNET) && defined(CONFIG_SIM_NETDEV)

View File

@ -98,7 +98,7 @@
# endif
#endif
/* Context Switching Definitions ******************************************/
/* Context Switching Definitions ********************************************/
#if defined(CONFIG_HOST_X86_64) && !defined(CONFIG_SIM_M32)
/* Storage order: %rbx, %rsp, %rbp, %r12, %r13, %r14, %r15, %rip */
@ -155,7 +155,7 @@
# define JB_PC 9
#endif
/* Simulated Heap Definitions **********************************************/
/* Simulated Heap Definitions ***********************************************/
/* Size of the simulated heap */
@ -204,10 +204,6 @@ extern volatile int g_eventloop;
#endif
#endif
#ifdef USE_DEVCONSOLE
extern volatile int g_uart_data_available;
#endif
#ifdef CONFIG_SMP
/* These spinlocks are used in the SMP configuration in order to implement
* up_cpu_pause(). The protocol for CPUn to pause CPUm is as follows
@ -231,42 +227,42 @@ volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS] SP_SECTION;
* Public Function Prototypes
****************************************************************************/
/* up_setjmp32.S **********************************************************/
/* up_setjmp32.S ************************************************************/
int up_setjmp(xcpt_reg_t *jb);
void up_longjmp(xcpt_reg_t *jb, int val) noreturn_function;
/* up_hostusleep.c ********************************************************/
/* up_hostusleep.c **********************************************************/
int up_hostusleep(unsigned int usec);
/* up_simsmp.c ************************************************************/
/* up_simsmp.c **************************************************************/
#ifdef CONFIG_SMP
int sim_cpu0_initialize(void);
void sim_cpu0_start(void);
#endif
/* up_smpsignal.c *********************************************************/
/* up_smpsignal.c ***********************************************************/
#ifdef CONFIG_SMP
void sim_cpu_pause(int cpu, FAR volatile spinlock_t *wait,
FAR volatile unsigned char *paused);
#endif
/* up_smphook.c ***********************************************************/
/* up_smphook.c *************************************************************/
#ifdef CONFIG_SMP
void sim_smp_hook(void);
#endif
/* up_tickless.c **********************************************************/
/* up_tickless.c ************************************************************/
#ifdef CONFIG_SCHED_TICKLESS
void up_timer_update(void);
#endif
/* rpmsg_serialinit *******************************************************/
/* rpmsg_serialinit *********************************************************/
#ifdef CONFIG_RPMSG_UART
void rpmsg_serialinit(void);
@ -274,35 +270,30 @@ void rpmsg_serialinit(void);
# define rpmsg_serialinit()
#endif
/* up_devconsole.c ********************************************************/
/* up_devconsole.c **********************************************************/
void up_devconsole(void);
void up_registerblockdevice(void);
void up_devconloop(void);
/* up_simuart.c ***********************************************************/
/* up_simuart.c *************************************************************/
void simuart_start(void);
int simuart_putc(int ch);
int simuart_getc(bool block);
int simuart_getc(void);
bool simuart_checkc(void);
/* up_uartwait.c **********************************************************/
void simuart_initialize(void);
void simuart_post(void);
void simuart_wait(void);
/* up_deviceimage.c *******************************************************/
/* up_deviceimage.c *********************************************************/
char *up_deviceimage(void);
void up_registerblockdevice(void);
/* up_netdev.c ************************************************************/
/* up_netdev.c **************************************************************/
#ifdef CONFIG_NET
unsigned long up_getwalltime(void);
#endif
/* up_x11framebuffer.c ****************************************************/
/* up_x11framebuffer.c ******************************************************/
#ifdef CONFIG_SIM_X11FB
int up_x11initialize(unsigned short width, unsigned short height,
@ -315,45 +306,45 @@ int up_x11cmap(unsigned short first, unsigned short len,
#endif
#endif
/* up_touchscreen.c *******************************************************/
/* up_touchscreen.c *********************************************************/
int sim_tsc_initialize(int minor);
void sim_tsc_uninitialize(void);
/* up_pminitialize.c ******************************************************/
/* up_pminitialize.c ********************************************************/
#ifdef CONFIG_PM
void up_pminitialize(void);
#endif
/* up_eventloop.c *********************************************************/
/* up_eventloop.c ***********************************************************/
#if defined(CONFIG_SIM_X11FB) && \
(defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK))
void up_x11events(void);
#endif
/* up_eventloop.c *********************************************************/
/* up_eventloop.c ***********************************************************/
#if defined(CONFIG_SIM_X11FB) && \
(defined(CONFIG_SIM_TOUCHSCREEN) || defined(CONFIG_SIM_AJOYSTICK))
int up_buttonevent(int x, int y, int buttons);
#endif
/* up_ajoystick.c *********************************************************/
/* up_ajoystick.c ***********************************************************/
#ifdef CONFIG_SIM_AJOYSTICK
int sim_ajoy_initialize(void);
#endif
/* up_ioexpander.c ********************************************************/
/* up_ioexpander.c **********************************************************/
#ifdef CONFIG_SIM_IOEXPANDER
struct ioexpander_dev_s;
FAR struct ioexpander_dev_s *sim_ioexpander_initialize(void);
#endif
/* up_tapdev.c ************************************************************/
/* up_tapdev.c **************************************************************/
#if defined(CONFIG_NET_ETHERNET) && !defined(__CYGWIN__)
void tapdev_init(void);
@ -369,7 +360,7 @@ void tapdev_ifdown(void);
# define netdev_ifdown() tapdev_ifdown()
#endif
/* up_wpcap.c *************************************************************/
/* up_wpcap.c ***************************************************************/
#if defined(CONFIG_NET_ETHERNET) && defined(__CYGWIN__)
void wpcap_init(void);
@ -383,7 +374,7 @@ void wpcap_send(unsigned char *buf, unsigned int buflen);
# define netdev_ifdown() {}
#endif
/* up_netdriver.c *********************************************************/
/* up_netdriver.c ***********************************************************/
#ifdef CONFIG_NET_ETHERNET
int netdriver_init(void);
@ -393,12 +384,12 @@ void netdriver_loop(void);
#ifdef CONFIG_RPTUN
/* up_shmem.c *************************************************************/
/* up_shmem.c ***************************************************************/
void *shmem_open(const char *name, size_t size, int master);
void shmem_close(void *mem);
/* up_rptun.c *************************************************************/
/* up_rptun.c ***************************************************************/
int up_rptun_init(void);
void up_rptun_loop(void);

View File

@ -42,42 +42,7 @@
#include <string.h>
#include <stdlib.h>
#include <termios.h>
#include <pthread.h>
#include <errno.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Simulated console UART input buffer size */
/* Must match the defintion in up_internal.h */
#define SIMUART_BUFSIZE 256
/****************************************************************************
* Private Data
****************************************************************************/
static char g_uartbuffer[SIMUART_BUFSIZE];
static volatile int g_uarthead;
static volatile int g_uarttail;
/****************************************************************************
* Public Data
****************************************************************************/
volatile int g_uart_data_available;
/****************************************************************************
* NuttX Domain Public Function Prototypes
****************************************************************************/
void sched_lock(void);
void sched_unlock(void);
void simuart_initialize(void);
void simuart_post(void);
void simuart_wait(void);
#include <poll.h>
/****************************************************************************
* Private Data
@ -125,67 +90,6 @@ static void restoremode(void)
tcsetattr(0, TCSANOW, &g_cooked);
}
/****************************************************************************
* Name: simuart_thread
****************************************************************************/
static void *simuart_thread(void *arg)
{
unsigned char ch;
ssize_t nread;
int next;
int prev;
/* Now loop, collecting a buffering data from stdin forever */
for (; ; )
{
/* Read one character from stdin */
nread = read(0, &ch, 1);
/* Check for failures (but don't do anything) */
if (nread == 1)
{
/* Get the index to the next slot in the UART buffer */
prev = g_uarthead;
next = prev + 1;
if (next >= SIMUART_BUFSIZE)
{
next = 0;
}
/* Would adding this character cause an overflow? */
if (next != g_uarttail)
{
/* No.. Add the character to the UART buffer */
g_uartbuffer[prev] = ch;
/* Update the head index (BEFORE posting) */
g_uarthead = next;
/* Was the buffer previously empty? */
if (prev == g_uarttail)
{
/* Yes.. signal any (NuttX) threads waiting for serial
* input.
*/
g_uart_data_available = 1;
}
}
}
}
return NULL;
}
/****************************************************************************
* Name: simuart_putraw
****************************************************************************/
@ -213,13 +117,6 @@ int simuart_putraw(int ch)
void simuart_start(void)
{
pthread_t tid;
/* This thread runs in the host domain */
/* Perform the NuttX domain initialization */
simuart_initialize();
/* Put stdin into raw mode */
setrawmode();
@ -227,12 +124,6 @@ void simuart_start(void)
/* Restore the original terminal mode before exit */
atexit(restoremode);
/* Start the simulated UART thread -- all default settings; no error
* checking.
*/
pthread_create(&tid, NULL, simuart_thread, NULL);
}
/****************************************************************************
@ -260,56 +151,24 @@ int simuart_putc(int ch)
* Name: simuart_getc
****************************************************************************/
int simuart_getc(bool block)
int simuart_getc(void)
{
int index;
int ret;
int ch;
/* Locking the scheduler should eliminate the race conditions in the
* unlikely case of multiple reading threads.
*/
sched_lock();
for (; ; )
{
/* Wait for a byte to become available */
if (!block && (g_uarthead == g_uarttail))
{
sched_unlock();
return -EAGAIN;
}
while (g_uarthead == g_uarttail)
{
simuart_wait();
}
/* The UART buffer is non-empty... Take the next byte from the tail
* of the buffer.
*/
index = g_uarttail;
ch = (int)g_uartbuffer[index];
/* Increment the tai index (with wrapping) */
if (++index >= SIMUART_BUFSIZE)
{
index = 0;
}
g_uarttail = index;
sched_unlock();
return ch;
}
ret = read(0, &ch, 1);
return ret < 0 ? ret : ch;
}
/****************************************************************************
* Name: simuart_getc
* Name: simuart_checkc
****************************************************************************/
bool simuart_checkc(void)
{
return g_uarthead != g_uarttail;
struct pollfd pfd;
pfd.fd = 0;
pfd.events = POLLIN;
return poll(&pfd, 1, 0) == 1;
}

View File

@ -1,86 +0,0 @@
/****************************************************************************
* arch/sim/src/sim/up_uartwait.c
*
* Copyright (C) 2014 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 NuttX 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/semaphore.h>
#include "up_internal.h"
/****************************************************************************
* Private Data
****************************************************************************/
static sem_t g_uartavail;
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: simuart_initialize
****************************************************************************/
void simuart_initialize(void)
{
/* The g_uartavail semaphore is used for signaling and, hence, should not
* have priority inheritance enabled.
*/
nxsem_init(&g_uartavail, 0, 0);
nxsem_setprotocol(&g_uartavail, SEM_PRIO_NONE);
}
/****************************************************************************
* Name: simuart_post
****************************************************************************/
void simuart_post(void)
{
nxsem_post(&g_uartavail);
}
/****************************************************************************
* Name: simuart_wait
****************************************************************************/
void simuart_wait(void)
{
/* Should only fail if interrupted by a signal */
while (nxsem_wait(&g_uartavail) < 0);
}