source: rtems/bsps/arm/atsam/contrib/libraries/libchip/source/qspi.c @ 54aabb7

5
Last change on this file since 54aabb7 was 54aabb7, checked in by Sebastian Huber <sebastian.huber@…>, on 04/22/18 at 13:11:43

bsp/atsam: Move libraries to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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