File indexing completed on 2025-05-11 08:23:38
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 #include <bspopts.h>
0044 #include <termios.h>
0045 #include <rtems/termiostypes.h>
0046 #include <bsp/tms570-sci-driver.h>
0047 #include <rtems/console.h>
0048 #include <bsp.h>
0049 #include <bsp/fatal.h>
0050 #include <bsp/irq.h>
0051
0052
0053
0054
0055
0056
0057 tms570_sci_context driver_context_table[] = {
0058 {
0059 .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI1"),
0060 .device_name = "/dev/console",
0061
0062
0063
0064 .regs = (volatile tms570_sci_t *) &TMS570_LIN,
0065 .irq = TMS570_IRQ_SCI_LEVEL_0,
0066 },
0067 {
0068 .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI2"),
0069 .device_name = "/dev/ttyS1",
0070 .regs = &TMS570_SCI,
0071 .irq = TMS570_IRQ_SCI2_LEVEL_0,
0072 }
0073 };
0074
0075 void tms570_sci_initialize(tms570_sci_context *ctx)
0076 {
0077 uint32_t rx_pin = 1 << 1;
0078 uint32_t tx_pin = 1 << 2;
0079
0080
0081 ctx->regs->GCR0 = TMS570_SCI_GCR0_RESET * 0;
0082 ctx->regs->GCR0 = TMS570_SCI_GCR0_RESET * 1;
0083
0084
0085 ctx->regs->CLEARINT = 0xffffffff;
0086
0087
0088 ctx->regs->CLEARINTLVL = 0xffffffff;
0089
0090 ctx->regs->GCR1 = TMS570_SCI_GCR1_TXENA * 0 |
0091 TMS570_SCI_GCR1_RXENA * 0 |
0092 TMS570_SCI_GCR1_CONT * 0 |
0093 TMS570_SCI_GCR1_LOOP_BACK * 0 |
0094 TMS570_SCI_GCR1_POWERDOWN * 0 |
0095 TMS570_SCI_GCR1_SLEEP * 0 |
0096 TMS570_SCI_GCR1_SWnRST * 0 |
0097 TMS570_SCI_GCR1_CLOCK * 1 |
0098 TMS570_SCI_GCR1_TIMING_MODE * 1 |
0099 TMS570_SCI_GCR1_COMM_MODE * 0;
0100
0101
0102 ctx->regs->PIO0 = rx_pin * 1 | tx_pin * 1;
0103 ctx->regs->PIO3 = rx_pin * 0 | tx_pin * 0;
0104 ctx->regs->PIO1 = rx_pin * 0 | tx_pin * 0;
0105 ctx->regs->PIO6 = rx_pin * 0 | tx_pin * 0;
0106 ctx->regs->PIO7 = rx_pin * 0 | tx_pin * 0;
0107 ctx->regs->PIO8 = rx_pin * 1 | tx_pin * 1;
0108
0109
0110 ctx->regs->GCR1 |= TMS570_SCI_GCR1_SWnRST;
0111 }
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 rtems_device_driver console_initialize(
0124 rtems_device_major_number major,
0125 rtems_device_minor_number minor,
0126 void *arg
0127 )
0128 {
0129 rtems_status_code sc;
0130 #if CONSOLE_USE_INTERRUPTS
0131 const rtems_termios_device_handler *handler = &tms570_sci_handler_interrupt;
0132 #else
0133 const rtems_termios_device_handler *handler = &tms570_sci_handler_polled;
0134 #endif
0135
0136
0137
0138
0139
0140
0141 rtems_termios_initialize();
0142
0143
0144 for (
0145 minor = 0;
0146 minor < RTEMS_ARRAY_SIZE(driver_context_table);
0147 ++minor
0148 ) {
0149 tms570_sci_context *ctx = &driver_context_table[minor];
0150
0151 tms570_sci_initialize(ctx);
0152
0153
0154
0155
0156
0157
0158
0159 sc = rtems_termios_device_install(
0160 ctx->device_name,
0161 handler,
0162 NULL,
0163 &ctx->base
0164 );
0165 if ( sc != RTEMS_SUCCESSFUL ) {
0166 bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV);
0167 }
0168 }
0169 return RTEMS_SUCCESSFUL;
0170 }
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181 static void tms570_sci_enable_interrupts(tms570_sci_context * ctx)
0182 {
0183 ctx->regs->SETINT = TMS570_SCI_SETINT_SET_RX_INT;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195 static void tms570_sci_disable_interrupts(tms570_sci_context * ctx)
0196 {
0197 ctx->regs->CLEARINT = TMS570_SCI_CLEARINT_CLR_RX_INT;
0198 }
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 static int tms570_sci_transmitted_chars(tms570_sci_context * ctx)
0212 {
0213 int ret;
0214
0215 ret = ctx->tx_chars_in_hw;
0216 if ( ret == 1 ) {
0217 ctx->tx_chars_in_hw = 0;
0218 return 1;
0219 }
0220 return ret;
0221 }
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232 bool tms570_sci_set_attributes(
0233 rtems_termios_device_context *base,
0234 const struct termios *t
0235 )
0236 {
0237 tms570_sci_context *ctx = (tms570_sci_context *) base;
0238 rtems_interrupt_lock_context lock_context;
0239 int32_t bauddiv;
0240 int32_t baudrate;
0241 uint32_t flr_tx_ready = TMS570_SCI_FLR_TX_EMPTY;
0242
0243
0244
0245
0246
0247
0248
0249
0250 baudrate = rtems_termios_baud_to_number(cfgetospeed(t));
0251
0252 rtems_termios_device_lock_acquire(base, &lock_context);
0253
0254 while ( (ctx->regs->GCR1 & TMS570_SCI_GCR1_TXENA) &&
0255 (ctx->regs->FLR & flr_tx_ready) != flr_tx_ready) {
0256
0257
0258
0259
0260
0261 rtems_interval tw;
0262
0263 rtems_termios_device_lock_release(base, &lock_context);
0264
0265 tw = rtems_clock_get_ticks_per_second();
0266 tw = tw * 5 / baudrate + 1;
0267 rtems_task_wake_after( tw );
0268
0269 rtems_termios_device_lock_acquire(base, &lock_context);
0270 }
0271
0272 ctx->regs->GCR1 &= ~( TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA |
0273 TMS570_SCI_GCR1_RXENA );
0274
0275 ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_STOP;
0276 ctx->regs->FORMAT = TMS570_SCI_FORMAT_CHAR(0x7);
0277
0278 switch ( t->c_cflag & ( PARENB|PARODD ) ) {
0279 case ( PARENB|PARODD ):
0280
0281 ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY;
0282 ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA;
0283 break;
0284
0285 case PARENB:
0286
0287 ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY;
0288 ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA;
0289 break;
0290
0291 default:
0292 case 0:
0293 case PARODD:
0294
0295 ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY_ENA;
0296 }
0297
0298
0299 baudrate *= 16;
0300 bauddiv = (TMS570_VCLK_HZ + baudrate / 2) / baudrate;
0301 ctx->regs->BRS = bauddiv? bauddiv - 1: 0;
0302
0303 ctx->regs->GCR1 |= TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA |
0304 TMS570_SCI_GCR1_RXENA;
0305
0306 rtems_termios_device_lock_release(base, &lock_context);
0307
0308 return true;
0309 }
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321 static void tms570_sci_interrupt_handler(void * arg)
0322 {
0323 rtems_termios_tty *tty = arg;
0324 tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
0325
0326
0327
0328
0329 if ( (ctx->regs->FLR & TMS570_SCI_FLR_RXRDY ) == TMS570_SCI_FLR_RXRDY ) {
0330 char buf[1];
0331
0332
0333 buf[0] = ctx->regs->RD & 0x000000FF;
0334
0335
0336 rtems_termios_enqueue_raw_characters(tty, buf, 1);
0337 }
0338
0339
0340
0341 if ( (ctx->regs->FLR & TMS570_SCI_FLR_TXRDY ) == TMS570_SCI_FLR_TXRDY ) {
0342 size_t n;
0343
0344 n = tms570_sci_transmitted_chars(ctx);
0345 if ( n > 0 ) {
0346
0347
0348
0349
0350
0351 rtems_termios_dequeue_characters(tty, n);
0352 }
0353 }
0354 }
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368 static void tms570_sci_interrupt_write(
0369 rtems_termios_device_context *base,
0370 const char *buf,
0371 size_t len
0372 )
0373 {
0374 tms570_sci_context *ctx = (tms570_sci_context *) base;
0375
0376 if ( len > 0 ) {
0377
0378 ctx->regs->TD = *buf;
0379
0380 ctx->tx_chars_in_hw = 1;
0381
0382 ctx->regs->SETINT = (1<<8);
0383
0384 } else {
0385
0386 ctx->regs->CLEARINT = (1<<8);
0387
0388 }
0389 }
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402 static void tms570_sci_poll_write(
0403 rtems_termios_device_context *base,
0404 const char *buf,
0405 size_t n
0406 )
0407 {
0408 tms570_sci_context *ctx = (tms570_sci_context *) base;
0409 size_t i;
0410
0411
0412
0413 for ( i = 0; i < n; ++i ) {
0414 while ( (ctx->regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) == 0) {
0415 ;
0416 }
0417 ctx->regs->TD = buf[i];
0418 }
0419 }
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430 static int TMS570_sci_can_read_char(
0431 tms570_sci_context * ctx
0432 )
0433 {
0434 return ctx->regs->FLR & TMS570_SCI_FLR_RXRDY;
0435 }
0436
0437
0438
0439
0440
0441
0442
0443
0444
0445 static char TMS570_sci_read_char(
0446 tms570_sci_context * ctx
0447 )
0448 {
0449 return ctx->regs->RD;
0450 }
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461 static int tms570_sci_poll_read(rtems_termios_device_context *base)
0462 {
0463 tms570_sci_context *ctx = (tms570_sci_context *) base;
0464
0465
0466 if ( TMS570_sci_can_read_char(ctx) ) {
0467 return TMS570_sci_read_char(ctx);
0468 } else {
0469 return -1;
0470 }
0471 }
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 static bool tms570_sci_poll_first_open(
0487 rtems_termios_tty *tty,
0488 rtems_termios_device_context *ctx,
0489 struct termios *term,
0490 rtems_libio_open_close_args_t *args
0491 )
0492 {
0493 bool ok;
0494
0495 rtems_termios_set_best_baud(term, TMS570_SCI_BAUD_RATE);
0496 ok = tms570_sci_set_attributes(ctx, term);
0497 if ( !ok ) {
0498 return false;
0499 }
0500 return true;
0501 }
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515 static bool tms570_sci_interrupt_first_open(
0516 rtems_termios_tty *tty,
0517 rtems_termios_device_context *base,
0518 struct termios *term,
0519 rtems_libio_open_close_args_t *args
0520 )
0521 {
0522 tms570_sci_context *ctx = (tms570_sci_context *) base;
0523 rtems_status_code sc;
0524 bool ret;
0525
0526 ret = tms570_sci_poll_first_open(tty, base, term, args);
0527 if ( ret == false ) {
0528 return false;
0529 }
0530
0531
0532 sc = rtems_interrupt_handler_install(ctx->irq,
0533 ctx->device_name,
0534 RTEMS_INTERRUPT_SHARED,
0535 tms570_sci_interrupt_handler,
0536 tty
0537 );
0538 if ( sc != RTEMS_SUCCESSFUL ) {
0539 return false;
0540 }
0541 tms570_sci_enable_interrupts(ctx);
0542 return true;
0543 }
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554 static void tms570_sci_poll_last_close(
0555 rtems_termios_tty *tty,
0556 rtems_termios_device_context *base,
0557 rtems_libio_open_close_args_t *args
0558 )
0559 {
0560 ;
0561 }
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574 static void tms570_sci_interrupt_last_close(
0575 rtems_termios_tty *tty,
0576 rtems_termios_device_context *base,
0577 rtems_libio_open_close_args_t *args
0578 )
0579 {
0580 tms570_sci_context *ctx = (tms570_sci_context *) base;
0581 rtems_interrupt_lock_context lock_context;
0582 rtems_interval tw;
0583 int32_t baudrate;
0584
0585
0586 rtems_termios_device_lock_acquire(base, &lock_context);
0587 tms570_sci_disable_interrupts(ctx);
0588 rtems_termios_device_lock_release(base, &lock_context);
0589
0590 tw = rtems_clock_get_ticks_per_second();
0591 baudrate = rtems_termios_baud_to_number(cfgetospeed(&tty->termios));
0592 tw = tw * 10 / baudrate + 1;
0593 while ( ( ctx->regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) == 0 ) {
0594 rtems_task_wake_after(tw);
0595 }
0596
0597
0598 rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);
0599
0600 tms570_sci_poll_last_close(tty, base, args);
0601 }
0602
0603
0604
0605
0606
0607
0608
0609 const rtems_termios_device_handler tms570_sci_handler_polled = {
0610 .first_open = tms570_sci_poll_first_open,
0611 .last_close = tms570_sci_poll_last_close,
0612 .poll_read = tms570_sci_poll_read,
0613 .write = tms570_sci_poll_write,
0614 .set_attributes = tms570_sci_set_attributes,
0615 .mode = TERMIOS_POLLED
0616 };
0617
0618
0619
0620
0621
0622
0623
0624 const rtems_termios_device_handler tms570_sci_handler_interrupt = {
0625 .first_open = tms570_sci_interrupt_first_open,
0626 .last_close = tms570_sci_interrupt_last_close,
0627 .poll_read = NULL,
0628 .write = tms570_sci_interrupt_write,
0629 .set_attributes = tms570_sci_set_attributes,
0630 .mode = TERMIOS_IRQ_DRIVEN
0631 };