📄 loop_serial.c
字号:
// And finally, the device table entries:
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL0
DEVTAB_ENTRY(loop_serial_io0,
CYGDAT_IO_SERIAL_LOOP_SERIAL0_NAME,
0, // Does not depend on a lower level interface
&cyg_io_serial_devio,
loop_serial_init,
loop_serial_lookup, // Serial driver may need initializing
&loop_serial_channel0
);
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL0
#ifdef CYGPKG_IO_SERIAL_LOOP_SERIAL1
DEVTAB_ENTRY(loop_serial_io1,
CYGDAT_IO_SERIAL_LOOP_SERIAL1_NAME,
0, // Does not depend on a lower level interface
&cyg_io_serial_devio,
loop_serial_init,
loop_serial_lookup, // Serial driver may need initializing
&loop_serial_channel1
);
#endif // CYGPKG_IO_SERIAL_LOOP_SERIAL1
//-------------------------------------------------------------------------
static bool
loop_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init)
{
// loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
if (new_config != &chan->config) {
chan->config = *new_config;
}
return true;
}
//-------------------------------------------------------------------------
// Function to initialize the device. Called at bootstrap time.
bool loop_serial_init(struct cyg_devtab_entry *tab)
{
serial_channel *chan = (serial_channel *)tab->priv;
// loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE
// Set up alarm for feeding data back into channels
cyg_alarm_create( cyg_real_time_clock(),
alarm_handler,
0,
&alarm_handle,
&alarm_obj);
cyg_alarm_initialize( alarm_handle, 1, 1 );
#endif
loop_serial_config_port(chan, &chan->config, true);
return true;
}
//-------------------------------------------------------------------------
// This routine is called when the device is "looked" up (i.e. attached)
static Cyg_ErrNo
loop_serial_lookup(struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
serial_channel *chan = (serial_channel *)(*tab)->priv;
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
return ENOERR;
}
//-------------------------------------------------------------------------
// Return 'true' if character is sent to device
bool
loop_serial_putc(serial_channel *chan, unsigned char c)
{
loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
struct fifo *f = loop_chan->write_fifo;
if( f->num == FIFO_SIZE )
return false;
f->buf[f->tail] = c;
f->num++;
f->tail++;
if( f->tail == sizeof(f->buf) )
f->tail = 0;
return true;
}
//-------------------------------------------------------------------------
unsigned char
loop_serial_getc(serial_channel *chan)
{
unsigned char c;
loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
struct fifo *f = loop_chan->read_fifo;
while( f->num == 0 )
continue;
c = f->buf[f->head];
f->num--;
f->head++;
if( f->head == sizeof(f->buf) )
f->head = 0;
return c;
}
//-------------------------------------------------------------------------
static Cyg_ErrNo
loop_serial_set_config(serial_channel *chan, cyg_uint32 key,
const void *xbuf, cyg_uint32 *len)
{
switch (key) {
case CYG_IO_SET_CONFIG_SERIAL_INFO:
{
cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
if ( *len < sizeof(cyg_serial_info_t) ) {
return -EINVAL;
}
*len = sizeof(cyg_serial_info_t);
if ( true != loop_serial_config_port(chan, config, false) )
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return ENOERR;
}
//-------------------------------------------------------------------------
// Enable the transmitter on the device
static void
loop_serial_start_xmit(serial_channel *chan)
{
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE
loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
loop_chan->write_fifo->tx_enable = true;
(chan->callbacks->xmt_char)(chan);
#endif
}
//-------------------------------------------------------------------------
// Disable the transmitter on the device
static void
loop_serial_stop_xmit(serial_channel *chan)
{
#ifndef CYGPKG_IO_SERIAL_LOOP_POLLED_MODE
loop_serial_info *loop_chan = (loop_serial_info *)chan->dev_priv;
loop_chan->write_fifo->tx_enable = false;
#endif
}
//-------------------------------------------------------------------------
static void alarm_handler(cyg_handle_t alarm, cyg_addrword_t data)
{
serial_channel *chan0 = &loop_serial_channel0;
serial_channel *chan1 = &loop_serial_channel1;
while( fifo0.num )
{
// Data ready for delivery to serial1
struct fifo *f = &fifo0;
char c;
c = f->buf[f->head];
f->num--;
f->head++;
if( f->head == sizeof(f->buf) )
f->head = 0;
(chan1->callbacks->rcv_char)(chan1, c);
if( f->tx_enable )
(chan0->callbacks->xmt_char)(chan0);
}
while( fifo1.num )
{
// Data ready for delivery to serial0
struct fifo *f = &fifo1;
char c;
c = f->buf[f->head];
f->num--;
f->head++;
if( f->head == sizeof(f->buf) )
f->head = 0;
(chan0->callbacks->rcv_char)(chan0, c);
if( f->tx_enable )
(chan1->callbacks->xmt_char)(chan1);
}
}
#endif // CYGPKG_IO_SERIAL_LOOP
//-------------------------------------------------------------------------
// EOF loop.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -