Changeset cb4c90b2 in rtems for c/src


Ignore:
Timestamp:
04/20/11 20:20:47 (13 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.11, 5, master
Children:
ad65fc7f
Parents:
5eb50f3
Message:

2011-04-20 Rohan Kangralkar <rkangral@…>

PR 1781/bsps

  • bf52x/include: Added additional MMR.
  • bf52x/interrupt: The BF52X processors have a different System interrupt controller than present in the 53X range of processors. The 52X have 8 interrupt assignment registers. The implementation uses tables to increase predictability.
  • serial/uart.?: Added DMA based and interrupt based transfer support. The uart code used a single ISR for TX and RX and tried to identify and multiplex inside the ISR. In the new code the type of interrupt is identified by the central ISR dispatcher bf52x/interrupt or interrupt/. This simplifies the UART ISR.
Location:
c/src/lib/libcpu/bfin
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libcpu/bfin/ChangeLog

    r5eb50f3 rcb4c90b2  
     12011-04-20  Rohan Kangralkar <rkangral@ece.neu.edu>
     2
     3        PR 1781/bsps
     4        * bf52x/include: Added additional MMR.
     5        * bf52x/interrupt: The BF52X processors have a different
     6        System interrupt controller than present in the 53X range of
     7        processors. The 52X have 8 interrupt assignment registers. The
     8        implementation uses tables to increase predictability.
     9        * serial/uart.?: Added DMA based and interrupt based transfer
     10        support. The uart code used a single ISR for TX and RX and tried
     11        to identify and multiplex inside the ISR. In the new code the
     12        type of interrupt is identified by the central ISR dispatcher
     13        bf52x/interrupt or interrupt/.  This simplifies the UART ISR.
     14
    1152011-02-11      Ralf Corsépius <ralf.corsepius@rtems.org>
    216
  • c/src/lib/libcpu/bfin/Makefile.am

    r5eb50f3 rcb4c90b2  
    1111noinst_PROGRAMS =
    1212
     13include_bspdir = $(includedir)/bsp
    1314include_libcpudir = $(includedir)/libcpu
     15
     16include_bsp_HEADERS =
    1417include_libcpu_HEADERS =
     18
     19
     20############
     21# Start of bf52x files
     22if bf52x
     23
     24include_HEADERS = bf52x/include/bf52x.h
     25
     26## INTERRUPT
     27include_bsp_HEADERS += bf52x/interrupt/interrupt.h
     28noinst_PROGRAMS += bf52x/interrupt.rel
     29bf52x_interrupt_rel_SOURCES = bf52x/interrupt/interrupt.c \
     30                              bf52x/interrupt/interrupt.h
     31bf52x_interrupt_rel_CPPFLAGS = $(AM_CPPFLAGS)
     32bf52x_interrupt_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
     33
     34endif
     35# endof bf52x
     36############
    1537
    1638include_libcpu_HEADERS += include/bf533.h
     
    4870mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
    4971
     72if bf52x
     73
     74else
    5075include_libcpu_HEADERS += interrupt/interrupt.h
    5176noinst_PROGRAMS += interrupt.rel
     
    5378interrupt_rel_CPPFLAGS = $(AM_CPPFLAGS)
    5479interrupt_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
     80
     81endif
    5582
    5683noinst_PROGRAMS += clock.rel
  • c/src/lib/libcpu/bfin/configure.ac

    r5eb50f3 rcb4c90b2  
    2525AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes")
    2626
     27# AM_CONDITIONAL(shared, test "$RTEMS_CPU_MODEL" = "bf52x")
     28AM_CONDITIONAL(bf52x, test "$RTEMS_CPU_MODEL" = "bf52x")
     29
     30
    2731RTEMS_AMPOLISH3
    2832
  • c/src/lib/libcpu/bfin/include/sicRegs.h

    r5eb50f3 rcb4c90b2  
    1717
    1818#define SIC_IMASK                (SIC_BASE_ADDRESS + 0x000c)
     19#define SIC_IMASK_PITCH          (0x40)
     20
     21#define SIC_ISR                  (SIC_BASE_ADDRESS + 0x0020)
     22#define SIC_ISR_PITCH            (0x40)
     23
    1924#define SIC_IAR_BASE_ADDRESS     (SIC_BASE_ADDRESS + 0x0010)
    2025#define SIC_IAR_PITCH                                   0x04
     26
    2127#define SIC_IAR0                 (SIC_BASE_ADDRESS + 0x0010)
    2228#if SIC_IAR_COUNT > 1
     
    2935#define SIC_IAR3                 (SIC_BASE_ADDRESS + 0x001c)
    3036#endif
    31 #define SIC_ISR                  (SIC_BASE_ADDRESS + 0x0020)
     37
    3238#define SIC_IWR                  (SIC_BASE_ADDRESS + 0x0024)
    3339
  • c/src/lib/libcpu/bfin/preinstall.am

    r5eb50f3 rcb4c90b2  
    1414CLEANFILES = $(PREINSTALL_FILES)
    1515
     16$(PROJECT_INCLUDE)/$(dirstamp):
     17        @$(MKDIR_P) $(PROJECT_INCLUDE)
     18        @: > $(PROJECT_INCLUDE)/$(dirstamp)
     19PREINSTALL_DIRS += $(PROJECT_INCLUDE)/$(dirstamp)
     20
     21$(PROJECT_INCLUDE)/bsp/$(dirstamp):
     22        @$(MKDIR_P) $(PROJECT_INCLUDE)/bsp
     23        @: > $(PROJECT_INCLUDE)/bsp/$(dirstamp)
     24PREINSTALL_DIRS += $(PROJECT_INCLUDE)/bsp/$(dirstamp)
     25
    1626$(PROJECT_INCLUDE)/libcpu/$(dirstamp):
    1727        @$(MKDIR_P) $(PROJECT_INCLUDE)/libcpu
     
    1929PREINSTALL_DIRS += $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
    2030
     31if bf52x
     32$(PROJECT_INCLUDE)/bf52x.h: bf52x/include/bf52x.h $(PROJECT_INCLUDE)/$(dirstamp)
     33        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bf52x.h
     34PREINSTALL_FILES += $(PROJECT_INCLUDE)/bf52x.h
     35
     36$(PROJECT_INCLUDE)/bsp/interrupt.h: bf52x/interrupt/interrupt.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
     37        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/interrupt.h
     38PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/interrupt.h
     39endif
    2140$(PROJECT_INCLUDE)/libcpu/bf533.h: include/bf533.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
    2241        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/bf533.h
     
    103122PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/mmu.h
    104123
     124if bf52x
     125else
    105126$(PROJECT_INCLUDE)/libcpu/interrupt.h: interrupt/interrupt.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
    106127        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/interrupt.h
    107128PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/interrupt.h
    108 
     129endif
    109130$(PROJECT_INCLUDE)/libcpu/uart.h: serial/uart.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
    110131        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/uart.h
  • c/src/lib/libcpu/bfin/serial/uart.c

    r5eb50f3 rcb4c90b2  
    77 *  found in the file LICENSE in this distribution or at
    88 *  http://www.rtems.com/license/LICENSE.
     9 *
     10 *  Modified:
     11 *  $ $Author$ Added interrupt support and DMA support
    912 *
    1013 *  $Id$
     
    1922
    2023#include <libcpu/uartRegs.h>
     24#include <libcpu/dmaRegs.h>
    2125#include "uart.h"
    22 
    2326
    2427/* flags */
     
    2932
    3033
    31 static void initializeHardware(int minor) {
    32   uint16_t divisor;
    33   char *base;
    34   uint16_t r;
    35 
    36   base = uartsConfig->channels[minor].base_address;
    37 
    38   *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
    39 
    40   if (uartsConfig->channels[minor].force_baud)
    41     divisor = (uint16_t) (uartsConfig->freq /
    42                           (uartsConfig->channels[minor].force_baud * 16));
    43   else
    44     divisor = (uint16_t) (uartsConfig->freq / (9600 * 16));
    45   *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_DLAB;
    46   *(uint16_t volatile *) (base + UART_DLL_OFFSET) = (divisor & 0xff);
    47   *(uint16_t volatile *) (base + UART_DLH_OFFSET) = ((divisor >> 8) & 0xff);
    48 
    49   *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_WLS_8;
    50 
    51   *(uint16_t volatile *) (base + UART_GCTL_OFFSET) = UART_GCTL_UCEN;
    52 
    53   r = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
    54   r = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
    55   r = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
    56 
    57   return;
    58 }
    59 
    6034static int pollRead(int minor) {
    6135  int c;
    62   char *base;
    63 
    64   base = uartsConfig->channels[minor].base_address;
     36  uint32_t base;
     37
     38  base = uartsConfig->channels[minor].uart_baseAddress;
    6539
    6640  /* check to see if driver is using interrupts so this call will be
    6741     harmless (though non-functional) in case some debug code tries to
    6842     use it */
    69   if (!uartsConfig->channels[minor].use_interrupts &&
     43  if (!uartsConfig->channels[minor].uart_useInterrupts &&
    7044      *((uint16_t volatile *) (base + UART_LSR_OFFSET)) & UART_LSR_DR)
    7145    c = *((uint16_t volatile *) (base + UART_RBR_OFFSET));
     
    7650}
    7751
    78 char bfin_uart_poll_read(int minor) {
     52char bfin_uart_poll_read(rtems_device_minor_number minor) {
    7953  int c;
    8054
     
    8761
    8862void bfin_uart_poll_write(int minor, char c) {
    89   char *base;
    90 
    91   base = uartsConfig->channels[minor].base_address;
     63  uint32_t base;
     64
     65  base = uartsConfig->channels[minor].uart_baseAddress;
    9266
    9367  while (!(*((uint16_t volatile *) (base + UART_LSR_OFFSET)) & UART_LSR_THRE))
     
    158132}
    159133
    160 static void enableInterrupts(int minor) {
    161   char *base;
    162 
    163   base = uartsConfig->channels[minor].base_address;
    164 
    165   *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI |
    166                                                     UART_IER_ERBFI;
    167 }
    168 
    169 static void disableAllInterrupts(void) {
    170   int i;
    171   char *base;
    172 
    173   for (i = 0; i < uartsConfig->num_channels; i++) {
    174     base = uartsConfig->channels[i].base_address;
    175     *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
    176   }
    177 }
    178 
    179 static ssize_t interruptWrite(int minor, const char *buf, size_t len) {
    180   char *base;
    181 
    182   base = uartsConfig->channels[minor].base_address;
    183 
    184   uartsConfig->channels[minor].flags |= BFIN_UART_XMIT_BUSY;
    185   *(uint16_t volatile *) (base + UART_THR_OFFSET) = *buf;
    186 
    187   /* one byte written */
    188   return 1;
    189 }
    190 
     134
     135/**
     136 * Routine to initialize the hardware. It initialize the DMA,
     137 * interrupt if required.
     138 * @param channel channel information
     139 */
     140static void initializeHardware(bfin_uart_channel_t *channel) {
     141  uint16_t divisor        = 0;
     142  uint32_t base           = 0;
     143  uint32_t tx_dma_base    = 0;
     144
     145  if ( NULL == channel ) {
     146    return;
     147  }
     148
     149  base        = channel->uart_baseAddress;
     150  tx_dma_base = channel->uart_txDmaBaseAddress;
     151  /**
     152   * RX based DMA and interrupt is not supported yet
     153   * uint32_t tx_dma_base    = 0;
     154   *
     155   * rx_dma_base = channel->uart_rxDmaBaseAddress;
     156   */
     157
     158
     159  *(uint16_t volatile *) (base + UART_IER_OFFSET) = 0;
     160
     161  if ( 0 != channel->uart_baud) {
     162    divisor = (uint16_t) (uartsConfig->freq /
     163        (channel->uart_baud * 16));
     164  } else {
     165    divisor = (uint16_t) (uartsConfig->freq / (9600 * 16));
     166  }
     167
     168  *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_DLAB;
     169  *(uint16_t volatile *) (base + UART_DLL_OFFSET) = (divisor & 0xff);
     170  *(uint16_t volatile *) (base + UART_DLH_OFFSET) = ((divisor >> 8) & 0xff);
     171
     172  *(uint16_t volatile *) (base + UART_LCR_OFFSET) = UART_LCR_WLS_8;
     173
     174  *(uint16_t volatile *) (base + UART_GCTL_OFFSET) = UART_GCTL_UCEN;
     175
     176  /**
     177   * To clear previous status
     178   * divisor is a temp variable here
     179   */
     180  divisor = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
     181  divisor = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
     182  divisor = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
     183
     184  if ( channel->uart_useDma ) {
     185    *(uint16_t  volatile *)(tx_dma_base + DMA_CONFIG_OFFSET) = 0;
     186    *(uint16_t  volatile *)(tx_dma_base + DMA_CONFIG_OFFSET) = DMA_CONFIG_DI_EN
     187        | DMA_CONFIG_SYNC ;
     188    *(uint16_t  volatile *)(tx_dma_base + DMA_IRQ_STATUS_OFFSET) |=
     189        DMA_IRQ_STATUS_DMA_DONE | DMA_IRQ_STATUS_DMA_ERR;
     190
     191  } else {
     192    /**
     193    * We use polling or interrupts only sending one char at a time :(
     194    */
     195  }
     196
     197  return;
     198}
     199
     200
     201/**
     202 * Set the UART attributes.
     203 * @param minor
     204 * @param termios
     205 * @return
     206 */
    191207static int setAttributes(int minor, const struct termios *termios) {
    192   char *base;
     208  uint32_t base;
    193209  int baud;
    194210  uint16_t divisor;
    195211  uint16_t lcr;
    196212
    197   base = uartsConfig->channels[minor].base_address;
     213  base = uartsConfig->channels[minor].uart_baseAddress;
    198214  switch (termios->c_cflag & CBAUD) {
    199215  case B0:
     
    261277    break;
    262278  }
    263   if (baud > 0 && uartsConfig->channels[minor].force_baud)
    264     baud = uartsConfig->channels[minor].force_baud;
     279  if (baud > 0 && uartsConfig->channels[minor].uart_baud)
     280    baud = uartsConfig->channels[minor].uart_baud;
    265281  switch (termios->c_cflag & CSIZE) {
    266282  case CS5:
     
    283299    break;
    284300  case PARENB | PARODD:
    285     lcr |= UART_LCR_PEN;
    286     break;
     301  lcr |= UART_LCR_PEN;
     302  break;
    287303  default:
    288304    break;
     
    302318}
    303319
    304 void bfin_uart_isr(int source) {
    305   int i;
    306   char *base;
    307   uint16_t uartStat;
    308   char c;
    309   uint8_t uartLSR;
    310 
    311   /* Just use one ISR and check for all UART interrupt sources in it.
    312      This is less efficient than making use of the vector to narrow down
    313      the things we need to check, but not all Blackfins separate the
    314      UART interrupt sources in the same ways.  This way we don't have
    315      to make this code dependent on the type of Blackfin.  */
    316   for (i = 0; i < uartsConfig->num_channels; i++) {
    317     if (uartsConfig->channels[i].use_interrupts) {
    318       base = uartsConfig->channels[i].base_address;
    319       uartStat = *(uint16_t volatile *) (base + UART_IIR_OFFSET);
    320       if ((uartStat & UART_IIR_NINT) == 0) {
    321         switch (uartStat & UART_IIR_STATUS_MASK) {
    322         case UART_IIR_STATUS_THRE:
    323           if (uartsConfig->channels[i].termios &&
    324               (uartsConfig->channels[i].flags & BFIN_UART_XMIT_BUSY)) {
    325             uartsConfig->channels[i].flags &= ~BFIN_UART_XMIT_BUSY;
    326             rtems_termios_dequeue_characters(uartsConfig->channels[i].termios,
    327                                              1);
    328           }
    329           break;
    330         case UART_IIR_STATUS_RDR:
    331           c = *(uint16_t volatile *) (base + UART_RBR_OFFSET);
    332           if (uartsConfig->channels[i].termios)
    333             rtems_termios_enqueue_raw_characters(
    334                 uartsConfig->channels[i].termios, &c, 1);
    335           break;
    336         case UART_IIR_STATUS_LS:
    337           uartLSR = *(uint16_t volatile *) (base + UART_LSR_OFFSET);
    338           /* break, framing error, parity error, or overrun error
    339              has been detected */
    340           break;
    341         default:
    342           break;
    343         }
    344       }
    345     }
    346   }
    347 }
    348 
     320/**
     321 * Interrupt based uart tx routine. The routine writes one character at a time.
     322 *
     323 * @param minor Minor number to indicate uart number
     324 * @param buf Character buffer which stores characters to be transmitted.
     325 * @param len Length of buffer to be transmitted.
     326 * @return
     327 */
     328static ssize_t uart_interruptWrite(int minor, const char *buf, size_t len) {
     329  uint32_t              base      = 0;
     330  bfin_uart_channel_t*  channel   = NULL;
     331  rtems_interrupt_level isrLevel;
     332
     333  /**
     334   * Sanity Check
     335   */
     336  if (NULL == buf || NULL == channel || NULL == uartsConfig || minor < 0) {
     337    return 0;
     338  }
     339
     340  channel = &(uartsConfig->channels[minor]);
     341
     342  if ( NULL == channel || channel->flags &  BFIN_UART_XMIT_BUSY ) {
     343    return 0;
     344  }
     345
     346  rtems_interrupt_disable(isrLevel);
     347
     348  base = channel->uart_baseAddress;
     349
     350  channel->flags |= BFIN_UART_XMIT_BUSY;
     351  channel->length = 1;
     352  *(uint16_t volatile *) (base + UART_THR_OFFSET) = *buf;
     353  *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI;
     354
     355  rtems_interrupt_enable(isrLevel);
     356
     357  return 0;
     358}
     359
     360/**
     361* This function implements RX ISR
     362*/
     363void bfinUart_rxIsr(void *_arg)
     364{
     365  /**
     366   * TODO: UART RX ISR implementation.
     367   */
     368
     369}
     370
     371
     372/**
     373 * This function implements TX ISR. The function gets called when the TX FIFO is
     374 * empty. It clears the interrupt and dequeues the character. It only tx one
     375 * character at a time.
     376 *
     377 * TODO: error handling.
     378 * @param _arg gets the channel information.
     379 */
     380void bfinUart_txIsr(void *_arg) {
     381  bfin_uart_channel_t*  channel = NULL;
     382  uint32_t              base    = 0;
     383
     384  /**
     385   * Sanity check
     386   */
     387  if (NULL == _arg) {
     388    /** It should never be NULL */
     389    return;
     390  }
     391
     392  channel = (bfin_uart_channel_t *) _arg;
     393
     394  base = channel->uart_baseAddress;
     395
     396  *(uint16_t volatile *) (base + UART_IER_OFFSET) &= ~UART_IER_ETBEI;
     397  channel->flags &= ~BFIN_UART_XMIT_BUSY;
     398
     399  rtems_termios_dequeue_characters(channel->termios, channel->length);
     400
     401  return;
     402}
     403
     404
     405
     406
     407/**
     408 * interrupt based DMA write Routine. It configure the DMA to write len bytes.
     409 * The DMA supports 64K data only.
     410 *
     411 * @param minor Identification number of the UART.
     412 * @param buf Character buffer pointer
     413 * @param len length of data items to be written
     414 * @return data already written
     415 */
     416static ssize_t uart_DmaWrite(int minor, const char *buf, size_t len) {
     417  uint32_t              base        = 0;
     418  bfin_uart_channel_t*  channel     = NULL;
     419  uint32_t              tx_dma_base = 0;
     420  rtems_interrupt_level isrLevel;
     421
     422  /**
     423   * Sanity Check
     424   */
     425  if ( NULL == buf || 0 > minor || NULL == uartsConfig ) {
     426    return 0;
     427  }
     428
     429  channel = &(uartsConfig->channels[minor]);
     430
     431  /**
     432   * Sanity Check and check for transmit busy.
     433   */
     434  if ( NULL == channel || BFIN_UART_XMIT_BUSY & channel->flags ) {
     435    return 0;
     436  }
     437
     438  rtems_interrupt_disable(isrLevel);
     439
     440  base        = channel->uart_baseAddress;
     441  tx_dma_base = channel->uart_txDmaBaseAddress;
     442
     443  channel->flags |= BFIN_UART_XMIT_BUSY;
     444  channel->length = len;
     445
     446  *(uint16_t volatile *) (tx_dma_base + DMA_CONFIG_OFFSET) &= ~DMA_CONFIG_DMAEN;
     447  *(uint32_t volatile *) (tx_dma_base + DMA_START_ADDR_OFFSET) = (uint32_t)buf;
     448  *(uint16_t volatile *) (tx_dma_base + DMA_X_COUNT_OFFSET) = channel->length;
     449  *(uint16_t volatile *) (tx_dma_base + DMA_X_MODIFY_OFFSET) = 1;
     450  *(uint16_t volatile *) (tx_dma_base + DMA_CONFIG_OFFSET) |= DMA_CONFIG_DMAEN;
     451  *(uint16_t volatile *) (base + UART_IER_OFFSET) = UART_IER_ETBEI;
     452
     453  rtems_interrupt_enable(isrLevel);
     454
     455  return 0;
     456}
     457
     458
     459/**
     460 * RX DMA ISR.
     461 * The polling route is used for receiving the characters. This is a place
     462 * holder for future implementation.
     463 * @param _arg
     464 */
     465void bfinUart_rxDmaIsr(void *_arg) {
     466/**
     467 * TODO: Implementation of RX DMA
     468 */
     469}
     470
     471/**
     472 * This function implements TX dma ISR. It clears the IRQ and dequeues a char
     473 * The channel argument will have the base address. Since there are two uart
     474 * and both the uarts can use the same tx dma isr.
     475 *
     476 * TODO: 1. Error checking 2. sending correct length ie after looking at the
     477 * number of elements the uart transmitted.
     478 *
     479 * @param _arg argument passed to the interrupt handler. It contains the
     480 * channel argument.
     481 */
     482void bfinUart_txDmaIsr(void *_arg) {
     483  bfin_uart_channel_t*  channel     = NULL;
     484  uint32_t              tx_dma_base = 0;
     485
     486  /**
     487   * Sanity check
     488   */
     489  if (NULL == _arg) {
     490    /** It should never be NULL */
     491    return;
     492  }
     493
     494  channel = (bfin_uart_channel_t *) _arg;
     495
     496  tx_dma_base = channel->uart_txDmaBaseAddress;
     497
     498  if ((*(uint16_t volatile *) (tx_dma_base + DMA_IRQ_STATUS_OFFSET)
     499      & DMA_IRQ_STATUS_DMA_DONE)) {
     500
     501    *(uint16_t volatile *) (tx_dma_base + DMA_IRQ_STATUS_OFFSET)
     502                            |= DMA_IRQ_STATUS_DMA_DONE | DMA_IRQ_STATUS_DMA_ERR;
     503    channel->flags &= ~BFIN_UART_XMIT_BUSY;
     504    rtems_termios_dequeue_characters(channel->termios, channel->length);
     505  } else {
     506    /* UART DMA did not generate interrupt.
     507     * This routine must not be called.
     508     */
     509  }
     510
     511  return;
     512}
     513
     514/**
     515 * Function called during exit
     516 */
     517void uart_exit(void)
     518{
     519  /**
     520   * TODO: Flushing of quques
     521   */
     522
     523}
     524
     525/**
     526 * Opens the device in different modes. The supported modes are
     527 * 1. Polling
     528 * 2. Interrupt
     529 * 3. DMA
     530 * At exit the uart_Exit function will be called to flush the device.
     531 *
     532 * @param major Major number of the device
     533 * @param minor Minor number of the device
     534 * @param arg
     535 * @return
     536 */
     537rtems_device_driver bfin_uart_open(rtems_device_major_number major,
     538    rtems_device_minor_number minor, void *arg) {
     539  rtems_status_code             sc    = RTEMS_NOT_DEFINED;;
     540  rtems_libio_open_close_args_t *args = NULL;
     541
     542  /**
     543   * Callback function for polling
     544   */
     545  static const rtems_termios_callbacks pollCallbacks = {
     546      NULL,                        /* firstOpen */
     547      NULL,                        /* lastClose */
     548      pollRead,                    /* pollRead */
     549      pollWrite,                   /* write */
     550      setAttributes,               /* setAttributes */
     551      NULL,                        /* stopRemoteTx */
     552      NULL,                        /* startRemoteTx */
     553      TERMIOS_POLLED               /* outputUsesInterrupts */
     554  };
     555
     556  /**
     557   * Callback function for interrupt based transfers without DMA.
     558   * We use interrupts for writing only. For reading we use polling.
     559   */
     560  static const rtems_termios_callbacks interruptCallbacks = {
     561      NULL,                        /* firstOpen */
     562      NULL,                        /* lastClose */
     563      pollRead,                    /* pollRead */
     564      uart_interruptWrite,              /* write */
     565      setAttributes,               /* setAttributes */
     566      NULL,                        /* stopRemoteTx */
     567      NULL,                        /* startRemoteTx */
     568      TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
     569  };
     570
     571  /**
     572   * Callback function for interrupt based DMA transfers.
     573   * We use interrupts for writing only. For reading we use polling.
     574   */
     575  static const rtems_termios_callbacks interruptDmaCallbacks = {
     576      NULL,                        /* firstOpen */
     577      NULL,                        /* lastClose */
     578      NULL,                        /* pollRead */
     579      uart_DmaWrite,              /* write */
     580      setAttributes,               /* setAttributes */
     581      NULL,                        /* stopRemoteTx */
     582      NULL,                        /* startRemoteTx */
     583      TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
     584  };
     585
     586
     587  if ( NULL == uartsConfig || 0 > minor || minor >= uartsConfig->num_channels) {
     588    return RTEMS_INVALID_NUMBER;
     589  }
     590
     591  /**
     592   * Opens device for handling uart send request either by
     593   * 1. interrupt with DMA
     594   * 2. interrupt based
     595   * 3. Polling
     596   */
     597  if ( uartsConfig->channels[minor].uart_useDma ) {
     598    sc = rtems_termios_open(major, minor, arg, &interruptDmaCallbacks);
     599  } else {
     600    sc = rtems_termios_open(major, minor, arg,
     601        uartsConfig->channels[minor].uart_useInterrupts ?
     602            &interruptCallbacks : &pollCallbacks);
     603  }
     604
     605  args = arg;
     606  uartsConfig->channels[minor].termios = args->iop->data1;
     607
     608  atexit(uart_exit);
     609
     610  return sc;
     611}
     612
     613
     614/**
     615* Uart initialization function.
     616* @param major major number of the device
     617* @param config configuration parameters
     618* @return rtems status code
     619*/
    349620rtems_status_code bfin_uart_initialize(rtems_device_major_number major,
    350                                        bfin_uart_config_t *config) {
    351   rtems_status_code status;
    352   int i;
    353 
    354   status = RTEMS_SUCCESSFUL;
     621    bfin_uart_config_t *config) {
     622  rtems_status_code sc = RTEMS_NOT_DEFINED;
     623  int               i  = 0;
    355624
    356625  rtems_termios_initialize();
     
    359628   *  Register Device Names
    360629   */
    361 
    362630  uartsConfig = config;
    363631  for (i = 0; i < config->num_channels; i++) {
    364632    config->channels[i].termios = NULL;
    365633    config->channels[i].flags = 0;
    366     initializeHardware(i);
    367     status = rtems_io_register_name(config->channels[i].name, major, i);
    368   }
    369 
    370    return RTEMS_SUCCESSFUL;
    371 }
    372 
    373 rtems_device_driver bfin_uart_open(rtems_device_major_number major,
    374                                    rtems_device_minor_number minor,
    375                                    void *arg) {
    376   rtems_status_code sc;
    377   rtems_libio_open_close_args_t *args;
    378   static const rtems_termios_callbacks pollCallbacks = {
    379     NULL,                        /* firstOpen */
    380     NULL,                        /* lastClose */
    381     pollRead,                    /* pollRead */
    382     pollWrite,                   /* write */
    383     setAttributes,               /* setAttributes */
    384     NULL,                        /* stopRemoteTx */
    385     NULL,                        /* startRemoteTx */
    386     TERMIOS_POLLED               /* outputUsesInterrupts */
    387   };
    388   static const rtems_termios_callbacks interruptCallbacks = {
    389     NULL,                        /* firstOpen */
    390     NULL,                        /* lastClose */
    391     NULL,                        /* pollRead */
    392     interruptWrite,              /* write */
    393     setAttributes,               /* setAttributes */
    394     NULL,                        /* stopRemoteTx */
    395     NULL,                        /* startRemoteTx */
    396     TERMIOS_IRQ_DRIVEN           /* outputUsesInterrupts */
    397   };
    398 
    399   if (uartsConfig == NULL || minor < 0 || minor >= uartsConfig->num_channels)
    400     return RTEMS_INVALID_NUMBER;
    401 
    402   sc = rtems_termios_open(major, minor, arg,
    403                           uartsConfig->channels[minor].use_interrupts ?
    404                           &interruptCallbacks : &pollCallbacks);
    405   args = arg;
    406   uartsConfig->channels[minor].termios = args->iop->data1;
    407 
    408   if (uartsConfig->channels[minor].use_interrupts)
    409     enableInterrupts(minor);
    410   atexit(disableAllInterrupts);
     634    initializeHardware(&(config->channels[i]));
     635    sc = rtems_io_register_name(config->channels[i].name, major, i);
     636    if (RTEMS_SUCCESSFUL != sc) {
     637      return sc;
     638    }
     639  }
    411640
    412641  return sc;
    413642}
    414 
  • c/src/lib/libcpu/bfin/serial/uart.h

    r5eb50f3 rcb4c90b2  
    99 *  http://www.rtems.com/license/LICENSE.
    1010 *
     11 *  Modified:
     12 *  $Author$ Added interrupt support and DMA support
     13 *
    1114 *  $Id$
    1215 */
    1316
    14 #ifndef _uart_h_
    15 #define _uart_h_
     17
     18#ifndef _UART_H_
     19#define _UART_H_
    1620
    1721
     
    2024#endif
    2125
     26/** bfin_uart_channel object
     27 */
     28typedef struct {
     29  const char        *name;                 /** Holds name of the device */
     30  uint32_t          uart_baseAddress;           /** UART base address */
     31  uint32_t          uart_rxDmaBaseAddress;      /** RX DMA base address */
     32  uint32_t          uart_txDmaBaseAddress;      /** TX DMA base address */
     33  bool              uart_useInterrupts;         /** are interrupts used */
     34  bool              uart_useDma;                /** is dma used */
     35  int               uart_baud;                  /** baud rate, 0 for default */
    2236
    23 typedef struct {
    24   const char *name;
    25   void *base_address;
    26   bool  use_interrupts;
    27   int force_baud;
    28   /* the following are for internal use */
    29   void *termios;
    30   uint8_t volatile flags;
     37  void              *termios;                   /** termios associated */
     38  uint8_t volatile  flags;                      /** flags for internal use */
     39  uint16_t          length;                     /** length for internal use */
    3140} bfin_uart_channel_t;
     41
    3242
    3343typedef struct {
     
    3747} bfin_uart_config_t;
    3848
     49/**
     50 * @param base_address defines the UART base address
     51 * @param source defines the source that caused the interrupt. This argument
     52 * will help us in identifying if Rx or TX caused the interrupt.
     53 */
     54typedef struct {
     55  uint32_t base_address;
     56  int source;
     57} bfin_uart_arg_t;
    3958
    40 char bfin_uart_poll_read(int minor);
     59
     60
     61char bfin_uart_poll_read(rtems_device_minor_number minor);
    4162
    4263void bfin_uart_poll_write(int minor, char c);
    4364
     65
     66/**
     67* Uart initialization function.
     68* @param major major number of the device
     69* @param config configuration parameters
     70* @return rtems status code
     71*/
    4472rtems_status_code bfin_uart_initialize(rtems_device_major_number major,
    45                                        bfin_uart_config_t *config);
     73    bfin_uart_config_t *config);
    4674
     75
     76
     77/**
     78 * Opens the device in different modes. The supported modes are
     79 * 1. Polling
     80 * 2. Interrupt
     81 * 3. DMA
     82 * At exit the uart_Exit function will be called to flush the device.
     83 *
     84 * @param major Major number of the device
     85 * @param minor Minor number of the device
     86 * @param arg
     87 * @return
     88 */
    4789rtems_device_driver bfin_uart_open(rtems_device_major_number major,
    48                                    rtems_device_minor_number minor,
    49                                    void *arg);
     90    rtems_device_minor_number minor, void *arg);
    5091
    51 void bfin_uart_isr(int source);
     92
     93
     94/**
     95 * This function implements TX dma ISR. It clears the IRQ and dequeues a char
     96 * The channel argument will have the base address. Since there are two uart
     97 * and both the uarts can use the same tx dma isr.
     98 *
     99 * TODO: 1. Error checking 2. sending correct length ie after looking at the
     100 * number of elements the uart transmitted.
     101 *
     102 * @param _arg argument passed to the interrupt handler. It contains the
     103 * channel argument.
     104 */
     105void bfinUart_txDmaIsr(void *_arg);
     106
     107
     108
     109/**
     110 * RX DMA ISR.
     111 * The polling route is used for receiving the characters. This is a place
     112 * holder for future implementation.
     113 * @param _arg
     114 */
     115void bfinUart_rxDmaIsr(void *_arg);
     116
     117
     118/**
     119 * This function implements TX ISR. The function gets called when the TX FIFO is
     120 * empty. It clears the interrupt and dequeues the character. It only tx one
     121 * character at a time.
     122 *
     123 * TODO: error handling.
     124 * @param _arg gets the channel information.
     125 */
     126void bfinUart_txIsr(void *_arg);
     127
     128
     129/**
     130* This function implements RX ISR
     131*/
     132void bfinUart_rxIsr(void *_arg);
    52133
    53134
     
    56137#endif
    57138
    58 #endif /* _uart_h_ */
     139#endif /* _UART_H_ */
    59140
Note: See TracChangeset for help on using the changeset viewer.