File indexing completed on 2025-05-11 08:23:45
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
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 #include <stdio.h>
0054 #include <fcntl.h>
0055 #include <termios.h>
0056 #include <malloc.h>
0057
0058 #include <bsp.h>
0059 #include <bsp/irq-generic.h>
0060 #include <rtems/libio.h>
0061 #include <rtems/termiostypes.h>
0062 #include <rtems/console.h>
0063 #include <rtems/bspIo.h>
0064
0065 #define UART_INTC0_IRQ_VECTOR(x) (64+35-(x))
0066
0067 #define MCF548X_PSC_SR_ERROR ( MCF548X_PSC_SR_RB_NEOF | \
0068 MCF548X_PSC_SR_FE_PHYERR | \
0069 MCF548X_PSC_SR_PE_CRCERR | \
0070 MCF548X_PSC_SR_OE )
0071
0072 static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
0073 static int IntUartPollRead (int minor);
0074 static int IntUartSetAttributes(int minor, const struct termios *t);
0075
0076 static void
0077 psc_output_char( char c )
0078 {
0079 rtems_interrupt_level level;
0080
0081 rtems_interrupt_disable(level);
0082 while (!((MCF548X_PSC_SR(CONSOLE_PORT) & MCF548X_PSC_SR_TXRDY)))
0083 continue;
0084 *((uint8_t *) &MCF548X_PSC_TB(CONSOLE_PORT)) = c;
0085 while (!((MCF548X_PSC_SR(CONSOLE_PORT) & MCF548X_PSC_SR_TXRDY)))
0086 continue;
0087 rtems_interrupt_enable(level);
0088 }
0089
0090 static void
0091 psc_output_char_init(char c)
0092 {
0093 IntUartSetAttributes(CONSOLE_PORT, NULL);
0094 BSP_output_char = psc_output_char;
0095 psc_output_char(c);
0096 }
0097
0098 BSP_output_char_function_type BSP_output_char = psc_output_char_init;
0099
0100 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0101
0102 #define MAX_UART_INFO 4
0103 #define RX_BUFFER_SIZE 248
0104
0105 struct IntUartInfoStruct
0106 {
0107 int iomode;
0108 volatile int imr;
0109 int baud;
0110 int databits;
0111 int parity;
0112 int stopbits;
0113 int hwflow;
0114 int rx_in;
0115 int rx_out;
0116 char rx_buffer[RX_BUFFER_SIZE];
0117 void *ttyp;
0118 };
0119
0120 struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
0121
0122 static int GetBaud( int baudHandle )
0123 {
0124 int baud = BSP_CONSOLE_BAUD;
0125 switch(baudHandle)
0126 {
0127 case B0:
0128 baud = (int)0;
0129 break;
0130 case B1200:
0131 baud = (int)1200;
0132 break;
0133 case B2400:
0134 baud = (int)2400;
0135 break;
0136 case B4800:
0137 baud = (int)4800;
0138 break;
0139 case B9600:
0140 baud = (int)9600;
0141 break;
0142 case B19200:
0143 baud = (int)19200;
0144 break;
0145 case B38400:
0146 baud = (int)38400;
0147 break;
0148 case B57600:
0149 baud = (int)57600;
0150 break;
0151 case B115200:
0152 baud = (int)115200;
0153 break;
0154 }
0155 return baud;
0156 }
0157
0158
0159
0160
0161
0162
0163 static void
0164 IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwflow)
0165 {
0166 uint8_t psc_mode_1 = 0, psc_mode_2 = 0;
0167 uint16_t divider;
0168 int level;
0169 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0170
0171 rtems_interrupt_disable(level);
0172
0173
0174
0175 MCF548X_PSC_IMR(minor) = 0x0000;
0176
0177
0178 MCF548X_PSC_OPSET(minor) &= ~(MCF548X_PSC_OPSET_RTS);
0179
0180
0181 MCF548X_PSC_CR(minor) &= ~(MCF548X_PSC_CR_RX_ENABLED | MCF548X_PSC_CR_TX_ENABLED);
0182
0183
0184 switch (minor)
0185 {
0186 case 0:
0187 MCF548X_GPIO_PAR_PSC0 = (0 | MCF548X_GPIO_PAR_PSC0_PAR_TXD0 | MCF548X_GPIO_PAR_PSC0_PAR_RXD0);
0188
0189 if(hwflow)
0190 {
0191 MCF548X_GPIO_PAR_PSC0 |= (0 | MCF548X_GPIO_PAR_PSC0_PAR_CTS0_CTS | MCF548X_GPIO_PAR_PSC0_PAR_RTS0_RTS);
0192 }
0193 break;
0194 case 1:
0195 MCF548X_GPIO_PAR_PSC1 = (0 | MCF548X_GPIO_PAR_PSC1_PAR_TXD1 | MCF548X_GPIO_PAR_PSC1_PAR_RXD1);
0196
0197 if(hwflow)
0198 {
0199 MCF548X_GPIO_PAR_PSC1 |= (0 | MCF548X_GPIO_PAR_PSC1_PAR_CTS1_CTS | MCF548X_GPIO_PAR_PSC1_PAR_RTS1_RTS);
0200 }
0201 break;
0202 case 2:
0203 MCF548X_GPIO_PAR_PSC2 = (0 | MCF548X_GPIO_PAR_PSC2_PAR_TXD2 | MCF548X_GPIO_PAR_PSC2_PAR_RXD2);
0204
0205 if(hwflow)
0206 {
0207 MCF548X_GPIO_PAR_PSC2 |= (0 | MCF548X_GPIO_PAR_PSC2_PAR_CTS2_CTS | MCF548X_GPIO_PAR_PSC2_PAR_RTS2_RTS);
0208 }
0209 break;
0210 case 3:
0211 MCF548X_GPIO_PAR_PSC3 = (0 | MCF548X_GPIO_PAR_PSC3_PAR_TXD3 | MCF548X_GPIO_PAR_PSC3_PAR_RXD3);
0212
0213 if(hwflow)
0214 {
0215 MCF548X_GPIO_PAR_PSC3 |= (0 | MCF548X_GPIO_PAR_PSC3_PAR_CTS3_CTS | MCF548X_GPIO_PAR_PSC3_PAR_RTS3_RTS);
0216 }
0217 break;
0218 default:
0219 break;
0220 }
0221
0222
0223 info->imr = 0;
0224 info->baud = baud;
0225 info->databits = databits;
0226 info->parity = parity;
0227 info->stopbits = stopbits;
0228 info->hwflow = hwflow;
0229
0230
0231 MCF548X_PSC_SICR(minor) = MCF548X_PSC_SICR_SIM_UART;
0232
0233
0234 MCF548X_PSC_CSR(minor) = (0 | MCF548X_PSC_CSR_RCSEL_SYS_CLK | MCF548X_PSC_CSR_TCSEL_SYS_CLK);
0235
0236
0237 divider = (uint16_t)((get_CPU_clock_speed())/(baud * 32));
0238 MCF548X_PSC_CTUR(minor) = (uint8_t) ((divider >> 8) & 0xFF);
0239 MCF548X_PSC_CTLR(minor) = (uint8_t) (divider & 0xFF);
0240
0241
0242 MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_RX;
0243 MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_TX;
0244 MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_ERROR;
0245 MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_BKCHGINT;
0246 MCF548X_PSC_CR(minor) = MCF548X_PSC_CR_RESET_MR;
0247
0248
0249 if ( hwflow )
0250 {
0251
0252 psc_mode_1 = MCF548X_PSC_MR_RXRTS;
0253 psc_mode_2 = MCF548X_PSC_MR_TXCTS;
0254 }
0255
0256
0257 psc_mode_1 |= (uint8_t)(parity | databits);
0258 psc_mode_2 |= (uint8_t)(stopbits);
0259
0260
0261 MCF548X_PSC_MR(minor) = psc_mode_1;
0262 MCF548X_PSC_MR(minor) = psc_mode_2;
0263
0264
0265 MCF548X_PSC_RFAR(minor) = MCF548X_PSC_RFAR_ALARM(248);
0266 MCF548X_PSC_TFAR(minor) = MCF548X_PSC_TFAR_ALARM(248);
0267
0268
0269 if ( info->iomode != TERMIOS_POLLED )
0270 {
0271
0272 info->imr |= MCF548X_PSC_IMR_RXRDY_FU;
0273 MCF548X_PSC_IMR(minor) = info->imr;
0274 }
0275
0276
0277 if ( hwflow )
0278 {
0279
0280 MCF548X_PSC_OPSET(minor) = MCF548X_PSC_OPSET_RTS;
0281 }
0282
0283 rtems_interrupt_enable(level);
0284
0285
0286 MCF548X_PSC_CR(minor) =(0 | MCF548X_PSC_CR_RX_ENABLED | MCF548X_PSC_CR_TX_ENABLED);
0287
0288
0289 }
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300 static int
0301 IntUartSetAttributes(int minor, const struct termios *t)
0302 {
0303
0304 #ifdef HAS_DBUG
0305 int baud = DBUG_SETTINGS.console_baudrate;
0306 #else
0307 int baud = (int)BSP_CONSOLE_BAUD;
0308 #endif
0309 int databits = (int)MCF548X_PSC_MR_BC_8;
0310 int parity = (int)MCF548X_PSC_MR_PM_NONE;
0311 int stopbits = (int)MCF548X_PSC_MR_SB_STOP_BITS_1;
0312 int hwflow = (int)1;
0313 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0314
0315
0316 if ( t != (const struct termios *)0 )
0317 {
0318
0319 baud = GetBaud( t->c_ospeed );
0320
0321
0322 switch ( t->c_cflag & CSIZE )
0323 {
0324 case CS5:
0325 databits = (int)MCF548X_PSC_MR_BC_5;
0326 break;
0327 case CS6:
0328 databits = (int)MCF548X_PSC_MR_BC_6;
0329 break;
0330 case CS7:
0331 databits = (int)MCF548X_PSC_MR_BC_7;
0332 break;
0333 case CS8:
0334 databits = (int)MCF548X_PSC_MR_BC_8;
0335 break;
0336 }
0337
0338
0339 if ( t->c_cflag & PARENB )
0340 {
0341 if ( t->c_cflag & PARODD )
0342 {
0343
0344 parity = (int)MCF548X_PSC_MR_PM_ODD;
0345 }
0346 else
0347 {
0348
0349 parity = (int)MCF548X_PSC_MR_PM_EVEN;
0350 }
0351 }
0352
0353
0354 if ( t->c_cflag & CSTOPB )
0355 {
0356
0357 stopbits = (int)MCF548X_PSC_MR_SB_STOP_BITS_2;
0358 }
0359
0360
0361 if ( t->c_cflag & CRTSCTS )
0362 {
0363 hwflow = 1;
0364 }
0365 }
0366
0367
0368 if ( ( baud != info->baud ) ||
0369 ( databits != info->databits ) ||
0370 ( parity != info->parity ) ||
0371 ( stopbits != info->stopbits ) ||
0372 ( hwflow != info->hwflow ) )
0373 {
0374
0375
0376 IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
0377 }
0378
0379 return RTEMS_SUCCESSFUL;
0380
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390 static rtems_isr
0391 IntUartInterruptHandler(rtems_vector_number v)
0392 {
0393 unsigned int chan = v - UART_INTC0_IRQ_VECTOR(0);
0394 struct IntUartInfoStruct *info = &IntUartInfo[chan];
0395
0396
0397 if ( MCF548X_PSC_ISR(chan) & MCF548X_PSC_ISR_RXRDY_FU )
0398 {
0399
0400 while ( MCF548X_PSC_SR(chan) & MCF548X_PSC_SR_RXRDY )
0401 {
0402
0403
0404 info->rx_buffer[info->rx_in] = *((volatile uint8_t *)&MCF548X_PSC_RB(chan));
0405
0406
0407 if ( MCF548X_PSC_SR(chan) & MCF548X_PSC_SR_ERROR )
0408 {
0409
0410 MCF548X_PSC_CR(chan) = MCF548X_PSC_CR_RESET_ERROR;
0411 }
0412
0413
0414 info->rx_in++;
0415
0416 if ( info->rx_in >= RX_BUFFER_SIZE )
0417 {
0418 info->rx_in = 0;
0419 }
0420 }
0421
0422 if ( info->ttyp )
0423 {
0424
0425
0426 if ( info->iomode == TERMIOS_TASK_DRIVEN )
0427 {
0428
0429 rtems_termios_rxirq_occured(info->ttyp);
0430 }
0431 else
0432 {
0433
0434 rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
0435 info->rx_in = 0;
0436 }
0437 }
0438 }
0439
0440
0441 if ( ( info->imr & MCF548X_PSC_IMR_TXRDY ) &&
0442 ( MCF548X_PSC_ISR(chan) & MCF548X_PSC_ISR_TXRDY ) )
0443 {
0444
0445
0446 info->imr &= ~MCF548X_PSC_IMR_TXRDY;
0447 MCF548X_PSC_IMR(chan) = info->imr;
0448
0449
0450 if ( info->ttyp )
0451 rtems_termios_dequeue_characters(info->ttyp, 1);
0452 }
0453
0454 }
0455
0456
0457
0458
0459
0460
0461
0462
0463 static void
0464 IntUartInitialize(void)
0465 {
0466 unsigned int chan;
0467 struct IntUartInfoStruct *info;
0468 rtems_isr_entry old_handler;
0469
0470 for ( chan = 0; chan < MAX_UART_INFO; chan++ )
0471 {
0472 info = &IntUartInfo[chan];
0473
0474 info->ttyp = NULL;
0475 info->rx_in = 0;
0476 info->rx_out = 0;
0477 info->baud = -1;
0478 info->databits = -1;
0479 info->parity = -1;
0480 info->stopbits = -1;
0481 info->hwflow = -1;
0482
0483 MCF548X_PSC_ACR(chan) = 0;
0484 MCF548X_PSC_IMR(chan) = 0;
0485 if ( info->iomode != TERMIOS_POLLED )
0486 {
0487 rtems_interrupt_catch (IntUartInterruptHandler,
0488 UART_INTC0_IRQ_VECTOR(chan),
0489 &old_handler);
0490 }
0491
0492
0493 IntUartSetAttributes(chan, NULL);
0494
0495
0496 bsp_interrupt_vector_enable(MCF548X_IRQ_PSC(chan));
0497 }
0498
0499 BSP_output_char = psc_output_char;
0500 }
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510 static ssize_t
0511 IntUartInterruptWrite (int minor, const char *buf, size_t len)
0512 {
0513 if (len > 0) {
0514
0515 *(volatile uint8_t *)(&MCF548X_PSC_TB(minor)) = *buf;
0516
0517
0518 IntUartInfo[minor].imr |= MCF548X_PSC_IMR_TXRDY;
0519 MCF548X_PSC_IMR(minor) = IntUartInfo[minor].imr;
0520 }
0521
0522 return 0;
0523 }
0524
0525
0526
0527
0528
0529
0530 static int
0531 IntUartInterruptOpen(int major, int minor, void *arg)
0532 {
0533 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0534
0535
0536 MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
0537
0538
0539 if ( info->iomode != TERMIOS_POLLED )
0540 {
0541
0542 info->imr |= MCF548X_PSC_IMR_RXRDY_FU;
0543 MCF548X_PSC_IMR(minor) = info->imr;
0544 }
0545
0546
0547 if ( info->hwflow )
0548 {
0549
0550 MCF548X_PSC_OPSET(minor) = MCF548X_PSC_OPSET_RTS;
0551 }
0552
0553 return 0;
0554 }
0555
0556
0557
0558
0559
0560
0561
0562 static int
0563 IntUartInterruptClose(int major, int minor, void *arg)
0564 {
0565 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0566
0567
0568 MCF548X_PSC_IMR(minor) = 0;
0569 MCF548X_PSC_CR(minor) = (MCF548X_PSC_CR_TX_ENABLED | MCF548X_PSC_CR_RX_ENABLED);
0570
0571
0572 info->ttyp = NULL;
0573 info->imr = 0;
0574 info->rx_in = 0;
0575 info->rx_out = 0;
0576
0577 return 0;
0578 }
0579
0580
0581
0582
0583
0584
0585
0586
0587 static int
0588 IntUartTaskRead(int minor)
0589 {
0590 char buffer[RX_BUFFER_SIZE];
0591 int count;
0592 int rx_in;
0593 int index = 0;
0594 struct IntUartInfoStruct *info = &IntUartInfo[minor];
0595
0596
0597 rx_in = info->rx_in;
0598 if ( info->rx_out <= rx_in )
0599 {
0600 count = rx_in - info->rx_out;
0601 }
0602 else
0603 {
0604 count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
0605 }
0606
0607
0608 while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
0609 {
0610
0611 buffer[index] = info->rx_buffer[info->rx_out];
0612 index++;
0613
0614
0615 info->rx_out++;
0616 if ( info->rx_out >= RX_BUFFER_SIZE )
0617 {
0618 info->rx_out = 0;
0619 }
0620 }
0621
0622
0623 if ( count > 0 )
0624 {
0625
0626 rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
0627 }
0628
0629 return EOF;
0630 }
0631
0632
0633
0634
0635
0636
0637
0638
0639 static int
0640 IntUartPollRead (int minor)
0641 {
0642 if (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_RXRDY)))
0643 return(-1);
0644
0645 return *((uint8_t *)&MCF548X_PSC_RB(minor));
0646 }
0647
0648
0649
0650
0651
0652
0653
0654
0655
0656 static ssize_t
0657 IntUartPollWrite (int minor, const char *buf, size_t len)
0658 {
0659 size_t retval = len;
0660
0661 while ( len-- )
0662 {
0663
0664 while (!((MCF548X_PSC_SR(minor) & MCF548X_PSC_SR_TXRDY)))
0665 continue;
0666
0667 *((uint8_t *)&MCF548X_PSC_TB(minor)) = *buf++;
0668 }
0669 return retval;
0670 }
0671
0672
0673
0674
0675
0676
0677
0678 rtems_device_driver console_initialize(
0679 rtems_device_major_number major,
0680 rtems_device_minor_number minor,
0681 void *arg )
0682 {
0683 rtems_status_code status;
0684
0685
0686
0687 rtems_termios_initialize ();
0688
0689
0690 IntUartInfo[minor].iomode = TERMIOS_IRQ_DRIVEN;
0691 IntUartInitialize();
0692
0693
0694 status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
0695 if ( status != RTEMS_SUCCESSFUL )
0696 {
0697 rtems_fatal_error_occurred (status);
0698 }
0699
0700
0701 if ( CONSOLE_PORT != 0 )
0702 {
0703 status = rtems_io_register_name ("/dev/tty00", major, 0);
0704 if ( status != RTEMS_SUCCESSFUL )
0705 {
0706 rtems_fatal_error_occurred (status);
0707 }
0708 }
0709 if ( CONSOLE_PORT != 1 )
0710 {
0711 status = rtems_io_register_name ("/dev/tty01", major, 1);
0712 if ( status != RTEMS_SUCCESSFUL )
0713 {
0714 rtems_fatal_error_occurred (status);
0715 }
0716 }
0717
0718 return(RTEMS_SUCCESSFUL);
0719 }
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729 rtems_device_driver console_open(
0730 rtems_device_major_number major,
0731 rtems_device_minor_number minor,
0732 void * arg)
0733 {
0734 rtems_status_code status = RTEMS_INVALID_NUMBER;
0735 rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *)arg;
0736 struct IntUartInfoStruct *info;
0737
0738 static const rtems_termios_callbacks IntUartPollCallbacks = {
0739 NULL,
0740 NULL,
0741 IntUartPollRead,
0742 IntUartPollWrite,
0743 IntUartSetAttributes,
0744 NULL,
0745 NULL,
0746 TERMIOS_POLLED
0747 };
0748 static const rtems_termios_callbacks IntUartIntrCallbacks = {
0749 IntUartInterruptOpen,
0750 IntUartInterruptClose,
0751 NULL,
0752 IntUartInterruptWrite,
0753 IntUartSetAttributes,
0754 NULL,
0755 NULL,
0756 TERMIOS_IRQ_DRIVEN
0757 };
0758
0759 static const rtems_termios_callbacks IntUartTaskCallbacks = {
0760 IntUartInterruptOpen,
0761 IntUartInterruptClose,
0762 IntUartTaskRead,
0763 IntUartInterruptWrite,
0764 IntUartSetAttributes,
0765 NULL,
0766 NULL,
0767 TERMIOS_TASK_DRIVEN
0768 };
0769
0770
0771 if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
0772 {
0773 info = &IntUartInfo[minor];
0774 switch ( info->iomode )
0775 {
0776 case TERMIOS_POLLED:
0777 status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
0778 break;
0779 case TERMIOS_IRQ_DRIVEN:
0780 status = rtems_termios_open(major, minor, arg, &IntUartIntrCallbacks);
0781 info->ttyp = args->iop->data1;
0782 break;
0783 case TERMIOS_TASK_DRIVEN:
0784 status = rtems_termios_open(major, minor, arg, &IntUartTaskCallbacks);
0785 info->ttyp = args->iop->data1;
0786 break;
0787 }
0788 }
0789
0790 return( status );
0791 }
0792
0793
0794
0795
0796
0797
0798 rtems_device_driver console_close(
0799 rtems_device_major_number major,
0800 rtems_device_minor_number minor,
0801 void * arg)
0802 {
0803 return(rtems_termios_close (arg));
0804 }
0805
0806
0807
0808
0809
0810
0811 rtems_device_driver console_read(
0812 rtems_device_major_number major,
0813 rtems_device_minor_number minor,
0814 void * arg)
0815 {
0816 return(rtems_termios_read (arg));
0817 }
0818
0819
0820
0821
0822
0823
0824 rtems_device_driver console_write(
0825 rtems_device_major_number major,
0826 rtems_device_minor_number minor,
0827 void * arg)
0828 {
0829 return(rtems_termios_write (arg));
0830 }
0831
0832
0833
0834
0835
0836
0837 rtems_device_driver console_control(
0838 rtems_device_major_number major,
0839 rtems_device_minor_number minor,
0840 void * arg)
0841 {
0842 return( rtems_termios_ioctl (arg) );
0843 }