On Wed, Feb 4, 2015 at 3:49 PM, Martin Galvan
<martin.gal...@tallertechnologies.com> wrote:
> On Wed, Feb 4, 2015 at 2:20 PM, Pavel Pisa <p...@cmp.felk.cvut.cz> wrote:
>> The structure tms570_sci_context holds state variable
>> tx_chars_in_hw which holds if and how many characters
>> (in the optional FIFO support for some Ti SCIs) are submitted
>> into hardware.
>>
>> When field is not writable then code breaks when RTEMS
>> is build for Flash area.
>>
>> The problem found and analyzed by Martin Galvan from tallertechnologies.
>
> Thanks for the patch. In addition, we've developed a refactored
> version of the driver which, besides being const-correct, addresses a
> number of other issues present in the current driver. Namely, it
> improves the coding style, fixes what seems to be an erroneous check
> for ctx->regs->SCIRD != 0 and uses the correct formula for the SCI
> prescaler value. I'm attaching it here so that it can be commited
> before us and Premek add further changes.
>
> Notice, however, that my driver sets BSP_PLL_OUT_CLOCK to 180 MHz in
> bsp.h and divides it by 2 when it's setting the prescaler, so the
> value of VCLK for the formula is 90 MHz. This may vary from board to
> board (I noticed the original code used 160 MHz instead of 90); we
> used 90 MHz because it's what HALCoGen generates by default. Notice as
> well that this code still relies on the device having been set up
> already (as Pavel said, right now we're using HALCoGen-generated code
> for that).

It appears my mail client wrapped the lines after 80 characters, so
the patch won't apply if you copy it directly from the e-mail. I'm
attaching it here as a separate file. Sorry for the inconvenience.
diff --git a/c/src/lib/libbsp/arm/tms570/console/printk-support.c b/c/src/lib/libbsp/arm/tms570/console/printk-support.c
index 241ca9b..8009e74 100644
--- a/c/src/lib/libbsp/arm/tms570/console/printk-support.c
+++ b/c/src/lib/libbsp/arm/tms570/console/printk-support.c
@@ -3,7 +3,9 @@
  *
  * @ingroup tms570
  *
- * @brief definitions of serial line for debugging.
+ * @brief Functions needed for using printk.
+ *
+ * Premysl: Debug functions always use serial dev 0 peripheral.
  */

 /*
@@ -15,6 +17,11 @@
  * 166 36 Praha 6
  * Czech Republic
  *
+ * Copyright (c) 2015 Taller Technologies
+ * Martin Galvan    <martin.gal...@tallertechnologies.com>
+ * Marcos Diaz      <marcos.d...@tallertechnologies.com>
+ * Eduardo Sanchez  <eduardo.sanc...@tallertechnologies.com>
+ *
  * Based on LPC24xx and LPC1768 BSP
  * by embedded brains GmbH and others
  *
@@ -28,11 +35,8 @@
 #include <bsp/tms570-sci.h>
 #include <bsp/tms570-sci-driver.h>

-
 /**
- * @brief Puts chars into peripheral
- *
- * debug functions always use serial dev 0 peripheral
+ * @brief Puts chars into the peripheral.
  *
  * @retval Void
  */
@@ -41,44 +45,43 @@ static void tms570_putc(char ch)
   rtems_interrupt_level level;

   rtems_interrupt_disable(level);
