]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_IAR_Keil/libboard_samv7-ek/source/s25fl1.c
Final V8.2.1 release ready for tagging:
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_IAR_Keil / libboard_samv7-ek / source / s25fl1.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License\r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2013, 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 /**\r
31  * \addtogroup at25d_module S25FL1 driver\r
32  * \ingroup lib_spiflash\r
33  * The S25FL1 serial dataflash driver is based on the corresponding S25FL1 SPI driver.\r
34  * A S25FL1 instance has to be initialized using the Dataflash levle function\r
35  * S25FL1D_Configure(). S25FL1 Dataflash can be automatically detected using\r
36  * the S25FL1D_FindDevice() function. Then S25FL1 dataflash operations such as\r
37  * read, write and erase DF can be launched using S25FL1D_SendCommand function\r
38  * with corresponding S25FL1 command set.\r
39  *\r
40  * \section Usage\r
41  * <ul>\r
42  * <li> Reads a serial flash device ID using S25FL1D_ReadJedecId().</li>\r
43  * <li> Reads data from the S25fl1 at the specified address using S25FL1D_Read().</li>\r
44  * <li> Writes data on the S25fl1 at the specified address using S25FL1D_Write().</li>\r
45  * <li> Erases all chip using S25FL1D_EraseBlock().</li>\r
46  * <li> Erases a specified block using S25FL1D_EraseBlock().</li>\r
47  * <li> Poll until the S25fl1 has completed of corresponding operations using\r
48  * S25FL1D_IsBusy().</li>\r
49  * <li> Retrieves and returns the S25fl1 current using S25FL1D_ReadStatus().</li>\r
50  * </ul>\r
51  *\r
52  * Related files :\n\r
53  * \ref at25d.c\n\r
54  * \ref at25d.h.\n\r
55  */\r
56 /*@{*/\r
57 /*@}*/\r
58 \r
59 /**\r
60  * \file\r
61  *\r
62  * Implementation for the S25FL1 Serialflash driver.\r
63  *\r
64  */\r
65 \r
66 /*----------------------------------------------------------------------------\r
67  *        Headers\r
68  *----------------------------------------------------------------------------*/\r
69 \r
70 #include <board.h>\r
71 //#include <libspiflash.h>\r
72 #include <assert.h>\r
73 #include "stdlib.h"\r
74 #include "string.h"\r
75 \r
76 \r
77 static qspiFrame *pDev, *pMem;\r
78 #define READ_DEV        0\r
79 #define WRITE_DEV       1 \r
80 /*----------------------------------------------------------------------------\r
81  *        Local functions\r
82  *----------------------------------------------------------------------------*/\r
83 \r
84 \r
85 \r
86 static void S25FL1D_DefaultParams(void)\r
87 {      \r
88     pDev->spiMode = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;\r
89     pDev->ContinuousRead = 0;\r
90     pDev->DataSize = 0;\r
91     pDev->DummyCycles = 0;\r
92     pDev->InstAddr = 0;\r
93     pDev->InstAddrFlag = 0;\r
94     pDev->OptionEn = 0;\r
95 \r
96 }\r
97 \r
98 \r
99 static uint8_t S25FL1D_SendCommand(uint8_t Instr, AccesType ReadWrite)\r
100 \r
101 {  \r
102     pDev->Instruction = Instr;\r
103     QSPI_SendFrame(QSPI, pDev, ReadWrite);\r
104 \r
105     return 0;\r
106 }\r
107 \r
108 \r
109 /**\r
110  * \brief Reads and returns the status register of the serial flash.\r
111  *\r
112  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
113  */\r
114 static uint8_t S25FL1D_ReadStatus(void)\r
115 {\r
116     uint8_t status;\r
117 \r
118     pDev->DataSize = 1;    \r
119     S25FL1D_SendCommand(0x05, READ_DEV);\r
120     status = *(pDev->pData);\r
121     return status;\r
122 }\r
123 \r
124 /**\r
125  * \brief Reads and returns the status register of the serial flash.\r
126  *\r
127  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
128  */\r
129 static uint8_t S25FL1D_ReadStatus2(void)\r
130 {\r
131     uint8_t status;\r
132 \r
133     pDev->DataSize = 1;\r
134     S25FL1D_SendCommand(0x35, READ_DEV);\r
135     status = *(pDev->pData);\r
136     return status;\r
137 }\r
138 \r
139 /**\r
140  * \brief Reads and returns the status register of the serial flash.\r
141  *\r
142  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
143  */\r
144 static uint8_t S25FL1D_ReadStatus3(void)\r
145 {\r
146     uint8_t status;\r
147 \r
148     pDev->DataSize = 1;\r
149     S25FL1D_SendCommand(0x33, READ_DEV);\r
150     status = *(pDev->pData);\r
151     return status;\r
152 }\r
153 /**\r
154  * \brief Wait for transfer to finish calling the SPI driver ISR. (interrupts are disabled)\r
155  *\r
156  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
157  */\r
158 static void S25FL1D_IsBusy(void)\r
159 {\r
160     while(S25FL1D_ReadStatus() & STATUS_RDYBSY);\r
161 }\r
162 \r
163 \r
164 \r
165 \r
166 \r
167 static void S25FL1D_EnableWrite(void)\r
168 {\r
169     uint8_t status;\r
170 \r
171     status = S25FL1D_ReadStatus();\r
172 \r
173 \r
174     while(status != STATUS_WEL)\r
175     {      \r
176         pDev->DataSize = 0;\r
177         S25FL1D_SendCommand(WRITE_ENABLE, READ_DEV);\r
178         status = S25FL1D_ReadStatus();\r
179     }\r
180 }\r
181 \r
182 \r
183 static void S25FL1D_DisableWrite(void)\r
184 {\r
185     uint8_t status;\r
186 \r
187     status = S25FL1D_ReadStatus();\r
188 \r
189     while( (status & STATUS_WEL) != 0)\r
190     {      \r
191         pDev->DataSize = 0;\r
192         S25FL1D_SendCommand(WRITE_DISABLE, READ_DEV);\r
193         status = S25FL1D_ReadStatus();\r
194     }\r
195 }\r
196 /**\r
197  * \brief Writes the given value in the status register of the serial flash device.\r
198  *\r
199  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
200  * \param status  Status to write.\r
201  */\r
202 static void S25FL1D_WriteStatus( uint8_t *pStatus)\r
203 {\r
204     S25FL1D_EnableWrite();\r
205 \r
206     pDev->DataSize = 3;\r
207     pDev->Instruction = WRITE_STATUS; \r
208     pDev->pData = pStatus;\r
209     QSPI_SendFrame(QSPI, pDev, Device_Write);\r
210     S25FL1D_DisableWrite();\r
211 }\r
212 \r
213 /**\r
214  * \brief Writes the given value in the status register of the serial flash device.\r
215  *\r
216  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
217  * \param status  Status to write.\r
218  */\r
219 static void S25FL1D_WriteVolatileStatus( uint8_t *pStatus)\r
220 {\r
221 \r
222 \r
223     pDev->DataSize = 0;\r
224     S25FL1D_SendCommand(0x50, READ_DEV);\r
225 \r
226     pDev->DataSize = 3;\r
227     pDev->Instruction = WRITE_STATUS; \r
228     pDev->pData = pStatus;\r
229     QSPI_SendFrame(QSPI, pDev, Device_Write);\r
230     S25FL1D_DisableWrite();\r
231 }\r
232 /*----------------------------------------------------------------------------\r
233  *         Global functions\r
234  *----------------------------------------------------------------------------*/\r
235 \r
236 \r
237 void S25FL1D_InitFlashInterface(void)\r
238 {\r
239     pDev = (qspiFrame *)malloc (sizeof(qspiFrame));  \r
240     memset(pDev, 0, sizeof(qspiFrame));\r
241     pDev->spiMode = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;\r
242     pDev->pData = (uint8_t *)malloc (sizeof(uint32_t));\r
243 \r
244 \r
245     pMem = (qspiFrame *)malloc (sizeof(qspiFrame));\r
246     memset(pMem, 0, sizeof(qspiFrame));\r
247     pMem->spiMode = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;\r
248     pMem->pData = (uint8_t *)malloc (sizeof(uint8_t));\r
249 }\r
250 \r
251 /**\r
252  * \brief Reads and returns the serial flash device ID.\r
253  *\r
254  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
255  */\r
256 unsigned int S25FL1D_ReadJedecId(void)\r
257 {\r
258     unsigned int id = 0;\r
259 \r
260     pDev->DataSize = 3;\r
261     S25FL1D_SendCommand(READ_JEDEC_ID, READ_DEV);\r
262 \r
263     id = ( (pDev->pData[0] << 16)  || (pDev->pData[1] << 8) || (pDev->pData[2]));\r
264 \r
265     return id;\r
266 }\r
267 \r
268 /**\r
269  * \brief Enables critical writes operation on a serial flash device, such as sector\r
270  * protection, status register, etc.\r
271  *\r
272  * \para pS25fl1  Pointer to an S25FL1 driver instance.\r
273  */\r
274 void S25FL1D_EnableQuadMode(void)\r
275 {\r
276 \r
277     uint8_t status[3];\r
278 \r
279     status[0] = S25FL1D_ReadStatus();\r
280     status[1] = S25FL1D_ReadStatus2();\r
281     status[2] = S25FL1D_ReadStatus3();\r
282 \r
283     while(!(status[1] & STATUS_QUAD_ENABLE))\r
284     {\r
285         status[1] |= STATUS_QUAD_ENABLE;\r
286         S25FL1D_WriteStatus(status);\r
287         status[1] = S25FL1D_ReadStatus2();\r
288         Wait(50);\r
289     }\r
290 }\r
291 \r
292 \r
293 /**\r
294  * \brief Enables critical writes operation on a serial flash device, such as sector\r
295  * protection, status register, etc.\r
296  *\r
297  * \para pS25fl1  Pointer to an S25FL1 driver instance.\r
298  */\r
299 void S25FL1D_EnableWrap(uint8_t ByetAlign)\r
300 {\r
301 \r
302     uint8_t status[3];\r
303 \r
304     status[0] = S25FL1D_ReadStatus();\r
305     status[1] = S25FL1D_ReadStatus2();\r
306     status[2] = S25FL1D_ReadStatus3();\r
307 \r
308     status[2] = (ByetAlign << 5);\r
309 \r
310     pDev->DataSize = 1;\r
311     *(pDev->pData) = status[2];\r
312     pDev->DummyCycles = 24;\r
313     S25FL1D_SendCommand(WRAP_ENABLE, WRITE_DEV);\r
314     pDev->DummyCycles = 0;\r
315 \r
316     S25FL1D_WriteVolatileStatus(status);\r
317     status[2] = S25FL1D_ReadStatus3();\r
318     Wait(50);\r
319 }\r
320 \r
321 void S25FL1D_SoftReset(void)\r
322 {\r
323 \r
324     pDev->DataSize = 0;\r
325     S25FL1D_SendCommand(SOFT_RESET_ENABLE, READ_DEV);\r
326     S25FL1D_SendCommand(SOFT_RESET, READ_DEV);\r
327 \r
328 }\r
329 \r
330 /**\r
331  * \brief Unprotects the contents of the serial flash device.\r
332  *\r
333  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
334  *\r
335  * \return 0 if the device has been unprotected; otherwise returns\r
336  * S25FL1D_ERROR_PROTECTED.\r
337  */\r
338 unsigned char S25FL1D_Unprotect(void)\r
339 {\r
340     unsigned char status[3];\r
341 \r
342 \r
343 \r
344     /* Get the status register value to check the current protection */\r
345     status[0]= S25FL1D_ReadStatus();\r
346     status[1]= S25FL1D_ReadStatus2();\r
347     status[2]= S25FL1D_ReadStatus3();\r
348     if ((status[0] & STATUS_SWP) == STATUS_SWP_PROTNONE) {\r
349 \r
350         /* Protection already disabled */\r
351         return 0;\r
352     }\r
353 \r
354     status[0] &= (!STATUS_SWP);\r
355     /* Check if sector protection registers are locked */\r
356     if ((status[0] & STATUS_SPRL) == STATUS_SPRL_LOCKED) {\r
357         status[0] &= (!STATUS_SPRL);\r
358         /* Unprotect sector protection registers by writing the status reg. */\r
359         S25FL1D_WriteStatus(status);\r
360     }\r
361 \r
362     S25FL1D_WriteStatus(status);\r
363 \r
364     /* Check the new status */\r
365     status[0] = S25FL1D_ReadStatus();\r
366     if ((status[0] & (STATUS_SPRL | STATUS_SWP)) != 0) {\r
367 \r
368         return ERROR_PROTECTED;\r
369     }\r
370     else {\r
371 \r
372         return 0;\r
373     }\r
374 }\r
375 \r
376 \r
377 /**\r
378  * \brief Unprotects the contents of the serial flash device.\r
379  *\r
380  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
381  *\r
382  * \return 0 if the device has been unprotected; otherwise returns\r
383  * S25FL1D_ERROR_PROTECTED.\r
384  */\r
385 unsigned char S25FL1D_Protect(uint32_t StartAddr, uint32_t Size)\r
386 {\r
387     unsigned char status[3];\r
388 \r
389 \r
390 \r
391     /* Get the status register value to check the current protection */\r
392     status[0]= S25FL1D_ReadStatus();\r
393     status[1]= S25FL1D_ReadStatus2();\r
394     status[2]= S25FL1D_ReadStatus3();\r
395 \r
396     status[0] &= (!STATUS_SWP);\r
397     /* Check if sector protection registers are locked */\r
398     if ((status[0] & STATUS_SPRL) == STATUS_SPRL_LOCKED) {\r
399         status[0] &= (!STATUS_SPRL);\r
400         /* Unprotect sector protection registers by writing the status reg. */\r
401         S25FL1D_WriteStatus(status);\r
402     }\r
403 \r
404     S25FL1D_WriteStatus(status);\r
405 \r
406     /* Check the new status */\r
407     status[0] = S25FL1D_ReadStatus();\r
408     if ((status[0] & (STATUS_SPRL | STATUS_SWP)) != 0) {\r
409 \r
410         return ERROR_PROTECTED;\r
411     }\r
412     else {\r
413 \r
414         return 0;\r
415     }\r
416 }\r
417 \r
418 \r
419 /**\r
420  * \brief Erases all the content of the memory chip.\r
421  *\r
422  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
423  *\r
424  * \return 0 if the device has been unprotected; otherwise returns\r
425  * ERROR_PROTECTED.\r
426  */\r
427 unsigned char S25FL1D_EraseChip(void)\r
428 {\r
429     char wait_ch[4] = {'\\','|','/','-' };\r
430     uint8_t i=0;\r
431 \r
432     S25FL1D_EnableWrite();   \r
433     pDev->DataSize=0;\r
434     S25FL1D_SendCommand(CHIP_ERASE_2, READ_DEV);\r
435     S25FL1D_ReadStatus();\r
436 \r
437     while(*(pDev->pData) & STATUS_RDYBSY)\r
438     {\r
439         S25FL1D_ReadStatus();      \r
440         Wait(500);\r
441         printf("Erasing flash memory %c\r", wait_ch[i]);\r
442         i++;\r
443         if(i==4)\r
444             i=0;\r
445     }\r
446     printf("\rErasing flash memory done..... 100%\n\r");\r
447     return 0;\r
448 }\r
449 \r
450 /**\r
451  *\brief  Erases the specified block of the serial firmware dataflash.\r
452  *\r
453  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
454  * \param address  Address of the block to erase.\r
455  *\r
456  * \return 0 if successful; otherwise returns ERROR_PROTECTED if the\r
457  * device is protected or ERROR_BUSY if it is busy executing a command.\r
458  */\r
459 unsigned char S25FL1D_EraseSector(unsigned int address)\r
460 {\r
461     uint8_t status;\r
462     uint32_t EraseAddr;\r
463 \r
464     EraseAddr = address;\r
465 \r
466     /* Check that the flash is ready and unprotected */\r
467     status = S25FL1D_ReadStatus();\r
468     if ((status & STATUS_RDYBSY) != STATUS_RDYBSY_READY) {\r
469         TRACE_ERROR("EraseBlock : Flash busy\n\r");\r
470         return ERROR_BUSY;\r
471     }\r
472     else if ((status & STATUS_SWP) != STATUS_SWP_PROTNONE) {\r
473         TRACE_ERROR("S25FL1D_EraseBlock : Flash protected\n\r");\r
474         return ERROR_PROTECTED;\r
475     }\r
476 \r
477 \r
478     /* Enable critical write operation */\r
479     S25FL1D_EnableWrite();\r
480 \r
481     pDev->InstAddrFlag = 1;\r
482     pDev->InstAddr = address;\r
483     /* Start the block erase command */\r
484     S25FL1D_SendCommand(BLOCK_ERASE_4K, WRITE_DEV);\r
485     S25FL1D_DefaultParams();\r
486 \r
487     /* Wait for transfer to finish */\r
488     S25FL1D_IsBusy();\r
489 \r
490 \r
491     return 0;\r
492 }\r
493 \r
494 /**\r
495  *\brief  Erases the specified 64KB block of the serial firmware dataflash.\r
496  *\r
497  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
498  * \param address  Address of the block to erase.\r
499  *\r
500  * \return 0 if successful; otherwise returns ERROR_PROTECTED if the\r
501  * device is protected or ERROR_BUSY if it is busy executing a command.\r
502  */\r
503 unsigned char S25FL1D_Erase64KBlock( unsigned int address)\r
504 {\r
505     unsigned char status;\r
506 \r
507     /* Check that the flash is ready and unprotected */\r
508     status = S25FL1D_ReadStatus();\r
509     if ((status & STATUS_RDYBSY) != STATUS_RDYBSY_READY) {\r
510         TRACE_ERROR("S25FL1D_EraseBlock : Flash busy\n\r");\r
511         return ERROR_BUSY;\r
512     }\r
513     else if ((status & STATUS_SWP) != STATUS_SWP_PROTNONE) {\r
514         TRACE_ERROR("EraseBlock : Flash protected\n\r");\r
515         return ERROR_PROTECTED;\r
516     }\r
517 \r
518     /* Enable critical write operation */\r
519     S25FL1D_EnableWrite();\r
520 \r
521     pDev->DataSize = 0;\r
522     pDev->InstAddrFlag = 1;\r
523     pDev->InstAddr = address;\r
524 \r
525     /* Start the block erase command */\r
526     S25FL1D_SendCommand(BLOCK_ERASE_64K, WRITE_DEV);\r
527     S25FL1D_DefaultParams();\r
528 \r
529     /* Wait for transfer to finish */\r
530     S25FL1D_IsBusy();\r
531 \r
532 \r
533     return 0;\r
534 }\r
535 \r
536 /**\r
537  * \brief Writes data at the specified address on the serial firmware dataflash. The\r
538  * page(s) to program must have been erased prior to writing. This function\r
539  * handles page boundary crossing automatically.\r
540  *\r
541  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
542  * \param pData  Data buffer.\r
543  * \param size  Number of bytes in buffer.\r
544  * \param address  Write address.\r
545  *\r
546  * \return 0 if successful; otherwise, returns ERROR_PROGRAM is there has\r
547  * been an error during the data programming.\r
548  */\r
549 unsigned char S25FL1D_Write(\r
550         uint8_t *pData,\r
551         uint32_t size,\r
552         uint32_t address)\r
553 {\r
554     unsigned int pageSize = 256;\r
555     unsigned int writeSize;\r
556     unsigned int i = 0;\r
557 \r
558 \r
559     writeSize = size >> 8;\r
560     S25FL1D_EnableWrite();\r
561     pMem->Instruction = 0x02; \r
562     pMem->InstAddrFlag=1; pMem->InstAddr=address;  \r
563     if(writeSize ==0)   // if less than page size\r
564     {\r
565         pMem->pData = (pData);\r
566         pMem->DataSize = size;\r
567         QSPI_SendFrameToMem(QSPI, pMem, Device_Write);\r
568     }\r
569     else                // mulptiple pagesize\r
570     {     \r
571         pMem->DataSize = pageSize;\r
572         for(i=0; i< writeSize; i++)\r
573         {\r
574             S25FL1D_EnableWrite();\r
575             pMem->pData = pData;        \r
576             QSPI_SendFrameToMem(QSPI, pMem, Device_Write);\r
577             S25FL1D_IsBusy();\r
578             pData += pageSize;\r
579             pMem->InstAddr += pageSize;\r
580             memory_barrier();\r
581         }\r
582         if((writeSize * pageSize) < size)\r
583         {\r
584             S25FL1D_EnableWrite();\r
585             pMem->DataSize = (size - (writeSize * pageSize)) ;\r
586             pMem->pData = pData;        \r
587             QSPI_SendFrameToMem(QSPI, pMem, Device_Write);\r
588             S25FL1D_IsBusy();\r
589         }\r
590     }\r
591 \r
592     S25FL1D_DisableWrite();\r
593 \r
594 \r
595     return 0;\r
596 }\r
597 \r
598 /**\r
599  * \brief Reads data from the specified address on the serial flash.\r
600  *\r
601  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
602  * \param pData  Data buffer.\r
603  * \param size  Number of bytes to read.\r
604  * \param address  Read address.\r
605  *\r
606  * \return 0 if successful; otherwise, fail.\r
607  */\r
608 unsigned char S25FL1D_Read(\r
609         uint8_t *pData,\r
610         uint32_t size,\r
611         uint32_t address)\r
612 {    \r
613     pMem->Instruction = READ_ARRAY_LF;\r
614     pMem->InstAddrFlag=1; pMem->InstAddr=address;\r
615     pMem->pData = pData;\r
616     pMem->DataSize = size;\r
617     pMem->DummyCycles = 0;\r
618     pMem->spiMode = QSPI_IFR_WIDTH_SINGLE_BIT_SPI;\r
619     QSPI_SendFrameToMem(QSPI, pMem, Device_Read);\r
620 \r
621     return 0;\r
622 }\r
623 \r
624 \r
625 /**\r
626  * \brief Reads data from the specified address on the serial flash.\r
627  *\r
628  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
629  * \param pData  Data buffer.\r
630  * \param size  Number of bytes to read.\r
631  * \param address  Read address.\r
632  *\r
633  * \return 0 if successful; otherwise, fail.\r
634  */\r
635 unsigned char S25FL1D_ReadDual(\r
636         uint8_t *pData,\r
637         uint32_t size,\r
638         uint32_t address)\r
639 {\r
640     pMem->Instruction = READ_ARRAY_DUAL;\r
641     pMem->InstAddrFlag=1; pMem->InstAddr=address;\r
642     pMem->pData = pData;\r
643     pMem->DataSize = size;\r
644     pMem->DummyCycles = 8;\r
645     pMem->spiMode = QSPI_IFR_WIDTH_DUAL_OUTPUT;\r
646     QSPI_SendFrameToMem(QSPI, pMem, Device_Read);\r
647 \r
648 \r
649     return 0;\r
650 }\r
651 \r
652 \r
653 /**\r
654  * \brief Reads data from the specified address on the serial flash.\r
655  *\r
656  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
657  * \param pData  Data buffer.\r
658  * \param size  Number of bytes to read.\r
659  * \param address  Read address.\r
660  *\r
661  * \return 0 if successful; otherwise, fail.\r
662  */\r
663 unsigned char S25FL1D_ReadQuad(\r
664         uint8_t *pData,\r
665         uint32_t size,\r
666         uint32_t address)\r
667 {\r
668 \r
669     pMem->Instruction = READ_ARRAY_QUAD;\r
670     pMem->InstAddrFlag=1; pMem->InstAddr=address;\r
671     pMem->pData = pData;\r
672     pMem->DataSize = size;\r
673     pMem->DummyCycles = 8;\r
674     pMem->spiMode = QSPI_IFR_WIDTH_QUAD_OUTPUT;\r
675     QSPI_SendFrameToMem(QSPI, pMem, Device_Read);\r
676 \r
677 \r
678     return 0;\r
679 }\r
680 \r
681 /**\r
682  * \brief Reads data from the specified address on the serial flash.\r
683  *\r
684  * \param pS25fl1  Pointer to an S25FL1 driver instance.\r
685  * \param pData  Data buffer.\r
686  * \param size  Number of bytes to read.\r
687  * \param address  Read address.\r
688  *\r
689  * \return 0 if successful; otherwise, fail.\r
690  */\r
691 unsigned char S25FL1D_ReadQuadIO(\r
692         uint8_t *pData,\r
693         uint32_t size,\r
694         uint32_t address,\r
695         uint8_t ContMode)\r
696 {\r
697 \r
698     pMem->Instruction = READ_ARRAY_QUAD_IO;\r
699     pMem->InstAddrFlag=1; \r
700     pMem->InstAddr=address;\r
701     pMem->pData = pData;\r
702     pMem->DataSize = size;    \r
703     pMem->DummyCycles = 6;\r
704     if(ContMode)\r
705     {\r
706         pMem->OptionLen = QSPI_IFR_OPTL_OPTION_4BIT;\r
707         pMem->Option = 0x2;\r
708         pMem->ContinuousRead = ContMode;\r
709         pMem->DummyCycles = 5;\r
710         pMem->OptionEn = ContMode;\r
711     }\r
712 \r
713     pMem->spiMode = QSPI_IFR_WIDTH_QUAD_IO;\r
714     QSPI_SendFrameToMem(QSPI, pMem, Device_Read);\r
715     pMem->OptionEn = 0;\r
716     pMem->ContinuousRead = 0;\r
717 \r
718     return 0;\r
719 }\r
720 \r
721 \r
722 \r