📄 ebsa285_serial.c
字号:
// ------------------------------------------------------------------------// ------------------------------------------------------------------------// Internal function to actually configure the hardware to desired baud rate, etc.static boolebsa285_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init){ int dummy, h, m, l; // Make sure everything is off *SA110_UART_CONTROL_REGISTER = SA110_UART_DISABLED | SA110_SIR_DISABLED; // Read the RXStat to drain the fifo dummy = *SA110_UART_RXSTAT; // Set the baud rate - this also turns the uart on. // // Note that the ordering of these writes is critical, // and the writes to the H_BAUD_CONTROL and CONTROL_REGISTER // are necessary to force the UART to update its register // contents. l = bauds[new_config->baud].divisor_low; // zeros in unused slots here m = bauds[new_config->baud].divisor_high; // and here h = SA110_UART_BREAK_DISABLED | select_stop_bits[new_config->stop] | // -1s in unused slots for these select_parity[new_config->parity] | // and these SA110_UART_FIFO_ENABLED | // and these below select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5]; if ( 0 != (l + m) && h >= 0 && h < 256 ) { *SA110_UART_L_BAUD_CONTROL = l; *SA110_UART_M_BAUD_CONTROL = m; *SA110_UART_H_BAUD_CONTROL = h; init = true; // AOK } else if ( init ) { // put in some sensible defaults *SA110_UART_L_BAUD_CONTROL = 0x13; // bp->divisor_low; *SA110_UART_M_BAUD_CONTROL = 0x00; // bp->divisor_high; *SA110_UART_H_BAUD_CONTROL = SA110_UART_BREAK_DISABLED | SA110_UART_PARITY_DISABLED | SA110_UART_STOP_BITS_ONE | SA110_UART_FIFO_ENABLED | SA110_UART_DATA_LENGTH_8_BITS; } // All set, re-enable the device: *SA110_UART_CONTROL_REGISTER = SA110_UART_ENABLED | SA110_SIR_DISABLED; if (init && new_config != &chan->config) { // record the new setup chan->config = *new_config; } // All done return init;}// Function to initialize the device. Called at bootstrap time.static bool ebsa285_serial_init(struct cyg_devtab_entry *tab){ serial_channel *chan = (serial_channel *)tab->priv; ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv;#ifdef CYGDBG_IO_INIT diag_printf("EBSA285 SERIAL init - dev: %x.%d\n", ebsa285_chan->base, ebsa285_chan->int_num);#endif (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices if (chan->out_cbuf.len != 0) { // first for rx cyg_drv_interrupt_create(ebsa285_chan->rx.int_num, 99, // Priority - unused (cyg_addrword_t)chan, // Data item passed to interrupt handler ebsa285_serial_rx_ISR, ebsa285_serial_rx_DSR, &ebsa285_chan->rx.serial_interrupt_handle, &ebsa285_chan->rx.serial_interrupt); cyg_drv_interrupt_attach(ebsa285_chan->rx.serial_interrupt_handle); cyg_drv_interrupt_unmask(ebsa285_chan->rx.int_num); // then for tx cyg_drv_interrupt_create(ebsa285_chan->tx.int_num, 99, // Priority - unused (cyg_addrword_t)chan, // Data item passed to interrupt handler ebsa285_serial_tx_ISR, ebsa285_serial_tx_DSR, &ebsa285_chan->tx.serial_interrupt_handle, &ebsa285_chan->tx.serial_interrupt); cyg_drv_interrupt_attach(ebsa285_chan->tx.serial_interrupt_handle); // DO NOT cyg_drv_interrupt_unmask(ebsa285_chan->tx.int_num); } (void)ebsa285_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 ebsa285_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 devicestatic boolebsa285_serial_putc(serial_channel *chan, unsigned char c){ if ((*SA110_UART_FLAG_REGISTER & SA110_TX_FIFO_STATUS_MASK) == SA110_TX_FIFO_BUSY) return false; // No space *SA110_UART_DATA_REGISTER = c; // Transmit buffer is empty return true;}// Fetch a character from the device input buffer, waiting if necessarystatic unsigned char ebsa285_serial_getc(serial_channel *chan){ unsigned char c; while ((*SA110_UART_FLAG_REGISTER & SA110_RX_FIFO_STATUS_MASK) == SA110_RX_FIFO_EMPTY) ; // wait for char c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); // no error checking... no way to return the info return c;}// Set up the device characteristics; baud rate, etc.static bool ebsa285_serial_set_config(serial_channel *chan, cyg_serial_info_t *config){ return ebsa285_serial_config_port(chan, config, false);}// Enable the transmitter on the device (nope, already in use by hal_diag)static voidebsa285_serial_start_xmit(serial_channel *chan){ ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv; cyg_drv_interrupt_unmask(ebsa285_chan->tx.int_num);}// Disable the transmitter on the device (nope, remains in use by hal_diag)static void ebsa285_serial_stop_xmit(serial_channel *chan){ ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(ebsa285_chan->tx.int_num);}// Serial I/O - low level interrupt handlers (ISR)static cyg_uint32 ebsa285_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(ebsa285_chan->rx.int_num); cyg_drv_interrupt_acknowledge(ebsa285_chan->rx.int_num); return CYG_ISR_CALL_DSR; // Cause DSR to be run}static cyg_uint32 ebsa285_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(ebsa285_chan->tx.int_num); cyg_drv_interrupt_acknowledge(ebsa285_chan->tx.int_num); return CYG_ISR_CALL_DSR; // Cause DSR to be run}// Serial I/O - high level interrupt handlers (DSR)static void ebsa285_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv; if ((*SA110_UART_FLAG_REGISTER & SA110_RX_FIFO_STATUS_MASK) != SA110_RX_FIFO_EMPTY) { char c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); int status; c = (char)(*SA110_UART_DATA_REGISTER & 0xFF); status = *SA110_UART_RXSTAT; if ( 0 == (status & (SA110_UART_FRAMING_ERROR_MASK | SA110_UART_PARITY_ERROR_MASK | SA110_UART_OVERRUN_ERROR_MASK)) ) (chan->callbacks->rcv_char)(chan, c); } cyg_drv_interrupt_unmask(ebsa285_chan->rx.int_num);}static void ebsa285_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; ebsa285_serial_info *ebsa285_chan = (ebsa285_serial_info *)chan->dev_priv; if ((*SA110_UART_FLAG_REGISTER & SA110_TX_FIFO_STATUS_MASK) != SA110_TX_FIFO_BUSY) { (chan->callbacks->xmt_char)(chan); } cyg_drv_interrupt_unmask(ebsa285_chan->tx.int_num);}#endif // CYGPKG_IO_SERIAL_ARM_EBSA285// ------------------------------------------------------------------------// EOF ebsa285_serial.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -