Beispiel #1
0
/**
 * @brief closes sci peripheral of interrupt driven driver
 *
 * calls tms570_sci_poll_last_close and disables interrupts
 *
 * @param[in] tty Termios control
 * @param[in] base context of the driver
 * @param[in] args
 * @retval false Error occured during initialization
 * @retval true Driver is open and ready
 */
static void tms570_sci_interrupt_last_close(
  rtems_termios_tty             *tty,
  rtems_termios_device_context  *base,
  rtems_libio_open_close_args_t *args
)
{
  tms570_sci_context *ctx = (tms570_sci_context *) base;
  rtems_interrupt_lock_context lock_context;
  rtems_interval tw;
  int32_t baudrate;

  /* Turn off RX interrupts */
  rtems_termios_device_lock_acquire(base, &lock_context);
  tms570_sci_disable_interrupts(ctx);
  rtems_termios_device_lock_release(base, &lock_context);

  tw = rtems_clock_get_ticks_per_second();
  baudrate = rtems_termios_baud_to_number(cfgetospeed(&tty->termios));
  tw = tw * 10 / baudrate + 1;
  while ( ( ctx->regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) == 0 ) {
     rtems_task_wake_after(tw);
  }

  /* uninstall ISR */
  rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);

  tms570_sci_poll_last_close(tty, base, args);
}
Beispiel #2
0
/* Handle UART interrupts */
static void apbuart_cons_isr(void *arg)
{
	rtems_termios_tty *tty = arg;
	rtems_termios_device_context *base;
	struct console_dev *condev = rtems_termios_get_device_context(tty);
	struct apbuart_priv *uart = condev_get_priv(condev);
	struct apbuart_regs *regs = uart->regs;
	unsigned int status;
	char buf[33];
	int cnt;

	if (uart->mode == TERMIOS_TASK_DRIVEN) {
		if ((status = regs->status) & APBUART_STATUS_DR) {
			rtems_interrupt_lock_context lock_context;

			/* Turn off RX interrupts */
			base = rtems_termios_get_device_context(tty);
			rtems_termios_device_lock_acquire(base, &lock_context);
			regs->ctrl &=
			    ~(APBUART_CTRL_DI | APBUART_CTRL_RI |
			      APBUART_CTRL_RF);
			rtems_termios_device_lock_release(base, &lock_context);
			/* Activate termios RX daemon task */
			rtems_termios_rxirq_occured(tty);
		}
	} else {
		/*
		 * Get all new characters from APBUART RX (FIFO) and store them
		 * on the stack. Then tell termios about the new characters.
		 * Maximum APBUART RX FIFO size is 32 characters.
		 */
		cnt = 0;
		while (
			((status=regs->status) & APBUART_STATUS_DR) &&
			(cnt < sizeof(buf))
		) {
			buf[cnt] = regs->data;
			cnt++;
		}
		if (0 < cnt) {
			/* Tell termios layer about new characters */
			rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt);
		}
	}

	if (uart->sending && (status & APBUART_STATUS_TE)) {
		/* Tell close that we sent everything */
		cnt = uart->sending;

		/*
		 * Tell termios how much we have sent. dequeue() may call
		 * write_interrupt() to refill the transmitter.
		 * write_interrupt() will eventually be called with 0 len to
		 * disable TX interrupts.
		 */
		rtems_termios_dequeue_characters(tty, cnt);
	}
}
Beispiel #3
0
/**
 * @brief Set attributes of the HW peripheral
 *
 * Sets attributes of the HW peripheral (parity, baud rate, etc.)
 *
 * @param[in] base context of the driver
 * @param[in] t termios driver
 * @retval true peripheral setting is changed
 */
static bool tms570_sci_set_attributes(
  rtems_termios_device_context *base,
  const struct termios *t
)
{
  tms570_sci_context *ctx = (tms570_sci_context *) base;
  rtems_interrupt_lock_context lock_context;
  int32_t bauddiv;
  int32_t baudrate;

  rtems_termios_device_lock_acquire(base, &lock_context);

  ctx->regs->GCR1 &= ~( TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA |
                        TMS570_SCI_GCR1_RXENA );

  ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_STOP;    /*one stop bit*/
  ctx->regs->FORMAT = TMS570_SCI_FORMAT_CHAR(0x7);

  switch ( t->c_cflag & ( PARENB|PARODD ) ) {
    case ( PARENB|PARODD ):
      /* Odd parity */
      ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY;
      ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA;
      break;

    case PARENB:
      /* Even parity */
      ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY;
      ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA;
      break;

    default:
    case 0:
    case PARODD:
      /* No Parity */
      ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY_ENA;
  }

  /* Baud rate */
  baudrate = rtems_termios_baud_to_number(cfgetospeed(t));
  baudrate *= 2 * 16;
  bauddiv = (BSP_PLL_OUT_CLOCK + baudrate / 2) / baudrate;
  ctx->regs->BRS = bauddiv;

  ctx->regs->GCR1 |= TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA |
                     TMS570_SCI_GCR1_RXENA;

  rtems_termios_device_lock_release(base, &lock_context);

  return true;
}
Beispiel #4
0
/**
 * @brief Set attributes of the HW peripheral
 *
 * Sets attributes of the HW peripheral (parity, baud rate, etc.)
 *
 * @param[in] base context of the driver
 * @param[in] t termios driver
 * @retval true peripheral setting is changed
 */
