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