📄 mg5uart.c
字号:
* wrappers which are nearly functionally identical. */#define __ISR(_TYPE, _OFFSET) \ MG5UART_STATIC void mg5uart_process_isr_ ## _TYPE ( \ int minor \ ); \ \ MG5UART_STATIC rtems_isr mg5uart_isr_ ## _TYPE ( \ rtems_vector_number vector \ ) \ { \ int minor; \ extern void mips_default_isr(int vector); \ \ for(minor=0 ; minor<Console_Port_Count ; minor++) { \ if( Console_Port_Tbl[minor].deviceType == SERIAL_MG5UART && \ vector == Console_Port_Tbl[minor].ulIntVector + _OFFSET ) { \ mg5uart_process_isr_ ## _TYPE (minor); \ return; \ } \ } \ mips_default_isr( vector ); \ }__ISR(rx_frame_error, MG5UART_IRQ_RX_FRAME_ERROR)__ISR(rx_overrun_error, MG5UART_IRQ_RX_OVERRUN_ERROR)__ISR(tx_empty, MG5UART_IRQ_TX_EMPTY)__ISR(tx_ready, MG5UART_IRQ_TX_READY)__ISR(rx_ready, MG5UART_IRQ_RX_READY)MG5UART_STATIC void mg5uart_process_isr_rx_error( int minor, unsigned32 mask ){ unsigned32 pMG5UART; int shift; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_IRQ_SHIFT; else shift = MONGOOSEV_UART1_IRQ_SHIFT; /* now clear the error */ MG5UART_SETREG( pMG5UART, MG5UART_STATUS_REGISTER, mask << shift );}MG5UART_STATIC void mg5uart_process_isr_rx_frame_error( int minor){ mg5uart_process_isr_rx_error( minor, MONGOOSEV_UART_RX_FRAME_ERROR );}MG5UART_STATIC void mg5uart_process_isr_rx_overrun_error( int minor){ mg5uart_process_isr_rx_error( minor, MONGOOSEV_UART_RX_OVERRUN_ERROR );}MG5UART_STATIC void mg5uart_process_tx_isr( int minor, unsigned32 source){ unsigned32 pMG5UART; int shift; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX); if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_IRQ_SHIFT; else shift = MONGOOSEV_UART1_IRQ_SHIFT; MG5UART_SETREG( pMG5UART, MG5UART_STATUS_REGISTER, source << shift ); if( rtems_termios_dequeue_characters( Console_Port_Data[minor].termios_data, 1) ) { mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL); return; } /* * There are no more characters to transmit. The tx interrupts are be cleared * by writing data to the uart, so just disable the tx interrupt sources. */ Console_Port_Data[minor].bActive = FALSE; /* mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX); */}MG5UART_STATIC void mg5uart_process_isr_tx_empty( int minor){ /* mg5uart_process_tx_isr( minor, MONGOOSEV_UART_TX_EMPTY ); */}MG5UART_STATIC void mg5uart_process_isr_tx_ready( int minor){ mg5uart_process_tx_isr( minor, MONGOOSEV_UART_TX_READY );}MG5UART_STATIC void mg5uart_process_isr_rx_ready( int minor){ unsigned32 pMG5UART_port; unsigned char c; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; /* reading the RX buffer automatically resets the interrupt flag */ c = (unsigned char) MG5UART_GETREG(pMG5UART_port, MG5UART_RX_BUFFER); rtems_termios_enqueue_raw_characters( Console_Port_Data[minor].termios_data, &c, 1 );}/* * mg5uart_initialize_interrupts * * This routine initializes the console's receive and transmit * ring buffers and loads the appropriate vectors to handle the interrupts. */MG5UART_STATIC void mg5uart_initialize_interrupts(int minor){ unsigned long v; mg5uart_init(minor); Console_Port_Data[minor].bActive = FALSE; v = Console_Port_Tbl[minor].ulIntVector; set_vector(mg5uart_isr_rx_frame_error, v + MG5UART_IRQ_RX_FRAME_ERROR, 1); set_vector(mg5uart_isr_rx_overrun_error, v + MG5UART_IRQ_RX_OVERRUN_ERROR, 1); set_vector(mg5uart_isr_tx_empty, v + MG5UART_IRQ_TX_EMPTY, 1); set_vector(mg5uart_isr_tx_ready, v + MG5UART_IRQ_TX_READY, 1); set_vector(mg5uart_isr_rx_ready, v + MG5UART_IRQ_RX_READY, 1); mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL_EXCEPT_TX);}/* * mg5uart_write_support_int * * Console Termios output entry point when using interrupt driven output. */MG5UART_STATIC int mg5uart_write_support_int( int minor, const char *buf, int len){ unsigned32 Irql; unsigned32 pMG5UART_port; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; /* * We are using interrupt driven output and termios only sends us * one character at a time. */ if ( !len ) return 0; /* * Put the character out and enable interrupts if necessary. */ rtems_interrupt_disable(Irql); MG5UART_SETREG(pMG5UART_port, MG5UART_TX_BUFFER, *buf); if( Console_Port_Data[minor].bActive == FALSE ) { Console_Port_Data[minor].bActive = TRUE; mg5uart_enable_interrupts(minor, MG5UART_ENABLE_ALL); } rtems_interrupt_enable(Irql); return 1;}/* * mg5uart_write_support_polled * * Console Termios output entry point when using polled output. * */MG5UART_STATIC int mg5uart_write_support_polled( int minor, const char *buf, int len){ int nwrite = 0; /* * poll each byte in the string out of the port. */ while (nwrite < len) { mg5uart_write_polled(minor, *buf++); nwrite++; } /* * return the number of bytes written. */ return nwrite;}/* * mg5uart_inbyte_nonblocking_polled * * Console Termios polling input entry point. */MG5UART_STATIC int mg5uart_inbyte_nonblocking_polled( int minor){ unsigned32 pMG5UART; unsigned32 pMG5UART_port; unsigned32 status; unsigned32 tmp,shift; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; pMG5UART_port = Console_Port_Tbl[minor].ulCtrlPort2; if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_IRQ_SHIFT; else shift = MONGOOSEV_UART1_IRQ_SHIFT; /* reset overrrun or framing errors */ status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift; if( (tmp = (status & 0x3)) ) { MG5UART_SETREG(pMG5UART, MG5UART_STATUS_REGISTER, (tmp << shift) ); status = MG5UART_GETREG(pMG5UART, MG5UART_STATUS_REGISTER) >> shift; } if ( status & MONGOOSEV_UART_RX_READY ) { return (int) MG5UART_GETREG(pMG5UART_port, MG5UART_RX_BUFFER); } else { return -1; }}/* * mg5uart_baud_rate */MG5UART_STATIC int mg5uart_baud_rate( int minor, int baud, unsigned int *code){ rtems_unsigned32 clock; rtems_unsigned32 tmp_code; rtems_unsigned32 baud_requested; baud_requested = baud & CBAUD; if (!baud_requested) baud_requested = B9600; /* default to 9600 baud */ baud_requested = termios_baud_to_number( baud_requested ); clock = (rtems_unsigned32) Console_Port_Tbl[minor].ulClock; if (!clock) rtems_fatal_error_occurred(RTEMS_INVALID_NUMBER); /* * Formula is Code = round(ClockFrequency / Baud - 1). * * Since this is integer math, we will divide by twice the baud and * check the remaining odd bit. */ tmp_code = (clock / baud_requested) - 1; /* * From section 12.7, "Keep C>100 for best receiver operation." * That is 100 cycles which is not a lot of instructions. It is * reasonable to think that the Mongoose-V could not keep * up with C < 100. */ if ( tmp_code < 100 ) return RTEMS_INVALID_NUMBER; /* * upper word is receiver baud and lower word is transmitter baud */ *code = (tmp_code << 16) | tmp_code; return 0;}/* * mg5uart_enable_interrupts * * This function enables specific interrupt sources on the DUART. */MG5UART_STATIC void mg5uart_enable_interrupts( int minor, int mask){ unsigned32 pMG5UART; unsigned32 maskSave; unsigned32 shift; rtems_interrupt_level Irql; pMG5UART = Console_Port_Tbl[minor].ulCtrlPort1; /* * Enable interrupts on RX and TX -- not break */ if ( Console_Port_Tbl[minor].ulDataPort == MG5UART_UART0 ) shift = MONGOOSEV_UART0_IRQ_SHIFT; else shift = MONGOOSEV_UART1_IRQ_SHIFT; rtems_interrupt_disable(Irql); maskSave = MG5UART_GETREG( pMG5UART, MG5UART_INTERRUPT_MASK_REGISTER ); MG5UART_SETREG( pMG5UART, MG5UART_INTERRUPT_MASK_REGISTER, (maskSave & ~(MONGOOSEV_UART_ALL_STATUS_BITS << shift)) | (mask << shift) ); rtems_interrupt_enable(Irql);}/* * Flow control is only supported when using interrupts */console_fns mg5uart_fns ={ libchip_serial_default_probe, /* deviceProbe */ mg5uart_open, /* deviceFirstOpen */ NULL, /* deviceLastClose */ NULL, /* deviceRead */ mg5uart_write_support_int, /* deviceWrite */ mg5uart_initialize_interrupts, /* deviceInitialize */ mg5uart_write_polled, /* deviceWritePolled */ mg5uart_set_attributes, /* deviceSetAttributes */ TRUE /* deviceOutputUsesInterrupts */};console_fns mg5uart_fns_polled ={ libchip_serial_default_probe, /* deviceProbe */ mg5uart_open, /* deviceFirstOpen */ mg5uart_close, /* deviceLastClose */ mg5uart_inbyte_nonblocking_polled, /* deviceRead */ mg5uart_write_support_polled, /* deviceWrite */ mg5uart_init, /* deviceInitialize */ mg5uart_write_polled, /* deviceWritePolled */ mg5uart_set_attributes, /* deviceSetAttributes */ FALSE, /* deviceOutputUsesInterrupts */};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -