]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libchip_samv7/source/qspi.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libchip_samv7 / source / qspi.c
1 /* ----------------------------------------------------------------------------\r
2  *         ATMEL Microcontroller Software Support\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2010, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /** \addtogroup spi_module Working with QSPI\r
31  * \ingroup peripherals_module\r
32  * The QSPI driver provides the interface to configure and use the QSPI\r
33  * peripheral.\r
34  *\r
35  * The Serial Peripheral Interface (QSPI) circuit is a synchronous serial\r
36  * data link that provides communication with external devices in Master\r
37  * or Slave Mode.\r
38  *\r
39  * To use the QSPI, the user has to follow these few steps:\r
40  * -# Enable the QSPI pins required by the application (see pio.h).\r
41  * -# Configure the QSPI using the \ref QSPI_Configure(). This enables the\r
42  *    peripheral clock. The mode register is loaded with the given value.\r
43  * -# Configure all the necessary chip selects with \ref QSPI_ConfigureNPCS().\r
44  * -# Enable the QSPI by calling \ref QSPI_Enable().\r
45  * -# Send/receive data using \ref QSPI_Write() and \ref QSPI_Read(). Note that \ref QSPI_Read()\r
46  *    must be called after \ref QSPI_Write() to retrieve the last value read.\r
47  * -# Send/receive data using the PDC with the \ref QSPI_WriteBuffer() and\r
48  *    \ref QSPI_ReadBuffer() functions.\r
49  * -# Disable the QSPI by calling \ref QSPI_Disable().\r
50  *\r
51  * For more accurate information, please look at the QSPI section of the\r
52  * Datasheet.\r
53  *\r
54  * Related files :\n\r
55  * \ref qspi.c\n\r
56  * \ref qspi.h.\n\r
57  */\r
58 /*@{*/\r
59 /*@}*/\r
60 \r
61 /**\r
62  * \file\r
63  *\r
64  * Implementation of Serial Peripheral Interface (QSPI) controller.\r
65  *\r
66  */\r
67 \r
68 /*----------------------------------------------------------------------------\r
69  *        Headers\r
70  *----------------------------------------------------------------------------*/\r
71 \r
72 #include "chip.h"\r
73 #include "stdlib.h"\r
74 #include "string.h"   \r
75 \r
76 #include <stdint.h>\r
77 \r
78 \r
79 \r
80 volatile uint8_t INSTRE_Flag =0;\r
81 /*----------------------------------------------------------------------------\r
82  *        Exported functions\r
83  *----------------------------------------------------------------------------*/\r
84 \r
85 /**\r
86  * \brief Enables a QSPI peripheral.\r
87  *\r
88  * \param qspi  Pointer to an Qspi instance.\r
89  */\r
90 extern void QSPI_Enable( Qspi* qspi )\r
91 {\r
92     qspi->QSPI_CR = QSPI_CR_QSPIEN ;\r
93     while(!(qspi->QSPI_SR & QSPI_SR_QSPIENS));\r
94 }\r
95 \r
96 /**\r
97  * \brief Disables a SPI peripheral.\r
98  *\r
99  * \param qspi  Pointer to an Qspi instance.\r
100  */\r
101 extern void QSPI_Disable( Qspi* qspi )\r
102 {\r
103     qspi->QSPI_CR = QSPI_CR_QSPIDIS ;\r
104 }\r
105 \r
106 /**\r
107  * \brief Reset a QSPI peripheral.\r
108  *\r
109  * \param qspi  Pointer to an Qspi instance.\r
110  */\r
111 extern void QSPI_SwReset( Qspi* qspi )\r
112 {\r
113     qspi->QSPI_CR = QSPI_CR_SWRST ;\r
114     qspi->QSPI_CR = QSPI_CR_SWRST ;\r
115 }\r
116 \r
117 /**\r
118  * \brief Enables one or more interrupt sources of a QSPI peripheral.\r
119  *\r
120  * \param qspi  Pointer to an Qspi instance.\r
121  * \param sources Bitwise OR of selected interrupt sources.\r
122  */\r
123 extern void QSPI_EnableIt( Qspi* qspi, uint32_t dwSources )\r
124 {\r
125     qspi->QSPI_IER = dwSources ;\r
126 }\r
127 \r
128 /**\r
129  * \brief Disables one or more interrupt sources of a QSPI peripheral.\r
130  *\r
131  * \param qspi  Pointer to an Qspi instance.\r
132  * \param sources Bitwise OR of selected interrupt sources.\r
133  */\r
134 extern void QSPI_DisableIt( Qspi* qspi, uint32_t dwSources )\r
135 {\r
136     qspi->QSPI_IDR = dwSources ;\r
137 }\r
138 \r
139 /**\r
140  * \brief Return the interrupt mask register.\r
141  *\r
142  * \return Qspi interrupt mask register.\r
143  */\r
144 extern uint32_t QSPI_GetItMask( Qspi* qspi )\r
145 {\r
146     return (qspi->QSPI_IMR) ;\r
147 }\r
148 \r
149 /**\r
150  * \brief Configures a QSPI peripheral as specified. The configuration can be computed\r
151  * using several macros (see \ref spi_configuration_macros).\r
152  *\r
153  * \param qspi  Pointer to an Qspi instance.\r
154  * \param id   Peripheral ID of the QSPI.\r
155  * \param configuration  Value of the QSPI configuration register.\r
156  */\r
157 extern void QSPI_Configure( Qspi* qspi, uint32_t dwConfiguration )\r
158 {\r
159     qspi->QSPI_CR = QSPI_CR_QSPIDIS ;\r
160 \r
161     /* Execute a software reset of the QSPI twice */\r
162     QSPI_SwReset(qspi);\r
163     qspi->QSPI_MR = dwConfiguration ;\r
164 }\r
165 \r
166 \r
167 /**\r
168  * \brief Configures a chip select of a QSPI peripheral. The chip select configuration\r
169  * is computed using several macros (see \ref spi_configuration_macros).\r
170  *\r
171  * \param qspi   Pointer to an Qspi instance.\r
172  * \param npcs  Chip select to configure (0, 1, 2 or 3).\r
173  * \param configuration  Desired chip select configuration.\r
174  */\r
175 void QSPI_ConfigureClock( Qspi* qspi,uint32_t dwConfiguration )\r
176 {\r
177     qspi->QSPI_SCR = dwConfiguration ;\r
178 }\r
179 \r
180 /**\r
181  * \brief Get the current status register of the given QSPI peripheral.\r
182  * \note This resets the internal value of the status register, so further\r
183  * read may yield different values.\r
184  * \param qspi   Pointer to a Qspi instance.\r
185  * \return  QSPI status register.\r
186  */\r
187 extern uint32_t QSPI_GetStatus( Qspi* qspi )\r
188 {\r
189     return qspi->QSPI_SR ;\r
190 }\r
191 \r
192 /**\r
193  * \brief Reads and returns the last word of data received by a SPI peripheral. This\r
194  * method must be called after a successful SPI_Write call.\r
195  *\r
196  * \param spi  Pointer to an Spi instance.\r
197  *\r
198  * \return readed data.\r
199  */\r
200 extern uint32_t QSPI_Read( Qspi* qspi )\r
201 {\r
202     while ( (qspi->QSPI_SR & SPI_SR_RDRF) == 0 ) ;\r
203 \r
204     return qspi->QSPI_RDR & 0xFFFF ;\r
205 }\r
206 \r
207 /**\r
208  * \brief Sends data through a SPI peripheral. If the SPI is configured to use a fixed\r
209  * peripheral select, the npcs value is meaningless. Otherwise, it identifies\r
210  * the component which shall be addressed.\r
211  *\r
212  * \param spi   Pointer to an Spi instance.\r
213  * \param npcs  Chip select of the component to address (0, 1, 2 or 3).\r
214  * \param data  Word of data to send.\r
215  */\r
216 extern void QSPI_Write( Qspi* qspi, uint16_t wData )\r
217 {\r
218     /* Send data */\r
219     while ( (qspi->QSPI_SR & QSPI_SR_TXEMPTY) == 0 ) ;\r
220     qspi->QSPI_TDR = wData  ;\r
221     while ( (qspi->QSPI_SR & QSPI_SR_TDRE) == 0 ) ;\r
222 }\r
223 \r
224 /**\r
225  * \brief Sends last data through a SPI peripheral.\r
226  * If the SPI is configured to use a fixed peripheral select, the npcs value is\r
227  * meaningless. Otherwise, it identifies the component which shall be addressed.\r
228  *\r
229  * \param spi   Pointer to an Spi instance.\r
230  * \param npcs  Chip select of the component to address (0, 1, 2 or 3).\r
231  * \param data  Word of data to send.\r
232  */\r
233 extern void QSPI_WriteLast( Qspi* qspi,  uint16_t wData )\r
234 {\r
235     /* Send data */\r
236     while ( (qspi->QSPI_SR & QSPI_SR_TXEMPTY) == 0 ) ;\r
237     qspi->QSPI_TDR = wData  ;\r
238     qspi->QSPI_CR |= QSPI_CR_LASTXFER;\r
239     while ( (qspi->QSPI_SR & QSPI_SR_TDRE) == 0 ) ;\r
240 }\r
241 \r
242 /**\r
243  * \brief Enable QSPI Chip Select.\r
244  * \param qspi   Pointer to a Qspi instance.\r
245  * \param cs    QSPI chip select index.\r
246  */\r
247 extern void QSPI_ConfigureCs( Qspi* qspi, uint8_t spiCs )\r
248 {\r
249     uint32_t dwSpiMr;\r
250 \r
251     /* Write to the MR register*/\r
252     dwSpiMr = qspi->QSPI_MR ;\r
253     dwSpiMr &= ~QSPI_MR_CSMODE_Msk ;\r
254     dwSpiMr |= spiCs;\r
255     qspi->QSPI_MR=dwSpiMr ;\r
256 }\r
257 \r
258 \r
259 \r
260 /**\r
261  * \brief Returns if data has been received. This\r
262  * method must be called after a successful QSPI_Write call.\r
263  *\r
264  * \param qspi  Pointer to an Qspi instance.\r
265  *\r
266  * \return 1 if no data has been received else return return 0.\r
267  */\r
268 extern int QSPI_RxEmpty(Qspi *qspi)\r
269 {\r
270     return ((qspi->QSPI_SR & QSPI_SR_RDRF) == 0);\r
271 }\r
272 \r
273 /**\r
274  * \brief Returns 1 if application can write data. This\r
275  * method must be called before QSPI_Write call.\r
276  *\r
277  * \param qspi  Pointer to an Qspi instance.\r
278  *\r
279  * \return 1 if application can write to the QSPI_TDR register else return return 0.\r
280  */\r
281 extern int QSPI_TxRdy(Qspi *qspi)\r
282 {\r
283     return ((qspi->QSPI_SR & QSPI_SR_TDRE) != 0);\r
284 }\r
285 \r
286 \r
287 /**\r
288  * \brief Check if QSPI transfer finish.\r
289  *\r
290  * \param qspi  Pointer to an Qspi instance.\r
291  *\r
292  * \return Returns 1 if there is no pending write operation on the QSPI; otherwise\r
293  * returns 0.\r
294  */\r
295 extern uint32_t QSPI_IsFinished( Qspi* qspi )\r
296 {\r
297     return ((qspi->QSPI_SR & QSPI_SR_TXEMPTY) != 0) ;\r
298 }\r
299 \r
300 /**\r
301  * \brief Check if QSPI Cs is asserted.\r
302  *\r
303  * \param qspi  Pointer to an Qspi instance.\r
304  *\r
305  * \return Returns 1 if tThe chip select is not asserted; otherwise\r
306  * returns 0.\r
307  */\r
308 extern uint32_t QSPI_IsCsAsserted( Qspi* qspi )\r
309 {\r
310     return ((qspi->QSPI_SR & QSPI_SR_CSS) != 0) ;\r
311 }\r
312 \r
313 /**\r
314  * \brief Check if QSPI Cs is asserted.\r
315  *\r
316  * \param qspi  Pointer to an Qspi instance.\r
317  *\r
318  * \return Returns 1 if At least one chip select rise has been detected since the last read of QSPI_SR; otherwise\r
319  * returns 0.\r
320  */\r
321 extern uint32_t QSPI_IsCsRise( Qspi* qspi )\r
322 {\r
323     return ((qspi->QSPI_SR & QSPI_SR_CSR) != 0) ;\r
324 }\r
325 \r
326 \r
327 /**\r
328  * \brief Check if QSPI Cs is asserted.\r
329  *\r
330  * \param qspi  Pointer to an Qspi instance.\r
331  *\r
332  * \return Returns 1 if At least one instruction end has been detected since the last read of QSPI_SR.; otherwise\r
333  * returns 0.\r
334  */\r
335 extern uint32_t QSPI_IsEOFInst( Qspi* qspi )\r
336 {\r
337     return ((qspi->QSPI_SR & QSPI_SR_INSTRE) != 0) ;\r
338 }\r
339 \r
340 /**\r
341  * \brief Send instrucion over SPI or QSPI\r
342  *\r
343  * \param qspi  Pointer to an Qspi instance.\r
344  *\r
345  * \return Returns 1 if At least one instruction end has been detected since the last read of QSPI_SR.; otherwise\r
346  * returns 0.\r
347  */\r
348 extern void QSPI_SendFrame( Qspi* qspi, qspiFrame *pFrame, AccesType  ReadWrite)\r
349 {  \r
350     uint32_t regIFR, regICR, DummyRead;\r
351     uint32_t *pQspiBuffer = (uint32_t *)QSPIMEM_ADDR;\r
352 \r
353     assert((qspi->QSPI_MR) & QSPI_MR_SMM);\r
354 \r
355     regIFR = (pFrame->spiMode | QSPI_IFR_INSTEN | (pFrame->OptionLen << QSPI_IFR_OPTL_Pos) | (pFrame->DummyCycles << QSPI_IFR_NBDUM_Pos)  | (pFrame->ContinuousRead << 14)) ;\r
356     // Write the instruction to reg\r
357     regICR = ( QSPI_ICR_OPT(pFrame->Option) | QSPI_ICR_INST(pFrame->Instruction));\r
358 \r
359     if(pFrame->OptionEn)\r
360     {\r
361         regIFR|=QSPI_IFR_OPTEN;\r
362     }\r
363 \r
364     /* Instruction frame without Data, only Instruction**/  \r
365     if(!(pFrame->DataSize))               \r
366     {\r
367         if(pFrame->InstAddrFlag)                            // If contain Address, put in IAr reg        \r
368         {\r
369             qspi->QSPI_IAR = pFrame->InstAddr;\r
370             regIFR |= QSPI_IFR_ADDREN;\r
371         }    \r
372         qspi->QSPI_ICR = regICR;                            //  update Instruction code reg\r
373         qspi->QSPI_IFR = regIFR;                            // Instruction Frame reg \r
374     }\r
375     else  /* Instruction frame with Data and Instruction**/\r
376     {    \r
377         regIFR |= QSPI_IFR_DATAEN;    \r
378         if(ReadWrite)\r
379         {\r
380             regIFR |= QSPI_IFR_TFRTYP_TRSFR_WRITE;      \r
381             qspi->QSPI_ICR = regICR;\r
382             qspi->QSPI_IFR = regIFR ;\r
383             DummyRead =  qspi->QSPI_IFR;                        // to synchronize system bus accesses   \r
384             if(pFrame->InstAddrFlag)\r
385             {\r
386                 pQspiBuffer +=  pFrame->InstAddr;\r
387             }\r
388             memcpy(pQspiBuffer  ,pFrame->pData,  pFrame->DataSize); \r
389         } \r
390         else\r
391         {      \r
392             qspi->QSPI_ICR = regICR;\r
393             qspi->QSPI_IFR = regIFR ;\r
394             DummyRead =  qspi->QSPI_IFR;                        // to synchronize system bus accesses   \r
395             memcpy(pFrame->pData,  pQspiBuffer,  pFrame->DataSize); \r
396         }\r
397 \r
398     }\r
399     memory_barrier();\r
400     qspi->QSPI_CR = QSPI_CR_LASTXFER;                     // End transmission after all data has been sent\r
401     while(!(qspi->QSPI_SR & QSPI_SR_INSTRE));             // poll CR reg to know status if Intrustion has end\r
402 \r
403 \r
404 \r
405 }\r
406 \r
407 \r
408 /**\r
409  * \brief Send instrucion over SPI or QSPI\r
410  *\r
411  * \param qspi  Pointer to an Qspi instance.\r
412  *\r
413  * \return Returns 1 if At least one instruction end has been detected since the last read of QSPI_SR.; otherwise\r
414  * returns 0.\r
415  */\r
416 extern void QSPI_SendFrameToMem( Qspi* qspi, qspiFrame *pFrame, AccesType  ReadWrite)\r
417 {\r
418     uint32_t regIFR, regICR, DummyRead ;\r
419     uint8_t *pQspiMem = (uint8_t *)QSPIMEM_ADDR;\r
420 \r
421     assert((qspi->QSPI_MR) & QSPI_MR_SMM);  \r
422 \r
423     regIFR = (pFrame->spiMode | QSPI_IFR_INSTEN | QSPI_IFR_DATAEN | QSPI_IFR_ADDREN | (pFrame->OptionLen << QSPI_IFR_OPTL_Pos) | (pFrame->DummyCycles << QSPI_IFR_NBDUM_Pos) | (pFrame->ContinuousRead << 14)) ;\r
424     // Write the instruction to reg\r
425     regICR = ( QSPI_ICR_OPT(pFrame->Option) | QSPI_ICR_INST(pFrame->Instruction));\r
426     if(pFrame->OptionEn)\r
427     {\r
428         regIFR|=QSPI_IFR_OPTEN;\r
429     }\r
430     pQspiMem +=  pFrame->InstAddr;\r
431     if(ReadWrite)\r
432     {   \r
433         regIFR |= QSPI_IFR_TFRTYP_TRSFR_WRITE_MEMORY;\r
434         memory_barrier();\r
435         qspi->QSPI_ICR = regICR;\r
436         qspi->QSPI_IFR = regIFR ;\r
437         DummyRead =  qspi->QSPI_IFR;                // to synchronize system bus accesses  \r
438 \r
439         memcpy(pQspiMem  ,pFrame->pData,  pFrame->DataSize); \r
440 \r
441     }\r
442     else\r
443     {\r
444         regIFR |= QSPI_IFR_TFRTYP_TRSFR_READ_MEMORY;\r
445         memory_barrier();\r
446         qspi->QSPI_ICR = regICR;\r
447         qspi->QSPI_IFR = regIFR ;\r
448         DummyRead =  qspi->QSPI_IFR;                                                // to synchronize system bus accesses \r
449         memcpy(pFrame->pData, pQspiMem , pFrame->DataSize);   //  Read QSPI AHB memory space \r
450 \r
451     } \r
452     memory_barrier();\r
453     qspi->QSPI_CR = QSPI_CR_LASTXFER;             // End transmission after all data has been sent\r
454     while(!(qspi->QSPI_SR & QSPI_SR_INSTRE));     // poll CR reg to know status if Intrustion has end\r
455 \r
456 }\r
457 \r