diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-12 15:34:31 +0100 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2016-01-19 08:36:20 +0100 |
commit | e1eeb883d82ce218c2a9c754795cb3c86ac0f36d (patch) | |
tree | 646a7c22772297094bb77303953eda0e71679dd9 /c/src/lib/libbsp/arm/atsam/libraries/libchip/source/afe_dma.c | |
parent | bsps/arm: Copy vector table only if necessary (diff) | |
download | rtems-e1eeb883d82ce218c2a9c754795cb3c86ac0f36d.tar.bz2 |
bsp/atsam: Import SAM Software Package
Import selected files of the "SAM V71 / V70 / E70 / S70 Software
Package" obtained from the "SAMV71-XULT GNU Software Package 1.5".
Converted files via dos2unix before import.
Update #2529.
Diffstat (limited to 'c/src/lib/libbsp/arm/atsam/libraries/libchip/source/afe_dma.c')
-rw-r--r-- | c/src/lib/libbsp/arm/atsam/libraries/libchip/source/afe_dma.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/afe_dma.c b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/afe_dma.c new file mode 100644 index 0000000000..b137d0194d --- /dev/null +++ b/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/afe_dma.c @@ -0,0 +1,257 @@ +/* ---------------------------------------------------------------------------- */ +/* 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 afe_dma_module Working with AFE (DMA support) + * \ingroup peripherals_module + * The afec driver provides the interface to configure and use the afecC + * peripheral with DMA support.\n + * + * For more accurate information, please look at the AFEC section of the + * Datasheet. + * + * Related files :\n + * \ref afe_dma.c\n + * \ref afe_dma.h\n + */ +/*@{*/ +/*@}*/ +/** + * \file + * + * + */ +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "chip.h" +#include "afe_dma.h" +#include "xdmad.h" + +#include <stdint.h> +#include <assert.h> + +/* DMA driver instance */ +static uint32_t afeDmaRxChannel; + +/*---------------------------------------------------------------------------- + * Local functions + *----------------------------------------------------------------------------*/ + +/** + * \brief AFE xDMA Rx callback + * Invoked on AFE DMA reception done. + * \param channel DMA channel. + * \param pArg Pointer to callback argument - Pointer to AfeDma instance. + */ +static void Afe_Rx_Cb(uint32_t channel, AfeDma *pArg) +{ + AfeCmd *pAfedCmd = pArg->pCurrentCommand; + + if (channel != afeDmaRxChannel) + return; + + /* Configure and enable interrupt on RC compare */ + NVIC_ClearPendingIRQ(XDMAC_IRQn); + NVIC_DisableIRQ(XDMAC_IRQn); + + /* Release the DMA channels */ + XDMAD_FreeChannel(pArg->pXdmad, afeDmaRxChannel); + SCB_InvalidateDCache_by_Addr(pAfedCmd->pRxBuff, pAfedCmd->RxSize); + /* Release the dataflash semaphore */ + pArg->semaphore++; + + /* Invoke the callback associated with the current command */ + if (pAfedCmd && pAfedCmd->callback) + pAfedCmd->callback(0, pAfedCmd->pArgument); +} + +/** + * \brief Configure the DMA Channels: 0 RX. + * Channels are disabled after configure. + * \param pXdmad Pointer to a AfeDma instance + * \returns 0 if the dma channel configuration successfully; otherwise returns + * AFE_ERROR_XXX. + */ +static uint8_t _AfeConfigureDmaChannels(AfeDma *pAfed) +{ + + /* Driver initialize */ + XDMAD_Initialize(pAfed->pXdmad, 0); + + XDMAD_FreeChannel(pAfed->pXdmad, afeDmaRxChannel); + + /* Allocate a DMA channel for AFE0/1 RX. */ + afeDmaRxChannel = + XDMAD_AllocateChannel(pAfed->pXdmad, pAfed->afeId, XDMAD_TRANSFER_MEMORY); + + if (afeDmaRxChannel == XDMAD_ALLOC_FAILED) + return AFE_ERROR; + + /* Setup callbacks for AFE0/1 RX */ + XDMAD_SetCallback(pAfed->pXdmad, afeDmaRxChannel, + (XdmadTransferCallback)Afe_Rx_Cb, pAfed); + + if (XDMAD_PrepareChannel(pAfed->pXdmad, afeDmaRxChannel)) + return AFE_ERROR; + + return AFE_OK; +} + +/** + * \brief Configure the DMA source and destination with Linker List mode. + * \param pXdmad Pointer to a AfeDma instance + * \param pCommand Pointer to AfeCmd instance + * \param AfeCmd Pointer to command + */ + +static uint8_t _Afe_configureLinkList(Afec *pAfeHw, void *pXdmad, + AfeCmd *pCommand) +{ + uint32_t xdmaCndc, xdmaInt; + sXdmadCfg xdmadRxCfg; + uint32_t afeId; + + if ((unsigned int)pAfeHw == (unsigned int)AFEC0) afeId = ID_AFEC0; + + if ((unsigned int)pAfeHw == (unsigned int)AFEC1) afeId = ID_AFEC1; + + /* Setup RX Link List */ + xdmadRxCfg.mbr_ubc = XDMA_UBC_NVIEW_NDV0 | + XDMA_UBC_NDE_FETCH_DIS | + XDMA_UBC_NDEN_UPDATED | + pCommand->RxSize; + + xdmadRxCfg.mbr_da = (uint32_t)pCommand->pRxBuff; + xdmadRxCfg.mbr_sa = (uint32_t) & (pAfeHw->AFEC_LCDR); + xdmadRxCfg.mbr_cfg = XDMAC_CC_TYPE_PER_TRAN | + XDMAC_CC_MBSIZE_SINGLE | + XDMAC_CC_DSYNC_PER2MEM | + XDMAC_CC_CSIZE_CHK_1 | + XDMAC_CC_DWIDTH_WORD | + XDMAC_CC_SIF_AHB_IF1 | + XDMAC_CC_DIF_AHB_IF1 | + XDMAC_CC_SAM_FIXED_AM | + XDMAC_CC_DAM_INCREMENTED_AM | + XDMAC_CC_PERID( + XDMAIF_Get_ChannelNumber(afeId, XDMAD_TRANSFER_RX)); + + xdmadRxCfg.mbr_bc = 0; + xdmadRxCfg.mbr_sus = 0; + xdmadRxCfg.mbr_dus = 0; + + xdmaInt = (XDMAC_CIE_BIE | + XDMAC_CIE_DIE | + XDMAC_CIE_FIE | + XDMAC_CIE_RBIE | + XDMAC_CIE_WBIE | + XDMAC_CIE_ROIE); + xdmaCndc = 0; + + if (XDMAD_ConfigureTransfer(pXdmad, afeDmaRxChannel, + &xdmadRxCfg, xdmaCndc, 0, xdmaInt)) + return AFE_ERROR; + + return AFE_OK; +} + +/*---------------------------------------------------------------------------- + * Exported functions + *----------------------------------------------------------------------------*/ + + +/** + * \brief Initializes the AfeDma structure and the corresponding AFE & 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 pAfed Pointer to a AfeDma instance. + * \param pAfeHw Associated Afe peripheral. + * \param AfeId Afe peripheral identifier. + * \param pDmad Pointer to a Dmad instance. + */ +uint32_t Afe_ConfigureDma(AfeDma *pAfed , + Afec *pAfeHw , + uint8_t AfeId, + sXdmad *pXdmad) +{ + /* Initialize the Afe structure */ + pAfed->pAfeHw = pAfeHw; + pAfed->afeId = AfeId; + pAfed->semaphore = 1; + pAfed->pCurrentCommand = 0; + pAfed->pXdmad = pXdmad; + return 0; +} + +/** + * \brief Starts a AFE transfer. This is a non blocking function. It will + * return as soon as the transfer is started. + * + * \param pAfed Pointer to a AfeDma instance. + * \param pCommand Pointer to the Afe command to execute. + * \returns 0 if the transfer has been started successfully; otherwise returns + * AFE_ERROR_LOCK is the driver is in use, or AFE_ERROR if the command is not + * valid. + */ +uint32_t Afe_SendData(AfeDma *pAfed, AfeCmd *pCommand) +{ + Afec *pAfeHw = pAfed->pAfeHw; + + /* Try to get the dataflash semaphore */ + if (pAfed->semaphore == 0) + + return AFE_ERROR_LOCK; + + pAfed->semaphore--; + + // Initialize the callback + pAfed->pCurrentCommand = pCommand; + + /* Initialize DMA controller using channel 0 for RX. */ + if (_AfeConfigureDmaChannels(pAfed)) + return AFE_ERROR_LOCK; + + /* Configure and enable interrupt on RC compare */ + NVIC_ClearPendingIRQ(XDMAC_IRQn); + NVIC_SetPriority(XDMAC_IRQn , 1); + NVIC_EnableIRQ(XDMAC_IRQn); + + if (_Afe_configureLinkList(pAfeHw, pAfed->pXdmad, pCommand)) + return AFE_ERROR_LOCK; + + AFEC_StartConversion(pAfeHw); + + /* Start DMA 0(RX) */ + if (XDMAD_StartTransfer(pAfed->pXdmad, afeDmaRxChannel)) + return AFE_ERROR_LOCK; + + return AFE_OK;; +} |