source: rtems/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/qspi_dma.c @ e1eeb883

5
Last change on this file since e1eeb883 was e1eeb883, checked in by Sebastian Huber <sebastian.huber@…>, on 01/12/16 at 14:34:31

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.

  • Property mode set to 100644
File size: 18.3 KB
Line 
1/* ---------------------------------------------------------------------------- */
2/*                  Atmel Microcontroller Software Support                      */
3/*                       SAM Software Package License                           */
4/* ---------------------------------------------------------------------------- */
5/* Copyright (c) 2015, Atmel Corporation                                        */
6/*                                                                              */
7/* All rights reserved.                                                         */
8/*                                                                              */
9/* Redistribution and use in source and binary forms, with or without           */
10/* modification, are permitted provided that the following condition is met:    */
11/*                                                                              */
12/* - Redistributions of source code must retain the above copyright notice,     */
13/* this list of conditions and the disclaimer below.                            */
14/*                                                                              */
15/* Atmel's name may not be used to endorse or promote products derived from     */
16/* this software without specific prior written permission.                     */
17/*                                                                              */
18/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
19/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
20/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
21/* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
22/* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
23/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
24/* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
25/* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
26/* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
27/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
28/* ---------------------------------------------------------------------------- */
29
30/**
31 * \addtogroup qspi_dma_module QSPI xDMA driver
32 * \ingroup peripherals_module
33 *
34 *
35 */
36
37/**
38 * \file
39 *
40 * Implementation for the SPI Flash with xDMA driver.
41 *
42 */
43
44
45/*----------------------------------------------------------------------------
46 *        Headers
47 *----------------------------------------------------------------------------*/
48
49#include "chip.h"
50
51/*----------------------------------------------------------------------------
52 *        Definitions
53 *----------------------------------------------------------------------------*/
54
55/** xDMA support */
56
57/** xDMA Link List size for SPI transmission*/
58#define DMA_QSPI_LLI     2
59
60/*-----------------------------------------------------------------------------
61 *        QSPI DMA Local functions
62 *----------------------------------------------------------------------------*/
63
64/**
65 * \brief SPI xDMA Rx callback
66 * Invoked on SPi DMA reception done.
67 * \param channel DMA channel.
68 * \param pArg Pointer to callback argument - Pointer to Spid instance.
69 */
70static void QSPID_Spi_Cb(uint32_t channel, QspiDma_t *pArg)
71{
72        Qspi *pQspiHw = pArg->Qspid.pQspiHw;
73
74        if (channel != pArg->RxChNum)
75                return;
76
77        /* Release the semaphore */
78        ReleaseMutex(pArg->progress);
79        QSPI_EndTransfer(pQspiHw);
80        SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->Qspid.qspiBuffer.pDataRx,
81                                                                 pArg->Qspid.qspiBuffer.RxDataSize);
82        memory_sync();
83}
84
85
86/**
87 * \brief QSPI xDMA Tx callback
88 * Invoked on QSPi DMA Write done.
89 * \param channel DMA channel.
90 * \param pArg Pointer to callback argument - Pointer to Spid instance.
91 */
92static void QSPID_qspiTx_Cb(uint32_t channel, QspiDma_t *pArg)
93{
94        Qspi *pQspiHw = pArg->Qspid.pQspiHw;
95
96        if (channel != pArg->TxChNum)
97                return;
98
99        /* Release the semaphore */
100        ReleaseMutex(pArg->progress);
101        QSPI_EndTransfer(pQspiHw);
102
103        while (!QSPI_GetStatus(pArg->Qspid.pQspiHw, IsEofInst));
104
105        memory_sync();
106}
107
108
109/**
110 * \brief QSPI xDMA Rx callback
111 * Invoked on SPi DMA reception done.
112 * \param channel DMA channel.
113 * \param pArg Pointer to callback argument - Pointer to Spid instance.
114 */
115static void QSPID_qspiRx_Cb(uint32_t channel, QspiDma_t *pArg)
116{
117        Qspi *pQspiHw = pArg->Qspid.pQspiHw;
118
119        if (channel != pArg->RxChNum)
120                return;
121
122        /* Release the semaphore */
123        ReleaseMutex(pArg->progress);
124        QSPI_EndTransfer(pQspiHw);
125
126        while (!QSPI_GetStatus(pArg->Qspid.pQspiHw, IsEofInst));
127
128        SCB_InvalidateDCache_by_Addr((uint32_t *)pArg->Qspid.qspiBuffer.pDataRx,
129                                                                 pArg->Qspid.qspiBuffer.RxDataSize);
130        memory_sync();
131}
132
133/**
134 * \brief Configures the DMA for QSPI
135 *
136 * \param pQspidma  Pointer to QSPI DMA structure
137 * \param Addr      Address to Read or write of QSPI flash memory
138 * \param pBuffer   Pointer input/output buffer
139 * \param ReadWrite Read or write memory flag
140 * \returns 0 if the dma multibuffer configuration successfully; otherwise returns
141 * QSPID_ERROR_XXX.
142 */
143static uint8_t QSPID_configureQpsiDma(QspiDma_t *pQspidma, uint32_t Addr,
144                                                                          QspiBuffer_t *pBuffer, Access_t const ReadWrite)
145{
146        sXdmadCfg xdmadCfg, xdmadRxCfg, xdmadTxCfg;
147        uint8_t chanNum;
148        uint8_t qspi_id =  pQspidma->Qspid.qspiId;
149        Qspi *pQspiHw = pQspidma->Qspid.pQspiHw;
150        uint32_t xdmaCndc, xdmaInt, BurstSize, ChannelWidth;
151
152
153        /* Setup DMA  for QSPI */
154
155        if (pQspidma->Qspid.qspiMode == QSPI_MR_SMM_SPI) {
156                // SPI mode
157                /* SPI TX DMA config */
158                xdmadTxCfg.mbr_sa   =   (uint32_t)pBuffer->pDataTx;
159                xdmadTxCfg.mbr_da   =   (uint32_t)&pQspiHw->QSPI_TDR;
160                xdmadTxCfg.mbr_ubc  =   (pBuffer->TxDataSize);
161
162                xdmadTxCfg.mbr_cfg =  XDMAC_CC_TYPE_PER_TRAN |
163                                                          XDMAC_CC_MBSIZE_SINGLE |
164                                                          XDMAC_CC_DSYNC_MEM2PER |
165                                                          XDMAC_CC_CSIZE_CHK_1 |
166                                                          XDMAC_CC_DWIDTH_BYTE |
167                                                          XDMAC_CC_SIF_AHB_IF0 |
168                                                          XDMAC_CC_DIF_AHB_IF1 |
169                                                          XDMAC_CC_SAM_INCREMENTED_AM |
170                                                          XDMAC_CC_DAM_FIXED_AM |
171                                                          XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
172                                                                                         (qspi_id, XDMAD_TRANSFER_TX));
173
174                xdmadTxCfg.mbr_bc = 0;
175                xdmadTxCfg.mbr_sus = 0;
176                xdmadTxCfg.mbr_dus = 0;
177
178                /* SPI RX DMA config */
179
180                xdmadRxCfg.mbr_da  =  (uint32_t)pBuffer->pDataRx;
181                xdmadRxCfg.mbr_sa  =  (uint32_t)&pQspiHw->QSPI_RDR;
182                xdmadRxCfg.mbr_ubc =   (pBuffer->RxDataSize);
183                xdmadRxCfg.mbr_cfg =    XDMAC_CC_TYPE_PER_TRAN |
184                                                                XDMAC_CC_MBSIZE_SINGLE |
185                                                                XDMAC_CC_DSYNC_PER2MEM |
186                                                                XDMAC_CC_CSIZE_CHK_1 |
187                                                                XDMAC_CC_DWIDTH_BYTE |
188                                                                XDMAC_CC_SIF_AHB_IF1 |
189                                                                XDMAC_CC_DIF_AHB_IF0 |
190                                                                XDMAC_CC_SAM_FIXED_AM |
191                                                                XDMAC_CC_DAM_INCREMENTED_AM |
192                                                                XDMAC_CC_PERID(XDMAIF_Get_ChannelNumber
193                                                                                           (qspi_id, XDMAD_TRANSFER_RX));
194
195                xdmadRxCfg.mbr_bc = 0;
196                xdmadRxCfg.mbr_sus = 0;
197                xdmadRxCfg.mbr_dus = 0;
198                xdmaCndc = 0;
199                /* Put all interrupts on for non LLI list setup of DMA */
200                xdmaInt =  (XDMAC_CIE_BIE   |
201                                        XDMAC_CIE_RBIE  |
202                                        XDMAC_CIE_WBIE  |
203                                        XDMAC_CIE_ROIE);
204
205                memory_barrier();
206
207                if (XDMAD_ConfigureTransfer
208                        (pQspidma->pXdmad, pQspidma->RxChNum, &xdmadRxCfg, xdmaCndc, 0, xdmaInt))
209                        return QSPID_ERROR;
210
211                if (XDMAD_ConfigureTransfer
212                        (pQspidma->pXdmad, pQspidma->TxChNum, &xdmadTxCfg, xdmaCndc, 0, xdmaInt))
213                        return QSPID_ERROR;
214
215                return 0;
216
217        } else {
218                if (ReadWrite == WriteAccess) {
219                        xdmadCfg.mbr_sa = (uint32_t)pBuffer->pDataTx;
220                        xdmadCfg.mbr_da = (uint32_t)(QSPIMEM_ADDR | Addr);
221                        xdmadCfg.mbr_ubc =  (pBuffer->TxDataSize);
222                        chanNum =  pQspidma->TxChNum;
223                        ChannelWidth = XDMAC_CC_DWIDTH_BYTE;
224                        BurstSize = XDMAC_CC_MBSIZE_SIXTEEN;
225                } else if (ReadWrite == ReadAccess) {
226                        xdmadCfg.mbr_da = (uint32_t)pBuffer->pDataRx;
227                        xdmadCfg.mbr_sa = (uint32_t)(QSPIMEM_ADDR | Addr);
228                        xdmadCfg.mbr_ubc =  ((pBuffer->RxDataSize >> 2));
229                        chanNum =  pQspidma->RxChNum;
230                        ChannelWidth = XDMAC_CC_DWIDTH_WORD;
231                        BurstSize = XDMAC_CC_MBSIZE_SIXTEEN;
232                } else {
233                        TRACE_ERROR(" QSPI error \n\r");
234                        return 1;
235                }
236
237                xdmadCfg.mbr_cfg = XDMAC_CC_TYPE_MEM_TRAN |
238                                                   XDMAC_CC_MEMSET_NORMAL_MODE |
239                                                   BurstSize |
240                                                   ChannelWidth |
241                                                   XDMAC_CC_SIF_AHB_IF1 |
242                                                   XDMAC_CC_DIF_AHB_IF1 |
243                                                   XDMAC_CC_SAM_INCREMENTED_AM |
244                                                   XDMAC_CC_DAM_INCREMENTED_AM;
245
246                xdmadCfg.mbr_bc = 0;
247                xdmadCfg.mbr_sus = 0;
248                xdmadCfg.mbr_dus = 0;
249
250                xdmaCndc = 0;
251
252
253                /* Put all interrupts on for non LLI list setup of DMA */
254                xdmaInt =  (XDMAC_CIE_BIE   |
255                                        XDMAC_CIE_RBIE  |
256                                        XDMAC_CIE_WBIE  |
257                                        XDMAC_CIE_ROIE);
258
259                memory_barrier();
260
261                if (XDMAD_ConfigureTransfer(pQspidma->pXdmad, chanNum, &xdmadCfg, xdmaCndc, 0,
262                                                                         xdmaInt))
263                        return QSPID_ERROR;
264
265                return 0;
266        }
267}
268
269/*----------------------------------------------------------------------------
270 *        Exported functions
271 *----------------------------------------------------------------------------*/
272/**
273 * \brief Initializes the pQspidma structure and the corresponding QSPI & DMA .
274 * hardware select value.
275 *
276 * \param pQspidma  Pointer to a QspiDma_t instance.
277 * \param Mode      Associated SPI peripheral.
278 * \param dwConf    QSPI peripheral configuration.
279 * \param pXdmad    Pointer to a Xdmad instance.
280 */
281uint32_t QSPID_Configure(QspiDma_t *pQspidma, QspiMode_t Mode,
282                                                  uint32_t dwConf, sXdmad *pXdmad)
283{
284        /* Initialize the QSPI structure */
285
286        QSPI_ConfigureInterface(&pQspidma->Qspid, Mode, dwConf);
287
288        pQspidma->Qspid.qspiCommand.Instruction = 0;
289        pQspidma->Qspid.qspiCommand.Option = 0;
290
291        pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
292        pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
293
294        pQspidma->pXdmad = pXdmad;
295
296        /* XDMA Driver initialize */
297        XDMAD_Initialize(pQspidma->pXdmad, 0);
298
299        /* Configure and enable interrupt  */
300        NVIC_ClearPendingIRQ(XDMAC_IRQn);
301        NVIC_SetPriority(XDMAC_IRQn , 1);
302        NVIC_EnableIRQ(XDMAC_IRQn);
303
304
305        return QSPI_SUCCESS;
306}
307
308
309
310/**
311 * \brief Enables a QSPI Rx channel. This function will allocate a dma Rx
312 *  channel for QSPI
313 *
314 * \param pQspidma  Pointer to a Spid instance.
315
316 * \returns 0 if the transfer has been started successfully; otherwise returns
317 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is not
318 * valid.
319 */
320uint32_t QSPID_EnableQspiRxChannel(QspiDma_t *pQspidma)
321{
322        static uint16_t DmaChannel;
323
324        /* Try to get the semaphore */
325        if (pQspidma->RxChNum != QSPID_CH_NOT_ENABLED)
326                return QSPID_ERROR_LOCK;
327
328        /* Allocate a DMA channel */
329        DmaChannel = XDMAD_AllocateChannel(
330                                         pQspidma->pXdmad, XDMAD_TRANSFER_MEMORY, XDMAD_TRANSFER_MEMORY);
331
332        if (DmaChannel == XDMAD_ALLOC_FAILED)
333                return QSPID_ERROR;
334
335        pQspidma->RxChNum = DmaChannel;
336        /* Setup callbacks*/
337        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum,
338                                          (XdmadTransferCallback)QSPID_qspiRx_Cb, pQspidma);
339
340        if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->RxChNum))
341                return QSPID_ERROR;
342
343        return 0;
344}
345
346
347/**
348 * \brief Enables a QSPI Tx channel. This function will allocate a dma Tx
349 * channel for QSPI
350 *
351 * \param pQspidma  Pointer to a Spid instance.
352
353 * \returns 0 if the transfer has been started successfully; otherwise returns
354 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
355 * not valid.
356 */
357uint32_t QSPID_EnableQspiTxChannel(QspiDma_t *pQspidma)
358{
359        static uint16_t DmaChannel;
360
361        /* Try to get the  semaphore */
362        if (pQspidma->TxChNum != QSPID_CH_NOT_ENABLED)
363                return QSPID_ERROR_LOCK;
364
365        /* Allocate a DMA channel */
366        DmaChannel = XDMAD_AllocateChannel(pQspidma->pXdmad,
367                                                                                XDMAD_TRANSFER_MEMORY, XDMAD_TRANSFER_MEMORY);
368
369        if (DmaChannel == XDMAD_ALLOC_FAILED)
370                return QSPID_ERROR;
371
372        pQspidma->TxChNum = DmaChannel;
373        /* Setup callbacks  */
374        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum,
375                                          (XdmadTransferCallback)QSPID_qspiTx_Cb, pQspidma);
376
377        if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->TxChNum))
378                return QSPID_ERROR;
379
380        return 0;
381}
382
383
384/**
385 * \brief Enables a QSPI SPI Rx channel. This function will allocate a dma
386 *  Rx channel for QSPI SPI mode
387 *
388 * \param pQspidma  Pointer to a Spid instance.
389
390 * \returns 0 if the transfer has been started successfully; otherwise returns
391 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
392 * not valid.
393 */
394uint32_t QSPID_EnableSpiChannel(QspiDma_t *pQspidma)
395{
396        static uint16_t DmaChannel;
397
398        /* Try to get the semaphore */
399        if (pQspidma->RxChNum != QSPID_CH_NOT_ENABLED)
400                return QSPID_ERROR_LOCK;
401
402        /* Try to get the  semaphore */
403        if (pQspidma->TxChNum != QSPID_CH_NOT_ENABLED)
404                return QSPID_ERROR_LOCK;
405
406        /* Allocate a DMA channel */
407        DmaChannel = XDMAD_AllocateChannel
408                                 (pQspidma->pXdmad, pQspidma->Qspid.qspiId, XDMAD_TRANSFER_MEMORY);
409
410        if (DmaChannel == XDMAD_ALLOC_FAILED)
411                return QSPID_ERROR;
412
413        pQspidma->RxChNum = DmaChannel;
414
415        /* Allocate a DMA channel */
416        DmaChannel = XDMAD_AllocateChannel(pQspidma->pXdmad,
417                                                                                XDMAD_TRANSFER_MEMORY, pQspidma->Qspid.qspiId);
418
419        if (DmaChannel == XDMAD_ALLOC_FAILED)
420                return QSPID_ERROR;
421
422        pQspidma->TxChNum = DmaChannel;
423
424        /* Setup callbacks*/
425        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum,
426                                          (XdmadTransferCallback)QSPID_Spi_Cb, pQspidma);
427
428        if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->RxChNum))
429                return QSPID_ERROR;
430
431        /* Setup callbacks for SPI0/1 TX (ignored) */
432        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum, NULL, NULL);
433
434        if (XDMAD_PrepareChannel(pQspidma->pXdmad, pQspidma->TxChNum))
435                return QSPID_ERROR;
436
437        return 0;
438}
439
440
441/**
442 * \brief Disables a QSPI Rx channel. This function will de-allocate previous
443 *  allocated dma Rx channel for QSPI
444 *
445 * \param pQspidma  Pointer to a Spid instance.
446
447 * \returns 0 if the transfer has been started successfully; otherwise returns
448 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
449 * not valid.
450 */
451uint32_t QSPID_DisableQspiRxChannel(QspiDma_t *pQspidma)
452{
453
454        XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->RxChNum);
455        XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->RxChNum);
456
457        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum, NULL, NULL);
458
459
460        /* Free allocated DMA channel for QSPI RX. */
461        XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->RxChNum);
462
463        pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
464
465        return 0;
466}
467
468
469
470/**
471 * \brief Disables a QSPI Tx channel. This function will de-allocate previous
472 * allocated dma Tx channel for QSPI
473 *
474 * \param pQspidma  Pointer to a Spid instance.
475
476 * \returns 0 if the transfer has been started successfully; otherwise returns
477 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
478 * not valid.
479 */
480uint32_t QSPID_DisableQspiTxChannel(QspiDma_t *pQspidma)
481{
482
483        XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->TxChNum);
484        XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->TxChNum);
485
486        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->TxChNum, NULL, NULL);
487
488        /* Free allocated DMA channel for QSPI TX. */
489        XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->TxChNum);
490
491        pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
492
493        return 0;
494}
495
496
497/**
498 * \brief Disables a QSPI SPI Rx and Tx channels. This function will
499 *  de-allocate privious allocated dma Rx, Txchannel for QSPI in SPI mode
500 *
501 * \param pQspidma  Pointer to a Spid instance.
502
503 * \returns 0 if the transfer has been started successfully; otherwise returns
504 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
505 * not valid.
506 */
507uint32_t QSPID_DisableSpiChannel(QspiDma_t *pQspidma)
508{
509
510        XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->RxChNum);
511        //XDMAC_SoftwareFlushReq(pQspidma->pXdmad->pXdmacs, pQspidma->TxChNum);
512        XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->RxChNum);
513        XDMAD_StopTransfer(pQspidma->pXdmad, pQspidma->TxChNum);
514
515        XDMAD_SetCallback(pQspidma->pXdmad, pQspidma->RxChNum, NULL, NULL);
516
517        /* Free allocated DMA channel for QSPI RX. */
518        XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->RxChNum);
519
520        XDMAD_FreeChannel(pQspidma->pXdmad, pQspidma->TxChNum);
521
522        pQspidma->RxChNum = QSPID_CH_NOT_ENABLED;
523        pQspidma->TxChNum = QSPID_CH_NOT_ENABLED;
524
525        return 0;
526}
527
528
529/**
530 * \brief Starts a QSPI read or write operation.
531 *
532 * \param pQspidma  Pointer to a Qspid instance.
533 * \param ReadWrite Defines the memory access type
534 * \returns 0 if the transfer has been started successfully; otherwise returns
535 * QSPID_ERROR_LOCK is the driver is in use, or QSPID_ERROR if the command is
536 * not valid.
537 */
538uint32_t QSPID_ReadWriteQSPI(QspiDma_t *pQspidma, Access_t const ReadWrite)
539{
540        QspiBuffer_t *pBuffer = &pQspidma->Qspid.qspiBuffer;
541        uint8_t chanNum;
542        uint32_t semTimer = 0x7FF;
543
544        //assert(pBuffer->pDataTx);
545
546        if (pQspidma->progress)
547                return QSPID_ERROR_LOCK;
548
549        LockMutex(pQspidma->progress, semTimer);
550
551        if (QSPID_configureQpsiDma
552                (pQspidma, pQspidma->Qspid.pQspiFrame->Addr, pBuffer, ReadWrite))
553                return QSPID_ERROR_LOCK;
554
555        if (ReadWrite == WriteAccess) {
556                chanNum =  pQspidma->TxChNum;
557                SCB_CleanDCache_by_Addr((uint32_t *)pBuffer->pDataTx, pBuffer->TxDataSize);
558        } else if (ReadWrite == ReadAccess)
559                chanNum =  pQspidma->RxChNum;
560        else
561                TRACE_ERROR("%s QSPI Access Error\n\r", __FUNCTION__);
562
563        /* Start DMA 0(RX) && 1(TX) */
564        if (XDMAD_StartTransfer(pQspidma->pXdmad, chanNum))
565                return QSPID_ERROR_LOCK;
566
567        return 0;
568}
569
570/**
571 * \brief Starts a SPI master transfer. This is a non blocking function. It will
572 *  return as soon as the transfer is started.
573 *
574 * \param pSpid  Pointer to a Spid instance.
575 * \param pCommand Pointer to the SPI command to execute.
576 * \returns 0 if the transfer has been started successfully; otherwise returns
577 * SPID_ERROR_LOCK is the driver is in use, or SPID_ERROR if the command is not
578 * valid.
579 */
580uint32_t QSPID_ReadWriteSPI(QspiDma_t *pQspidma, Access_t const ReadWrite)
581{
582        QspiBuffer_t *pBuffer = &pQspidma->Qspid.qspiBuffer;
583        uint32_t semTimer = 0x7FF;
584
585        assert(pBuffer->pDataRx);
586        assert(pBuffer->pDataTx);
587
588        /* Try to get the dataflash semaphore */
589        if (pQspidma->progress)
590
591                return QSPID_ERROR_LOCK;
592
593        LockMutex(pQspidma->progress, semTimer);
594
595        if (QSPID_configureQpsiDma
596                (pQspidma, pQspidma->Qspid.pQspiFrame->Addr, pBuffer, ReadWrite))
597                return QSPID_ERROR_LOCK;
598
599        SCB_CleanDCache_by_Addr((uint32_t *)pBuffer->pDataTx, pBuffer->TxDataSize);
600
601        /* Start DMA 0(RX) && 1(TX) */
602        if (XDMAD_StartTransfer(pQspidma->pXdmad, pQspidma->RxChNum))
603                return QSPID_ERROR_LOCK;
604
605        if (XDMAD_StartTransfer(pQspidma->pXdmad, pQspidma->TxChNum))
606                return QSPID_ERROR_LOCK;
607
608        return 0;
609}
610
611/**
612 * \brief Check if the QSPI driver is busy.
613 *
614 * \param pSpid  Pointer to a Spid instance.
615 * \returns 1 if the SPI driver is currently busy executing a command; otherwise
616 */
617uint32_t QSPID_IsBusy(volatile uint8_t *QspiSemaphore)
618{
619        if (Is_LockFree(QspiSemaphore))
620                return 1;
621        else
622                return 0;
623}
Note: See TracBrowser for help on using the repository browser.