summaryrefslogtreecommitdiffstats
path: root/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c')
-rw-r--r--bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c238
1 files changed, 238 insertions, 0 deletions
diff --git a/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c b/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c
new file mode 100644
index 0000000000..5675499f95
--- /dev/null
+++ b/bsps/arm/atsam/contrib/libraries/libchip/source/dac_dma.c
@@ -0,0 +1,238 @@
+/* ---------------------------------------------------------------------------- */
+/* Atmel Microcontroller Software Support */
+/* SAM Software Package License */
+/* ---------------------------------------------------------------------------- */
+/* Copyright (c) 2015, Atmel Corporation */
+/* */
+/* All rights reserved. */
+/* */
+/* Redistribution and use in source and binary forms, with or without */
+/* modification, are permitted provided that the following condition is met: */
+/* */
+/* - Redistributions of source code must retain the above copyright notice, */
+/* this list of conditions and the disclaimer below. */
+/* */
+/* Atmel's name may not be used to endorse or promote products derived from */
+/* this software without specific prior written permission. */
+/* */
+/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */
+/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */
+/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */
+/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
+/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
+/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
+/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
+/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
+/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
+/* ---------------------------------------------------------------------------- */
+
+/** \addtogroup dacc_module Working with DACC
+ * \ingroup peripherals_module
+ * The DACC driver provides the interface to configure and use the DACC
+ * peripheral.\n
+ *
+ * The DACC(Digital-to-Analog Converter Controller) converts digital code to
+ * analog output.
+ * The data to be converted are sent in a common register for all channels.
+ * It offers up to 2 analog outputs.The output voltage ranges from (1/6)ADVREF
+ * to (5/6)ADVREF.
+ *
+ * To Enable a DACC conversion,the user has to follow these few steps:
+ * <ul>
+ * <li> Select an appropriate reference voltage on ADVREF </li>
+ * <li> Configure the DACC according to its requirements and special needs,
+ * which could be broken down into several parts:
+ * -# Enable DACC in free running mode by clearing TRGEN in DACC_MR;
+ * -# Configure Refresh Period through setting REFRESH fields
+ * in DACC_MR; The refresh mechanism is used to protect the output analog
+ * value from
+ * decreasing.
+ * -# Enable channels and write digital code to DACC_CDR,in free running mode,
+ * the conversion is started right after at least one channel is enabled and
+ * data is written .
+ </li>
+ * </ul>
+ *
+ * For more accurate information, please look at the DACC section of the
+ * Datasheet.
+ *
+ * Related files :\n
+ * \ref dac_dma.c\n
+ * \ref dac_dma.h\n
+ */
+/*@{*/
+/*@}*/
+/**
+ * \file
+ *
+ * Implementation of Digital-to-Analog Converter Controller (DACC).
+ *
+ */
+
+/*----------------------------------------------------------------------------
+ * Headers
+ *----------------------------------------------------------------------------*/
+
+#include "chip.h"
+
+#include <stdint.h>
+#include <assert.h>
+
+/* DMA driver instance */
+static uint32_t dacDmaTxChannel;
+static LinkedListDescriporView1 dmaWriteLinkList[256];
+/*----------------------------------------------------------------------------
+ * Local functions
+ *----------------------------------------------------------------------------*/
+
+/**
+ * \brief Configure the DMA Channels: 0 RX.
+ * Channels are disabled after configure.
+ * \returns 0 if the dma channel configuration successfully; otherwise returns
+ * DAC_ERROR_XXX.
+ */
+static uint8_t _DacConfigureDmaChannels(DacDma *pDacd)
+{
+
+ /* Driver initialize */
+ XDMAD_FreeChannel(pDacd->pXdmad, dacDmaTxChannel);
+
+ /* Allocate a DMA channel for DAC0/1 TX. */
+ dacDmaTxChannel =
+ XDMAD_AllocateChannel(pDacd->pXdmad, XDMAD_TRANSFER_MEMORY, ID_DACC);
+
+ if (dacDmaTxChannel == XDMAD_ALLOC_FAILED)
+ return DAC_ERROR;
+
+ if (XDMAD_PrepareChannel(pDacd->pXdmad, dacDmaTxChannel))
+ return DAC_ERROR;
+
+ return DAC_OK;
+}
+
+
+/**
+ * \brief Configure the DMA source and destination with Linker List mode.
+ *
+ * \param pBuffer Pointer to dac buffer
+ * \param size length of buffer
+ */
+
+static uint8_t _Dac_configureLinkList(Dacc *pDacHw, void *pXdmad,
+ DacCmd *pCommand)
+{
+ uint32_t xdmaCndc;
+ sXdmadCfg xdmadCfg;
+ uint32_t *pBuffer;
+ /* Setup TX Link List */
+ uint8_t i;
+ pBuffer = (uint32_t *)pCommand->pTxBuff;
+
+ for (i = 0; i < pCommand->TxSize; i++) {
+ dmaWriteLinkList[i].mbr_ubc = XDMA_UBC_NVIEW_NDV1
+ | XDMA_UBC_NDE_FETCH_EN
+ | XDMA_UBC_NSEN_UPDATED
+ | XDMAC_CUBC_UBLEN(4);
+ dmaWriteLinkList[i].mbr_sa = (uint32_t)pBuffer;
+ dmaWriteLinkList[i].mbr_da =
+ (uint32_t) & (pDacHw->DACC_CDR[pCommand->dacChannel]);
+
+ if (i == (pCommand->TxSize - 1)) {
+ if (pCommand->loopback)
+ dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[0];
+ else
+ dmaWriteLinkList[i].mbr_nda = 0;
+ } else
+ dmaWriteLinkList[i].mbr_nda = (uint32_t)&dmaWriteLinkList[i + 1];
+
+ pBuffer++;
+ }
+
+ xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN
+ | XDMAC_CC_MBSIZE_SINGLE
+ | XDMAC_CC_DSYNC_MEM2PER
+ | XDMAC_CC_CSIZE_CHK_1
+ | XDMAC_CC_DWIDTH_WORD
+ | XDMAC_CC_SIF_AHB_IF1
+ | XDMAC_CC_DIF_AHB_IF1
+ | XDMAC_CC_SAM_INCREMENTED_AM
+ | XDMAC_CC_DAM_FIXED_AM
+ | XDMAC_CC_PERID(
+ XDMAIF_Get_ChannelNumber(ID_DACC, XDMAD_TRANSFER_TX));
+ xdmaCndc = XDMAC_CNDC_NDVIEW_NDV1
+ | XDMAC_CNDC_NDE_DSCR_FETCH_EN
+ | XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED
+ | XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
+ XDMAD_ConfigureTransfer(pXdmad, dacDmaTxChannel, &xdmadCfg, xdmaCndc,
+ (uint32_t)&dmaWriteLinkList[0], XDMAC_CIE_LIE);
+ return DAC_OK;
+}
+
+/*----------------------------------------------------------------------------
+ * Exported functions
+ *----------------------------------------------------------------------------*/
+/**
+ * \brief Initializes the DacDma structure and the corresponding DAC & DMA .
+ * hardware select value.
+ * The driver will uses DMA channel 0 for RX .
+ * The DMA channels are freed automatically when no DMA command processing.
+ *
+ * \param pDacd Pointer to a DacDma instance.
+ * \param pDacHw Associated Dac peripheral.
+ * \param DacId Dac peripheral identifier.
+ * \param pDmad Pointer to a Dmad instance.
+ */
+uint32_t Dac_ConfigureDma(DacDma *pDacd ,
+ Dacc *pDacHw ,
+ uint8_t DacId,
+ sXdmad *pXdmad)
+{
+ /* Initialize the Dac structure */
+ pDacd->pDacHw = pDacHw;
+ pDacd->dacId = DacId;
+ pDacd->semaphore = 1;
+ pDacd->pCurrentCommand = 0;
+ assert(pXdmad == &XDMAD_Instance);
+ pDacd->pXdmad = pXdmad;
+ return 0;
+}
+
+/**
+ * \brief Starts a DAC transfer. This is a non blocking function. It will
+ * return as soon as the transfer is started.
+ *
+ * \param pDacd Pointer to a DacDma instance.
+ * \param pCommand Pointer to the Dac command to execute.
+ * \returns 0 if the transfer has been started successfully; otherwise returns
+ * DAC_ERROR_LOCK is the driver is in use, or DAC_ERROR if the command is not
+ * valid.
+ */
+uint32_t Dac_SendData(DacDma *pDacd, DacCmd *pCommand)
+{
+ Dacc *pDacHw = pDacd->pDacHw;
+
+ /* Try to get the dataflash semaphore */
+ if (pDacd->semaphore == 0)
+ return DAC_ERROR_LOCK;
+
+ pDacd->semaphore--;
+
+ // Initialize the callback
+ pDacd->pCurrentCommand = pCommand;
+
+ /* Initialize DMA controller using channel 0 for RX. */
+ if (_DacConfigureDmaChannels(pDacd))
+ return DAC_ERROR_LOCK;
+
+ if (_Dac_configureLinkList(pDacHw, pDacd->pXdmad, pCommand))
+ return DAC_ERROR_LOCK;
+
+ SCB_CleanDCache();
+
+ /* Start DMA TX */
+ if (XDMAD_StartTransfer(pDacd->pXdmad, dacDmaTxChannel))
+ return DAC_ERROR_LOCK;
+
+ return DAC_OK;;
+}