| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
DataflashManager.c
Go to the documentation of this file.
1 /*
2 * @note
3 * Copyright(C) NXP Semiconductors, 2012
4 * All rights reserved.
5 *
6 * @par
7 * Software that is described herein is for illustrative purposes only
8 * which provides customers with programming information regarding the
9 * LPC products. This software is supplied "AS IS" without any warranties of
10 * any kind, and NXP Semiconductors and its licensor disclaim any and
11 * all warranties, express or implied, including all implied warranties of
12 * merchantability, fitness for a particular purpose and non-infringement of
13 * intellectual property rights. NXP Semiconductors assumes no responsibility
14 * or liability for the use of the software, conveys no license or rights under any
15 * patent, copyright, mask work right, or any other intellectual property rights in
16 * or to any products. NXP Semiconductors reserves the right to make changes
17 * in the software without notification. NXP Semiconductors also makes no
18 * representation or warranty that such application will be suitable for the
19 * specified use without further testing or modification.
20 *
21 * @par
22 * Permission to use, copy, modify, and distribute this software and its
23 * documentation is hereby granted, under NXP Semiconductors' and its
24 * licensor's relevant copyrights in the software, without fee, provided that it
25 * is used in conjunction with NXP Semiconductors microcontrollers. This
26 * copyright, permission, and disclaimer notice must appear in all copies of
27 * this code.
28 */
29
38 #define INCLUDE_FROM_DATAFLASHMANAGER_C
39 #include "DataflashManager.h"
40
41 /*****************************************************************************
42 * Private types/enumerations/variables
43 ****************************************************************************/
44
45 static int InitializedFlag = 1;
46
47 /*****************************************************************************
48 * Public types/enumerations/variables
49 ****************************************************************************/
50
51 /*****************************************************************************
52 * Private functions
53 ****************************************************************************/
54
55 /*****************************************************************************
56 * Public functions
57 ****************************************************************************/
58
67 void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t *const MSInterfaceInfo,
68 const uint32_t BlockAddress,
69 uint16_t TotalBlocks)
70 {
71 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
72 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
73 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
74 bool UsingSecondBuffer = false;
75
76 /* Select the correct starting Dataflash IC for the block requested */
77 Dataflash_SelectChipFromPage(CurrDFPage);
78
79 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
80 /* Copy selected dataflash's current page contents to the Dataflash buffer */
81 Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
82 Dataflash_SendAddressBytes(CurrDFPage, 0);
83 Dataflash_WaitWhileBusy();
84 #endif
85
86 /* Send the Dataflash buffer write command */
87 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
88 Dataflash_SendAddressBytes(0, CurrDFPageByte);
89
90 /* Wait until endpoint is ready before continuing */
91 if (Endpoint_WaitUntilReady()) {
92 return;
93 }
94
95 while (TotalBlocks) {
96 uint8_t BytesInBlockDiv16 = 0;
97
98 /* Write an endpoint packet sized data block to the Dataflash */
99 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) {
100 /* Check if the endpoint is currently empty */
101 if (!(Endpoint_IsReadWriteAllowed())) {
102 /* Clear the current endpoint bank */
103 Endpoint_ClearOUT();
104
105 /* Wait until the host has sent another packet */
106 if (Endpoint_WaitUntilReady()) {
107 return;
108 }
109 }
110
111 /* Check if end of Dataflash page reached */
112 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) {
113 /* Write the Dataflash buffer contents back to the Dataflash page */
114 Dataflash_WaitWhileBusy();
115 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
116 Dataflash_SendAddressBytes(CurrDFPage, 0);
117
118 /* Reset the Dataflash buffer counter, increment the page counter */
119 CurrDFPageByteDiv16 = 0;
120 CurrDFPage++;
121
122 /* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
123 if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS)) {
124 UsingSecondBuffer = !(UsingSecondBuffer);
125 }
126
127 /* Select the next Dataflash chip based on the new Dataflash page index */
128 Dataflash_SelectChipFromPage(CurrDFPage);
129
130 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
131 /* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */
132 if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4)) {
133 /* Copy selected dataflash's current page contents to the Dataflash buffer */
134 Dataflash_WaitWhileBusy();
135 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
136 Dataflash_SendAddressBytes(CurrDFPage, 0);
137 Dataflash_WaitWhileBusy();
138 }
139 #endif
140
141 /* Send the Dataflash buffer write command */
142 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
143 Dataflash_SendAddressBytes(0, 0);
144 }
145
146 /* Write one 16-byte chunk of data to the Dataflash */
147 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
148 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
149 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
150 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
151 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
152 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
153 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
154 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
155 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
156 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
157 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
158 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
159 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
160 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
161 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
162 Dataflash_SendByte(Endpoint_Read_8(MSInterfaceInfo->Config.PortNumber));
163
164 /* Increment the Dataflash page 16 byte block counter */
165 CurrDFPageByteDiv16++;
166
167 /* Increment the block 16 byte block counter */
168 BytesInBlockDiv16++;
169
170 /* Check if the current command is being aborted by the host */
171 if (MSInterfaceInfo->State.IsMassStoreReset) {
172 return;
173 }
174 }
175
176 /* Decrement the blocks remaining counter */
177 TotalBlocks--;
178 }
179
180 /* Write the Dataflash buffer contents back to the Dataflash page */
181 Dataflash_WaitWhileBusy();
182 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
183 Dataflash_SendAddressBytes(CurrDFPage, 0x00);
184 Dataflash_WaitWhileBusy();
185
186 /* If the endpoint is empty, clear it ready for the next packet from the host */
187 if (!(Endpoint_IsReadWriteAllowed())) {
188 Endpoint_ClearOUT();
189 }
190
191 /* Deselect all Dataflash chips */
192 Dataflash_DeselectChip();
193 }
194
203 void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t *const MSInterfaceInfo,
204 const uint32_t BlockAddress,
205 uint16_t TotalBlocks)
206 {
207 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
208 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
209 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
210
211 /* Select the correct starting Dataflash IC for the block requested */
212 Dataflash_SelectChipFromPage(CurrDFPage);
213
214 /* Send the Dataflash main memory page read command */
215 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
216 Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
217 Dataflash_SendByte(0x00);
218 Dataflash_SendByte(0x00);
219 Dataflash_SendByte(0x00);
220 Dataflash_SendByte(0x00);
221
222 /* Wait until endpoint is ready before continuing */
223 if (Endpoint_WaitUntilReady()) {
224 return;
225 }
226
227 while (TotalBlocks) {
228 uint8_t BytesInBlockDiv16 = 0;
229
230 /* Write an endpoint packet sized data block to the Dataflash */
231 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) {
232 /* Check if the endpoint is currently full */
233 if (!(Endpoint_IsReadWriteAllowed())) {
234 /* Clear the endpoint bank to send its contents to the host */
235 Endpoint_ClearIN();
236
237 /* Wait until the endpoint is ready for more data */
238 if (Endpoint_WaitUntilReady()) {
239 return;
240 }
241 }
242
243 /* Check if end of Dataflash page reached */
244 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) {
245 /* Reset the Dataflash buffer counter, increment the page counter */
246 CurrDFPageByteDiv16 = 0;
247 CurrDFPage++;
248
249 /* Select the next Dataflash chip based on the new Dataflash page index */
250 Dataflash_SelectChipFromPage(CurrDFPage);
251
252 /* Send the Dataflash main memory page read command */
253 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
254 Dataflash_SendAddressBytes(CurrDFPage, 0);
255 Dataflash_SendByte(0x00);
256 Dataflash_SendByte(0x00);
257 Dataflash_SendByte(0x00);
258 Dataflash_SendByte(0x00);
259 }
260
261 /* Read one 16-byte chunk of data from the Dataflash */
262 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
263 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
264 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
265 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
266 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
267 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
268 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
269 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
270 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
271 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
272 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
273 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
274 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
275 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
276 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
277 Endpoint_Write_8(MSInterfaceInfo->Config.PortNumber, Dataflash_ReceiveByte());
278
279 /* Increment the Dataflash page 16 byte block counter */
280 CurrDFPageByteDiv16++;
281
282 /* Increment the block 16 byte block counter */
283 BytesInBlockDiv16++;
284
285 /* Check if the current command is being aborted by the host */
286 if (MSInterfaceInfo->State.IsMassStoreReset) {
287 return;
288 }
289 }
290
291 /* Decrement the blocks remaining counter */
292 TotalBlocks--;
293 }
294
295 /* If the endpoint is full, send its contents to the host */
296 if (!(Endpoint_IsReadWriteAllowed())) {
297 Endpoint_ClearIN(MSInterfaceInfo->Config.PortNumber);
298 }
299
300 /* Deselect all Dataflash chips */
301 Dataflash_DeselectChip();
302 }
303
313 void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress,
314 uint16_t TotalBlocks,
315 uint8_t *BufferPtr)
316 {
317 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
318 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
319 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
320 bool UsingSecondBuffer = false;
321
322 /* Select the correct starting Dataflash IC for the block requested */
323 Dataflash_SelectChipFromPage(CurrDFPage);
324
325 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
326 /* Copy selected dataflash's current page contents to the Dataflash buffer */
327 Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
328 Dataflash_SendAddressBytes(CurrDFPage, 0);
329 Dataflash_WaitWhileBusy();
330 #endif
331
332 /* Send the Dataflash buffer write command */
333 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
334 Dataflash_SendAddressBytes(0, CurrDFPageByte);
335
336 while (TotalBlocks) {
337 uint8_t BytesInBlockDiv16 = 0;
338
339 /* Write an endpoint packet sized data block to the Dataflash */
340 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) {
341 /* Check if end of Dataflash page reached */
342 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) {
343 /* Write the Dataflash buffer contents back to the Dataflash page */
344 Dataflash_WaitWhileBusy();
345 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
346 Dataflash_SendAddressBytes(CurrDFPage, 0);
347
348 /* Reset the Dataflash buffer counter, increment the page counter */
349 CurrDFPageByteDiv16 = 0;
350 CurrDFPage++;
351
352 /* Once all the Dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
353 if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS)) {
354 UsingSecondBuffer = !(UsingSecondBuffer);
355 }
356
357 /* Select the next Dataflash chip based on the new Dataflash page index */
358 Dataflash_SelectChipFromPage(CurrDFPage);
359
360 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
361 /* If less than one Dataflash page remaining, copy over the existing page to preserve trailing data */
362 if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4)) {
363 /* Copy selected dataflash's current page contents to the Dataflash buffer */
364 Dataflash_WaitWhileBusy();
365 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
366 Dataflash_SendAddressBytes(CurrDFPage, 0);
367 Dataflash_WaitWhileBusy();
368 }
369 #endif
370
371 /* Send the Dataflash buffer write command */
372 Dataflash_ToggleSelectedChipCS();
373 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
374 Dataflash_SendAddressBytes(0, 0);
375 }
376
377 /* Write one 16-byte chunk of data to the Dataflash */
378 for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++) {
379 Dataflash_SendByte(*(BufferPtr++));
380 }
381
382 /* Increment the Dataflash page 16 byte block counter */
383 CurrDFPageByteDiv16++;
384
385 /* Increment the block 16 byte block counter */
386 BytesInBlockDiv16++;
387 }
388
389 /* Decrement the blocks remaining counter */
390 TotalBlocks--;
391 }
392
393 /* Write the Dataflash buffer contents back to the Dataflash page */
394 Dataflash_WaitWhileBusy();
395 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
396 Dataflash_SendAddressBytes(CurrDFPage, 0x00);
397 Dataflash_WaitWhileBusy();
398
399 /* Deselect all Dataflash chips */
400 Dataflash_DeselectChip();
401 }
402
412 void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress,
413 uint16_t TotalBlocks,
414 uint8_t *BufferPtr)
415 {
416 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
417 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
418 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
419
420 /* Select the correct starting Dataflash IC for the block requested */
421 Dataflash_SelectChipFromPage(CurrDFPage);
422
423 /* Send the Dataflash main memory page read command */
424 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
425 Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
426 Dataflash_SendByte(0x00);
427 Dataflash_SendByte(0x00);
428 Dataflash_SendByte(0x00);
429 Dataflash_SendByte(0x00);
430
431 while (TotalBlocks) {
432 uint8_t BytesInBlockDiv16 = 0;
433
434 /* Write an endpoint packet sized data block to the Dataflash */
435 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) {
436 /* Check if end of Dataflash page reached */
437 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4)) {
438 /* Reset the Dataflash buffer counter, increment the page counter */
439 CurrDFPageByteDiv16 = 0;
440 CurrDFPage++;
441
442 /* Select the next Dataflash chip based on the new Dataflash page index */
443 Dataflash_SelectChipFromPage(CurrDFPage);
444
445 /* Send the Dataflash main memory page read command */
446 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
447 Dataflash_SendAddressBytes(CurrDFPage, 0);
448 Dataflash_SendByte(0x00);
449 Dataflash_SendByte(0x00);
450 Dataflash_SendByte(0x00);
451 Dataflash_SendByte(0x00);
452 }
453
454 /* Read one 16-byte chunk of data from the Dataflash */
455 for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++) {
456 *(BufferPtr++) = Dataflash_ReceiveByte();
457 }
458
459 /* Increment the Dataflash page 16 byte block counter */
460 CurrDFPageByteDiv16++;
461
462 /* Increment the block 16 byte block counter */
463 BytesInBlockDiv16++;
464 }
465
466 /* Decrement the blocks remaining counter */
467 TotalBlocks--;
468 }
469
470 /* Deselect all Dataflash chips */
471 Dataflash_DeselectChip();
472 }
473
475 void DataflashManager_ResetDataflashProtections(void)
476 {
477 /* Select first Dataflash chip, send the read status register command */
478 Dataflash_SelectChip(DATAFLASH_CHIP1);
479 Dataflash_SendByte(DF_CMD_GETSTATUS);
480
481 /* Check if sector protection is enabled */
482 if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON) {
483 Dataflash_ToggleSelectedChipCS();
484
485 /* Send the commands to disable sector protection */
486 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
487 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
488 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
489 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
490 }
491
492 /* Select second Dataflash chip (if present on selected board), send read status register command */
493 #if (DATAFLASH_TOTALCHIPS == 2)
494 Dataflash_SelectChip(DATAFLASH_CHIP2);
495 Dataflash_SendByte(DF_CMD_GETSTATUS);
496
497 /* Check if sector protection is enabled */
498 if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON) {
499 Dataflash_ToggleSelectedChipCS();
500
501 /* Send the commands to disable sector protection */
502 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
503 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
504 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
505 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
506 }
507 #endif
508
509 /* Deselect current Dataflash chip */
510 Dataflash_DeselectChip();
511 }
512
517 bool DataflashManager_CheckDataflashOperation(void)
518 {
519 uint8_t ReturnByte;
520
521 /* Test first Dataflash IC is present and responding to commands */
522 Dataflash_SelectChip(DATAFLASH_CHIP1);
523 Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
524 ReturnByte = Dataflash_ReceiveByte();
525 Dataflash_DeselectChip();
526
527 /* If returned data is invalid, fail the command */
528 if (ReturnByte != DF_MANUFACTURER_ATMEL) {
529 return false;
530 }
531
532 #if (DATAFLASH_TOTALCHIPS == 2)
533 /* Test second Dataflash IC is present and responding to commands */
534 Dataflash_SelectChip(DATAFLASH_CHIP2);
535 Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
536 ReturnByte = Dataflash_ReceiveByte();
537 Dataflash_DeselectChip();
538
539 /* If returned data is invalid, fail the command */
540 if (ReturnByte != DF_MANUFACTURER_ATMEL) {
541 return false;
542 }
543 #endif
544
545 return true;
546 }