static bool tms570_sci_set_attributes(
  rtems_termios_device_context *base,
  const struct termios *t
)
{
  tms570_sci_context *ctx = (tms570_sci_context *) base;
  rtems_interrupt_lock_context lock_context;
  int32_t bauddiv;
  int32_t baudrate;

  rtems_termios_device_lock_acquire(base, &lock_context);

  ctx->regs->SCIGCR1 &= ~( (1<<7) | (1<<25) | (1<<24) );

  ctx->regs->SCIGCR1 &= ~(1<<4);    /*one stop bit*/
  ctx->regs->SCIFORMAT = 0x7;

  switch ( t->c_cflag & ( PARENB|PARODD ) ) {
    case ( PARENB|PARODD ):
      /* Odd parity */
      ctx->regs->SCIGCR1 &= ~(1<<3);
      ctx->regs->SCIGCR1 |= (1<<2);
      break;

    case PARENB:
      /* Even parity */
      ctx->regs->SCIGCR1 |= (1<<3);
      ctx->regs->SCIGCR1 |= (1<<2);
      break;

    default:
    case 0:
    case PARODD:
      /* No Parity */
      ctx->regs->SCIGCR1 &= ~(1<<2);
  }

  /* Baud rate */
  baudrate = rtems_termios_baud_to_number(cfgetospeed(t));
  baudrate *= 2 * 16;
  bauddiv = (BSP_PLL_OUT_CLOCK + baudrate / 2) / baudrate;
  ctx->regs->BRS = bauddiv;

  ctx->regs->SCIGCR1 |= (1<<7) | (1<<25) | (1<<24);

  rtems_termios_device_lock_release(base, &lock_context);

  return true;
}
Beispiel #5
0
/* This function is called from TERMIOS rxdaemon task without device lock. */
static int read_task(rtems_termios_device_context *base)
{
	rtems_interrupt_lock_context lock_context;
	struct apbuart_priv *uart = base_get_priv(base);
	struct apbuart_regs *regs = uart->regs;
	int cnt;
	char buf[33];
	struct rtems_termios_tty *tty;
	uint32_t ctrl_add;

	ctrl_add = APBUART_CTRL_RI;
	if (uart->cap & CAP_DI) {
		ctrl_add |= (APBUART_CTRL_DI | APBUART_CTRL_RF);
	}
	tty = uart->tty;
	do {
		cnt = 0;
		while (
			(regs->status & APBUART_STATUS_DR) &&
			(cnt < sizeof(buf))
		) {
			buf[cnt] = regs->data;
			cnt++;
		}
		if (0 < cnt) {
			/* Tell termios layer about new characters */
			rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt);
		}

		/*
		 * Turn on RX interrupts. A new character in FIFO now may not
		 * cause interrupt so we must check data ready again
		 * afterwards.
		 */
		rtems_termios_device_lock_acquire(base, &lock_context);
		regs->ctrl |= ctrl_add;
		rtems_termios_device_lock_release(base, &lock_context);
	} while (regs->status & APBUART_STATUS_DR);

	return EOF;
}
Beispiel #6
0
static void apbuart_last_close_interrupt(
  rtems_termios_tty *tty,
  rtems_termios_device_context *base,
  rtems_libio_open_close_args_t *args
)
{
  struct apbuart_context *uart = (struct apbuart_context *) base;
  rtems_interrupt_lock_context lock_context;

  /* Turn off RX interrupts */
  rtems_termios_device_lock_acquire(base, &lock_context);
  uart->regs->ctrl &= ~(APBUART_CTRL_RI);
  rtems_termios_device_lock_release(base, &lock_context);

  /**** Flush device ****/
  while (uart->sending) {
    /* Wait until all data has been sent */
  }

  /* uninstall ISR */
  rtems_interrupt_handler_remove(uart->irq, apbuart_isr, tty);
}
Beispiel #7
0
static void last_close(
	rtems_termios_tty *tty,
	rtems_termios_device_context *base,
	rtems_libio_open_close_args_t *args
)
{
	struct apbuart_priv *uart = base_get_priv(base);
	rtems_interrupt_lock_context lock_context;

	if (uart->mode != TERMIOS_POLLED) {
		/* Turn off RX interrupts */
		rtems_termios_device_lock_acquire(base, &lock_context);
		uart->regs->ctrl &=
			~(APBUART_CTRL_DI | APBUART_CTRL_RI | APBUART_CTRL_RF);
		rtems_termios_device_lock_release(base, &lock_context);

		/**** Flush device ****/
		while (uart->sending) {
			/* Wait until all data has been sent */
		}
		while (
			(uart->regs->ctrl & APBUART_CTRL_TE) &&
			!(uart->regs->status & APBUART_STATUS_TS)
		) {
			/* Wait until all data has left shift register */
		}

		/* Disable and unregister interrupt handler */
		drvmgr_interrupt_unregister(uart->dev, 0, apbuart_cons_isr, tty);
	}

#ifdef LEON3
	/* Disable TX/RX if not used for DEBUG */
	if (uart->regs != leon3_debug_uart)
		uart->regs->ctrl &= ~(APBUART_CTRL_RE | APBUART_CTRL_TE);
#endif
}
Beispiel #8
0
/**
 * @brief closes sci peripheral of interrupt driven driver
 *
 * calls tms570_sci_poll_last_close and disables interrupts
 *
 * @param[in] tty Termios control
 * @param[in] base context of the driver
 * @param[in] args
 * @retval false Error occured during initialization
 * @retval true Driver is open and ready
 */
