6646278ee5bcd2ab52bd3500183eb15b7ff1502d
[pub/USBasp.git] / Demos / Device / ClassDriver / MassStorage / Lib / DataflashManager.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 /** \file
32 *
33 * Functions to manage the physical dataflash media, including reading and writing of
34 * blocks of data. These functions are called by the SCSI layer when data must be stored
35 * or retrieved to/from the physical storage media. If a different media is used (such
36 * as a SD card or EEPROM), functions similar to these will need to be generated.
37 */
38
39 #define INCLUDE_FROM_DATAFLASHMANAGER_C
40 #include "DataflashManager.h"
41
42 /** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board dataflash IC(s), from
43 * the pre-selected data OUT endpoint. This routine reads in OS sized blocks from the endpoint and writes
44 * them to the dataflash in Dataflash page sized blocks.
45 *
46 * \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
47 * \param[in] BlockAddress Data block starting address for the write sequence
48 * \param[in] TotalBlocks Number of blocks of data to write
49 */
50 void DataflashManager_WriteBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)
51 {
52 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
53 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
54 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
55 bool UsingSecondBuffer = false;
56
57 /* Select the correct starting Dataflash IC for the block requested */
58 Dataflash_SelectChipFromPage(CurrDFPage);
59
60 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
61 /* Copy selected dataflash's current page contents to the dataflash buffer */
62 Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
63 Dataflash_SendAddressBytes(CurrDFPage, 0);
64 Dataflash_WaitWhileBusy();
65 #endif
66
67 /* Send the dataflash buffer write command */
68 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
69 Dataflash_SendAddressBytes(0, CurrDFPageByte);
70
71 /* Wait until endpoint is ready before continuing */
72 if (Endpoint_WaitUntilReady())
73 return;
74
75 while (TotalBlocks)
76 {
77 uint8_t BytesInBlockDiv16 = 0;
78
79 /* Write an endpoint packet sized data block to the dataflash */
80 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
81 {
82 /* Check if the endpoint is currently empty */
83 if (!(Endpoint_IsReadWriteAllowed()))
84 {
85 /* Clear the current endpoint bank */
86 Endpoint_ClearOUT();
87
88 /* Wait until the host has sent another packet */
89 if (Endpoint_WaitUntilReady())
90 return;
91 }
92
93 /* Check if end of dataflash page reached */
94 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
95 {
96 /* Write the dataflash buffer contents back to the dataflash page */
97 Dataflash_WaitWhileBusy();
98 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
99 Dataflash_SendAddressBytes(CurrDFPage, 0);
100
101 /* Reset the dataflash buffer counter, increment the page counter */
102 CurrDFPageByteDiv16 = 0;
103 CurrDFPage++;
104
105 /* Once all the dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
106 if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))
107 UsingSecondBuffer = !(UsingSecondBuffer);
108
109 /* Select the next dataflash chip based on the new dataflash page index */
110 Dataflash_SelectChipFromPage(CurrDFPage);
111
112 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
113 /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */
114 if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))
115 {
116 /* Copy selected dataflash's current page contents to the dataflash buffer */
117 Dataflash_WaitWhileBusy();
118 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
119 Dataflash_SendAddressBytes(CurrDFPage, 0);
120 Dataflash_WaitWhileBusy();
121 }
122 #endif
123
124 /* Send the dataflash buffer write command */
125 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2WRITE : DF_CMD_BUFF1WRITE);
126 Dataflash_SendAddressBytes(0, 0);
127 }
128
129 /* Write one 16-byte chunk of data to the dataflash */
130 Dataflash_SendByte(Endpoint_Read_Byte());
131 Dataflash_SendByte(Endpoint_Read_Byte());
132 Dataflash_SendByte(Endpoint_Read_Byte());
133 Dataflash_SendByte(Endpoint_Read_Byte());
134 Dataflash_SendByte(Endpoint_Read_Byte());
135 Dataflash_SendByte(Endpoint_Read_Byte());
136 Dataflash_SendByte(Endpoint_Read_Byte());
137 Dataflash_SendByte(Endpoint_Read_Byte());
138 Dataflash_SendByte(Endpoint_Read_Byte());
139 Dataflash_SendByte(Endpoint_Read_Byte());
140 Dataflash_SendByte(Endpoint_Read_Byte());
141 Dataflash_SendByte(Endpoint_Read_Byte());
142 Dataflash_SendByte(Endpoint_Read_Byte());
143 Dataflash_SendByte(Endpoint_Read_Byte());
144 Dataflash_SendByte(Endpoint_Read_Byte());
145 Dataflash_SendByte(Endpoint_Read_Byte());
146
147 /* Increment the dataflash page 16 byte block counter */
148 CurrDFPageByteDiv16++;
149
150 /* Increment the block 16 byte block counter */
151 BytesInBlockDiv16++;
152
153 /* Check if the current command is being aborted by the host */
154 if (MSInterfaceInfo->State.IsMassStoreReset)
155 return;
156 }
157
158 /* Decrement the blocks remaining counter and reset the sub block counter */
159 TotalBlocks--;
160 }
161
162 /* Write the dataflash buffer contents back to the dataflash page */
163 Dataflash_WaitWhileBusy();
164 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
165 Dataflash_SendAddressBytes(CurrDFPage, 0x00);
166 Dataflash_WaitWhileBusy();
167
168 /* If the endpoint is empty, clear it ready for the next packet from the host */
169 if (!(Endpoint_IsReadWriteAllowed()))
170 Endpoint_ClearOUT();
171
172 /* Deselect all dataflash chips */
173 Dataflash_DeselectChip();
174 }
175
176 /** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board dataflash IC(s), into
177 * the pre-selected data IN endpoint. This routine reads in Dataflash page sized blocks from the Dataflash
178 * and writes them in OS sized blocks to the endpoint.
179 *
180 * \param[in] MSInterfaceInfo Pointer to a structure containing a Mass Storage Class configuration and state
181 * \param[in] BlockAddress Data block starting address for the read sequence
182 * \param[in] TotalBlocks Number of blocks of data to read
183 */
184 void DataflashManager_ReadBlocks(USB_ClassInfo_MS_Device_t* MSInterfaceInfo, const uint32_t BlockAddress, uint16_t TotalBlocks)
185 {
186 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
187 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
188 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
189
190 /* Select the correct starting Dataflash IC for the block requested */
191 Dataflash_SelectChipFromPage(CurrDFPage);
192
193 /* Send the dataflash main memory page read command */
194 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
195 Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
196 Dataflash_SendByte(0x00);
197 Dataflash_SendByte(0x00);
198 Dataflash_SendByte(0x00);
199 Dataflash_SendByte(0x00);
200
201 /* Wait until endpoint is ready before continuing */
202 if (Endpoint_WaitUntilReady())
203 return;
204
205 while (TotalBlocks)
206 {
207 uint8_t BytesInBlockDiv16 = 0;
208
209 /* Write an endpoint packet sized data block to the dataflash */
210 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
211 {
212 /* Check if the endpoint is currently full */
213 if (!(Endpoint_IsReadWriteAllowed()))
214 {
215 /* Clear the endpoint bank to send its contents to the host */
216 Endpoint_ClearIN();
217
218 /* Wait until the endpoint is ready for more data */
219 if (Endpoint_WaitUntilReady())
220 return;
221 }
222
223 /* Check if end of dataflash page reached */
224 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
225 {
226 /* Reset the dataflash buffer counter, increment the page counter */
227 CurrDFPageByteDiv16 = 0;
228 CurrDFPage++;
229
230 /* Select the next dataflash chip based on the new dataflash page index */
231 Dataflash_SelectChipFromPage(CurrDFPage);
232
233 /* Send the dataflash main memory page read command */
234 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
235 Dataflash_SendAddressBytes(CurrDFPage, 0);
236 Dataflash_SendByte(0x00);
237 Dataflash_SendByte(0x00);
238 Dataflash_SendByte(0x00);
239 Dataflash_SendByte(0x00);
240 }
241
242 /* Read one 16-byte chunk of data from the dataflash */
243 Endpoint_Write_Byte(Dataflash_ReceiveByte());
244 Endpoint_Write_Byte(Dataflash_ReceiveByte());
245 Endpoint_Write_Byte(Dataflash_ReceiveByte());
246 Endpoint_Write_Byte(Dataflash_ReceiveByte());
247 Endpoint_Write_Byte(Dataflash_ReceiveByte());
248 Endpoint_Write_Byte(Dataflash_ReceiveByte());
249 Endpoint_Write_Byte(Dataflash_ReceiveByte());
250 Endpoint_Write_Byte(Dataflash_ReceiveByte());
251 Endpoint_Write_Byte(Dataflash_ReceiveByte());
252 Endpoint_Write_Byte(Dataflash_ReceiveByte());
253 Endpoint_Write_Byte(Dataflash_ReceiveByte());
254 Endpoint_Write_Byte(Dataflash_ReceiveByte());
255 Endpoint_Write_Byte(Dataflash_ReceiveByte());
256 Endpoint_Write_Byte(Dataflash_ReceiveByte());
257 Endpoint_Write_Byte(Dataflash_ReceiveByte());
258 Endpoint_Write_Byte(Dataflash_ReceiveByte());
259
260 /* Increment the dataflash page 16 byte block counter */
261 CurrDFPageByteDiv16++;
262
263 /* Increment the block 16 byte block counter */
264 BytesInBlockDiv16++;
265
266 /* Check if the current command is being aborted by the host */
267 if (MSInterfaceInfo->State.IsMassStoreReset)
268 return;
269 }
270
271 /* Decrement the blocks remaining counter */
272 TotalBlocks--;
273 }
274
275 /* If the endpoint is full, send its contents to the host */
276 if (!(Endpoint_IsReadWriteAllowed()))
277 Endpoint_ClearIN();
278
279 /* Deselect all dataflash chips */
280 Dataflash_DeselectChip();
281 }
282
283 /** Writes blocks (OS blocks, not Dataflash pages) to the storage medium, the board dataflash IC(s), from
284 * the a given RAM buffer. This routine reads in OS sized blocks from the buffer and writes them to the
285 * dataflash in Dataflash page sized blocks. This can be linked to FAT libraries to write files to the
286 * dataflash.
287 *
288 * \param[in] BlockAddress Data block starting address for the write sequence
289 * \param[in] TotalBlocks Number of blocks of data to write
290 * \param[in] BufferPtr Pointer to the data source RAM buffer
291 */
292 void DataflashManager_WriteBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)
293 {
294 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
295 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
296 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
297 bool UsingSecondBuffer = false;
298
299 /* Select the correct starting Dataflash IC for the block requested */
300 Dataflash_SelectChipFromPage(CurrDFPage);
301
302 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
303 /* Copy selected dataflash's current page contents to the dataflash buffer */
304 Dataflash_SendByte(DF_CMD_MAINMEMTOBUFF1);
305 Dataflash_SendAddressBytes(CurrDFPage, 0);
306 Dataflash_WaitWhileBusy();
307 #endif
308
309 /* Send the dataflash buffer write command */
310 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
311 Dataflash_SendAddressBytes(0, CurrDFPageByte);
312
313 while (TotalBlocks)
314 {
315 uint8_t BytesInBlockDiv16 = 0;
316
317 /* Write an endpoint packet sized data block to the dataflash */
318 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
319 {
320 /* Check if end of dataflash page reached */
321 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
322 {
323 /* Write the dataflash buffer contents back to the dataflash page */
324 Dataflash_WaitWhileBusy();
325 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
326 Dataflash_SendAddressBytes(CurrDFPage, 0);
327
328 /* Reset the dataflash buffer counter, increment the page counter */
329 CurrDFPageByteDiv16 = 0;
330 CurrDFPage++;
331
332 /* Once all the dataflash ICs have had their first buffers filled, switch buffers to maintain throughput */
333 if (Dataflash_GetSelectedChip() == DATAFLASH_CHIP_MASK(DATAFLASH_TOTALCHIPS))
334 UsingSecondBuffer = !(UsingSecondBuffer);
335
336 /* Select the next dataflash chip based on the new dataflash page index */
337 Dataflash_SelectChipFromPage(CurrDFPage);
338
339 #if (DATAFLASH_PAGE_SIZE > VIRTUAL_MEMORY_BLOCK_SIZE)
340 /* If less than one dataflash page remaining, copy over the existing page to preserve trailing data */
341 if ((TotalBlocks * (VIRTUAL_MEMORY_BLOCK_SIZE >> 4)) < (DATAFLASH_PAGE_SIZE >> 4))
342 {
343 /* Copy selected dataflash's current page contents to the dataflash buffer */
344 Dataflash_WaitWhileBusy();
345 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_MAINMEMTOBUFF2 : DF_CMD_MAINMEMTOBUFF1);
346 Dataflash_SendAddressBytes(CurrDFPage, 0);
347 Dataflash_WaitWhileBusy();
348 }
349 #endif
350
351 /* Send the dataflash buffer write command */
352 Dataflash_ToggleSelectedChipCS();
353 Dataflash_SendByte(DF_CMD_BUFF1WRITE);
354 Dataflash_SendAddressBytes(0, 0);
355 }
356
357 /* Write one 16-byte chunk of data to the dataflash */
358 for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)
359 Dataflash_SendByte(*(BufferPtr++));
360
361 /* Increment the dataflash page 16 byte block counter */
362 CurrDFPageByteDiv16++;
363
364 /* Increment the block 16 byte block counter */
365 BytesInBlockDiv16++;
366 }
367
368 /* Decrement the blocks remaining counter and reset the sub block counter */
369 TotalBlocks--;
370 }
371
372 /* Write the dataflash buffer contents back to the dataflash page */
373 Dataflash_WaitWhileBusy();
374 Dataflash_SendByte(UsingSecondBuffer ? DF_CMD_BUFF2TOMAINMEMWITHERASE : DF_CMD_BUFF1TOMAINMEMWITHERASE);
375 Dataflash_SendAddressBytes(CurrDFPage, 0x00);
376 Dataflash_WaitWhileBusy();
377
378 /* Deselect all dataflash chips */
379 Dataflash_DeselectChip();
380 }
381
382 /** Reads blocks (OS blocks, not Dataflash pages) from the storage medium, the board dataflash IC(s), into
383 * the a preallocated RAM buffer. This routine reads in Dataflash page sized blocks from the Dataflash
384 * and writes them in OS sized blocks to the given buffer. This can be linked to FAT libraries to read
385 * the files stored on the dataflash.
386 *
387 * \param[in] BlockAddress Data block starting address for the read sequence
388 * \param[in] TotalBlocks Number of blocks of data to read
389 * \param[out] BufferPtr Pointer to the data destination RAM buffer
390 */
391 void DataflashManager_ReadBlocks_RAM(const uint32_t BlockAddress, uint16_t TotalBlocks, uint8_t* BufferPtr)
392 {
393 uint16_t CurrDFPage = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) / DATAFLASH_PAGE_SIZE);
394 uint16_t CurrDFPageByte = ((BlockAddress * VIRTUAL_MEMORY_BLOCK_SIZE) % DATAFLASH_PAGE_SIZE);
395 uint8_t CurrDFPageByteDiv16 = (CurrDFPageByte >> 4);
396
397 /* Select the correct starting Dataflash IC for the block requested */
398 Dataflash_SelectChipFromPage(CurrDFPage);
399
400 /* Send the dataflash main memory page read command */
401 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
402 Dataflash_SendAddressBytes(CurrDFPage, CurrDFPageByte);
403 Dataflash_SendByte(0x00);
404 Dataflash_SendByte(0x00);
405 Dataflash_SendByte(0x00);
406 Dataflash_SendByte(0x00);
407
408 while (TotalBlocks)
409 {
410 uint8_t BytesInBlockDiv16 = 0;
411
412 /* Write an endpoint packet sized data block to the dataflash */
413 while (BytesInBlockDiv16 < (VIRTUAL_MEMORY_BLOCK_SIZE >> 4))
414 {
415 /* Check if end of dataflash page reached */
416 if (CurrDFPageByteDiv16 == (DATAFLASH_PAGE_SIZE >> 4))
417 {
418 /* Reset the dataflash buffer counter, increment the page counter */
419 CurrDFPageByteDiv16 = 0;
420 CurrDFPage++;
421
422 /* Select the next dataflash chip based on the new dataflash page index */
423 Dataflash_SelectChipFromPage(CurrDFPage);
424
425 /* Send the dataflash main memory page read command */
426 Dataflash_SendByte(DF_CMD_MAINMEMPAGEREAD);
427 Dataflash_SendAddressBytes(CurrDFPage, 0);
428 Dataflash_SendByte(0x00);
429 Dataflash_SendByte(0x00);
430 Dataflash_SendByte(0x00);
431 Dataflash_SendByte(0x00);
432 }
433
434 /* Read one 16-byte chunk of data from the dataflash */
435 for (uint8_t ByteNum = 0; ByteNum < 16; ByteNum++)
436 *(BufferPtr++) = Dataflash_ReceiveByte();
437
438 /* Increment the dataflash page 16 byte block counter */
439 CurrDFPageByteDiv16++;
440
441 /* Increment the block 16 byte block counter */
442 BytesInBlockDiv16++;
443 }
444
445 /* Decrement the blocks remaining counter */
446 TotalBlocks--;
447 }
448
449 /* Deselect all dataflash chips */
450 Dataflash_DeselectChip();
451 }
452
453 /** Disables the dataflash memory write protection bits on the board Dataflash ICs, if enabled. */
454 void DataflashManager_ResetDataflashProtections(void)
455 {
456 /* Select first dataflash chip, send the read status register command */
457 Dataflash_SelectChip(DATAFLASH_CHIP1);
458 Dataflash_SendByte(DF_CMD_GETSTATUS);
459
460 /* Check if sector protection is enabled */
461 if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)
462 {
463 Dataflash_ToggleSelectedChipCS();
464
465 /* Send the commands to disable sector protection */
466 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
467 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
468 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
469 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
470 }
471
472 /* Select second dataflash chip (if present on selected board), send read status register command */
473 #if (DATAFLASH_TOTALCHIPS == 2)
474 Dataflash_SelectChip(DATAFLASH_CHIP2);
475 Dataflash_SendByte(DF_CMD_GETSTATUS);
476
477 /* Check if sector protection is enabled */
478 if (Dataflash_ReceiveByte() & DF_STATUS_SECTORPROTECTION_ON)
479 {
480 Dataflash_ToggleSelectedChipCS();
481
482 /* Send the commands to disable sector protection */
483 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[0]);
484 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[1]);
485 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[2]);
486 Dataflash_SendByte(DF_CMD_SECTORPROTECTIONOFF[3]);
487 }
488 #endif
489
490 /* Deselect current dataflash chip */
491 Dataflash_DeselectChip();
492 }
493
494 /** Performs a simple test on the attached Dataflash IC(s) to ensure that they are working.
495 *
496 * \return Boolean true if all media chips are working, false otherwise
497 */
498 bool DataflashManager_CheckDataflashOperation(void)
499 {
500 uint8_t ReturnByte;
501
502 /* Test first Dataflash IC is present and responding to commands */
503 Dataflash_SelectChip(DATAFLASH_CHIP1);
504 Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
505 ReturnByte = Dataflash_ReceiveByte();
506 Dataflash_DeselectChip();
507
508 /* If returned data is invalid, fail the command */
509 if (ReturnByte != DF_MANUFACTURER_ATMEL)
510 return false;
511
512 #if (DATAFLASH_TOTALCHIPS == 2)
513 /* Test second Dataflash IC is present and responding to commands */
514 Dataflash_SelectChip(DATAFLASH_CHIP2);
515 Dataflash_SendByte(DF_CMD_READMANUFACTURERDEVICEINFO);
516 ReturnByte = Dataflash_ReceiveByte();
517 Dataflash_DeselectChip();
518
519 /* If returned data is invalid, fail the command */
520 if (ReturnByte != DF_MANUFACTURER_ATMEL)
521 return false;
522 #endif
523
524 return true;
525 }