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