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