📄 cme555_serial_with_ints.c
字号:
// Disable port interrupts while changing hardware
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
old_isrstate = sccxr;
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_LOOPS);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_WOMS);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_ILT);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PT);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_M);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_WAKE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RWU);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_SBK);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TIE);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TCIE);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RIE);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_ILIE);
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
// Set databits, stopbits and parity.
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
if(frame_length == 11)
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_M;
else
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_M);
switch(new_config->parity)
{
case CYGNUM_SERIAL_PARITY_NONE:
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PE);
break;
case CYGNUM_SERIAL_PARITY_EVEN:
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PE;
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PT);
break;
case CYGNUM_SERIAL_PARITY_ODD:
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PE;
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PT;
break;
default:
break;
}
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
// Set baud rate.
baud_rate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR0_OTHR);
baud_rate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR0_LINKBD);
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR0, sccxr);
sccxr &= ~(MPC555_SERIAL_SCCxR0_SCxBR);
sccxr |= baud_rate;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR0, sccxr);
// Enable the device
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
sccxr |= MPC555_SERIAL_SCCxR1_TE;
sccxr |= MPC555_SERIAL_SCCxR1_RE;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
if(init)
{ // enable the receiver interrupt
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
sccxr |= MPC555_SERIAL_SCCxR1_RIE;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
}
else // Restore the old interrupt state
{
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
sccxr |= old_isrstate;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
}
if(new_config != &chan->config)
chan->config = *new_config;
return true;
}
//--------------------------------------------------------------
// Function to initialize the device. Called at bootstrap time.
//--------------------------------------------------------------
static hal_mpc5xx_arbitration_data arbiter;
static bool mpc555_serial_init(struct cyg_devtab_entry * tab)
{
serial_channel * chan = (serial_channel *)tab->priv;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
if(!mpc555_serial_config_port(chan, &chan->config, true))
return false;
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
if(chan->out_cbuf.len != 0)
{
arbiter.priority = CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI;
arbiter.data = 0;
arbiter.arbiter = hal_arbitration_isr_qsci;
// Install the arbitration isr, Make sure that is is not installed twice
hal_mpc5xx_remove_arbitration_isr(CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI);
hal_mpc5xx_install_arbitration_isr(&arbiter);
// Create the Tx interrupt, do not enable it yet
cyg_drv_interrupt_create(mpc555_chan->tx_interrupt_num,
mpc555_chan->tx_interrupt_priority,
(cyg_addrword_t)chan, // Data item passed to interrupt handler
mpc555_serial_tx_ISR,
mpc555_serial_tx_DSR,
&mpc555_chan->tx_interrupt_handle,
&mpc555_chan->tx_interrupt);
cyg_drv_interrupt_attach(mpc555_chan->tx_interrupt_handle);
// Create the Rx interrupt, this can be safely unmasked now
cyg_drv_interrupt_create(mpc555_chan->rx_interrupt_num,
mpc555_chan->rx_interrupt_priority,
(cyg_addrword_t)chan,
mpc555_serial_rx_ISR,
mpc555_serial_rx_DSR,
&mpc555_chan->rx_interrupt_handle,
&mpc555_chan->rx_interrupt);
cyg_drv_interrupt_attach(mpc555_chan->rx_interrupt_handle);
cyg_drv_interrupt_unmask(mpc555_chan->rx_interrupt_num);
}
return true;
}
//----------------------------------------------------------------------
// This routine is called when the device is "looked" up (i.e. attached)
//----------------------------------------------------------------------
static Cyg_ErrNo mpc555_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;
}
//----------------------------------------------
// Send a character to the device output buffer.
// Return 'true' if character is sent to device
//----------------------------------------------
static bool mpc555_serial_putc(serial_channel * chan, unsigned char c)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_addrword_t port = mpc555_chan->base;
cyg_uint16 scsr;
cyg_uint16 scdr;
HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
if(scsr & MPC555_SERIAL_SCxSR_TDRE)
{ // Ok, we have space, write the character and return success
scdr = (cyg_uint16)c;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxDR, scdr);
return true;
}
else
// We cannot write to the transmitter, return failure
return false;
}
//---------------------------------------------------------------------
// Fetch a character from the device input buffer, waiting if necessary
//---------------------------------------------------------------------
static unsigned char mpc555_serial_getc(serial_channel * chan)
{
unsigned char c;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_addrword_t port = mpc555_chan->base;
cyg_uint16 scsr;
cyg_uint16 scdr;
do {
HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
} while(!(scsr & MPC555_SERIAL_SCxSR_RDRF));
// Ok, data is received, read it out and return
HAL_READ_UINT16(port + MPC555_SERIAL_SCxDR, scdr);
c = (unsigned char)scdr;
return c;
}
//---------------------------------------------------
// Set up the device characteristics; baud rate, etc.
//---------------------------------------------------
static bool mpc555_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 != mpc555_serial_config_port(chan, config, false))
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return ENOERR;
}
//-------------------------------------
// Enable the transmitter on the device
//-------------------------------------
static void mpc555_serial_start_xmit(serial_channel * chan)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
mpc555_chan->tx_interrupt_enable = true;
cyg_drv_interrupt_unmask(mpc555_chan->tx_interrupt_num);
// No need to call xmt_char, this will generate an interrupt immediately.
}
//--------------------------------------
// Disable the transmitter on the device
//--------------------------------------
static void mpc555_serial_stop_xmit(serial_channel * chan)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_drv_dsr_lock();
mpc555_chan->tx_interrupt_enable = false;
cyg_drv_interrupt_mask(mpc555_chan->tx_interrupt_num);
cyg_drv_dsr_unlock();
}
//-----------------------------------------
// The low level transmit interrupt handler
//-----------------------------------------
static cyg_uint32 mpc555_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_drv_interrupt_mask(mpc555_chan->tx_interrupt_num);
cyg_drv_interrupt_acknowledge(mpc555_chan->tx_interrupt_num);
return CYG_ISR_CALL_DSR; // cause the DSR to run
}
//----------------------------------------
// The low level receive interrupt handler
//----------------------------------------
static cyg_uint32 mpc555_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_drv_interrupt_mask(mpc555_chan->rx_interrupt_num);
cyg_drv_interrupt_acknowledge(mpc555_chan->rx_interrupt_num);
return CYG_ISR_CALL_DSR; // cause the DSR to run
}
//------------------------------------------
// The high level transmit interrupt handler
//------------------------------------------
static void mpc555_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
(chan->callbacks->xmt_char)(chan);
if(mpc555_chan->tx_interrupt_enable)
cyg_drv_interrupt_unmask(mpc555_chan->tx_interrupt_num);
}
//-----------------------------------------
// The high level receive interrupt handler
//-----------------------------------------
#define MPC555_SERIAL_SCxSR_ERRORS (MPC555_SERIAL_SCxSR_OR | \
MPC555_SERIAL_SCxSR_NF | \
MPC555_SERIAL_SCxSR_FE | \
MPC555_SERIAL_SCxSR_PF)
static void mpc555_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_addrword_t port = mpc555_chan->base;
cyg_uint16 scdr;
cyg_uint16 scsr;
// Allways read out the received character, in order to clear receiver flags
HAL_READ_UINT16(port + MPC555_SERIAL_SCxDR, scdr);
HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
if(scsr & (cyg_uint16)MPC555_SERIAL_SCxSR_ERRORS)
{
scsr &= ~((cyg_uint16)MPC555_SERIAL_SCxSR_ERRORS);
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
}
else
{
(chan->callbacks->rcv_char)(chan, (cyg_uint8)scdr);
}
cyg_drv_interrupt_unmask(mpc555_chan->rx_interrupt_num);
}
#endif // CYGPKG_IO_SERIAL_POWERPC_CME555
// EOF cmd555_serial_with_ints.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -