Changeset 8a9bdc5 in rtems


Ignore:
Timestamp:
Oct 7, 2014, 9:37:55 AM (6 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, master
Children:
77dd9a4
Parents:
2fd3e65f
git-author:
Sebastian Huber <sebastian.huber@…> (10/07/14 09:37:55)
git-committer:
Sebastian Huber <sebastian.huber@…> (10/07/14 14:35:20)
Message:

libchip/serial: Task driven mode for NS16550

Location:
c/src/libchip/serial
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/libchip/serial/ns16550-context.c

    r2fd3e65f r8a9bdc5  
    9999}
    100100
     101static void ns16550_clear_and_set_interrupts(
     102  ns16550_context *ctx,
     103  uint8_t          clear,
     104  uint8_t          set
     105)
     106{
     107  rtems_interrupt_lock_context lock_context;
     108  ns16550_get_reg get_reg = ctx->get_reg;
     109  ns16550_set_reg set_reg = ctx->set_reg;
     110  uintptr_t port = ctx->port;
     111  uint8_t val;
     112
     113  rtems_termios_device_lock_acquire(&ctx->base, &lock_context);
     114  val = (*get_reg)(port, NS16550_INTERRUPT_ENABLE);
     115  val &= ~clear;
     116  val |= set;
     117  (*set_reg)(port, NS16550_INTERRUPT_ENABLE, val);
     118  rtems_termios_device_lock_release(&ctx->base, &lock_context);
     119}
     120
    101121/*
    102122 *  ns16550_probe
     
    180200  return out;
    181201}
    182 
    183 #if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
    184202
    185203/**
     
    226244  } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
    227245}
    228 #endif
     246
     247static void ns16550_isr_task(void *arg)
     248{
     249  rtems_termios_tty *tty = arg;
     250  ns16550_context *ctx = rtems_termios_get_device_context(tty);
     251  uint8_t status = (*ctx->get_reg)(ctx->port, NS16550_LINE_STATUS);
     252
     253  if ((status & SP_LSR_RDY) != 0) {
     254    ns16550_clear_and_set_interrupts(ctx, SP_INT_RX_ENABLE, 0);
     255    rtems_termios_rxirq_occured(tty);
     256  }
     257
     258  if (ctx->out_total > 0 && (status & SP_LSR_THOLD) != 0) {
     259    size_t current = ctx->out_current;
     260
     261    ctx->out_buf += current;
     262    ctx->out_remaining -= current;
     263
     264    if (ctx->out_remaining > 0) {
     265      ctx->out_current =
     266        ns16550_write_to_fifo(ctx, ctx->out_buf, ctx->out_remaining);
     267    } else {
     268      size_t done = ctx->out_total;
     269
     270      ctx->out_total = 0;
     271      ns16550_clear_and_set_interrupts(ctx, SP_INT_TX_ENABLE, 0);
     272      rtems_termios_dequeue_characters(tty, done);
     273    }
     274  }
     275}
     276
     277static int ns16550_read_task(rtems_termios_device_context *base)
     278{
     279  ns16550_context *ctx = (ns16550_context *) base;
     280  uint32_t port = ctx->port;
     281  ns16550_get_reg get = ctx->get_reg;
     282  char buf[SP_FIFO_SIZE];
     283  int i;
     284
     285  for (i = 0; i < SP_FIFO_SIZE; ++i) {
     286    if ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
     287      buf[i] = (char) get(port, NS16550_RECEIVE_BUFFER);
     288    } else {
     289      break;
     290    }
     291  }
     292
     293  rtems_termios_enqueue_raw_characters(ctx->tty, buf, i);
     294  ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_RX_ENABLE);
     295
     296  return -1;
     297}
    229298
    230299/*
     
    235304static void ns16550_initialize_interrupts(
    236305  struct rtems_termios_tty *tty,
    237   ns16550_context          *ctx
     306  ns16550_context          *ctx,
     307  void                    (*isr)(void *)
    238308)
    239309{
     
    245315        "NS16550",
    246316        RTEMS_INTERRUPT_SHARED,
    247         ns16550_isr,
     317        isr,
    248318        tty
    249319      );
     
    260330        rtems_irq_connect_data cd = {
    261331          ctx->irq,
    262           ns16550_isr,
     332          isr,
    263333          tty,
    264334          NULL,
     
    271341        rtems_irq_connect_data cd = {
    272342          ctx->irq,
    273           ns16550_isr,
     343          isr,
    274344          tty,
    275345          NULL,
     
    301371  ns16550_context *ctx = (ns16550_context *) base;
    302372
     373  ctx->tty = tty;
     374
    303375  /* Set initial baud */
    304376  rtems_termios_set_initial_baud(tty, ctx->initial_baud);
    305377
    306378  if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
    307     ns16550_initialize_interrupts(tty, ctx);
     379    ns16550_initialize_interrupts(tty, ctx, ns16550_isr);
     380    ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
     381  } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) {
     382    ns16550_initialize_interrupts(tty, ctx, ns16550_isr_task);
    308383    ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
    309384  }
     
    314389static void ns16550_cleanup_interrupts(
    315390  struct rtems_termios_tty *tty,
    316   ns16550_context          *ctx
     391  ns16550_context          *ctx,
     392  void                    (*isr)(void *)
    317393)
    318394{
     
    321397    sc = rtems_interrupt_handler_remove(
    322398      ctx->irq,
    323       ns16550_isr,
     399      isr,
    324400      tty
    325401    );
     
    333409    rtems_irq_connect_data cd = {
    334410      .name = ctx->irq,
    335       .hdl = ns16550_isr,
     411      .hdl = isr,
    336412      .handle = tty
    337413    };
     
    360436
    361437  if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
    362     ns16550_cleanup_interrupts(tty, ctx);
     438    ns16550_cleanup_interrupts(tty, ctx, ns16550_isr);
     439  } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) {
     440    ns16550_cleanup_interrupts(tty, ctx, ns16550_isr_task);
    363441  }
    364442}
     
    612690  } else {
    613691    ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
     692  }
     693}
     694
     695static void ns16550_write_support_task(
     696  rtems_termios_device_context *base,
     697  const char                   *buf,
     698  size_t                        len
     699)
     700{
     701  ns16550_context *ctx = (ns16550_context *) base;
     702
     703  ctx->out_total = len;
     704
     705  if (len > 0) {
     706    ctx->out_remaining = len;
     707    ctx->out_buf = buf;
     708    ctx->out_current = ns16550_write_to_fifo(ctx, buf, len);
     709
     710    ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_TX_ENABLE);
    614711  }
    615712}
     
    695792  .mode = TERMIOS_POLLED
    696793};
     794
     795const rtems_termios_device_handler ns16550_handler_task = {
     796  .first_open = ns16550_open,
     797  .last_close = ns16550_close,
     798  .poll_read = ns16550_read_task,
     799  .write = ns16550_write_support_task,
     800  .set_attributes = ns16550_set_attributes,
     801  .mode = TERMIOS_TASK_DRIVEN
     802};
  • c/src/libchip/serial/ns16550.h

    r2fd3e65f r8a9bdc5  
    7575  size_t out_current;
    7676  const char *out_buf;
     77  rtems_termios_tty *tty;
    7778} ns16550_context;
    7879
    7980extern const rtems_termios_device_handler ns16550_handler_interrupt;
    8081extern const rtems_termios_device_handler ns16550_handler_polled;
     82extern const rtems_termios_device_handler ns16550_handler_task;
    8183
    8284extern const rtems_termios_device_flow ns16550_flow_rtscts;
Note: See TracChangeset for help on using the changeset viewer.