📄 h8s_sci_serial.c
字号:
0, // no ISR for er interrupts
&ph8s_chan->serial_er_interrupt_handle,
&ph8s_chan->serial_er_interrupt);
cyg_drv_interrupt_attach(ph8s_chan->serial_er_interrupt_handle);
//
// This unmasks both interrupt sources.
//
cyg_drv_interrupt_unmask(ph8s_chan->rx_int_num);
} // End of if (chan->in_cbuf.len != 0)
ret = h8s_serial_config_port(pchan, &pchan->config, true);
return ret;
}
//==========================================================================
// SERIAL LOOK UP
// DESCRIPTION:
// This routine is called when the device is "looked" up (i.e. attached)
//
// ARGUMENTS:
// '**tab' Points to pointer to device tab entry of this driver
//
// RETURNS:
// ENOERR on success
//==========================================================================
static Cyg_ErrNo h8s_serial_lookup(
struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
serial_channel *pchan = (serial_channel *)(*tab)->priv;
//
// Really only required for interrupt driven devices
//
(pchan->callbacks->serial_init)(pchan);
return ENOERR;
}
//==========================================================================
// PUT CHAR TO DEVICE OUTPUT BUFFER
// DESCRIPTION:
// Send a character to the device output buffer.
//
// ARGUMENTS:
// '*pchan' Points to serial channel
// 'c' Char to bes sent
//
// RETURNS:
// 'true' if character is sent to device
//==========================================================================
static bool h8s_serial_putc(serial_channel *pchan, unsigned char c)
{
cyg_uint8 _ssr;
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
HAL_READ_UINT8(ph8s_chan->ctrl_base + SCI_SCSSR, _ssr);
//
// Check if transmit buffer is empty - that means it
//
if (_ssr & CYGARC_REG_SCSSR_TDRE)
{
//
// Transmit buffer is empty
//
HAL_WRITE_UINT8(ph8s_chan->ctrl_base + SCI_SCTDR, c);
//
// Clear empty flag.
//
HAL_WRITE_UINT8(ph8s_chan->ctrl_base + SCI_SCSSR,
CYGARC_REG_SCSSR_CLEARMASK & ~CYGARC_REG_SCSSR_TDRE);
return true;
}
else
{
//
// No space
//
return false;
}
}
//==========================================================================
// GET CHAR FROM DEVICE INPUT BUFFER
// DESCRIPTION:
// Fetch a character from the device input buffer, waiting if necessary
//
// ARGUMENTS:
// '*pchan' Points to serial channel
//
// RETURNS:
// Recveived character
//==========================================================================
static unsigned char h8s_serial_getc(serial_channel *pchan)
{
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
unsigned char c;
cyg_uint8 _ssr;
//
// Wait until we receive one character
//
do
{
HAL_READ_UINT8(ph8s_chan->ctrl_base + SCI_SCSSR, _ssr);
//
// Check if ORER, FER or PER received - we have to clear it
//
if(_ssr & CYGARC_REG_SCSSR_RCVERR)
{
_ssr &=~CYGARC_REG_SCSSR_RCVERR;
HAL_WRITE_UINT8(ph8s_chan->ctrl_base + SCI_SCSSR, _ssr);
}
}
while ((_ssr & CYGARC_REG_SCSSR_RDRF) == 0);
HAL_READ_UINT8(ph8s_chan->ctrl_base + SCI_SCRDR, c);
//
// Clear buffer full flag.
//
HAL_WRITE_UINT8(ph8s_chan->ctrl_base + SCI_SCSSR,
CYGARC_REG_SCSSR_CLEARMASK & ~CYGARC_REG_SCSSR_RDRF);
return c;
}
//==========================================================================
// SET UP DEVICE CHARACTERISTICS
// DESCRIPTION:
// Set up the device characteristics; baud rate, etc.
//
// ARGUMENTS:
// '*pchan' Points to serial channel
// 'key' Configuration key value
// '*pxbuf Points to xbuf
// '*plen' Points to lenof xbuf
//
// RETURNS:
// 'ENOERR' on success
// '-EINVAL' on error
//==========================================================================
static Cyg_ErrNo h8s_serial_set_config(
serial_channel *pchan,
cyg_uint32 key,
const void *pxbuf,
cyg_uint32 *plen)
{
switch (key)
{
case CYG_IO_SET_CONFIG_SERIAL_INFO:
{
cyg_serial_info_t *pconfig = (cyg_serial_info_t *)pxbuf;
if (*plen < sizeof(cyg_serial_info_t))
{
return -EINVAL;
}
*plen = sizeof(cyg_serial_info_t);
if (true != h8s_serial_config_port(pchan, pconfig, false))
{
return -EINVAL;
}
}
break;
default:
return -EINVAL;
} // End of switch (key)
return ENOERR;
}
//==========================================================================
// ENABLE TRANSMITTER
// DESCRIPTION:
// In interrupt mode, turn on the transmitter and allow for transmit
// interrupts.
//
// ARGUMENTS:
// '*pchan' Points to serial channel
//==========================================================================
static void h8s_serial_start_xmit(serial_channel *pchan)
{
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
ph8s_chan->tx_enabled = true;
//
// Mask the interrupts (all sources of the unit) while changing
// the CR since a rx interrupt in the middle of this would result
// in a bad CR state. cyg_drv_interrupt_umask is interrupt save -
// so there is no need to mask any other interrupts here
//
cyg_drv_interrupt_unmask(ph8s_chan->tx_int_num);
}
//==========================================================================
// DISABLE TRANSMITTER
// DESCRIPTION:
// In interrupt mode, turn off the transmitter.
//
// ARGUMENTS:
// '*pchan' Points to serial channel
//==========================================================================
static void h8s_serial_stop_xmit(serial_channel *pchan)
{
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
ph8s_chan->tx_enabled = false;
//
// Mask the interrupts (all sources of the unit) while changing
// the CR since a rx interrupt in the middle of this would result
// in a bad CR state. cyg_drv_interrupt_umask is interrupt save -
// so there is no need to mask any other interrupt here
//
// disable transmit interrupts
//
cyg_drv_interrupt_mask(ph8s_chan->tx_int_num);
}
//==========================================================================
// TX ISR
// DESCRIPTION:
// Serial I/O - tx interrupt handler (ISR). This handler will do only
// the minimum required low level stuff an then posts a DSR for
// further processing.
//
// ARGUMENTS:
// 'vector' Interrupt vector
// 'pdata' Points to interrupt data
//==========================================================================
static cyg_uint32 h8s_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t pdata)
{
serial_channel *pchan = (serial_channel *)pdata;
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
#if DEBUG & 1
int_cnt_tx_isr++;
#endif
//
// interrupts are disabled here in the ISR so we can call
// cyg_drv_interrupt_mask_intunsafe. We do not acknowledge the interrupt
// because the hardware independent driver calls putc later and this will
// clear the TDRE flag.
//
cyg_drv_interrupt_mask_intunsafe(ph8s_chan->tx_int_num);
//
// post DSR
//
return CYG_ISR_CALL_DSR | CYG_ISR_HANDLED;
}
//==========================================================================
// TX DSR
// DESCRIPTION:
// Serial I/O - high level tx interrupt handler (DSR)
//
// ARGUMENTS:
// 'vector' Interrupt vector
// 'count'
// 'pdata' Points to interrupt data
//==========================================================================
static void h8s_serial_tx_DSR(
cyg_vector_t vector,
cyg_ucount32 count,
cyg_addrword_t pdata)
{
serial_channel *pchan = (serial_channel *)pdata;
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
#if DEBUG & 1
int_cnt_tx_dsr++;
#endif
(pchan->callbacks->xmt_char)(pchan);
//
// if interrupts are enabled for this channel then turn them on now
//
if (ph8s_chan->tx_enabled)
{
//
// unmask tx interrupts - because in DSR interrupts are enabled we
// have to use cyg_drv_interrupt_unmask because it is interrupt safe
//
cyg_drv_interrupt_unmask(ph8s_chan->tx_int_num);
}
}
//==========================================================================
// RX ISR
// DESCRIPTION:
// Serial I/O - low level RX interrupt handler (ISR). This ISR handles
// only the minimum low level stuff and posts a DSR for further
// processing
//
// ARGUMENTS:
// 'vector' Interrupt vector
// 'pdata' Points to interrupt data
//==========================================================================
static cyg_uint32 h8s_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t pdata)
{
serial_channel *pchan = (serial_channel *)pdata;
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
#if DEBUG & 1
int_cnt_rx_isr++;
#endif
//
// mask out rx interrupts until the dsr execution completes and then
// acknowledge the interrrupt (this will clear the RDRF flag)
//
cyg_drv_interrupt_mask_intunsafe(ph8s_chan->rx_int_num);
//
// Cause DSR to run
//
return CYG_ISR_HANDLED | CYG_ISR_CALL_DSR;
}
//==========================================================================
// RX DSR
// DESCRIPTION:
// Serial I/O - high level rx interrupt handler (DSR)
//
// ARGUMENTS:
// 'vector' Interrupt vector
// 'count'
// 'pdata' Points to interrupt data
//==========================================================================
static void h8s_serial_rx_DSR(
cyg_vector_t vector,
cyg_ucount32 count,
cyg_addrword_t pdata)
{
serial_channel *pchan = (serial_channel *)pdata;
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
cyg_uint8 _c;
#if DEBUG & 1
int_cnt_rx_dsr++;
#endif
//
// read received char, acknowledge the interrupt and post
// received char to high level serial driver
//
HAL_READ_UINT8(ph8s_chan->ctrl_base + SCI_SCRDR, _c);
cyg_drv_interrupt_acknowledge(ph8s_chan->rx_int_num);
(pchan->callbacks->rcv_char)(pchan, _c);
//
// Now it is save to unmask interrupts again
//
cyg_drv_interrupt_unmask(ph8s_chan->rx_int_num);
}
//==========================================================================
// ERROR ISR
// DESCRIPTION:
// Serial I/O - low level error interrupt handler (ISR)
//
// ARGUMENTS:
// 'vector' Interrupt vector
// 'pdata' Points to interrupt data
//==========================================================================
static cyg_uint32 h8s_serial_er_ISR(cyg_vector_t vector, cyg_addrword_t pdata)
{
serial_channel *pchan = (serial_channel *)pdata;
h8s_sci_info *ph8s_chan = (h8s_sci_info *)pchan->dev_priv;
cyg_drv_interrupt_acknowledge(ph8s_chan->er_int_num);
//
// We do not use a DSR for failures
//
return CYG_ISR_HANDLED;
}
//---------------------------------------------------------------------------
#endif // #ifdef CYGDAT_IO_SERIAL_H8S_SCI_INL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -