File indexing completed on 2025-05-11 08:23:47
0001
0002
0003
0004
0005
0006
0007 #include <stdio.h>
0008 #include <fcntl.h>
0009 #include <termios.h>
0010 #include <malloc.h>
0011
0012 #include <rtems/libio.h>
0013 #include <rtems/termiostypes.h>
0014 #include <rtems/bspIo.h>
0015 #include <rtems/console.h>
0016 #include <bsp.h>
0017
0018 #define UART_INTC0_IRQ_VECTOR(x) (64+13+(x))
0019
0020 #define MCF5235_UART_USR_ERROR ( MCF5235_UART_USR_RB | \
0021 MCF5235_UART_USR_FE | \
0022 MCF5235_UART_USR_PE | \
0023 MCF5235_UART_USR_OE )
0024
0025 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
0026 static ssize_t IntUartInterruptWrite (int minor, const char *buf, size_t len);
0027
0028 static void
0029 _BSP_null_char( char c )
0030 {
0031 int level;
0032
0033 rtems_interrupt_disable(level);
0034 while ( (MCF5235_UART_USR(CONSOLE_PORT) & MCF5235_UART_USR_TXRDY) == 0 )
0035 continue;
0036 MCF5235_UART_UTB(CONSOLE_PORT) = c;
0037 while ( (MCF5235_UART_USR(CONSOLE_PORT) & MCF5235_UART_USR_TXRDY) == 0 )
0038 continue;
0039 rtems_interrupt_enable(level);
0040 }
0041 BSP_output_char_function_type BSP_output_char = _BSP_null_char;
0042 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0043
0044 #define MAX_UART_INFO 3
0045 #define RX_BUFFER_SIZE 512
0046
0047 struct IntUartInfoStruct
0048 {
0049 int iomode;
0050 volatile int uimr;
0051 int baud;
0052 int databits;
0053 int parity;
0054 int stopbits;
0055 int hwflow;
0056 int rx_in;
0057 int rx_out;
0058 char rx_buffer[RX_BUFFER_SIZE];
0059 void *ttyp;
0060 };
0061
0062 struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
0063
0064
0065
0066
0067
0068
0069 static void
0070 IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwflow)
0071 {
0072 int divisor;
0073 uint32_t clock_speed;
0074 uint8_t umr1 = 0;
0075 uint8_t umr2 = 0;
0076 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0077 int level;
0078
0079 rtems_interrupt_disable(level);
0080
0081
0082
0083 MCF5235_UART_UIMR(minor) = 0;
0084 MCF5235_UART_UOP0(minor) = 1;
0085 MCF5235_UART_UCR(minor) = (MCF5235_UART_UCR_TX_DISABLED | MCF5235_UART_UCR_RX_DISABLED);
0086
0087
0088 info->uimr = 0;
0089 info->baud = baud;
0090 info->databits = databits;
0091 info->parity = parity;
0092 info->stopbits = stopbits;
0093 info->hwflow = hwflow;
0094
0095 clock_speed = get_CPU_clock_speed();
0096
0097 divisor = ((clock_speed/2) / ( 32 * baud ));
0098 if ( divisor < 2 ) {
0099 divisor = 2;
0100 }
0101
0102
0103 if ( hwflow )
0104 {
0105
0106 umr1 |= MCF5235_UART_UMR_RXRTS;
0107 umr2 |= MCF5235_UART_UMR_TXCTS;
0108 }
0109
0110
0111 umr1 |= (parity | databits);
0112 umr2 |= (stopbits);
0113
0114
0115 MCF5235_UART_UCR(minor) = MCF5235_UART_UCR_RESET_ERROR;
0116 MCF5235_UART_UCR(minor) = MCF5235_UART_UCR_RESET_RX;
0117 MCF5235_UART_UCR(minor) = MCF5235_UART_UCR_RESET_TX;
0118
0119
0120 MCF5235_UART_UCR(minor) = MCF5235_UART_UCR_RESET_MR;
0121 MCF5235_UART_UMR(minor) = umr1;
0122 MCF5235_UART_UMR(minor) = umr2;
0123
0124
0125 MCF5235_UART_UCSR(minor) = (MCF5235_UART_UCSR_RCS_SYS_CLK | MCF5235_UART_UCSR_TCS_SYS_CLK);
0126 MCF5235_UART_UBG1(minor) = (divisor & 0xff00) >> 8;
0127 MCF5235_UART_UBG2(minor) = (divisor & 0x00ff);
0128
0129
0130 MCF5235_UART_UCR(minor) = (MCF5235_UART_UCR_TX_ENABLED | MCF5235_UART_UCR_RX_ENABLED);
0131
0132
0133 if ( info->iomode != TERMIOS_POLLED )
0134 {
0135
0136 info->uimr |= MCF5235_UART_UIMR_FFULL;
0137 MCF5235_UART_UIMR(minor) = info->uimr;
0138 }
0139
0140
0141 if ( hwflow )
0142 {
0143
0144 MCF5235_UART_UOP1(minor) = 1;
0145 }
0146
0147 rtems_interrupt_enable(level);
0148
0149 }
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 static int
0162 IntUartSetAttributes(int minor, const struct termios *t)
0163 {
0164
0165 int baud = (int)19200;
0166 int databits = (int)MCF5235_UART_UMR_BC_8;
0167 int parity = (int)MCF5235_UART_UMR_PM_NONE;
0168 int stopbits = (int)MCF5235_UART_UMR_STOP_BITS_1;
0169 int hwflow = (int)0;
0170 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0171
0172
0173 if ( t != (const struct termios *)0 )
0174 {
0175
0176 baud = rtems_termios_baud_to_number(t->c_ospeed);
0177
0178
0179 switch ( t->c_cflag & CSIZE )
0180 {
0181 case CS5:
0182 databits = (int)MCF5235_UART_UMR_BC_5;
0183 break;
0184 case CS6:
0185 databits = (int)MCF5235_UART_UMR_BC_6;
0186 break;
0187 case CS7:
0188 databits = (int)MCF5235_UART_UMR_BC_7;
0189 break;
0190 case CS8:
0191 databits = (int)MCF5235_UART_UMR_BC_8;
0192 break;
0193 }
0194
0195
0196 if ( t->c_cflag & PARENB )
0197 {
0198 if ( t->c_cflag & PARODD )
0199 {
0200
0201 parity = (int)MCF5235_UART_UMR_PM_ODD;
0202 }
0203 else
0204 {
0205
0206 parity = (int)MCF5235_UART_UMR_PM_EVEN;
0207 }
0208 }
0209
0210
0211 if ( t->c_cflag & CSTOPB )
0212 {
0213
0214 stopbits = (int)MCF5235_UART_UMR_STOP_BITS_2;
0215 }
0216
0217
0218 if ( t->c_cflag & CRTSCTS )
0219 {
0220 hwflow = 1;
0221 }
0222 }
0223
0224
0225 if ( ( baud != info->baud ) ||
0226 ( databits != info->databits ) ||
0227 ( parity != info->parity ) ||
0228 ( stopbits != info->stopbits ) ||
0229 ( hwflow != info->hwflow ) )
0230 {
0231
0232
0233 IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
0234 }
0235
0236 return( RTEMS_SUCCESSFUL );
0237
0238 }
0239
0240
0241
0242
0243
0244
0245
0246
0247 static rtems_isr
0248 IntUartInterruptHandler(rtems_vector_number v)
0249 {
0250 unsigned int chan = v - UART_INTC0_IRQ_VECTOR(0);
0251 struct IntUartInfoStruct *info = &IntUartInfo[chan];
0252
0253
0254 if ( MCF5235_UART_UISR(chan) & MCF5235_UART_UISR_RXRDY )
0255 {
0256
0257 while ( MCF5235_UART_USR(chan) & MCF5235_UART_USR_RXRDY )
0258 {
0259
0260 if ( MCF5235_UART_USR(chan) & MCF5235_UART_USR_ERROR )
0261 {
0262
0263 MCF5235_UART_UCR(chan) = MCF5235_UART_UCR_RESET_ERROR;
0264 }
0265
0266 info->rx_buffer[info->rx_in] = MCF5235_UART_URB(chan);
0267
0268
0269 info->rx_in++;
0270
0271 if ( info->rx_in >= RX_BUFFER_SIZE )
0272 {
0273 info->rx_in = 0;
0274 }
0275 }
0276
0277 if ( info->ttyp )
0278 {
0279
0280
0281 if ( info->iomode == TERMIOS_TASK_DRIVEN )
0282 {
0283
0284 rtems_termios_rxirq_occured(info->ttyp);
0285 }
0286 else
0287 {
0288
0289 rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
0290 info->rx_in = 0;
0291 }
0292 }
0293 }
0294
0295
0296 if ( ( info->uimr & MCF5235_UART_UIMR_TXRDY ) &&
0297 ( MCF5235_UART_UISR(chan) & MCF5235_UART_UISR_TXRDY ) )
0298 {
0299
0300
0301 info->uimr &= ~MCF5235_UART_UIMR_TXRDY;
0302 MCF5235_UART_UIMR(chan) = info->uimr;
0303
0304
0305 if ( info->ttyp )
0306 rtems_termios_dequeue_characters(info->ttyp, 1);
0307 }
0308 }
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319 static void
0320 IntUartInitialize(void)
0321 {
0322 unsigned int chan;
0323 struct IntUartInfoStruct *info;
0324 rtems_isr_entry old_handler;
0325 int level;
0326
0327 for ( chan = 0; chan < MAX_UART_INFO; chan++ )
0328 {
0329 info = &IntUartInfo[chan];
0330
0331 info->ttyp = NULL;
0332 info->rx_in = 0;
0333 info->rx_out = 0;
0334 info->baud = -1;
0335 info->databits = -1;
0336 info->parity = -1;
0337 info->stopbits = -1;
0338 info->hwflow = -1;
0339 info->iomode = TERMIOS_POLLED;
0340
0341 MCF5235_UART_UACR(chan) = 0;
0342 MCF5235_UART_UIMR(chan) = 0;
0343 if ( info->iomode != TERMIOS_POLLED )
0344 {
0345 rtems_interrupt_catch (IntUartInterruptHandler,
0346 UART_INTC0_IRQ_VECTOR(chan),
0347 &old_handler);
0348 }
0349
0350
0351 IntUartSetAttributes(chan, NULL);
0352
0353
0354 rtems_interrupt_disable(level);
0355 switch(chan) {
0356 case 0:
0357 MCF5235_INTC0_ICR13 = MCF5235_INTC_ICR_IL(UART0_IRQ_LEVEL) |
0358 MCF5235_INTC_ICR_IP(UART0_IRQ_PRIORITY);
0359 MCF5235_INTC0_IMRL &= ~(MCF5235_INTC0_IMRL_INT13 |
0360 MCF5235_INTC0_IMRL_MASKALL);
0361 break;
0362
0363 case 1:
0364 MCF5235_INTC0_ICR14 = MCF5235_INTC_ICR_IL(UART1_IRQ_LEVEL) |
0365 MCF5235_INTC_ICR_IP(UART1_IRQ_PRIORITY);
0366 MCF5235_INTC0_IMRL &= ~(MCF5235_INTC0_IMRL_INT14 |
0367 MCF5235_INTC0_IMRL_MASKALL);
0368 break;
0369
0370 case 2:
0371 MCF5235_INTC0_ICR15 = MCF5235_INTC_ICR_IL(UART2_IRQ_LEVEL) |
0372 MCF5235_INTC_ICR_IP(UART2_IRQ_PRIORITY);
0373 MCF5235_INTC0_IMRL &= ~(MCF5235_INTC0_IMRL_INT15 |
0374 MCF5235_INTC0_IMRL_MASKALL);
0375 break;
0376 }
0377 rtems_interrupt_enable(level);
0378
0379 }
0380
0381
0382 }
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393 static ssize_t
0394 IntUartInterruptWrite (int minor, const char *buf, size_t len)
0395 {
0396 if (len > 0) {
0397
0398 MCF5235_UART_UTB(minor) = *buf;
0399
0400
0401 IntUartInfo[minor].uimr |= MCF5235_UART_UIMR_TXRDY;
0402 MCF5235_UART_UIMR(minor) = IntUartInfo[minor].uimr;
0403 }
0404
0405 return( 0 );
0406 }
0407
0408
0409
0410
0411
0412
0413 static int
0414 IntUartInterruptOpen(int major, int minor, void *arg)
0415 {
0416 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0417
0418
0419 MCF5235_UART_UCR(minor) = (MCF5235_UART_UCR_TX_ENABLED | MCF5235_UART_UCR_RX_ENABLED);
0420
0421
0422 if ( info->iomode != TERMIOS_POLLED )
0423 {
0424
0425 info->uimr |= MCF5235_UART_UIMR_FFULL;
0426 MCF5235_UART_UIMR(minor) = info->uimr;
0427 }
0428
0429
0430 if ( info->hwflow )
0431 {
0432
0433 MCF5235_UART_UOP1(minor) = 1;
0434 }
0435
0436 return( 0 );
0437 }
0438
0439
0440
0441
0442
0443
0444
0445
0446 static int
0447 IntUartInterruptClose(int major, int minor, void *arg)
0448 {
0449 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0450
0451
0452 MCF5235_UART_UIMR(minor) = 0;
0453 MCF5235_UART_UCR(minor) = (MCF5235_UART_UCR_TX_DISABLED | MCF5235_UART_UCR_RX_DISABLED);
0454
0455
0456 info->ttyp = NULL;
0457 info->uimr = 0;
0458 info->rx_in = 0;
0459 info->rx_out = 0;
0460
0461 return( 0 );
0462 }
0463
0464
0465
0466
0467
0468
0469
0470
0471 static int
0472 IntUartTaskRead(int minor)
0473 {
0474 char buffer[RX_BUFFER_SIZE];
0475 int count;
0476 int rx_in;
0477 int index = 0;
0478 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0479
0480
0481 rx_in = info->rx_in;
0482 if ( info->rx_out <= rx_in )
0483 {
0484 count = rx_in - info->rx_out;
0485 }
0486 else
0487 {
0488 count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
0489 }
0490
0491
0492 while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
0493 {
0494
0495 buffer[index] = info->rx_buffer[info->rx_out];
0496 index++;
0497
0498
0499 info->rx_out++;
0500 if ( info->rx_out >= RX_BUFFER_SIZE )
0501 {
0502 info->rx_out = 0;
0503 }
0504 }
0505
0506
0507 if ( count > 0 )
0508 {
0509
0510 rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
0511 }
0512
0513 return( EOF );
0514 }
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524 static int
0525 IntUartPollRead (int minor)
0526 {
0527 if ( (MCF5235_UART_USR(minor) & MCF5235_UART_USR_RXRDY) == 0 )
0528 return(-1);
0529
0530 return(MCF5235_UART_URB(minor));
0531 }
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541 static ssize_t
0542 IntUartPollWrite (int minor, const char *buf, size_t len)
0543 {
0544 size_t retval = len;
0545
0546 while ( len-- )
0547 {
0548
0549 while ( (MCF5235_UART_USR(minor) & MCF5235_UART_USR_TXRDY) == 0 )
0550 continue;
0551
0552 MCF5235_UART_UTB(minor) = *buf++;
0553 }
0554 return retval;
0555 }
0556
0557
0558
0559
0560
0561
0562
0563 rtems_device_driver console_initialize(
0564 rtems_device_major_number major,
0565 rtems_device_minor_number minor,
0566 void *arg )
0567 {
0568 rtems_status_code status;
0569
0570
0571
0572 rtems_termios_initialize ();
0573
0574
0575 IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN;
0576 IntUartInitialize();
0577
0578
0579 status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
0580 if ( status != RTEMS_SUCCESSFUL )
0581 {
0582 rtems_fatal_error_occurred (status);
0583 }
0584
0585
0586 if ( CONSOLE_PORT != 0 )
0587 {
0588 status = rtems_io_register_name ("/dev/tty00", major, 0);
0589 if ( status != RTEMS_SUCCESSFUL )
0590 {
0591 rtems_fatal_error_occurred (status);
0592 }
0593 }
0594 if ( CONSOLE_PORT != 1 )
0595 {
0596 status = rtems_io_register_name ("/dev/tty01", major, 1);
0597 if ( status != RTEMS_SUCCESSFUL )
0598 {
0599 rtems_fatal_error_occurred (status);
0600 }
0601 }
0602
0603 return(RTEMS_SUCCESSFUL);
0604 }
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614 rtems_device_driver console_open(
0615 rtems_device_major_number major,
0616 rtems_device_minor_number minor,
0617 void * arg)
0618 {
0619 rtems_status_code status = RTEMS_INVALID_NUMBER;
0620 rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *)arg;
0621 struct IntUartInfoStruct *info;
0622
0623 static const rtems_termios_callbacks IntUartPollCallbacks = {
0624 NULL,
0625 NULL,
0626 IntUartPollRead,
0627 IntUartPollWrite,
0628 IntUartSetAttributes,
0629 NULL,
0630 NULL,
0631 TERMIOS_POLLED
0632 };
0633 static const rtems_termios_callbacks IntUartIntrCallbacks = {
0634 IntUartInterruptOpen,
0635 IntUartInterruptClose,
0636 NULL,
0637 IntUartInterruptWrite,
0638 IntUartSetAttributes,
0639 NULL,
0640 NULL,
0641 TERMIOS_IRQ_DRIVEN
0642 };
0643
0644 static const rtems_termios_callbacks IntUartTaskCallbacks = {
0645 IntUartInterruptOpen,
0646 IntUartInterruptClose,
0647 IntUartTaskRead,
0648 IntUartInterruptWrite,
0649 IntUartSetAttributes,
0650 NULL,
0651 NULL,
0652 TERMIOS_TASK_DRIVEN
0653 };
0654
0655
0656 if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
0657 {
0658 info = &IntUartInfo[minor];
0659 switch ( info->iomode )
0660 {
0661 case TERMIOS_POLLED:
0662 status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
0663 break;
0664 case TERMIOS_IRQ_DRIVEN:
0665 status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
0666 info->ttyp = args->iop->data1;
0667 break;
0668 case TERMIOS_TASK_DRIVEN:
0669 status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
0670 info->ttyp = args->iop->data1;
0671 break;
0672 }
0673 }
0674
0675 if (status == RTEMS_SUCCESSFUL)
0676 {
0677
0678
0679
0680 struct termios term;
0681 if (tcgetattr (STDIN_FILENO, &term) >= 0)
0682 {
0683 term.c_cflag &= ~(CSIZE);
0684 term.c_cflag |= CS8;
0685 term.c_ispeed = B19200;
0686 term.c_ospeed = B19200;
0687 tcsetattr (STDIN_FILENO, TCSANOW, &term);
0688 }
0689 }
0690
0691 return( status );
0692 }
0693
0694
0695
0696
0697
0698
0699 rtems_device_driver console_close(
0700 rtems_device_major_number major,
0701 rtems_device_minor_number minor,
0702 void * arg)
0703 {
0704 return(rtems_termios_close (arg));
0705 }
0706
0707
0708
0709
0710
0711
0712
0713 rtems_device_driver console_read(
0714 rtems_device_major_number major,
0715 rtems_device_minor_number minor,
0716 void * arg)
0717 {
0718 return(rtems_termios_read (arg));
0719 }
0720
0721
0722
0723
0724
0725
0726 rtems_device_driver console_write(
0727 rtems_device_major_number major,
0728 rtems_device_minor_number minor,
0729 void * arg)
0730 {
0731 return(rtems_termios_write (arg));
0732 }
0733
0734
0735
0736
0737
0738
0739 rtems_device_driver console_control(
0740 rtems_device_major_number major,
0741 rtems_device_minor_number minor,
0742 void * arg)
0743 {
0744 return( rtems_termios_ioctl (arg) );
0745 }