?? sh_sci_serial.c
字號:
&sh_chan->serial_tx_interrupt);
cyg_drv_interrupt_attach(sh_chan->serial_tx_interrupt_handle);
cyg_drv_interrupt_unmask(sh_chan->tx_int_num);
sh_chan->tx_enabled = false;
}
if (chan->in_cbuf.len != 0) {
// Receive interrupt
cyg_drv_interrupt_create(sh_chan->rx_int_num,
3,
(cyg_addrword_t)chan, // Data item passed to interrupt handler
sh_serial_rx_ISR,
sh_serial_rx_DSR,
&sh_chan->serial_rx_interrupt_handle,
&sh_chan->serial_rx_interrupt);
cyg_drv_interrupt_attach(sh_chan->serial_rx_interrupt_handle);
// Receive error interrupt
cyg_drv_interrupt_create(sh_chan->er_int_num,
3,
(cyg_addrword_t)chan, // Data item passed to interrupt handler
sh_serial_er_ISR,
sh_serial_er_DSR,
&sh_chan->serial_er_interrupt_handle,
&sh_chan->serial_er_interrupt);
cyg_drv_interrupt_attach(sh_chan->serial_er_interrupt_handle);
// This unmasks both interrupt sources.
cyg_drv_interrupt_unmask(sh_chan->rx_int_num);
}
sh_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
sh_serial_lookup(struct cyg_devtab_entry **tab,
struct cyg_devtab_entry *sub_tab,
const char *name)
{
serial_channel *chan = (serial_channel *)(*tab)->priv;
// Really only required for interrupt driven devices
(chan->callbacks->serial_init)(chan);
return ENOERR;
}
// Send a character to the device output buffer.
// Return 'true' if character is sent to device
static bool
sh_serial_putc(serial_channel *chan, unsigned char c)
{
cyg_uint8 _ssr;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSSR, _ssr);
if (_ssr & CYGARC_REG_SCI_SCSSR_TDRE) {
// Transmit buffer is empty
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCTDR, c);
// Clear empty flag.
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSSR,
CYGARC_REG_SCI_SCSSR_CLEARMASK & ~CYGARC_REG_SCI_SCSSR_TDRE);
return true;
} else {
// No space
return false;
}
}
// Fetch a character from the device input buffer, waiting if necessary
static unsigned char
sh_serial_getc(serial_channel *chan)
{
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
unsigned char c;
cyg_uint8 _ssr;
do {
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSSR, _ssr);
} while ((_ssr & CYGARC_REG_SCI_SCSSR_RDRF) == 0);
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCRDR, c);
// Clear buffer full flag.
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSSR,
CYGARC_REG_SCI_SCSSR_CLEARMASK & ~CYGARC_REG_SCI_SCSSR_RDRF);
return c;
}
// Set up the device characteristics; baud rate, etc.
static Cyg_ErrNo
sh_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 != sh_serial_config_port(chan, config, false) )
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return ENOERR;
}
// Enable the transmitter on the device
static void
sh_serial_start_xmit(serial_channel *chan)
{
cyg_uint8 _scr;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
sh_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_mask(sh_chan->rx_int_num);
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr |= CYGARC_REG_SCI_SCSCR_TIE; // Enable xmit interrupt
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
cyg_drv_interrupt_unmask(sh_chan->rx_int_num);
}
// Disable the transmitter on the device
static void
sh_serial_stop_xmit(serial_channel *chan)
{
cyg_uint8 _scr;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
sh_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_mask(sh_chan->rx_int_num);
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr &= ~CYGARC_REG_SCI_SCSCR_TIE; // Disable xmit interrupt
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
cyg_drv_interrupt_unmask(sh_chan->rx_int_num);
}
// Serial I/O - low level tx interrupt handler (ISR)
static cyg_uint32
sh_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel *chan = (serial_channel *)data;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
cyg_uint8 _scr;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr &= ~CYGARC_REG_SCI_SCSCR_TIE; // mask out tx interrupts
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
return CYG_ISR_CALL_DSR; // Cause DSR to be run
}
// Serial I/O - high level tx interrupt handler (DSR)
static void
sh_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel *chan = (serial_channel *)data;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
(chan->callbacks->xmt_char)(chan);
if (sh_chan->tx_enabled) {
cyg_uint8 _scr;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr |= CYGARC_REG_SCI_SCSCR_TIE; // unmask tx interrupts
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
}
}
// Serial I/O - low level RX interrupt handler (ISR)
static cyg_uint32
sh_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel *chan = (serial_channel *)data;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
cyg_uint8 _scr;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr &= ~CYGARC_REG_SCI_SCSCR_RIE; // mask rx interrupts
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
return CYG_ISR_CALL_DSR; // Cause DSR to be run
}
// Serial I/O - high level rx interrupt handler (DSR)
static void
sh_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel *chan = (serial_channel *)data;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
cyg_uint8 _ssr, _scr;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSSR, _ssr);
if (_ssr & CYGARC_REG_SCI_SCSSR_RDRF) {
cyg_uint8 _c;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCRDR, _c);
// Clear buffer full flag.
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSSR,
CYGARC_REG_SCI_SCSSR_CLEARMASK & ~CYGARC_REG_SCI_SCSSR_RDRF);
(chan->callbacks->rcv_char)(chan, _c);
}
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr |= CYGARC_REG_SCI_SCSCR_RIE; // unmask rx interrupts
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
}
static volatile int sh_serial_error_orer = 0;
static volatile int sh_serial_error_fer = 0;
static volatile int sh_serial_error_per = 0;
// Serial I/O - low level error interrupt handler (ISR)
static cyg_uint32
sh_serial_er_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel *chan = (serial_channel *)data;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
cyg_uint8 _scr;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr &= ~CYGARC_REG_SCI_SCSCR_RIE; // mask rx interrupts
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
return CYG_ISR_CALL_DSR; // Cause DSR to be run
}
// Serial I/O - high level error interrupt handler (DSR)
static void
sh_serial_er_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel *chan = (serial_channel *)data;
sh_sci_info *sh_chan = (sh_sci_info *)chan->dev_priv;
cyg_uint8 _ssr, _ssr2, _scr;
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSSR, _ssr);
_ssr2 = CYGARC_REG_SCI_SCSSR_CLEARMASK;
if (_ssr & CYGARC_REG_SCI_SCSSR_ORER) {
_ssr2 &= ~CYGARC_REG_SCI_SCSSR_ORER;
sh_serial_error_orer++;
}
if (_ssr & CYGARC_REG_SCI_SCSSR_FER) {
_ssr2 &= ~CYGARC_REG_SCI_SCSSR_FER;
sh_serial_error_fer++;
}
if (_ssr & CYGARC_REG_SCI_SCSSR_PER) {
_ssr2 &= ~CYGARC_REG_SCI_SCSSR_PER;
sh_serial_error_per++;
}
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSSR, _ssr2);
HAL_READ_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
_scr |= CYGARC_REG_SCI_SCSCR_RIE; // unmask rx interrupts
HAL_WRITE_UINT8(sh_chan->ctrl_base+SCI_SCSCR, _scr);
}
#endif // ifdef CYGDAT_IO_SERIAL_SH_SCI_INL
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -