source: rtems/c/src/lib/libbsp/arm/atsam/libraries/libchip/source/qspi.c @ 0fddefe

Last change on this file since 0fddefe was 0fddefe, checked in by Alexander Krutwig <alexander.krutwig@…>, on Jun 8, 2016 at 7:55:53 AM

bsp/atsam: Fix QSPI driver API

We support read/write of arbitrary buffers.

  • Property mode set to 100644
File size: 20.5 KB
RevLine 
[e1eeb883]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/** \addtogroup qspi_module Working with QSPI
31 * \ingroup peripherals_module
32 * The QSPI driver provides the interface to configure and use the QSPI
33 * peripheral.
34 *
35 * The Serial Peripheral Interface (QSPI) circuit is a synchronous serial
36 * data link that provides communication with external devices in Master
37 * or Slave Mode.
38 *
39 * To use the QSPI, the user has to follow these few steps:
40 * -# Enable the QSPI pins required by the application (see pio.h).
41 * -# Configure the QSPI using the \ref QSPI_Configure(). This enables the
42 *    peripheral clock. The mode register is loaded with the given value.
43 * -# Configure all the necessary chip selects with \ref QSPI_ConfigureNPCS().
44 * -# Enable the QSPI by calling \ref QSPI_Enable().
45 * -# Send/receive data using \ref QSPI_Write() and \ref QSPI_Read(). Note that
46*  \ref QSPI_Read()
47 *    must be called after \ref QSPI_Write() to retrieve the last value read.
48 * -# Send/receive data using the PDC with the \ref QSPI_WriteBuffer() and
49 *    \ref QSPI_ReadBuffer() functions.
50 * -# Disable the QSPI by calling \ref QSPI_Disable().
51 *
52 * For more accurate information, please look at the QSPI section of the
53 * Datasheet.
54 *
55 * Related files :\n
56 * \ref qspi.c\n
57 * \ref qspi.h.\n
58 */
59/*@{*/
60/*@}*/
61
62/**
63 * \file
64 *
65 * Implementation of Serial Peripheral Interface (QSPI) controller.
66 *
67 */
68
69/*----------------------------------------------------------------------------
70 *        Headers
71 *----------------------------------------------------------------------------*/
72
73#include "chip.h"
74#include "stdlib.h"
75#include "string.h"
76
77#include <stdint.h>
78
79
80#define SCRAMBLE_KEY    0x0BADDEAD
81/*----------------------------------------------------------------------------
82 *        Internal functions
83 *----------------------------------------------------------------------------*/
84
85
86
87/**
88 * \brief Configure QSPI/SPI mode
89 *
90 * \param pQspi  Pointer to a Qspi instance.
91 */
92__STATIC_INLINE void QSPI_ConfigureMode(Qspi *pQspi, uint8_t dMode)
93{
94        assert(pQspi);
95        pQspi->QSPI_MR =  dMode;
96}
97
98/**
99 * \brief Configure mode register of QSPI
100 *
101 * \param pQspi  Pointer to a Qspi instance.
102 */
103__STATIC_INLINE void QSPI_Configure(Qspi *pQspi, uint32_t dwConfiguration)
104{
105        assert(pQspi);
106        pQspi->QSPI_MR |=  dwConfiguration;
107}
108
109
110/**
111 * \brief Configures a instruction address for QSPI in QSPI mode
112 *
113 * \param pQspi   Pointer to a Qspi instance.
114 * \param dwAddr  Instruction Address
115 */
116__STATIC_INLINE void QSPI_SetInstAddr(Qspi *pQspi, uint32_t dwAddr)
117{
118        assert(pQspi);
119        pQspi->QSPI_IAR = dwAddr;
120}
121
122
123/**
124 * \brief Configures instruction register with a given command for QSPI
125 *
126 * \param pQspi   Pointer to a Qspi instance.
127 * \param dwInst  Instruction Code
128 * \param dwOpt   Instruction Code option
129 */
130__STATIC_INLINE void QSPI_SetInst(Qspi *pQspi, uint8_t dwInst, uint8_t dwOpt)
131{
132        assert(pQspi);
133        pQspi->QSPI_ICR = (dwInst | QSPI_ICR_OPT(dwOpt));
134}
135
136/**
137 * \brief Configures instruction frame register of QSPI
138 *
139 * \param pQspi         Pointer to a Qspi instance.
140 * \param pInstFrame    Instruction Frame configuration
141 */
142__STATIC_INLINE void QSPI_SetInstFrame(Qspi *pQspi,
143                                                                                QspiInstFrame_t *pInstFrame)
144{
145        assert(pQspi);
146        pQspi->QSPI_IFR = pInstFrame->InstFrame.val;
147}
148
149/**
150 * \brief Reads the Instruction frame of QSPI
151 *
152 * \param pQspi   Pointer to an Qspi instance.
153 */
154__STATIC_INLINE uint32_t QSPI_GetInstFrame(Qspi *pQspi)
155{
156        assert(pQspi);
157        return pQspi->QSPI_IFR;
158}
159
160/**
161 * \brief Read QSPI RDR register for SPI mode
162 *
163 * \param pQspi   Pointer to an Qspi instance.
164 */
165__STATIC_INLINE uint16_t QSPI_ReadSPI(Qspi *pQspi)
166{
167        assert(pQspi);
168
169        while (!QSPI_GetStatus(pQspi, IsReceived));
170
171        return  pQspi->QSPI_RDR;
172}
173
174
175/**
176 * \brief Write to QSPI Tx register in SPI mode
177 *
178 * \param pQspi   Pointer to an Qspi instance.
179 * \param wData   Data to transmit
180 */
181__STATIC_INLINE void QSPI_WriteSPI(Qspi *pQspi, uint16_t wData)
182{
183        assert(pQspi);
184
185        /* Send data */
186        while (!QSPI_GetStatus(pQspi, IsTxEmpty));
187
188        pQspi->QSPI_TDR = wData;
189
190        while (!QSPI_GetStatus(pQspi, IsTxSent));
191}
192
193/**
194 * \brief Configures QSPI scrambling with a given Key
195 *
196 * \param pQspi         Pointer to an Qspi instance.
197 * \param wKey          Key for scramble/unscramble
198 * \param EnableFlag    Enable/disable scramble
199 * \param Random        Add random value with given key
200 */
201__STATIC_INLINE void QSPI_ScrambleData(Qspi *pQspi, uint32_t wKey,
202                                                                                uint8_t EnableFlag, uint8_t Random)
203{
204        assert(pQspi);
205        assert(EnableFlag < 2);
206        assert(Random < 2);
207
208        if (EnableFlag)
209                pQspi->QSPI_SKR = wKey;
210
211        pQspi->QSPI_SMR = (EnableFlag | (Random << 1));
212}
213
[033443c]214static void do_copy(uint8_t *dst, const uint8_t *src, size_t n, bool aligned)
215{
216        if (aligned) {
217                while (n > 3) {
218                        *(uint32_t *)dst = *(uint32_t *)src;
219                        dst += 4;
220                        src += 4;
221                        n -= 4;
222                }
223        }
224
225        while (n > 0) {
226                *dst = *src;
227                ++dst;
228                ++src;
229                --n;
230        }
231}
232
233static void copy_to_io(void *dst, const void *src, size_t n)
234{
235        do_copy(dst, src, n, ((uintptr_t)dst) % 4 == 0);
236}
237
238static void copy_from_io(void *dst, const void *src, size_t n)
239{
240        do_copy(dst, src, n, ((uintptr_t)src) % 4 == 0);
241}
242
[e1eeb883]243/*----------------------------------------------------------------------------
244 *        Exported functions
245 *----------------------------------------------------------------------------*/
246
247/**
248 * \brief Enables a QSPI peripheral.
249 *
250 * \param pQspi  Pointer to a Qspi instance.
251 */
252void QSPI_Enable(Qspi *pQspi)
253{
254        assert(pQspi);
255        pQspi->QSPI_CR = QSPI_CR_QSPIEN;
256
257        while (!(pQspi->QSPI_SR & QSPI_SR_QSPIENS));
258}
259
260/**
261 * \brief Disables a QSPI peripheral.
262 *
263 * \param pQspi  Pointer to a Qspi instance.
264 */
265void QSPI_Disable(Qspi *pQspi)
266{
267        assert(pQspi);
268        pQspi->QSPI_CR = QSPI_CR_QSPIDIS;
269
270        while (pQspi->QSPI_SR & QSPI_SR_QSPIENS);
271}
272
273/**
274 * \brief Resets a QSPI peripheral.
275 *
276 * \param pQspi  Pointer to a Qspi instance.
277 */
278void QSPI_SwReset(Qspi *pQspi)
279{
280        assert(pQspi);
281        pQspi->QSPI_CR = QSPI_CR_SWRST;
282}
283
284/**
285 * \brief Enables one or more interrupt sources of a QSPI peripheral.
286 *
287 * \param pQspi  Pointer to a Qspi instance.
288 * \param sources Bitwise OR of selected interrupt sources.
289 */
290QspidStatus_t QSPI_EnableIt(Qspi *pQspi, uint32_t dwSources)
291{
292        assert(pQspi);
293        pQspi->QSPI_IER = dwSources;
294        return QSPI_SUCCESS;
295}
296
297/**
298 * \brief Disables one or more interrupt sources of a QSPI peripheral.
299 *
300 * \param pQspi  Pointer to a Qspi instance.
301 * \param sources Bitwise OR of selected interrupt sources.
302 */
303QspidStatus_t QSPI_DisableIt(Qspi *pQspi, uint32_t dwSources)
304{
305        assert(pQspi);
306        pQspi->QSPI_IDR = dwSources;
307        return QSPI_SUCCESS;
308}
309
310/**
311 * \brief Return the interrupt mask register.
312 *
313 * \return Qspi interrupt mask register.
314 */
315uint32_t QSPI_GetItMask(Qspi *pQspi)
316{
317        assert(pQspi);
318        return (pQspi->QSPI_IMR);
319}
320
321/**
322 * \brief Returns enabled interrupt status
323 *
324 * \return Qspi interrupt mask register.
325 */
326uint32_t QSPI_GetEnabledItStatus(Qspi *pQspi)
327{
328        assert(pQspi);
329        return (pQspi->QSPI_IMR & QSPI_GetStatus(pQspi, (QspiStatus_t)0xFFFFFFFF));
330}
331
332/**
333 * \brief Get the current status register of the given QSPI peripheral.
334 * \note This resets the internal value of the status register, so further
335 * read may yield different values.
336 * \param pQspi   Pointer to a Qspi instance.
337 * \param rStatus Compare status with given status bit
338 * \return  QSPI status register.
339 */
340uint32_t QSPI_GetStatus(Qspi *pQspi, const QspiStatus_t rStatus)
341{
342        assert(pQspi);
343        return (pQspi->QSPI_SR & rStatus);
344}
345
346/**
347 * \brief Configures peripheral clock of a QSPI/SPI peripheral.
348 *
349 * \param pQspi   Pointer to an Qspi instance.
350 * \param dwConfiguration  Desired clock configuration.
351 */
352void QSPI_ConfigureClock(Qspi *pQspi, QspiClockMode_t ClockMode,
353                                                  uint32_t dwClockCfg)
354{
355        assert(pQspi);
356        pQspi->QSPI_SCR = ClockMode;
357        pQspi->QSPI_SCR |= dwClockCfg;
358}
359
360/**
361 * \brief Configures QSPI/SPI
362 *
363 * \param pQspi             Pointer to an Qspi instance.
364 * \param Mode              Mode for QSPI or SPI
365 * \param dwConfiguration   Config of SPI or QSPI mode
366 */
367QspidStatus_t QSPI_ConfigureInterface(Qspid_t *pQspid, QspiMode_t Mode,
368                                                                           uint32_t dwConfiguration)
369{
370        pQspid->pQspiHw = QSPI;
371        pQspid->qspiId = ID_QSPI;
372
373        QSPI_Disable(pQspid->pQspiHw);
374        QSPI_SwReset(pQspid->pQspiHw);
375
376        QSPI_ConfigureMode(pQspid->pQspiHw, Mode);
377        QSPI_Configure(pQspid->pQspiHw, dwConfiguration);
378
379        return QSPI_SUCCESS;
380}
381
382
383/**
384 * \brief Ends ongoing transfer by releasing CS of QSPI peripheral.
385 *
386 * \param pQspi  Pointer to an Qspi instance.
387 */
388QspidStatus_t QSPI_EndTransfer(Qspi *pQspi)
389{
390        assert(pQspi);
391
392        while (!QSPI_GetStatus(pQspi, IsTxEmpty));
393
394        pQspi->QSPI_CR = QSPI_CR_LASTXFER;
395
396        return QSPI_SUCCESS;
397}
398
399
400/*----------------------------------------------------------------------------
401 *        SPI functions
402 *----------------------------------------------------------------------------*/
403/**
404 * \brief Reads the data received by a SPI peripheral. This
405 * method must be called after a successful SPI_Write call.
406 *
407 * \param pQspid    Pointer to a Qspi instance.
408 * \param pData     Buffer to put read value
409 * \return Qspi status
410 */
411QspidStatus_t QSPI_SingleReadSPI(Qspid_t *pQspid, uint16_t *const pData)
412{
413        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
414        Qspi *pQspi = pQspid->pQspiHw;
415        uint32_t NumOfAttempt = 0;
416        uint16_t Dummy = 0xFF;
417
418        for (;;) {
419                if (QSPI_GetStatus(pQspi, IsReceived)) {
420                        *pData = QSPI_ReadSPI(pQspi);
421                        QSPI_WriteSPI(pQspi, Dummy);
422                        *pData = QSPI_ReadSPI(pQspi);
423                        NumOfAttempt = 0;
424                        Status = QSPI_SUCCESS;
425                } else {
426                        if (NumOfAttempt > 0xFFFF) {
427                                Status = QSPI_READ_ERROR;
428                                TRACE_ERROR(" SPI Read Error \n\r");
429                                break;
430                        } else {
431                                Status = QSPI_READ_ERROR;
432                                NumOfAttempt++;
433                        }
434                }
435        }
436
437        return Status;
438}
439
440/**
441 * \brief Reads multiple data received by a SPI peripheral. This
442 * method must be called after a successful SPI_Write call.
443 *
444 * \param pQspid        Pointer to a Qspi instance.
445 * \param pData         Pointer to read buffer
446 * \param NumOfBytes    Num of bytes to read
447 *
448 * \return Qspi status
449 */
450QspidStatus_t QSPI_MultiReadSPI(Qspid_t *pQspid, uint16_t *const pData,
451                                                                 uint32_t NumOfBytes)
452{
453        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
454        Qspi *pQspi = pQspid->pQspiHw;
455        uint32_t NumOfBytesRead = 0;
456        uint32_t NumOfAttempt = 0;
457        uint8_t *pwData = (uint8_t *)pData;
458        uint16_t Dummy = 0xFF;
459
460        /* Dummy read  and write to discard  first bytes recvd and start
461            receiving new data*/
462        Dummy = QSPI_ReadSPI(pQspi);
463        QSPI_WriteSPI(pQspi, Dummy);
464
465        for (; NumOfBytesRead < NumOfBytes;) {
466                if (QSPI_GetStatus(pQspi, IsTxSent)) {
467                        *pwData = QSPI_ReadSPI(pQspi);
468
469                        if (pQspi->QSPI_MR & QSPI_MR_NBBITS_Msk)
470                                pwData += sizeof(uint16_t);
471                        else
472                                pwData += sizeof(uint8_t);
473
474                        NumOfBytesRead++;
475                        NumOfAttempt = 0;
476                        Status = QSPI_SUCCESS;
477                        QSPI_WriteSPI(pQspi, Dummy);
478                } else {
479                        if (NumOfAttempt > 0xFFFF) {
480                                Status = QSPI_READ_ERROR;
481                                TRACE_ERROR(" SPI MultiRead Error \n\r");
482                                break;
483                        } else {
484                                Status = QSPI_READ_ERROR;
485                                NumOfAttempt++;
486                        }
487                }
488        }
489
490        return Status;
491}
492
493/**
494 * \brief Sends a single data through a SPI peripheral.
495 *
496 * \param pQspid    Pointer to a Qspi instance.
497 * \param pData     Pointer to Tx data
498 *
499 * \return Qspi status
500 */
501QspidStatus_t QSPI_SingleWriteSPI(Qspid_t *pQspid, uint16_t const *pData)
502{
503        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
504        Qspi *pQspi = pQspid->pQspiHw;
505        uint32_t NumOfAttempt = 0;
506
507        for (;;) {
508                if (QSPI_GetStatus(pQspi, IsTxSent)) {
509                        QSPI_WriteSPI(pQspi, *pData);
510                        NumOfAttempt = 0;
511                        Status = QSPI_SUCCESS;
512                        break;
513                } else {
514                        Status = QSPI_BUSY_SENDING;
515                        NumOfAttempt++;
516
517                        if (NumOfAttempt > 0xFFFF) {
518                                Status = QSPI_WRITE_ERROR;
519                                TRACE_ERROR(" SPI Write Error \n\r");
520                                break;
521                        }
522                }
523        }
524
525        return Status;
526
527}
528
529/**
530 * \brief Sends multiple data through a SPI peripheral.
531 *
532 * \param pQspid        Pointer to a Qspi instance.
533 * \param pData         Pointer to a Tx buffer
534 * \param NumOfBytes    Num of data to send.
535 */
536QspidStatus_t QSPI_MultiWriteSPI(Qspid_t *pQspid, uint16_t const *pData,
537                                                                  uint32_t NumOfBytes)
538{
539        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
540        Qspi *pQspi = pQspid->pQspiHw;
541        uint32_t NumOfBytesWrite = 0;
542        uint32_t NumOfAttempt = 0;
543        uint8_t *pwData = (uint8_t *)pData;
544        uint8_t Addr_Inc = 0;
545
546        if (pQspi->QSPI_MR & QSPI_MR_NBBITS_Msk)
547                Addr_Inc = sizeof(uint16_t);
548        else
549                Addr_Inc = sizeof(uint8_t);
550
551        for (; NumOfBytesWrite < NumOfBytes;) {
552                if (QSPI_GetStatus(pQspi, IsTxEmpty)) {
553                        QSPI_WriteSPI(pQspi, (uint16_t)*pwData);
554                        pwData += Addr_Inc;
555                        NumOfBytesWrite++;
556                        NumOfAttempt = 0;
557                        Status = QSPI_SUCCESS;
558                } else {
559                        Status = QSPI_BUSY_SENDING;
560                        NumOfAttempt++;
561
562                        if (NumOfAttempt > 0xFFFF) {
563                                Status = QSPI_WRITE_ERROR;
564                                TRACE_ERROR(" SPI Multi Write Error \n\r");
565                                break;
566                        }
567                }
568        }
569
570        return Status;
571
572}
573
574/*----------------------------------------------------------------------------
575 *        QSPI functions
576 *----------------------------------------------------------------------------*/
577
578/**
579 * \brief Send an instruction over QSPI (oly a flash command no data)
580 *
581 * \param pQspi     Pointer to an Qspi instance.
582 * \param KeepCfg   To keep Instruction fram value or restes to zero
583 *
584 * \return Returns 1 if At least one instruction end has been detected since
585 * the last read of QSPI_SR.; otherwise
586 * returns 0.
587 */
588QspidStatus_t QSPI_SendCommand(Qspid_t *pQspid, uint8_t const KeepCfg)
589{
590        QspiInstFrame_t  *const pFrame = pQspid->pQspiFrame;
591        QspiMemCmd_t  pCommand = pQspid->qspiCommand;
592        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
593
594        if (pFrame->InstFrame.bm.bAddrEn)
595                QSPI_SetInstAddr(pQspid->pQspiHw, pFrame->Addr);
596
597        QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
598                                 ((pCommand.Option >> QSPI_ICR_OPT_Pos) & 0xFF));
599        QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
600
601        memory_sync();
602
603        while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
604
605        // poll CR reg to know status if instruction has end
606        if (!KeepCfg)
607                pFrame->InstFrame.val = 0;
608
609        return Status;
610}
611
612
613
614/**
615 * \brief Send instruction over QSPI with data
616 *
617 * \param pQspi     Pointer to an Qspi instance.
618 * \param KeepCfg   To keep Instruction fram value or restes to zero
619 *
620 * \return Returns 1 if At least one instruction end has been detected
621 *  since the last read of QSPI_SR.; otherwise returns 0.
622 */
623QspidStatus_t QSPI_SendCommandWithData(Qspid_t *pQspid, uint8_t const KeepCfg)
624{
625        QspiInstFrame_t *const  pFrame = pQspid->pQspiFrame;
626        QspiMemCmd_t  pCommand = pQspid->qspiCommand;
627        QspiBuffer_t    pBuffer     =  pQspid->qspiBuffer;
628        uint32_t *pQspiBuffer = (uint32_t *)QSPIMEM_ADDR;
629        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
630
631        //assert(pBuffer.pDataRx);
632        assert(pBuffer.pDataTx);
633
634        QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
635                                 (pCommand.Option & 0xFF));
636        QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
637
638        QSPI_GetInstFrame(pQspid->pQspiHw);
639
640        // to synchronize system bus accesses
641        if (!KeepCfg)
642                pFrame->InstFrame.val = 0;
643
644        memcpy(pQspiBuffer  , pBuffer.pDataTx ,  pBuffer.TxDataSize);
645        memory_sync();
646        QSPI_EndTransfer(pQspid->pQspiHw);
647
648        // End transmission after all data has been sent
649        while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
650
651        // poll CR reg to know status if instruction has end
652
653        return Status;
654}
655
656/**
657 * \brief Send instruction over QSPI to read data
658 *
659 * \param pQspi     Pointer to an Qspi instance.
660 * \param KeepCfg   To keep Instruction from value or resets to zero
661 *
662 * \return Returns 1 if At least one instruction end has been detected
663 * since the last read of QSPI_SR.; otherwise returns 0.
664 */
665QspidStatus_t QSPI_ReadCommand(Qspid_t *pQspid, uint8_t const KeepCfg)
666{
667        QspiInstFrame_t *const  pFrame = pQspid->pQspiFrame;
668        QspiMemCmd_t  pCommand = pQspid->qspiCommand;
669        QspiBuffer_t    pBuffer     =  pQspid->qspiBuffer;
670        uint32_t *pQspiBuffer = (uint32_t *)QSPIMEM_ADDR;
671        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
672
673        assert(pBuffer.pDataRx);
674
675        QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
676                                 (pCommand.Option & 0xFF));
677        QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
678
679        QSPI_GetInstFrame(pQspid->pQspiHw);
680
681        // to synchronize system bus accesses
682        if (!KeepCfg)
683                pFrame->InstFrame.val = 0;
684
685        memcpy(pBuffer.pDataRx , pQspiBuffer,  pBuffer.RxDataSize);
686        memory_sync();
687        QSPI_EndTransfer(pQspid->pQspiHw);
688
689        // End transmission after all data has been sent
690        while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
691
692        // poll CR reg to know status if instruction has end
693
694        return Status;
695}
696
697/**
698 * \brief Sends an instruction over QSPI and configures other related address
699*  like Addr , Frame and synchronise bus access before data read or write
700 *
701 * \param pQspi         Pointer to an Qspi instance.
702 * \param KeepCfg       To keep Instruction from value or resets to zero
703 * \param ScrambleFlag  Enable or disable scramble on QSPI
704 *
705 * \return Returns 1 if At least one instruction end has been detected since
706 * the last read of QSPI_SR.; otherwise returns 0.
707 */
708QspidStatus_t QSPI_EnableMemAccess(Qspid_t *pQspid, uint8_t const KeepCfg,
709                                                                        uint8_t ScrambleFlag)
710{
711        QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
712        QspiMemCmd_t  pCommand = pQspid->qspiCommand;
713
714        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
715
716        QSPI_SetInst(pQspid->pQspiHw, (pCommand.Instruction & 0xFF),
717                                 (pCommand.Option & 0xFF));
718
719        if (ScrambleFlag)
720                QSPI_ScrambleData(pQspid->pQspiHw, SCRAMBLE_KEY, ScrambleFlag, 1);
721
722        QSPI_SetInstFrame(pQspid->pQspiHw, pFrame);
723
724        QSPI_GetInstFrame(pQspid->pQspiHw);
725
726        // to synchronize system bus accesses
727        if (!KeepCfg)
728                pFrame->InstFrame.val = 0;
729
730        Status = QSPI_SUCCESS;
731        return Status;
732}
733
734/**
735 * \brief Writes or reads the QSPI memory (0x80000000) to transmit or
736 * receive data from Flash memory
737 * \param pQspi         Pointer to an Qspi instance.
738 * \param ReadWrite     Flag to indicate read/write QSPI memory access
739 *
740 * \return Returns 1 if At least one instruction end has been detected since
741 * the last read of QSPI_SR.; otherwise returns 0.
742 */
743QspidStatus_t QSPI_ReadWriteMem(Qspid_t *pQspid, Access_t const ReadWrite)
744{
745        QspidStatus_t Status = QSPI_UNKNOWN_ERROR;
746        QspiInstFrame_t *const pFrame = pQspid->pQspiFrame;
[0fddefe]747        void *pQspiMem = (void *)(QSPIMEM_ADDR | pFrame->Addr);
[e1eeb883]748        QspiBuffer_t    pBuffer     =  pQspid->qspiBuffer;
749
750        assert(((ReadWrite > CmdAccess)
751                          && (ReadWrite <= WriteAccess)) ? true : false);
752
[033443c]753        if (ReadWrite == WriteAccess) {
754                copy_to_io(pQspiMem, pBuffer.pDataTx , pBuffer.TxDataSize);
755        } else {
756                copy_from_io(pBuffer.pDataRx, pQspiMem, pBuffer.RxDataSize);
757        }
[e1eeb883]758        memory_sync();
759        QSPI_EndTransfer(pQspid->pQspiHw);
760
761        // End transmission after all data has been sent
762        while (!(pQspid->pQspiHw->QSPI_SR & QSPI_SR_INSTRE));
763
764        // poll CR reg to know status if instruction has end
765
766        Status = QSPI_SUCCESS;
767        return Status;
768}
Note: See TracBrowser for help on using the repository browser.