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

5
Last change on this file since 4aba8d79 was 4aba8d79, checked in by Sebastian Huber <sebastian.huber@…>, on 12/16/16 at 12:05:34

bsp/atsam: Use standard XDMA for QSPI support

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