static void tms570_sci_interrupt_last_close(
  rtems_termios_tty             *tty,
  rtems_termios_device_context  *base,
  rtems_libio_open_close_args_t *args
)
{
  tms570_sci_context *ctx = (tms570_sci_context *) base;
  rtems_interrupt_lock_context lock_context;

  /* Turn off RX interrupts */
  rtems_termios_device_lock_acquire(base, &lock_context);
  tms570_sci_disable_interrupts(ctx);
  rtems_termios_device_lock_release(base, &lock_context);

  /* Flush device */
  while ( ( ctx->regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) > 0 ) {
    ;/* Wait until all data has been sent */
  }

  /* uninstall ISR */
  rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);

  tms570_sci_poll_last_close(tty, base, args);
}
Beispiel #9
0
static bool apbuart_set_attributes(
  rtems_termios_device_context *base,
  const struct termios *t
)
{
  struct apbuart_context *uart = (struct apbuart_context *) base;
  rtems_interrupt_lock_context lock_context;
  unsigned int scaler;
  unsigned int ctrl;
  int baud;

  switch (t->c_cflag & CSIZE) {
    default:
    case CS5:
    case CS6:
    case CS7:
      /* Hardware doesn't support other than CS8 */
      return false;
    case CS8:
      break;
  }

  rtems_termios_device_lock_acquire(base, &lock_context);

  /* Read out current value */
  ctrl = uart->regs->ctrl;

  switch (t->c_cflag & (PARENB|PARODD)) {
    case (PARENB|PARODD):
      /* Odd parity */
      ctrl |= APBUART_CTRL_PE|APBUART_CTRL_PS;
      break;

    case PARENB:
      /* Even parity */
      ctrl &= ~APBUART_CTRL_PS;
      ctrl |= APBUART_CTRL_PE;
      break;

    default:
    case 0:
    case PARODD:
      /* No Parity */
      ctrl &= ~(APBUART_CTRL_PS|APBUART_CTRL_PE);
  }

  if (!(t->c_cflag & CLOCAL)) {
    ctrl |= APBUART_CTRL_FL;
  } else {
    ctrl &= ~APBUART_CTRL_FL;
  }

  /* Update new settings */
  uart->regs->ctrl = ctrl;

  rtems_termios_device_lock_release(base, &lock_context);

  /* Baud rate */
  baud = rtems_termios_baud_to_number(t->c_cflag);
  if (baud > 0) {
    /* Calculate Baud rate generator "scaler" number */
    scaler = (((uart->freq_hz * 10) / (baud * 8)) - 5) / 10;

    /* Set new baud rate by setting scaler */
    uart->regs->scaler = scaler;
  }

  return true;
}
Beispiel #10
0
static bool set_attributes(
	rtems_termios_device_context *base,
	const struct termios *t
)
{
	unsigned int core_clk_hz;
	unsigned int scaler;
	unsigned int ctrl;
	int baud;
	struct apbuart_priv *uart = base_get_priv(base);
	rtems_interrupt_lock_context lock_context;

	switch(t->c_cflag & CSIZE) {
		default:
		case CS5:
		case CS6:
		case CS7:
			/* Hardware doesn't support other than CS8 */
			return false;
		case CS8:
			break;
	}

	rtems_termios_device_lock_acquire(base, &lock_context);

	/* Read out current value */
	ctrl = uart->regs->ctrl;

	switch(t->c_cflag & (PARENB|PARODD)){
		case (PARENB|PARODD):
			/* Odd parity */
			ctrl |= LEON_REG_UART_CTRL_PE|LEON_REG_UART_CTRL_PS;
			break;

		case PARENB:
			/* Even parity */
			ctrl &= ~LEON_REG_UART_CTRL_PS;
			ctrl |= LEON_REG_UART_CTRL_PE;
			break;

		default:
		case 0:
		case PARODD:
			/* No Parity */
			ctrl &= ~(LEON_REG_UART_CTRL_PS|LEON_REG_UART_CTRL_PE);
	}

	if (!(t->c_cflag & CLOCAL))
		ctrl |= LEON_REG_UART_CTRL_FL;
	else
		ctrl &= ~LEON_REG_UART_CTRL_FL;

	/* Update new settings */
	uart->regs->ctrl = ctrl;

	rtems_termios_device_lock_release(base, &lock_context);

	/* Baud rate */
  baud = apbuart_baud_num2baud(t->c_ospeed);
	if (baud > 0){
		/* Get APBUART core frequency */
		drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz);

		/* Calculate Baud rate generator "scaler" number */
		scaler = (((core_clk_hz*10)/(baud*8))-5)/10;

		/* Set new baud rate by setting scaler */
		uart->regs->scaler = scaler;
	}

	return true;
}
Beispiel #11
0
/**
 * @brief Set attributes of the HW peripheral
 *
 * Sets attributes of the HW peripheral (parity, baud rate, etc.)
 *
 * @param[in] base context of the driver
 * @param[in] t termios driver
 * @retval true peripheral setting is changed
 */
