SAMV71 Xplained Ultra Software Package 1.5

qspi_dma.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031  * \addtogroup qspi_dma_module QSPI xDMA driver
00032  * \ingroup peripherals_module
00033  *
00034  *
00035  */
00036 
00037 /**
00038  * \file
00039  *
00040  * Implementation for the SPI Flash with xDMA driver.
00041  *
00042  */
00043 
00044 
00045 /*----------------------------------------------------------------------------
00046  *        Headers
00047  *----------------------------------------------------------------------------*/
00048 
00049 #include "chip.h"
00050 
00051 /*----------------------------------------------------------------------------
00052  *        Definitions
00053  *----------------------------------------------------------------------------*/
00054 
00055 /** xDMA support */
00056 
00057 /** xDMA Link List size for SPI transmission*/
00058 #define DMA_QSPI_LLI     2
00059 
00060 /*-----------------------------------------------------------------------------
00061  *        QSPI DMA Local functions
00062  *----------------------------------------------------------------------------*/
00063 
00064 /**
00065  * \brief SPI xDMA Rx callback
00066  * Invoked on SPi DMA reception done.
00067  * \param channel DMA channel.
00068  * \param pArg Pointer to callback argument - Pointer to Spid instance.
00069  */
00070 static void QSPID_Spi_Cb(uint32_t channel, QspiDma_t *pArg)
00071 {
00072     Qspi *pQspiHw = pArg->Qspid.pQspiHw;
00073 
00074     if (channel != pArg->RxChNum)
00075         return;
00076 
00077     /* Release the semaphore */
00078     ReleaseMutex(pArg->progress);
00079     QSPI_EndTransfer(pQspiHw);
00080     SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->Qspid.qspiBuffer.pDataRx,
00081                                  pArg->Qspid.qspiBuffer.RxDataSize);
00082     memory_sync();
00083 }
00084 
00085 
00086 /**
00087  * \brief QSPI xDMA Tx callback
00088  * Invoked on QSPi DMA Write done.
00089  * \param channel DMA channel.
00090  * \param pArg Pointer to callback argument - Pointer to Spid instance.
00091  */
00092 static void QSPID_qspiTx_Cb(uint32_t channel, QspiDma_t *pArg)
00093 {
00094     Qspi *pQspiHw = pArg->Qspid.pQspiHw;
00095 
00096     if (channel != pArg->TxChNum)
00097         return;
00098 
00099     /* Release the semaphore */
00100     ReleaseMutex(pArg->progress);
00101     QSPI_EndTransfer(pQspiHw);
00102 
00103     while (!QSPI_GetStatus(pArg->Qspid.pQspiHw, IsEofInst));
00104 
00105     memory_sync();
00106 }
00107 
00108 
00109 /**
00110  * \brief QSPI xDMA Rx callback
00111  * Invoked on SPi DMA reception done.
00112  * \param channel DMA channel.
00113  * \param pArg Pointer to callback argument - Pointer to Spid instance.
00114  */
00115 static void QSPID_qspiRx_Cb(uint32_t channel, QspiDma_t *pArg)
00116 {
00117     Qspi *pQspiHw = pArg->Qspid.pQspiHw;
00118 
00119     if (channel != pArg->RxChNum)
00120         return;
00121 
00122     /* Release the semaphore */
00123     ReleaseMutex(pArg->progress);
00124     QSPI_EndTransfer(pQspiHw);
00125 
00126     while (!QSPI_GetStatus(pArg->Qspid.pQspiHw, IsEofInst));
00127 
00128     SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->Qspid.qspiBuffer.pDataRx,
00129                                  pArg->Qspid.qspiBuffer.RxDataSize);
00130     memory_sync();
00131 }
00132 
00133 /**
00134  * \brief Configures the DMA for QSPI
00135  *
00136  * \param pQspidma  Pointer to QSPI DMA structure
00137  * \param Addr      Address to Read or write of QSPI flash memory
00138  * \param pBuffer   Pointer input/output buffer
00139  * \param ReadWrite Read or write memory flag
00140  * \returns 0 if the dma multibuffer configuration successfully; otherwise returns
00141  * QSPID_ERROR_XXX.
00142  */
00143 static uint8_t QSPID_configureQpsiDma(QspiDma_t *pQspidma, uint32_t Addr,
00144                                       QspiBuffer_t *pBuffer, Access_t const ReadWrite)
00145 {
00146     sXdmadCfg xdmadCfg, xdmadRxCfg, xdmadTxCfg;
00147     uint8_t chanNum;
00148     uint8_t qspi_id =  pQspidma->Qspid.qspiId;
00149     Qspi *pQspiHw = pQspidma->Qspid.pQspiHw;
00150     uint32_t xdmaCndc, xdmaInt, BurstSize, ChannelWidth;
00151 
00152 
00153     /* Setup DMA  for QSPI */
00154 
00155     if (pQspidma->Qspid.qspiMode == QSPI_MR_SMM_SPI) {
00156         // SPI mode
00157         /* SPI TX DMA config */
00158         xdmadTxCfg.mbr_sa   =   (uint32_t)pBuffer->pDataTx;
00159         xdmadTxCfg.mbr_da   =   (uint32_t)&pQspiHw->QSPI_TDR;
00160         xdmadTxCfg.mbr_ubc  =   (pBuffer->TxDataSize);
00161 
00162         xdmadTxCfg.mbr_cfg =  XDMAC_CC_TYPE_PER_TRAN |
00163                               XDMAC_CC_MBSIZE_SINGLE |
00164                               XDMAC_CC_DSYNC_MEM2PER |
00165                               XDMAC_CC_CSIZE_CHK_1 |
00166                               XDMAC_CC_DWIDTH_BYTE |
00167                               XDMAC_CC_SIF_AHB_IF0 |
00168                               XDMAC_CC_DIF_AHB_IF1 |
00169                               XDMAC_CC_SAM_INCREMENTED_AM |
00170                               XDMAC_CC_DAM_FIXED_AM |
00171                               XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
00172                                              (qspi_id, XDMAD_TRANSFER_TX));
00173 
00174         xdmadTxCfg.mbr_bc = 0;
00175         xdmadTxCfg.mbr_sus = 0;
00176         xdmadTxCfg.mbr_dus = 0;
00177 
00178         /* SPI RX DMA config */
00179 
00180         xdmadRxCfg.mbr_da  =  (uint32_t)pBuffer->pDataRx;
00181         xdmadRxCfg.mbr_sa  =  (uint32_t)&pQspiHw->QSPI_RDR;
00182         xdmadRxCfg.mbr_ubc =   (pBuffer->RxDataSize);
00183         xdmadRxCfg.mbr_cfg =    XDMAC_CC_TYPE_PER_TRAN |
00184                                 XDMAC_CC_MBSIZE_SINGLE |
00185                                 XDMAC_CC_DSYNC_PER2MEM |
00186                                 XDMAC_CC_CSIZE_CHK_1 |
00187                                 XDMAC_CC_DWIDTH_BYTE |
00188                                 XDMAC_CC_SIF_AHB_IF1 |
00189                                 XDMAC_CC_DIF_AHB_IF0 |
00190                                 XDMAC_CC_SAM_FIXED_AM |
00191                                 XDMAC_CC_DAM_INCREMENTED_AM |
00192                                 XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
00193                                                (qspi_id, XDMAD_TRANSFER_RX));
00194 
00195         xdmadRxCfg.mbr_bc = 0;
00196         xdmadRxCfg.mbr_sus = 0;
00197         xdmadRxCfg.mbr_dus = 0;
00198         xdmaCndc = 0;
00199         /* Put all interrupts on for non LLI list setup of DMA */
00200         xdmaInt =  (XDMAC_CIE_BIE   |
00201                     XDMAC_CIE_RBIE  |
00202                     XDMAC_CIE_WBIE  |
00203                     XDMAC_CIE_ROIE);
00204 
00205         memory_barrier();
00206 
00207         if (XDMAD_ConfigureTransfer
00208             (pQspidma->pXdmad, pQspidma->RxChNum, &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
00209             return QSPID_ERROR;
00210 
00211         if (XDMAD_ConfigureTransfer
00212             (pQspidma->pXdmad, pQspidma->TxChNum, &xdmadTxCfg, xdmaCndc, 0, xdmaInt))
00213             return QSPID_ERROR;
00214 
00215         return 0;
00216 
00217     } else {
00218         if (ReadWrite == WriteAccess) {
00219             xdmadCfg.mbr_sa = (uint32_t)pBuffer->pDataTx;
00220             xdmadCfg.mbr_da = (uint32_t)(QSPIMEM_ADDR | Addr);
00221             xdmadCfg.mbr_ubc =  (pBuffer->TxDataSize);
00222             chanNum =  pQspidma->TxChNum;
00223             ChannelWidth = XDMAC_CC_DWIDTH_BYTE;
00224             BurstSize = XDMAC_CC_MBSIZE_SIXTEEN;
00225         } else if (ReadWrite == ReadAccess) {
00226             xdmadCfg.mbr_da = (uint32_t)pBuffer->pDataRx;
00227             xdmadCfg.mbr_sa = (uint32_t)(QSPIMEM_ADDR | Addr);
00228             xdmadCfg.mbr_ubc =  ((pBuffer->RxDataSize >> 2));
00229             chanNum =  pQspidma->RxChNum;
00230             ChannelWidth = XDMAC_CC_DWIDTH_WORD;
00231             BurstSize = XDMAC_CC_MBSIZE_SIXTEEN;
00232         } else {
00233             TRACE_ERROR(" QSPI error \n\r");
00234             return 1;
00235         }
00236 
00237         xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_MEM_TRAN |
00238                            XDMAC_CC_MEMSET_NORMAL_MODE |
00239                            BurstSize |
00240                            ChannelWidth |
00241                            XDMAC_CC_SIF_AHB_IF1 |
00242                            XDMAC_CC_DIF_AHB_IF1 |
00243                            XDMAC_CC_SAM_INCREMENTED_AM |
00244                            XDMAC_CC_DAM_INCREMENTED_AM;
00245 
00246         xdmadCfg.mbr_bc = 0;
00247         xdmadCfg.mbr_sus = 0;
00248         xdmadCfg.mbr_dus = 0;
00249 
00250         xdmaCndc = 0;
00251 
00252 
00253         /* Put all interrupts on for non LLI list setup of DMA */
00254         xdmaInt =  (XDMAC_CIE_BIE   |
00255                     XDMAC_CIE_RBIE  |
00256                     XDMAC_CIE_WBIE  |
00257                     XDMAC_CIE_ROIE);
00258 
00259         memory_barrier();
00260 
00261         if (XDMAD_ConfigureTransfer(pQspidma->pXdmad, chanNum, &xdmadCfg, xdmaCndc, 0,
00262                                      xdmaInt))
00263             return QSPID_ERROR;
00264 
00265         return 0;
00266     }
00267 }
00268 
00269 /*----------------------------------------------------------------------------
00270  *        Exported functions
00271  *----------------------------------------------------------------------------*/
00272 /**
00273  * \brief Initializes the pQspidma structure and the corresponding QSPI & DMA .
00274  * hardware select value.
00275  *
00276  * \param pQspidma  Pointer to a QspiDma_t instance.
00277  * \param Mode      Associated SPI peripheral.
00278  * \param dwConf    QSPI peripheral configuration.
00279  * \param pXdmad    Pointer to a Xdmad instance.
00280  */
00281 uint32_t QSPID_Configure(QspiDma_t *pQspidma, QspiMode_t Mode,
00282                           uint32_t dwConf, sXdmad *pXdmad)
00283 {
00284     /* Initialize the QSPI structure */
00285 
00286     QSPI_ConfigureInterface(&pQspidma->Qspid, Mode, dwConf);
00287 
00288     pQspidma->Qspid.qspiCommand.Instruction = 0;
00289     pQspidma->Qspid.qspiCommand.Option = 0;
00290 
00291     pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
00292     pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
00293 
00294     pQspidma->pXdmad = pXdmad;
00295 
00296     /* XDMA Driver initialize */
00297     XDMAD_Initialize(pQspidma->pXdmad, 0);
00298 
00299     /* Configure and enable interrupt  */
00300     NVIC_ClearPendingIRQ(XDMAC_IRQn);
00301     NVIC_SetPriority(XDMAC_IRQn , 1);
00302     NVIC_EnableIRQ(XDMAC_IRQn);
00303 
00304 
00305     return QSPI_SUCCESS;
00306 }
00307 
00308 
00309 
00310 /**
00311  * \brief Enables a QSPI Rx channel. This function will allocate a dma Rx
00312  *  channel for QSPI
00313  *
00314  * \param pQspidma  Pointer to a Spid instance.
00315 
00316  * \returns 0 if the transfer has been started successfully; otherwise returns
00317  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is not
00318  * valid.
00319  */
00320 uint32_t QSPID_EnableQspiRxChannel(QspiDma_t *pQspidma)
00321 {
00322     static uint16_t DmaChannel;
00323 
00324     /* Try to get the semaphore */
00325     if (pQspidma->RxChNum != QSPID_CH_NOT_ENABLED)
00326         return QSPID_ERROR_LOCK;
00327 
00328     /* Allocate a DMA channel */
00329     DmaChannel = XDMAD_AllocateChannel(
00330                      pQspidma->pXdmad, XDMAD_TRANSFER_MEMORY, XDMAD_TRANSFER_MEMORY);
00331 
00332     if (DmaChannel == XDMAD_ALLOC_FAILED)
00333         return QSPID_ERROR;
00334 
00335     pQspidma->RxChNum = DmaChannel;
00336     /* Setup callbacks*/
00337     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum,
00338                       (XdmadTransferCallback)QSPID_qspiRx_Cb, pQspidma);
00339 
00340     if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->RxChNum))
00341         return QSPID_ERROR;
00342 
00343     return 0;
00344 }
00345 
00346 
00347 /**
00348  * \brief Enables a QSPI Tx channel. This function will allocate a dma Tx
00349  * channel for QSPI
00350  *
00351  * \param pQspidma  Pointer to a Spid instance.
00352 
00353  * \returns 0 if the transfer has been started successfully; otherwise returns
00354  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
00355  * not valid.
00356  */
00357 uint32_t QSPID_EnableQspiTxChannel(QspiDma_t *pQspidma)
00358 {
00359     static uint16_t DmaChannel;
00360 
00361     /* Try to get the  semaphore */
00362     if (pQspidma->TxChNum != QSPID_CH_NOT_ENABLED)
00363         return QSPID_ERROR_LOCK;
00364 
00365     /* Allocate a DMA channel */
00366     DmaChannel = XDMAD_AllocateChannel(pQspidma->pXdmad,
00367                                         XDMAD_TRANSFER_MEMORY, XDMAD_TRANSFER_MEMORY);
00368 
00369     if (DmaChannel == XDMAD_ALLOC_FAILED)
00370         return QSPID_ERROR;
00371 
00372     pQspidma->TxChNum = DmaChannel;
00373     /* Setup callbacks  */
00374     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum,
00375                       (XdmadTransferCallback)QSPID_qspiTx_Cb, pQspidma);
00376 
00377     if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->TxChNum))
00378         return QSPID_ERROR;
00379 
00380     return 0;
00381 }
00382 
00383 
00384 /**
00385  * \brief Enables a QSPI SPI Rx channel. This function will allocate a dma
00386  *  Rx channel for QSPI SPI mode
00387  *
00388  * \param pQspidma  Pointer to a Spid instance.
00389 
00390  * \returns 0 if the transfer has been started successfully; otherwise returns
00391  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
00392  * not valid.
00393  */
00394 uint32_t QSPID_EnableSpiChannel(QspiDma_t *pQspidma)
00395 {
00396     static uint16_t DmaChannel;
00397 
00398     /* Try to get the semaphore */
00399     if (pQspidma->RxChNum != QSPID_CH_NOT_ENABLED)
00400         return QSPID_ERROR_LOCK;
00401 
00402     /* Try to get the  semaphore */
00403     if (pQspidma->TxChNum != QSPID_CH_NOT_ENABLED)
00404         return QSPID_ERROR_LOCK;
00405 
00406     /* Allocate a DMA channel */
00407     DmaChannel = XDMAD_AllocateChannel
00408                  (pQspidma->pXdmad, pQspidma->Qspid.qspiId, XDMAD_TRANSFER_MEMORY);
00409 
00410     if (DmaChannel == XDMAD_ALLOC_FAILED)
00411         return QSPID_ERROR;
00412 
00413     pQspidma->RxChNum = DmaChannel;
00414 
00415     /* Allocate a DMA channel */
00416     DmaChannel = XDMAD_AllocateChannel(pQspidma->pXdmad,
00417                                         XDMAD_TRANSFER_MEMORY, pQspidma->Qspid.qspiId);
00418 
00419     if (DmaChannel == XDMAD_ALLOC_FAILED)
00420         return QSPID_ERROR;
00421 
00422     pQspidma->TxChNum = DmaChannel;
00423 
00424     /* Setup callbacks*/
00425     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum,
00426                       (XdmadTransferCallback)QSPID_Spi_Cb, pQspidma);
00427 
00428     if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->RxChNum))
00429         return QSPID_ERROR;
00430 
00431     /* Setup callbacks for SPI0/1 TX (ignored) */
00432     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum, NULL, NULL);
00433 
00434     if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->TxChNum))
00435         return QSPID_ERROR;
00436 
00437     return 0;
00438 }
00439 
00440 
00441 /**
00442  * \brief Disables a QSPI Rx channel. This function will de-allocate previous
00443  *  allocated dma Rx channel for QSPI
00444  *
00445  * \param pQspidma  Pointer to a Spid instance.
00446 
00447  * \returns 0 if the transfer has been started successfully; otherwise returns
00448  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
00449  * not valid.
00450  */
00451 uint32_t QSPID_DisableQspiRxChannel(QspiDma_t *pQspidma)
00452 {
00453 
00454     XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->RxChNum);
00455     XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->RxChNum);
00456 
00457     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum, NULL, NULL);
00458 
00459 
00460     /* Free allocated DMA channel for QSPI RX. */
00461     XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->RxChNum);
00462 
00463     pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
00464 
00465     return 0;
00466 }
00467 
00468 
00469 
00470 /**
00471  * \brief Disables a QSPI Tx channel. This function will de-allocate previous
00472  * allocated dma Tx channel for QSPI
00473  *
00474  * \param pQspidma  Pointer to a Spid instance.
00475 
00476  * \returns 0 if the transfer has been started successfully; otherwise returns
00477  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
00478  * not valid.
00479  */
00480 uint32_t QSPID_DisableQspiTxChannel(QspiDma_t *pQspidma)
00481 {
00482 
00483     XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->TxChNum);
00484     XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->TxChNum);
00485 
00486     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum, NULL, NULL);
00487 
00488     /* Free allocated DMA channel for QSPI TX. */
00489     XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->TxChNum);
00490 
00491     pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
00492 
00493     return 0;
00494 }
00495 
00496 
00497 /**
00498  * \brief Disables a QSPI SPI Rx and Tx channels. This function will
00499  *  de-allocate privious allocated dma Rx, Txchannel for QSPI in SPI mode
00500  *
00501  * \param pQspidma  Pointer to a Spid instance.
00502 
00503  * \returns 0 if the transfer has been started successfully; otherwise returns
00504  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
00505  * not valid.
00506  */
00507 uint32_t QSPID_DisableSpiChannel(QspiDma_t *pQspidma)
00508 {
00509 
00510     XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->RxChNum);
00511     //XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->TxChNum);
00512     XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->RxChNum);
00513     XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->TxChNum);
00514 
00515     XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum, NULL, NULL);
00516 
00517     /* Free allocated DMA channel for QSPI RX. */
00518     XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->RxChNum);
00519 
00520     XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->TxChNum);
00521 
00522     pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
00523     pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
00524 
00525     return 0;
00526 }
00527 
00528 
00529 /**
00530  * \brief Starts a QSPI read or write operation.
00531  *
00532  * \param pQspidma  Pointer to a Qspid instance.
00533  * \param ReadWrite Defines the memory access type
00534  * \returns 0 if the transfer has been started successfully; otherwise returns
00535  * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
00536  * not valid.
00537  */
00538 uint32_t QSPID_ReadWriteQSPI(QspiDma_t *pQspidma, Access_t const ReadWrite)
00539 {
00540     QspiBuffer_t *pBuffer = &pQspidma->Qspid.qspiBuffer;
00541     uint8_t chanNum;
00542     uint32_t semTimer = 0x7FF;
00543 
00544     //assert(pBuffer->pDataTx);
00545 
00546     if (pQspidma->progress)
00547         return QSPID_ERROR_LOCK;
00548 
00549     LockMutex(pQspidma->progress, semTimer);
00550 
00551     if (QSPID_configureQpsiDma
00552         (pQspidma, pQspidma->Qspid.pQspiFrame->Addr, pBuffer, ReadWrite))
00553         return QSPID_ERROR_LOCK;
00554 
00555     if (ReadWrite == WriteAccess) {
00556         chanNum =  pQspidma->TxChNum;
00557         SCB_CleanDCache_by_Addr((uint32_t *)pBuffer->pDataTx, pBuffer->TxDataSize);
00558     } else if (ReadWrite == ReadAccess)
00559         chanNum =  pQspidma->RxChNum;
00560     else
00561         TRACE_ERROR("%s QSPI Access Error\n\r", __FUNCTION__);
00562 
00563     /* Start DMA 0(RX) && 1(TX) */
00564     if (XDMAD_StartTransfer(pQspidma->pXdmad, chanNum))
00565         return QSPID_ERROR_LOCK;
00566 
00567     return 0;
00568 }
00569 
00570 /**
00571  * \brief Starts a SPI master transfer. This is a non blocking function. It will
00572  *  return as soon as the transfer is started.
00573  *
00574  * \param pSpid  Pointer to a Spid instance.
00575  * \param pCommand Pointer to the SPI command to execute.
00576  * \returns 0 if the transfer has been started successfully; otherwise returns
00577  * SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
00578  * valid.
00579  */
00580 uint32_t QSPID_ReadWriteSPI(QspiDma_t *pQspidma, Access_t const ReadWrite)
00581 {
00582     QspiBuffer_t *pBuffer = &pQspidma->Qspid.qspiBuffer;
00583     uint32_t semTimer = 0x7FF;
00584 
00585     assert(pBuffer->pDataRx);
00586     assert(pBuffer->pDataTx);
00587 
00588     /* Try to get the dataflash semaphore */
00589     if (pQspidma->progress)
00590 
00591         return QSPID_ERROR_LOCK;
00592 
00593     LockMutex(pQspidma->progress, semTimer);
00594 
00595     if (QSPID_configureQpsiDma
00596         (pQspidma, pQspidma->Qspid.pQspiFrame->Addr, pBuffer, ReadWrite))
00597         return QSPID_ERROR_LOCK;
00598 
00599     SCB_CleanDCache_by_Addr((uint32_t *)pBuffer->pDataTx, pBuffer->TxDataSize);
00600 
00601     /* Start DMA 0(RX) && 1(TX) */
00602     if (XDMAD_StartTransfer(pQspidma->pXdmad, pQspidma->RxChNum))
00603         return QSPID_ERROR_LOCK;
00604 
00605     if (XDMAD_StartTransfer(pQspidma->pXdmad, pQspidma->TxChNum))
00606         return QSPID_ERROR_LOCK;
00607 
00608     return 0;
00609 }
00610 
00611 /**
00612  * \brief Check if the QSPI driver is busy.
00613  *
00614  * \param pSpid  Pointer to a Spid instance.
00615  * \returns 1 if the SPI driver is currently busy executing a command; otherwise
00616  */
00617 uint32_t QSPID_IsBusy(volatile uint8_t *QspiSemaphore)
00618 {
00619     if (Is_LockFree(QspiSemaphore))
00620         return 1;
00621     else
00622         return 0;
00623 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines