Changeset 6878519 in rtems


Ignore:
Timestamp:
Feb 6, 2018, 3:28:28 PM (20 months ago)
Author:
Christian Mauderer <christian.mauderer@…>
Branches:
master
Children:
bf70702
Parents:
538a0a8
git-author:
Christian Mauderer <christian.mauderer@…> (02/06/18 15:28:28)
git-committer:
Christian Mauderer <christian.mauderer@…> (02/12/18 13:25:02)
Message:

bsp/atsam: Fix cache / DMA handling in SPI.

This patch fixes the cache handling for the atsam SPI driver. Note that
this solution might doesn't have the best performance for small packets.

Files:
2 added
4 edited

Legend:

Unmodified
Added
Removed
  • bsps/arm/atsam/headers.am

    r538a0a8 r6878519  
    1212include_bsp_HEADERS += ../../../../../../bsps/arm/atsam/include/bsp/atsam-spi.h
    1313include_bsp_HEADERS += ../../../../../../bsps/arm/atsam/include/bsp/i2c.h
     14include_bsp_HEADERS += ../../../../../../bsps/arm/atsam/include/bsp/iocopy.h
    1415include_bsp_HEADERS += ../../../../../../bsps/arm/atsam/include/bsp/irq.h
    1516include_bsp_HEADERS += ../../../../../../bsps/arm/atsam/include/bsp/pin-config.h
  • c/src/lib/libbsp/arm/atsam/Makefile.am

    r538a0a8 r6878519  
    157157libbsp_a_SOURCES += rtc/rtc-config.c
    158158
     159# Helper functions
     160libbsp_a_SOURCES += utils/iocopy.c
     161
    159162# Includes
    160163libbsp_a_CPPFLAGS += -I$(srcdir)/../shared/CMSIS/Include
  • c/src/lib/libbsp/arm/atsam/libraries/libchip/source/qspi.c

    r538a0a8 r6878519  
    7676
    7777#include <stdint.h>
     78#include <bsp/iocopy.h>
    7879
    7980
     
    210211
    211212        pQspi->QSPI_SMR = (EnableFlag | (Random << 1));
    212 }
    213 
    214 static void do_copy(uint8_t *dst, const uint8_t *src, size_t n, bool aligned)
    215 {
    216         if (aligned) {
    217                 while (n > 3) {
    218                         *(uint32_t *)dst = *(uint32_t *)src;
    219                         dst += 4;
    220                         src += 4;
    221                         n -= 4;
    222                 }
    223         }
    224 
    225         while (n > 0) {
    226                 *dst = *src;
    227                 ++dst;
    228                 ++src;
    229                 --n;
    230         }
    231 }
    232 
    233 static void copy_to_io(void *dst, const void *src, size_t n)
    234 {
    235         do_copy(dst, src, n, ((uintptr_t)dst) % 4 == 0);
    236 }
    237 
    238 static void copy_from_io(void *dst, const void *src, size_t n)
    239 {
    240         do_copy(dst, src, n, ((uintptr_t)src) % 4 == 0);
    241213}
    242214
     
    767739
    768740        if (ReadWrite == WriteAccess) {
    769                 copy_to_io(pQspiMem, pBuffer.pDataTx , pBuffer.TxDataSize);
     741                atsam_copy_to_io(pQspiMem, pBuffer.pDataTx ,
     742                    pBuffer.TxDataSize);
    770743        } else {
    771                 copy_from_io(pBuffer.pDataRx, pQspiMem, pBuffer.RxDataSize);
     744                atsam_copy_from_io(pBuffer.pDataRx, pQspiMem,
     745                    pBuffer.RxDataSize);
    772746        }
    773747        memory_sync();
  • c/src/lib/libbsp/arm/atsam/spi/atsam_spi_bus.c

    r538a0a8 r6878519  
    3131#include <bsp/atsam-clock-config.h>
    3232#include <bsp/atsam-spi.h>
     33#include <bsp/iocopy.h>
    3334
    3435#include <dev/spi/spi.h>
     
    3738
    3839#define MAX_SPI_FREQUENCY 50000000
     40
     41#define DMA_NR_DESC_PER_DIR 3
     42#define DMA_DESC_ALLIGNMENT 4
     43
     44#define DMA_BUF_RX 0
     45#define DMA_BUF_TX 1
     46#define DMA_BUF_DIRS 2
     47
     48struct atsam_spi_xdma_buf {
     49  LinkedListDescriporView0 desc[DMA_NR_DESC_PER_DIR];
     50  uint8_t leadbuf[CPU_CACHE_LINE_BYTES];
     51  uint8_t trailbuf[CPU_CACHE_LINE_BYTES];
     52};
    3953
    4054typedef struct {
     
    4256  bool msg_cs_change;
    4357  const spi_ioc_transfer *msg_current;
     58  const spi_ioc_transfer *msg_next;
    4459  uint32_t msg_todo;
    4560  int msg_error;
     
    4863  uint32_t dma_tx_channel;
    4964  uint32_t dma_rx_channel;
     65  struct atsam_spi_xdma_buf *dma_bufs;
     66  size_t leadbuf_rx_buffered_len;
     67  size_t trailbuf_rx_buffered_len;
    5068  int transfer_in_progress;
    5169  bool chip_select_active;
     
    128146}
    129147
     148static void atsam_spi_check_alignment_and_set_up_dma_descriptors(
     149  atsam_spi_bus *bus,
     150  struct atsam_spi_xdma_buf *buf,
     151  const uint8_t *start,
     152  size_t len,
     153  bool tx
     154)
     155{
     156  LinkedListDescriporView0 *curdesc = buf->desc;
     157  size_t misaligned_begin;
     158  size_t misaligned_end;
     159  size_t len_main;
     160  const uint8_t *start_main;
     161  const uint8_t *start_trail;
     162
     163  /* Check alignments. */
     164  if (len < CPU_CACHE_LINE_BYTES) {
     165    misaligned_begin = len;
     166    misaligned_end = 0;
     167    len_main = 0;
     168  } else {
     169    misaligned_begin = ((uint32_t) start) % CPU_CACHE_LINE_BYTES;
     170    misaligned_end = (((uint32_t) start) + len) % CPU_CACHE_LINE_BYTES;
     171    len_main = len - misaligned_begin - misaligned_end;
     172  }
     173  start_main = start + misaligned_begin;
     174  start_trail = start_main + len_main;
     175
     176  /* Store length for copying data back. */
     177  if (!tx) {
     178    bus->leadbuf_rx_buffered_len = misaligned_begin;
     179    bus->trailbuf_rx_buffered_len = misaligned_end;
     180  }
     181
     182  /* Handle misalignment on begin. */
     183  if (misaligned_begin != 0) {
     184    if (tx) {
     185      atsam_copy_to_io(buf->leadbuf, start, misaligned_begin);
     186    }
     187    curdesc->mbr_nda = (uint32_t) (&curdesc[1]);
     188    curdesc->mbr_ta = (uint32_t) buf->leadbuf;
     189    curdesc->mbr_ubc = misaligned_begin;
     190  }
     191
     192  /* Main part */
     193  if (len_main > 0) {
     194    curdesc->mbr_ubc |= tx ? XDMA_UBC_NSEN_UPDATED : XDMA_UBC_NDEN_UPDATED;
     195    curdesc->mbr_ubc |= XDMA_UBC_NVIEW_NDV0;
     196    curdesc->mbr_ubc |= XDMA_UBC_NDE_FETCH_EN;
     197    ++curdesc;
     198
     199    curdesc->mbr_nda = (uint32_t) (&curdesc[1]);
     200    curdesc->mbr_ta = (uint32_t) start_main;
     201    curdesc->mbr_ubc = len_main;
     202    if (tx) {
     203      rtems_cache_flush_multiple_data_lines(start_main, len_main);
     204    } else {
     205      rtems_cache_invalidate_multiple_data_lines(start_main, len_main);
     206    }
     207  }
     208
     209  /* Handle misalignment on end */
     210  if (misaligned_end != 0) {
     211    curdesc->mbr_ubc |= tx ? XDMA_UBC_NSEN_UPDATED : XDMA_UBC_NDEN_UPDATED;
     212    curdesc->mbr_ubc |= XDMA_UBC_NVIEW_NDV0;
     213    curdesc->mbr_ubc |= XDMA_UBC_NDE_FETCH_EN;
     214    ++curdesc;
     215
     216    if (tx) {
     217      atsam_copy_to_io(buf->trailbuf, start_trail, misaligned_end);
     218    }
     219    curdesc->mbr_nda = 0;
     220    curdesc->mbr_ta = (uint32_t) buf->trailbuf;
     221    curdesc->mbr_ubc = misaligned_end;
     222    curdesc->mbr_ubc |= XDMA_UBC_NDE_FETCH_DIS;
     223  }
     224}
     225
     226static void atsam_spi_copy_back_rx_after_dma_transfer(
     227  atsam_spi_bus *bus
     228)
     229{
     230  if (bus->leadbuf_rx_buffered_len != 0) {
     231    atsam_copy_from_io(
     232      bus->msg_current->rx_buf,
     233      bus->dma_bufs[DMA_BUF_RX].leadbuf,
     234      bus->leadbuf_rx_buffered_len
     235    );
     236  }
     237  if (bus->trailbuf_rx_buffered_len != 0) {
     238    atsam_copy_from_io(
     239      bus->msg_current->rx_buf + bus->msg_current->len -
     240        bus->trailbuf_rx_buffered_len,
     241      bus->dma_bufs[DMA_BUF_RX].trailbuf,
     242      bus->trailbuf_rx_buffered_len
     243    );
     244  }
     245}
     246
    130247static void atsam_spi_start_dma_transfer(
    131248  atsam_spi_bus *bus,
     
    134251{
    135252  Xdmac *pXdmac = XDMAC;
    136 
    137   XDMAC_SetDestinationAddr(pXdmac, bus->dma_rx_channel, (uint32_t)msg->rx_buf);
    138   XDMAC_SetSourceAddr(pXdmac, bus->dma_tx_channel, (uint32_t)msg->tx_buf);
    139   XDMAC_SetMicroblockControl(pXdmac, bus->dma_rx_channel, msg->len);
    140   XDMAC_SetMicroblockControl(pXdmac, bus->dma_tx_channel, msg->len);
     253  size_t i;
     254
     255  atsam_spi_check_alignment_and_set_up_dma_descriptors(
     256    bus,
     257    &bus->dma_bufs[DMA_BUF_RX],
     258    msg->rx_buf,
     259    msg->len,
     260    false
     261  );
     262  atsam_spi_check_alignment_and_set_up_dma_descriptors(
     263    bus,
     264    &bus->dma_bufs[DMA_BUF_TX],
     265    msg->tx_buf,
     266    msg->len,
     267    true
     268  );
     269
     270  XDMAC_SetDescriptorAddr(
     271    pXdmac,
     272    bus->dma_rx_channel,
     273    (uint32_t) bus->dma_bufs[DMA_BUF_RX].desc,
     274    0
     275  );
     276  XDMAC_SetDescriptorControl(
     277    pXdmac,
     278    bus->dma_rx_channel,
     279    XDMAC_CNDC_NDVIEW_NDV0 |
     280    XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED |
     281    XDMAC_CNDC_NDE_DSCR_FETCH_EN
     282  );
     283  XDMAC_SetDescriptorAddr(
     284    pXdmac,
     285    bus->dma_tx_channel,
     286    (uint32_t) bus->dma_bufs[DMA_BUF_TX].desc,
     287    0
     288  );
     289  XDMAC_SetDescriptorControl(
     290    pXdmac,
     291    bus->dma_tx_channel,
     292    XDMAC_CNDC_NDVIEW_NDV0 |
     293    XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
     294    XDMAC_CNDC_NDE_DSCR_FETCH_EN
     295  );
     296
    141297  XDMAC_StartTransfer(pXdmac, bus->dma_rx_channel);
    142298  XDMAC_StartTransfer(pXdmac, bus->dma_tx_channel);
     
    206362
    207363  if (msg_todo > 0) {
    208     const spi_ioc_transfer *msg = bus->msg_current;
     364    const spi_ioc_transfer *msg = bus->msg_next;
    209365    int error;
    210366
    211367    bus->msg_cs_change = msg->cs_change;
    212     bus->msg_current = msg + 1;
     368    bus->msg_next = msg + 1;
     369    bus->msg_current = msg;
    213370    bus->msg_todo = msg_todo - 1;
    214371
     
    232389
    233390  if (bus->transfer_in_progress == 0) {
     391    atsam_spi_copy_back_rx_after_dma_transfer(bus);
    234392    atsam_spi_setup_transfer(bus);
    235393  }
     
    242400)
    243401{
     402  rtems_status_code sc;
    244403  atsam_spi_bus *bus = (atsam_spi_bus *)base;
    245404
    246405  bus->msg_cs_change = false;
    247   bus->msg_current = &msgs[0];
     406  bus->msg_next = &msgs[0];
     407  bus->msg_current = NULL;
    248408  bus->msg_todo = msg_count;
    249409  bus->msg_error = 0;
    250410  bus->msg_task = rtems_task_self();
    251411  atsam_spi_setup_transfer(bus);
    252   rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     412  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     413  assert(sc == RTEMS_SUCCESSFUL);
    253414  return bus->msg_error;
    254415}
     
    281442  SPI_Disable(bus->spi.pSpiHw);
    282443  PMC_DisablePeripheral(bus->spi.spiId);
     444
     445  rtems_cache_coherent_free(bus->dma_bufs);
    283446
    284447  spi_bus_destroy_and_free(&bus->base);
     
    306469  uint8_t channel;
    307470  eXdmadRC rc;
     471  uint32_t xdma_cndc;
     472
     473  bus->dma_bufs = rtems_cache_coherent_allocate(
     474    DMA_BUF_DIRS * sizeof(*(bus->dma_bufs)),
     475    DMA_DESC_ALLIGNMENT,
     476    0
     477  );
     478  assert(bus->dma_bufs != NULL);
    308479
    309480  bus->dma_tx_channel = XDMAD_AllocateChannel(
     
    343514  assert(rc == XDMAD_OK);
    344515
    345   /* Put all interrupts on for non LLI list setup of DMA */
     516  /* Put all relevant interrupts on */
    346517  xdmaInt =  (
    347518    XDMAC_CIE_BIE |
     
    367538    XDMAC_CC_DAM_INCREMENTED_AM |
    368539    XDMAC_CC_PERID(channel);
     540  xdma_cndc = XDMAC_CNDC_NDVIEW_NDV0 |
     541    XDMAC_CNDC_NDE_DSCR_FETCH_EN |
     542    XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED |
     543    XDMAC_CNDC_NDSUP_SRC_PARAMS_UNCHANGED;
    369544  rc = XDMAD_ConfigureTransfer(
    370545    bus->spi.pXdmad,
    371546    bus->dma_rx_channel,
    372547    &cfg,
    373     0,
    374     0,
     548    xdma_cndc,
     549    (uint32_t) bus->dma_bufs[DMA_BUF_RX].desc,
    375550    xdmaInt
    376551  );
     
    392567    XDMAC_CC_DAM_FIXED_AM |
    393568    XDMAC_CC_PERID(channel);
     569  xdma_cndc = XDMAC_CNDC_NDVIEW_NDV0 |
     570    XDMAC_CNDC_NDE_DSCR_FETCH_EN |
     571    XDMAC_CNDC_NDDUP_DST_PARAMS_UNCHANGED |
     572    XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED;
    394573  rc = XDMAD_ConfigureTransfer(
    395574    bus->spi.pXdmad,
    396575    bus->dma_tx_channel,
    397576    &cfg,
    398     0,
    399     0,
     577    xdma_cndc,
     578    (uint32_t) bus->dma_bufs[DMA_BUF_TX].desc,
    400579    xdmaInt
    401580  );
Note: See TracChangeset for help on using the changeset viewer.