bool tms570_sci_set_attributes(
  rtems_termios_device_context *base,
  const struct termios *t
)
{
  tms570_sci_context *ctx = (tms570_sci_context *) base;
  rtems_interrupt_lock_context lock_context;
  int32_t bauddiv;
  int32_t baudrate;
  uint32_t flr_tx_ready = TMS570_SCI_FLR_TX_EMPTY;
  /*
   * Test for TMS570_SCI_FLR_TXRDY is not necessary
   * because both SCITD and SCITXSHF has to be empty
   * to TX_EMPTY be asserted. But there is no interrupt
   * option for TX_EMPTY. Polling is used isntead.
   */

  /* Baud rate */
  baudrate = rtems_termios_baud_to_number(cfgetospeed(t));

  rtems_termios_device_lock_acquire(base, &lock_context);

  while ( (ctx->regs->GCR1 & TMS570_SCI_GCR1_TXENA) &&
          (ctx->regs->FLR & flr_tx_ready) != flr_tx_ready) {
    /*
     * There are pending characters in the hardware,
     * change in the middle of the character Tx leads
     * to disturb of the character and SCI engine
     */
    rtems_interval tw;

    rtems_termios_device_lock_release(base, &lock_context);

    tw = rtems_clock_get_ticks_per_second();
    tw = tw * 5 / baudrate + 1;
    rtems_task_wake_after( tw );

    rtems_termios_device_lock_acquire(base, &lock_context);
  }

  ctx->regs->GCR1 &= ~( TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA |
                        TMS570_SCI_GCR1_RXENA );

  ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_STOP;    /*one stop bit*/
  ctx->regs->FORMAT = TMS570_SCI_FORMAT_CHAR(0x7);

  switch ( t->c_cflag & ( PARENB|PARODD ) ) {
    case ( PARENB|PARODD ):
      /* Odd parity */
      ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY;
      ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA;
      break;

    case PARENB:
      /* Even parity */
      ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY;
      ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA;
      break;

    default:
    case 0:
    case PARODD:
      /* No Parity */
      ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY_ENA;
  }

  /* Apply baudrate to the hardware */
  baudrate *= 2 * 16;
  bauddiv = (BSP_PLL_OUT_CLOCK + baudrate / 2) / baudrate;
  ctx->regs->BRS = bauddiv? bauddiv - 1: 0;

  ctx->regs->GCR1 |= TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA |
                     TMS570_SCI_GCR1_RXENA;

  rtems_termios_device_lock_release(base, &lock_context);

  return true;
}