File indexing completed on 2025-05-11 08:23:50
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #include <bsp/irq.h>
0037 #include <dev/serial/uartlite.h>
0038 #include <bspopts.h>
0039
0040 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0041 static void microblaze_uart_interrupt( void *arg )
0042 {
0043 rtems_termios_tty *tty = arg;
0044 uart_lite_context *ctx = rtems_termios_get_device_context( tty );
0045
0046 while ( !XUartLite_IsReceiveEmpty( ctx->address ) ) {
0047 char c = (char) XUartLite_ReadReg( ctx->address, XUL_RX_FIFO_OFFSET );
0048 rtems_termios_enqueue_raw_characters( tty, &c, 1 );
0049 }
0050
0051 if ( ctx->transmitting && XUartLite_IsTransmitEmpty( ctx->address ) ) {
0052 size_t sent = ctx->tx_queued;
0053 ctx->transmitting = false;
0054 ctx->tx_queued = 0;
0055 rtems_termios_dequeue_characters( tty, sent );
0056 }
0057 }
0058 #endif
0059
0060 static bool uart_first_open(
0061 struct rtems_termios_tty *tty,
0062 rtems_termios_device_context *base,
0063 struct termios *term,
0064 rtems_libio_open_close_args_t *args
0065 )
0066 {
0067 uart_lite_context *ctx = (uart_lite_context *) base;
0068 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0069 rtems_status_code sc;
0070 #endif
0071
0072 rtems_termios_set_initial_baud( tty, ctx->initial_baud );
0073
0074 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0075 XUartLite_EnableIntr( ctx->address );
0076
0077 sc = rtems_interrupt_handler_install(
0078 ctx->irq,
0079 "UART",
0080 RTEMS_INTERRUPT_SHARED,
0081 microblaze_uart_interrupt,
0082 tty
0083 );
0084 if ( sc != RTEMS_SUCCESSFUL ) {
0085 return false;
0086 }
0087
0088 ctx->tty = tty;
0089 #endif
0090
0091 return true;
0092 }
0093
0094 static void uart_last_close(
0095 rtems_termios_tty *tty,
0096 rtems_termios_device_context *base,
0097 rtems_libio_open_close_args_t *args
0098 )
0099 {
0100 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0101 rtems_interrupt_handler_remove( 1, microblaze_uart_interrupt, tty );
0102 #endif
0103 }
0104
0105 #ifndef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0106 static int uart_read_polled( rtems_termios_device_context *base )
0107 {
0108 uart_lite_context *ctx = (uart_lite_context *) base;
0109
0110 if ( XUartLite_IsReceiveEmpty( ctx->address ) ) {
0111 return -1;
0112 }
0113
0114 return XUartLite_ReadReg( ctx->address, XUL_RX_FIFO_OFFSET );
0115 }
0116 #endif
0117
0118 static void uart_write(
0119 rtems_termios_device_context *base,
0120 const char *s,
0121 size_t n
0122 )
0123 {
0124 uart_lite_context *ctx = (uart_lite_context *) base;
0125
0126 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0127 if ( n > 0 ) {
0128 size_t remaining = n;
0129 const char *p = &s[0];
0130
0131 while (!XUartLite_IsTransmitFull( ctx->address ) && remaining > 0) {
0132 XUartLite_SendByte( ctx->address, *p );
0133 p++;
0134 remaining--;
0135 }
0136
0137 ctx->transmitting = true;
0138 ctx->tx_queued = n - remaining;
0139 }
0140 #else
0141 size_t i = 0;
0142
0143 for ( i = 0; i < n; ++i ) {
0144 XUartLite_SendByte( ctx->address, s[i] );
0145 }
0146 #endif
0147 }
0148
0149 const rtems_termios_device_handler microblaze_uart_fns = {
0150 .first_open = uart_first_open,
0151 .last_close = uart_last_close,
0152 .write = uart_write,
0153 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0154 .mode = TERMIOS_IRQ_DRIVEN
0155 #else
0156 .poll_read = uart_read_polled,
0157 .mode = TERMIOS_POLLED
0158 #endif
0159 };