📄 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 + -