-  while ( ( driver_context_table[0].regs->SCIFLR & 0x100 ) == 0) {
+
+  while (!(driver_context_table[0].regs->SCIFLR & TXRDY)) {
     rtems_interrupt_flash(level);
   }
+
   driver_context_table[0].regs->SCITD = ch;
   rtems_interrupt_enable(level);
 }

 /**
- * @brief debug console output
+ * @brief Debug console output.
  *
- * debug functions always use serial dev 0 peripheral
+ * This function is called by the kernel's generic putk() to output a char.
  *
  * @retval Void
  */
 static void tms570_uart_output(char c)
 {
-  if ( c == '\n' ) {
-    char r = '\r';
-    tms570_putc(r);
+  if (c == '\n') {
+    tms570_putc('\r');
   }
+
   tms570_putc(c);
 }

 /**
- * @brief debug console input
+ * @brief Debug console input.
  *
- * debug functions always use serial dev 0 peripheral
+ * Is called by the kernel's generic getchark() to read a char.
  *
- * @retval x Read char
- * @retval -1 No input character available
+ * @retval x Read char.
+ * @retval -1 No input character available.
  */
-static int tms570_uart_input( void )
+static int tms570_uart_input(void)
 {
-  if ( driver_context_table[0].regs->SCIFLR & (1<<9) ) {
-      return driver_context_table[0].regs->SCIRD;
-  } else {
-      return -1;
-  }
+  return driver_context_table[0].regs->SCIFLR & RXRDY ?
+         driver_context_table[0].regs->SCIRD : -1;
 }

 BSP_output_char_function_type BSP_output_char = tms570_uart_output;
diff --git a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
index 56ed04e..de45cc6 100644
--- a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
+++ b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
@@ -3,7 +3,7 @@
  *
  * @ingroup tms570
  *
- * @brief Serial communication interface (SCI) functions definitions.
+ * @brief Serial Communication Interface (SCI) function definitions.
  */

 /*
@@ -15,6 +15,11 @@
  * 166 36 Praha 6
  * Czech Republic
  *
+ * Copyright (c) 2015 Taller Technologies
+ * Martin Galvan    <martin.gal...@tallertechnologies.com>
+ * Marcos Diaz      <marcos.d...@tallertechnologies.com>
+ * Eduardo Sanchez  <eduardo.sanc...@tallertechnologies.com>
+ *
  * Based on LPC24xx and LPC1768 BSP
  * by embedded brains GmbH and others
  *
@@ -33,14 +38,14 @@
 #include <bsp/fatal.h>
 #include <bsp/irq.h>

-#define TMS570_SCI_BUFFER_SIZE 1
+#define TMS570_SCI_BUFFER_SIZE 1u

 /**
  * @brief Table including all serial drivers
  *
  * Definitions of all serial drivers
  */
-const tms570_sci_context driver_context_table[] = {
+tms570_sci_context driver_context_table[] = {
   {
     .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI1"),
     .device_name = "/dev/console",
@@ -58,20 +63,20 @@ const tms570_sci_context driver_context_table[] = {
 /**
  * @brief Serial drivers init function
  *
- * Initialize all serial drivers specified in driver_context_table
+ * Initialize all the serial drivers specified in driver_context_table.
  *
  * @param[in] major
  * @param[in] minor
  * @param[in] arg
  * @retval RTEMS_SUCCESSFUL Initialization completed
  */
-rtems_device_driver console_initialize(
-  rtems_device_major_number  major,
-  rtems_device_minor_number  minor,
-  void                      *arg
-)
+rtems_device_driver console_initialize(rtems_device_major_number major,
+                                       rtems_device_minor_number minor,
+                                       void *arg)
 {
-  rtems_status_code sc;
+  rtems_status_code status;
+  tms570_sci_context *ctx;
+
 #if CONSOLE_USE_INTERRUPTS
   const rtems_termios_device_handler *handler = &tms570_sci_handler_interrupt;
 #else
@@ -86,12 +91,8 @@ rtems_device_driver console_initialize(
   rtems_termios_initialize();

   /* Initialize each device */
-  for (
-    minor = 0;
-    minor < RTEMS_ARRAY_SIZE(driver_context_table);
-    ++minor
-  ) {
-    const tms570_sci_context *ctx = &driver_context_table[minor];
+  for (minor = 0; minor < RTEMS_ARRAY_SIZE(driver_context_table); ++minor) {
+    ctx = &driver_context_table[minor];

     /*
      * Install this device in the file system and Termios.  In order
@@ -99,152 +100,106 @@ rtems_device_driver console_initialize(
      * on stdin, stdout and stderr), one device must be registered as
      * "/dev/console" (CONSOLE_DEVICE_NAME).
      */
-    sc = rtems_termios_device_install(
-        ctx->device_name,
-        major,
-        minor,
-        handler,
-  NULL,
-        RTEMS_DECONST(rtems_termios_device_context *, &ctx->base)
-    );
-    if ( sc != RTEMS_SUCCESSFUL ) {
+    status = rtems_termios_device_install(ctx->device_name, major, minor,
+                                          handler, NULL, &ctx->base);
+
+    if (status != RTEMS_SUCCESSFUL) {
       bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV);
     }
   }
+
   return RTEMS_SUCCESSFUL;
 }

 /**
- * @brief Reads chars from HW
+ * @brief Set the SCI parity control.
  *
- * Reads chars from HW peripheral specified in driver context.
- * TMS570 does not have HW buffer for serial line so this function can
- * return only 0 or 1 char
+ * Sets the SCIGCR1 parity bits according to the current Termios settings.
  *
- * @param[in] ctx context of the driver
- * @param[out] buf read data buffer
- * @param[in] N size of buffer
- * @retval x Number of read chars from peripherals
+ * @param[in] ctx Context of the driver.
+ * @param[in] c_cflag Termios control flag.
+ * @retval void.
  */
-static int tms570_sci_read_received_chars(
-  tms570_sci_context * ctx,
-  char * buf,
-  int N)
+
+static void tms570_sci_set_parity(tms570_sci_context *const ctx,
+                                  const tcflag_t c_cflag)
 {
-  if ( N < 1 ) {
-    return 0;
-  }
-  if ( ctx->regs->SCIRD != 0 ) {
-     buf[0] = ctx->regs->SCIRD;
-    return 1;
+  if (c_cflag & PARENB) {
+    ctx->regs->SCIGCR1 |= PARITY_ENA;
+
+    if (c_cflag & PARODD) {  /* Odd parity */
+      ctx->regs->SCIGCR1 &= ~(EVEN_PARITY);
+    } else {  /* Even parity */
+      ctx->regs->SCIGCR1 |= EVEN_PARITY;
+    }
+  } else {  /* No Parity */
+    ctx->regs->SCIGCR1 &= ~(PARITY_ENA);
   }
-  return 0;
 }

 /**
- * @brief Enables RX interrupt
+ * @brief Set the SCI prescaler.
  *
- * Enables RX interrupt source of SCI peripheral
- * specified in the driver context.
+ * Sets the value of the BRS corresponding to the desired baud rate.
  *
- * @param[in] ctx context of the driver
- * @retval Void
+ * @param[in] ctx Context of the driver.
+ * @param[in] terminal Termios driver.
+ * @retval void.
  */
-static void tms570_sci_enable_interrupts(tms570_sci_context * ctx)
+static void tms570_sci_set_prescaler(tms570_sci_context *const ctx,
+                                     const struct termios *terminal)
 {
-  ctx->regs->SCISETINT = (1<<9);
-}
+  uint32_t factor;
+  uint32_t vclk;
+  rtems_termios_baud_t baudrate;
+  rtems_termios_baud_t prescaler;

-/**
- * @brief Disables RX interrupt
- *
- * Disables RX interrupt source of SCI peripheral specified in the driver
- * context.
- *
- * @param[in] ctx context of the driver
- * @retval Void
- */
-static void tms570_sci_disable_interrupts(tms570_sci_context * ctx)
-{
-  ctx->regs->SCICLEARINT = (1<<9);
-}
+  vclk = BSP_PLL_OUT_CLOCK / 2u;

-/**
- * @brief Check whether driver has put char in HW
- *
- * Check whether driver has put char in HW.
- * This information is read from the driver context not from a peripheral.
- * TMS570 does not have write data buffer asociated with SCI
- * so the return can be only 0 or 1.
- *
- * @param[in] ctx context of the driver
- * @retval x
- */
-static int tms570_sci_transmitted_chars(tms570_sci_context * ctx)
-{
-  int ret;
+  /* Determine whether we're in synchronous or asynchronous mode, and select
+    the appropriate divider factor. */
+  factor = ctx->regs->SCIGCR1 & TIMING_MODE ? 16u : 1u;

-  ret = ctx->tx_chars_in_hw;
-  if ( ret == 1 ) {
-    ctx->tx_chars_in_hw = 0;
-    return 1;
-  }
-  return ret;
+  /* Set the prescaler for the desired baud rate.
+   * According to the datasheet, the formula for the baudrate is:
+   * baudrate = vclk / (factor * (prescaler + 1))
+   */
+  baudrate = rtems_termios_baud_to_number(cfgetospeed(terminal));
+  prescaler = (vclk / (factor * baudrate)) - 1;
+  ctx->regs->BRS = prescaler;
 }

 /**
- * @brief Set attributes of the HW peripheral
+ * @brief Set the attributes of the SCI peripheral.
  *
- * Sets attributes of the HW peripheral (parity, baud rate, etc.)
+ * Sets the attributes of the SCI peripheral (parity, baud rate, etc.).
  *
- * @param[in] base context of the driver
- * @param[in] t termios driver
- * @retval true peripheral setting is changed
+ * @param[in] base Context of the driver.
+ * @param[in] terminal Termios driver.
+ * @retval true Peripheral settings are changed.
  */
-static bool tms570_sci_set_attributes(
-  rtems_termios_device_context *base,
-  const struct termios *t
-)
+static bool tms570_sci_set_attributes(rtems_termios_device_context *base,
+                                      const struct termios *terminal)
 {
-  tms570_sci_context *ctx = (tms570_sci_context *) base;
+  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);
-  }
+  /* Put the SCI into reset state, and disable transmissions and receptions. */
+  ctx->regs->SCIGCR1 &= ~(SWnRST | RXENA | TXENA);

-  /* 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 &= ~(STOP); /* One stop bit */
+  ctx->regs->SCIFORMAT = 0x7u;   /* Characters are 8 bits long */

-  ctx->regs->SCIGCR1 |= (1<<7) | (1<<25) | (1<<24);
+  /* Set the parity control bits. */
+  tms570_sci_set_parity(ctx, terminal->c_cflag);
+
+  /* Set the prescaler register. */
+  tms570_sci_set_prescaler(ctx, terminal);
+
+  /* Put the SCI into ready state, and enable transmissions and receptions. */
+  ctx->regs->SCIGCR1 |= (SWnRST | RXENA | TXENA);

   rtems_termios_device_lock_release(base, &lock_context);

@@ -252,200 +207,150 @@ static bool tms570_sci_set_attributes(
 }

 /**
- * @brief sci interrupt handler
+ * @brief SCI interrupt handler.
  *
- * Handler checks which interrupt occured and provides nessesary maintenance
- * dequeue characters in termios driver whether character is send succesfully
- * enqueue characters in termios driver whether character is recieved
+ * The handler checks which interrupt occured and acts accordingly.
+ *  - If a character was sent, remove it from the Termios queue.
+ *  - If a character was received, add it to the Termios queue.
  *
- * @param[in] arg rtems_termios_tty
+ * @param[in] arg The rtems_termios_tty
  * @retval Void
  */
-static void tms570_sci_interrupt_handler(void * arg)
+static void tms570_sci_interrupt_handler(void *arg)
 {
   rtems_termios_tty *tty = arg;
   tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
-  char buf[TMS570_SCI_BUFFER_SIZE];
-  size_t n;
+  char buffer[TMS570_SCI_BUFFER_SIZE];
+
+  /* Check if we've received something. */
+  if (ctx->regs->SCIFLR & RXRDY) {
+    buffer[0] = (char)ctx->regs->SCIRD;
+    /*
+     * Hand the data over to the Termios infrastructure.
+     * We send 1 as the "len" value because we can read only one byte at a time.
+     */
+    rtems_termios_enqueue_raw_characters(tty, buffer, 1u);
+  } /* else, we didn't receive anything. */

   /*
-   * Check if we have received something.
-   */
-   if ( (ctx->regs->SCIFLR & (1<<9) ) == (1<<9) ) {
-      n = tms570_sci_read_received_chars(ctx, buf, TMS570_SCI_BUFFER_SIZE);
-      if ( n > 0 ) {
-        /* Hand the data over to the Termios infrastructure */
-        rtems_termios_enqueue_raw_characters(tty, buf, n);
-      }
-    }
-  /*
-   * Check if we have something transmitted.
+   * Check if we transmitted something and are ready to transmit again.
+   * We need to check ctx->wrote_data because the TXRDY flag is set
+   * at system reset. If we were to reset the system and then handle an RX interrupt,
+   * TXRDY would be set and the interrupt handler would think we transmitted something.
    */
-  if ( (ctx->regs->SCIFLR & (1<<8) ) == (1<<8) ) {
-    n = tms570_sci_transmitted_chars(ctx);
-    if ( n > 0 ) {
-      /*
-       * Notify Termios that we have transmitted some characters.  It
-       * will call now the interrupt write function if more characters
-       * are ready for transmission.
-       */
-      rtems_termios_dequeue_characters(tty, n);
-    }
-  }
+
+  if ((ctx->regs->SCIFLR & TXRDY) && ctx->wrote_data) {
+    ctx->wrote_data = false;
+    /*
+     * Notify Termios that we have transmitted some characters.
+     * It'll call the interrupt write function if more characters
+     * are ready for transmission.
+     * We send 1 as the "len" value because we can transmit only one byte at a time.
+     */
+    rtems_termios_dequeue_characters(tty, 1u);
+  }  /* else, we either didn't transmit anything or aren't ready to transmit yet. */
 }

 /**
- * @brief sci write function called from interrupt
+ * @brief SCI write function called from the interrupt handler.
  *
- * Nonblocking write function. Writes characters to HW peripheral
- * TMS570 does not have write data buffer asociated with SCI
- * so only one character can be written.
+ * Nonblocking write function. Writes characters to HW peripheral.
+ * As SCITD only has 8 bits for its transmit data buffer, we can only transmit
+ * one byte at the time.
  *
- * @param[in] base context of the driver
- * @param[in] buf buffer of characters pending to send
- * @param[in] len size of the buffer
+ * @param[in] base Context of the driver.
+ * @param[in] buffer Buffer of characters pending to be transmitted.
+ * @param[in] length Buffer size.
  * @retval Void
  */
-static void tms570_sci_interrupt_write(
-  rtems_termios_device_context *base,
-  const char *buf,
-  size_t len
-)
+static void tms570_sci_interrupt_write(rtems_termios_device_context *base,
+                                       const char *buffer, size_t length)
 {
-  tms570_sci_context *ctx = (tms570_sci_context *) base;
-
-  if ( len > 0 ) {
-    /* start UART TX, this will result in an interrupt when done */
-    ctx->regs->SCITD = *buf;
-    /* character written - raise count*/
-    ctx->tx_chars_in_hw = 1;
-    /* Enable TX interrupt (interrupt is edge-triggered) */
-    ctx->regs->SCISETINT = (1<<8);
-
-  } else {
-    /* No more to send, disable TX interrupts */
-    ctx->regs->SCICLEARINT = (1<<8);
-    /* Tell close that we sent everything */
+  tms570_sci_context *ctx = (tms570_sci_context *)base;
+
+  if (length) {
+    /* Start UART TX, this will result in an interrupt when done. */
+    ctx->regs->SCITD = *buffer;
+    /* Let the interrupt handler know that we wrote something. */
+    ctx->wrote_data = true;
+    /* Enable TX interrupts (these are edge-triggered). */
+    ctx->regs->SCISETINT = TX_INT;
+  } else {  /* No more to send, disable TX interrupts. */
+    ctx->regs->SCICLEARINT = TX_INT;
   }
 }

 /**
- * @brief sci write function
+ * @brief SCI poll write function.
  *
- * Blocking write function. Waits until HW peripheral is ready and then writes
- * character to HW peripheral. Writes all characters in the buffer.
+ * Blocking write function. Waits until the HW peripheral is ready and then writes
+ * a character to it. Writes all the characters in the buffer.
  *
- * @param[in] base context of the driver
- * @param[in] buf buffer of characters pending to send
- * @param[in] len size of the buffer
+ * @param[in] base Context of the driver.
+ * @param[in] buffer Buffer of characters pending to be transmitted.
+ * @param[in] length Size of the buffer.
  * @retval Void
  */
-static void tms570_sci_poll_write(
-  rtems_termios_device_context *base,
-  const char *buf,
-  size_t n
-)
+static void tms570_sci_poll_write(rtems_termios_device_context *base,
+                                  const char *buffer, size_t length)
 {
-  tms570_sci_context *ctx = (tms570_sci_context *) base;
+  const tms570_sci_context *const ctx = (tms570_sci_context *)base;
   size_t i;

-  /* Write */
-
-  for ( i = 0; i < n; ++i ) {
-    while ( (ctx->regs->SCIFLR & (1<<11) ) == 0) {
-      ;
+  for (i = 0; i < length; ++i) {
+    while (!(ctx->regs->SCIFLR & TX_EMPTY)) {
+      continue; /* Wait until the transmitter's buffer registers are empty. */
     }
-    ctx->regs->SCITD = buf[i];
-  }
-}
-
-/**
- * @brief See if there is recieved charakter to read
- *
- * read the RX flag from peripheral specified in context
- *
- * @param[in] ctx context of the driver
- * @retval 0 No character to read
- * @retval x Character ready to read
- */
-static int TMS570_sci_can_read_char(
-  tms570_sci_context * ctx
-)
-{
-  return ctx->regs->SCIFLR & (1<<9);
-}

-/**
- * @brief reads character from peripheral
- *
- * reads the recieved character from peripheral specified in context
- *
- * @param[in] ctx context of the driver
- * @retval x Character
- */
-static char TMS570_sci_read_char(
-  tms570_sci_context * ctx
-)
-{
-  return ctx->regs->SCIRD;
+    ctx->regs->SCITD = buffer[i];
+  }
 }

 /**
- * @brief sci read function
+ * @brief SCI poll read function.
  *
- * check if there is recieved character to be read and reads it.
+ * Check if there's data available in SCIRD, and read it.
  *
- * @param[in] base context of the driver
- * @retval -1 No character to be read
- * @retval x Read character
+ * @param[in] base Context of the driver.
+ * @retval -1 No data available to read.
+ * @retval x Read character.
  */
 static int tms570_sci_poll_read(rtems_termios_device_context *base)
 {
-  tms570_sci_context *ctx = (tms570_sci_context *) base;
+  const tms570_sci_context *const ctx = (tms570_sci_context *)base;

-  /* Check if a character is available */
-  if ( TMS570_sci_can_read_char(ctx) ) {
-    return TMS570_sci_read_char(ctx);
-  } else {
-    return -1;
-  }
+  return ctx->regs->SCIFLR & RXRDY ?
+         ctx->regs->SCIRD : -1;
 }

 /**
- * @brief initialization of the driver
+ * @brief Driver initialization function (polling mode).
  *
- * initialization of the HW peripheral specified in contex of the driver.
+ * This function performs the necessary HW intialization for the polling mode.
  * This function is called only once when opening the driver.
  *
- * @param[in] tty Termios control
- * @param[in] ctx context of the driver
- * @param[in] term Termios attributes
+ * @param[in] tty Termios control.
+ * @param[in] ctx Context of the driver.
+ * @param[in] terminal Termios attributes.
  * @param[in] args
- * @retval false Error occured during initialization
- * @retval true Driver is open and ready
+ * @retval false Error occured during initialization.
+ * @retval true Driver is open and ready.
  */
-static bool tms570_sci_poll_first_open(
-  rtems_termios_tty             *tty,
-  rtems_termios_device_context  *ctx,
-  struct termios                *term,
-  rtems_libio_open_close_args_t *args
-)
+static bool tms570_sci_poll_first_open(rtems_termios_tty *tty,
+                                       rtems_termios_device_context *ctx,
+                                       struct termios *terminal,
+                                       rtems_libio_open_close_args_t *args)
 {
-  bool ok;
-
-  rtems_termios_set_best_baud(term, TMS570_SCI_BAUD_RATE);
-  ok = tms570_sci_set_attributes(ctx, term);
-  if ( !ok ) {
-    return false;
-  }
-  return true;
+  rtems_termios_set_best_baud(terminal, TMS570_SCI_BAUD_RATE);
+  return tms570_sci_set_attributes(ctx, terminal);
 }

 /**
- * @brief initialization of the interrupt driven driver
+ * @brief Driver initialization function (interrupt mode).
  *
- * calls tms570_sci_poll_first_open function.
- * install and enables interrupts.
+ * This function performs the necessary HW intialization for the interrupt-driven mode.
+ * It installs an interrupt handler and enables interrupts.
+ * This function is called only once when opening the driver.
  *
  * @param[in] tty Termios control
  * @param[in] base context of the driver
@@ -453,99 +358,74 @@ static bool tms570_sci_poll_first_open(
  * @retval false Error occured during initialization
  * @retval true Driver is open and ready
  */
-static bool tms570_sci_interrupt_first_open(
-  rtems_termios_tty             *tty,
-  rtems_termios_device_context  *base,
-  struct termios                *term,
-  rtems_libio_open_close_args_t *args
-)
-{
-  tms570_sci_context *ctx = (tms570_sci_context *) base;
-  rtems_status_code sc;
-  bool ret;
-
-  ret = tms570_sci_poll_first_open(tty, base, term, args);
-  if ( ret == false ) {
-    return false;
-  }
-  ctx->regs->SCISETINTLVL = 0;
-  /* Register Interrupt handler */
-  sc = rtems_interrupt_handler_install(ctx->irq,
-      ctx->device_name,
-      RTEMS_INTERRUPT_SHARED,
-      tms570_sci_interrupt_handler,
-      tty
-  );
-  if ( sc != RTEMS_SUCCESSFUL ) {
-    return false;
-  }
-  tms570_sci_enable_interrupts(ctx);
-  return true;
-}

-/**
- * @brief closes sci peripheral
- *
- * @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_poll_last_close(
-  rtems_termios_tty             *tty,
-  rtems_termios_device_context  *base,
-  rtems_libio_open_close_args_t *args
-)
+static bool tms570_sci_interrupt_first_open(rtems_termios_tty *tty,
+                                            rtems_termios_device_context *base,
+                                            struct termios *terminal,
+                                            rtems_libio_open_close_args_t *args)
 {
-  ;
+  tms570_sci_context *ctx = (tms570_sci_context *)base;
+  rtems_status_code status;
+  bool success = true;
+
+  success = tms570_sci_poll_first_open(tty, base, terminal, args);
+
+  if (success) {
+    /* Register Interrupt handler */
+    status = rtems_interrupt_handler_install(ctx->irq, ctx->device_name,
+                                             RTEMS_INTERRUPT_SHARED,
+                                             tms570_sci_interrupt_handler, tty);
+    if (status == RTEMS_SUCCESSFUL) {
+      /* Enable RX interrupts */
+      ctx->regs->SCISETINT = RX_INT;
+    } else { /* We couldn't install the interrupt handler. */
+      success = false;
+    }
+  } /* else, we couldn't set up the hardware. */
+
+  return success;
 }

 /**
- * @brief closes sci peripheral of interrupt driven driver
+ * @brief Closes the SCI driver in the interrupt-driven mode.
  *
- * calls tms570_sci_poll_last_close and disables interrupts
+ * Calls tms570_sci_poll_last_close and disables interrupts.
  *
- * @param[in] tty Termios control
- * @param[in] base context of the driver
+ * @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
+ * @retval Void
  */
-static void tms570_sci_interrupt_last_close(
-  rtems_termios_tty             *tty,
-  rtems_termios_device_context  *base,
-  rtems_libio_open_close_args_t *args
-)
+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 */
+  /* Disable RX interrupts. */
   rtems_termios_device_lock_acquire(base, &lock_context);
-  tms570_sci_disable_interrupts(ctx);
+  ctx->regs->SCICLEARINT = RX_INT;
   rtems_termios_device_lock_release(base, &lock_context);

-  /* Flush device */
-  while ( ( ctx->regs->SCIFLR & (1<<11) ) > 0 ) {
-    ;/* Wait until all data has been sent */
+  /* Flush device. */
+  while (ctx->regs->SCIFLR & TX_EMPTY) {
+    continue; /* Wait until all data has been sent. */
   }

-  /* uninstall ISR */
+  /* Uninstall interrupt handler. */
   rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);
-
-  tms570_sci_poll_last_close(tty, base, args);
 }

 /**
  * @brief Struct containing definitions of polled driver functions.
  *
  * Encapsulates polled driver functions.
- * Use of this table is determited by not defining TMS570_USE_INTERRUPTS
+ * Use of this table is determited by not defining TMS570_USE_INTERRUPTS.
  */
 const rtems_termios_device_handler tms570_sci_handler_polled = {
   .first_open = tms570_sci_poll_first_open,
-  .last_close = tms570_sci_poll_last_close,
+  .last_close = NULL,
   .poll_read = tms570_sci_poll_read,
   .write = tms570_sci_poll_write,
   .set_attributes = tms570_sci_set_attributes,
@@ -556,7 +436,7 @@ const rtems_termios_device_handler tms570_sci_handler_polled = {
  * @brief Struct containing definitions of interrupt driven driver functions.
  *
  * Encapsulates interrupt driven driver functions.
- * Use of this table is determited by defining TMS570_USE_INTERRUPTS
+ * Use of this table is determited by defining TMS570_USE_INTERRUPTS.
  */
 const rtems_termios_device_handler tms570_sci_handler_interrupt  = {
   .first_open = tms570_sci_interrupt_first_open,
diff --git a/c/src/lib/libbsp/arm/tms570/include/bsp.h b/c/src/lib/libbsp/arm/tms570/include/bsp.h
index 81bc4cd..5453d16 100644
--- a/c/src/lib/libbsp/arm/tms570/include/bsp.h
+++ b/c/src/lib/libbsp/arm/tms570/include/bsp.h
@@ -15,6 +15,11 @@
  * 166 36 Praha 6
  * Czech Republic
  *
+ * Copyright (c) 2015 Taller Technologies
+ * Martin Galvan    <martin.gal...@tallertechnologies.com>
+ * Marcos Diaz      <marcos.d...@tallertechnologies.com>
+ * Eduardo Sanchez  <eduardo.sanc...@tallertechnologies.com>
+ *
  * Based on LPC24xx and LPC1768 BSP
  *
  * The license and distribution terms for this file may be
@@ -36,11 +41,13 @@
 #include <rtems/clockdrv.h>
 #include <bsp/default-initial-extension.h>

-#define BSP_OSCILATOR_CLOCK 8000000
-#define BSP_PLL_OUT_CLOCK 160000000
+#define BSP_OSCILATOR_CLOCK 8000000u
+
+/* This is the output of the main PLL, and the source of the Global Clock Module (GCM). */
+#define BSP_PLL_OUT_CLOCK 180000000u

 /** Define operation count for Tests */
-#define OPERATION_COUNT 4
+#define OPERATION_COUNT 4u

 #ifdef __cplusplus
 extern "C" {
diff --git a/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h b/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
index f32eaea..10fb134 100644
--- a/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
+++ b/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
@@ -3,7 +3,7 @@
  *
  * @ingroup tms570
  *
- * @brief Declaration of serial's driver inner structure.
+ * @brief Declaration of the serial's driver inner structure.
  */

 /*
@@ -15,6 +15,11 @@
  * 166 36 Praha 6
  * Czech Republic
  *
+ * Copyright (c) 2015 Taller Technologies
+ * Martin Galvan    <martin.gal...@tallertechnologies.com>
+ * Marcos Diaz      <marcos.d...@tallertechnologies.com>
+ * Eduardo Sanchez  <eduardo.sanc...@tallertechnologies.com>
+ *
  * Based on LPC24xx and LPC1768 BSP
  * by embedded brains GmbH and others
  *
@@ -39,7 +44,7 @@ typedef struct {
   rtems_termios_device_context base;
   const char *device_name;
   volatile tms570_sci_t *regs;
-  int tx_chars_in_hw;
+  bool wrote_data;
   rtems_vector_number irq;
 } tms570_sci_context;

@@ -47,7 +52,7 @@ extern const rtems_termios_device_handler tms570_sci_handler_polled;

 extern const rtems_termios_device_handler tms570_sci_handler_interrupt;

-extern const tms570_sci_context driver_context_table[];
+extern tms570_sci_context driver_context_table[];

 /** @} */

diff --git a/c/src/lib/libbsp/arm/tms570/include/tms570-sci.h b/c/src/lib/libbsp/arm/tms570/include/tms570-sci.h
index 6ed68e2..c0506e5 100644
--- a/c/src/lib/libbsp/arm/tms570/include/tms570-sci.h
+++ b/c/src/lib/libbsp/arm/tms570/include/tms570-sci.h
@@ -15,6 +15,11 @@
  * 166 36 Praha 6
  * Czech Republic
  *
+ * Copyright (c) 2015 Taller Technologies
+ * Martin Galvan    <martin.gal...@tallertechnologies.com>
+ * Marcos Diaz      <marcos.d...@tallertechnologies.com>
+ * Eduardo Sanchez  <eduardo.sanc...@tallertechnologies.com>
+ *
  * Based on LPC24xx and LPC1768 BSP
  * by embedded brains GmbH and others
  *
@@ -36,41 +41,57 @@ extern "C" {
 #endif /* __cplusplus */

 typedef struct {
-  uint32_t SCIGCR0;         /*SCIGlobalControlRegister0*/
-  uint32_t SCIGCR1;         /*SCIGlobalControlRegister1*/
-  uint32_t reserved1 [0x4/4];
-  uint32_t SCISETINT;       /*SCISetInterruptRegister*/
-  uint32_t SCICLEARINT;     /*SCIClearInterruptRegister*/
-  uint32_t SCISETINTLVL;    /*SCISetInterruptLevelRegister*/
-  uint32_t SCICLEARINTLVL;  /*SCIClearInterruptLevelRegister*/
-  uint32_t SCIFLR;          /*SCIFlagsRegister*/
-  uint32_t SCIINTVECT0;     /*SCIInterruptVectorOffset0*/
-  uint32_t SCIINTVECT1;     /*SCIInterruptVectorOffset1*/
-  uint32_t SCIFORMAT;       /*SCIFormatControlRegister*/
-  uint32_t BRS;             /*BaudRateSelectionRegister*/
-  uint32_t SCIED;           /*ReceiverEmulationDataBuffer*/
-  uint32_t SCIRD;           /*ReceiverDataBuffer*/
-  uint32_t SCITD;           /*TransmitDataBuffer*/
-  uint32_t SCIPIO0;         /*SCIPinI/OControlRegister0*/
-  uint32_t SCIPIO1;         /*SCIPinI/OControlRegister1*/
-  uint32_t SCIPIO2;         /*SCIPinI/OControlRegister2*/
-  uint32_t SCIPIO3;         /*SCIPinI/OControlRegister3*/
-  uint32_t SCIPIO4;         /*SCIPinI/OControlRegister4*/
-  uint32_t SCIPIO5;         /*SCIPinI/OControlRegister5*/
-  uint32_t SCIPIO6;         /*SCIPinI/OControlRegister6*/
-  uint32_t SCIPIO7;         /*SCIPinI/OControlRegister7*/
-  uint32_t SCIPIO8;         /*SCIPinI/OControlRegister8*/
-  uint32_t reserved2 [0x30/4];
-  uint32_t IODFTCTRL;       /*Input/OutputErrorEnableRegister*/
-}tms570_sci_t;
+  uint32_t SCIGCR0;         /* SCI Global Control Register 0 */
+  uint32_t SCIGCR1;         /* SCI Global Control Register 1 */
+  uint32_t reserved1;
+  uint32_t SCISETINT;       /* SCI Set Interrupt Register */
+  uint32_t SCICLEARINT;     /* SCI Clear Interrupt Register */
+  uint32_t SCISETINTLVL;    /* SCI Set Interrupt Level Register */
+  uint32_t SCICLEARINTLVL;  /* SCI Clear Interrupt Level Register */
+  uint32_t SCIFLR;          /* SCI Flags Register */
+  uint32_t SCIINTVECT0;     /* SCI Interrupt Vector Offset 0 */
+  uint32_t SCIINTVECT1;     /* SCI Interrupt Vector Offset 1 */
+  uint32_t SCIFORMAT;       /* SCI Format Control Register */
+  uint32_t BRS;             /* Baud Rate Selection Register */
+  uint32_t SCIED;           /* Receiver Emulation Data Buffer */
+  uint32_t SCIRD;           /* Receiver Data Buffer */
+  uint32_t SCITD;           /* Transmit Data Buffer */
+  uint32_t SCIPIO0;         /* SCI Pin I/O Control Register 0 */
+  uint32_t SCIPIO1;         /* SCI Pin I/O Control Register 1 */
+  uint32_t SCIPIO2;         /* SCI Pin I/O Control Register 2 */
+  uint32_t SCIPIO3;         /* SCI Pin I/O Control Register 3 */
+  uint32_t SCIPIO4;         /* SCI Pin I/O Control Register 4 */
+  uint32_t SCIPIO5;         /* SCI Pin I/O Control Register 5 */
+  uint32_t SCIPIO6;         /* SCI Pin I/O Control Register 6 */
+  uint32_t SCIPIO7;         /* SCI Pin I/O Control Register 7 */
+  uint32_t SCIPIO8;         /* SCI Pin I/O Control Register 8 */
+  uint32_t reserved2[12];
+  uint32_t IODFTCTRL;       /* I/O Error Enable Register */
+} tms570_sci_t;
+
+#define TMS570_SCI (*(volatile tms570_sci_t *)0xFFF7E400u)
+#define TMS570_SCI2 (*(volatile tms570_sci_t *)0xFFF7E500u)
+
+/* SCI Global Control Register 1 (SCIGCR1) */
+#define TIMING_MODE  (1u << 1u)  /* 0: Synchronous; 1: Asynchronous */
+#define PARITY_ENA   (1u << 2u)  /* 0: Parity is disabled; 1: Parity is enabled */
+#define EVEN_PARITY  (1u << 3u)  /* 0: Odd parity; 1: Even parity */
+#define STOP         (1u << 4u)  /* 0: One stop bit; 1: Two stop bits */
+#define SWnRST       (1u << 7u)  /* 0: SCI/LIN is in reset state; 1: SCI/LIN is in ready state */
+#define RXENA        (1u << 24u) /* 0: Receive disabled; 1: Receive enabled */
+#define TXENA        (1u << 25u) /* 0: Transmit disabled; 1: Transmit enabled */

-#define TMS570_SCI (*(volatile tms570_sci_t*)0xFFF7E400U)
-#define TMS570_SCI2 (*(volatile tms570_sci_t*)0xFFF7E500U)
+/* SCI Flags Register (SCIFLR) */
+#define TXRDY    (1u << 8u)  /* 0: SCITD is full; 1: SCITD is ready to receive the next character */
+#define RXRDY    (1u << 9u)  /* 0: No new data in SCIRD; 1: New data is ready to be read from SCIRD */
+#define TX_EMPTY (1u << 11u) /* 0: Transmit buffers are loaded; 1: Transmit buffers are empty */

-/** @} */
+/* Interrupt bits (SCISETINT and SCICLEARINT) */
+#define TX_INT (1u << 8u) /* TX interrupts */
+#define RX_INT (1u << 9u) /* RX interrupts */

 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

-#endif
+#endif /* LIBBSP_ARM_TMS570_SCI_H */
_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to