?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * Microchip File System (MPFS) File Access API
4 * Module for Microchip TCP/IP Stack
5 * -Provides single API for accessing web pages and other files
6 * from internal program memory or an external serial EEPROM memory
7 * -Reference: AN833
8 *
9 *********************************************************************
10 * FileName: MPFS.c
11 * Dependencies: SPIEEPROM.c, SPIFlash.c, or MPFSImg2.c/.s
12 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
13 * Compiler: Microchip C32 v1.05 or higher
14 * Microchip C30 v3.12 or higher
15 * Microchip C18 v3.30 or higher
16 * HI-TECH PICC-18 PRO 9.63PL2 or higher
17 * Company: Microchip Technology, Inc.
18 *
19 * Software License Agreement
20 *
21 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
22 * reserved.
23 *
24 * Microchip licenses to you the right to use, modify, copy, and
25 * distribute:
26 * (i) the Software when embedded on a Microchip microcontroller or
27 * digital signal controller product ("Device") which is
28 * integrated into Licensee's product; or
29 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
30 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
31 * used in conjunction with a Microchip ethernet controller for
32 * the sole purpose of interfacing with the ethernet controller.
33 *
34 * You should refer to the license agreement accompanying this
35 * Software for additional information regarding your rights and
36 * obligations.
37 *
38 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
39 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
40 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
41 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
42 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
43 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
44 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
45 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
46 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
47 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
48 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
49 *
50 *
51 * Author Date Comment
52 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53 * Elliott Wood 07/2007 Complete rewrite as MPFS2
54 * E. Wood 04/2008 Updated as MPFS2.1
55 ********************************************************************/
56 #define __MPFS2_C
57  
58 #include "TCPIP Stack/TCPIP.h"
59  
60 #if defined(STACK_USE_MPFS2)
61  
62 //Supports long file names to 64 characters
63 #define MAX_FILE_NAME_LEN (64u)
64  
65 /*
66 * MPFS Structure:
67 * [M][P][F][S]
68 * [BYTE Ver Hi][BYTE Ver Lo][WORD Number of Files]
69 * [Name Hash 0][Name Hash 1]...[Name Hash N]
70 * [File Record 0][File Record 1]...[File Record N]
71 * [String 0][String 1]...[String N]
72 * [File Data 0][File Data 1]...[File Data N]
73 *
74 * Name Hash (2 bytes):
75 * hash = 0
76 * for each(byte in name)
77 * hash += byte
78 * hash <<= 1
79 *
80 * Technically this means the hash only includes the
81 * final 15 characters of a name.
82 *
83 * File Record Structure (22 bytes):
84 * [DWORD String Ptr][DWORD Data Ptr]
85 * [DWORD Len][DWORD Timestamp][DWORD Microtime]
86 * [WORD Flags]
87 *
88 * Pointers are absolute addresses within the MPFS image.
89 * Timestamp is the UNIX timestamp
90 * Microtime is currently unimplemented
91 *
92 * String Structure (1 to 64 bytes):
93 * ["path/to/file.ext"][0x00]
94 *
95 * File Data Structure (arbitrary length):
96 * [File Data]
97 *
98 * Unlike previous versions, there are no delimiters.
99 *
100 * Name hash is calculated as follows:
101 * hash = 0
102 * for each(byte in name)
103 * hash += byte, hash <<= 1
104 *
105 * When a file has an index, that index file has no file name,
106 * but is accessible as the file immediately following in the image.
107 *
108 * Current version is 2.1
109 */
110  
111 /****************************************************************************
112 Section:
113 Module-Only Globals and Functions
114 ***************************************************************************/
115  
116 // Track the MPFS File Handles
117 // MPFSStubs[0] is reserved for internal use (FAT access)
118 static MPFS_STUB MPFSStubs[MAX_MPFS_HANDLES+1];
119  
120 // Allows the MPFS to be locked, preventing access during updates
121 static BOOL isMPFSLocked;
122  
123 // FAT record cache
124 static MPFS_FAT_RECORD fatCache;
125  
126 // ID of currently loaded fatCache
127 static WORD fatCacheID;
128  
129 // Number of files in this MPFS image
130 static WORD numFiles;
131  
132  
133 static void _LoadFATRecord(WORD fatID);
134 static void _Validate(void);
135  
136 /****************************************************************************
137 Section:
138 EEPROM vs Flash Storage Settings
139 ***************************************************************************/
140  
141 #if defined(MPFS_USE_EEPROM)
142  
143 // Beginning address of MPFS Image
144 #define MPFS_HEAD MPFS_RESERVE_BLOCK
145  
146 // Track the last read address to prevent unnecessary
147 // data overhead to switch locations.
148 MPFS_PTR lastRead;
149  
150  
151 #elif defined(MPFS_USE_SPI_FLASH)
152  
153 // Beginning address of MPFS Image
154 #define MPFS_HEAD MPFS_RESERVE_BLOCK
155  
156 #else
157  
158 // An address where MPFS data starts in program memory.
159 #if defined(__18CXX) || defined(__C32__)
160 extern ROM BYTE MPFS_Start[];
161 #define MPFS_HEAD ((DWORD)(&MPFS_Start[0]))
162 #else
163 extern DWORD MPFS_Start;
164 #define MPFS_HEAD MPFS_Start;
165 #endif
166  
167 #endif
168  
169 /****************************************************************************
170 Section:
171 Stack-Level Functions
172 ***************************************************************************/
173  
174 /*****************************************************************************
175 Function:
176 void MPFSInit(void)
177  
178 Summary:
179 Initializes the MPFS module.
180  
181 Description:
182 Sets all MPFS handles to closed, and initializes access to the EEPROM
183 if necessary.
184  
185 Precondition:
186 None
187  
188 Parameters:
189 None
190  
191 Returns:
192 None
193  
194 Remarks:
195 This function is called only one during lifetime of the application.
196 ***************************************************************************/
197 void MPFSInit(void)
198 {
199 BYTE i;
200  
201 for(i = 1; i <= MAX_MPFS_HANDLES; i++)
202 {
203 MPFSStubs[i].addr = MPFS_INVALID;
204 }
205  
206 #if defined(MPFS_USE_EEPROM)
207 // Initialize the EEPROM access routines.
208 XEEInit();
209 lastRead = MPFS_INVALID;
210 #endif
211  
212 #if defined(MPFS_USE_SPI_FLASH)
213 // Initialize SPI Flash access routines.
214 SPIFlashInit();
215 #endif
216  
217 // Validate the image and load numFiles
218 _Validate();
219  
220 isMPFSLocked = FALSE;
221  
222 }
223  
224 /****************************************************************************
225 Section:
226 Handle Management Functions
227 ***************************************************************************/
228  
229 /*****************************************************************************
230 Function:
231 MPFS_HANDLE MPFSOpen(BYTE* cFile)
232  
233 Description:
234 Opens a file in the MPFS2 file system.
235  
236 Precondition:
237 None
238  
239 Parameters:
240 cFile - a null terminated file name to open
241  
242 Returns:
243 An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE
244 if the file could not be found or no free handles exist.
245 ***************************************************************************/
246 MPFS_HANDLE MPFSOpen(BYTE* cFile)
247 {
248 MPFS_HANDLE hMPFS;
249 WORD nameHash, i;
250 WORD hashCache[8];
251 BYTE *ptr, c;
252  
253 // Initialize c to avoid "may be used uninitialized" compiler warning
254 c = 0;
255  
256 // Make sure MPFS is unlocked and we got a filename
257 if(*cFile == '\0' || isMPFSLocked == TRUE)
258 return MPFS_INVALID_HANDLE;
259  
260 // Calculate the name hash to speed up searching
261 for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
262 {
263 nameHash += *ptr;
264 nameHash <<= 1;
265 }
266  
267 // Find a free file handle to use
268 for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++)
269 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
270 break;
271 if(hMPFS == MAX_MPFS_HANDLES)
272 return MPFS_INVALID_HANDLE;
273  
274 // Read in hashes, and check remainder on a match. Store 8 in cache for performance
275 for(i = 0; i < numFiles; i++)
276 {
277 // For new block of 8, read in data
278 if((i & 0x07) == 0u)
279 {
280 MPFSStubs[0].addr = 8 + i*2;
281 MPFSStubs[0].bytesRem = 16;
282 MPFSGetArray(0, (BYTE*)hashCache, 16);
283 }
284  
285 // If the hash matches, compare the full filename
286 if(hashCache[i&0x07] == nameHash)
287 {
288 _LoadFATRecord(i);
289 MPFSStubs[0].addr = fatCache.string;
290 MPFSStubs[0].bytesRem = 255;
291  
292 // Loop over filename to perform comparison
293 for(ptr = cFile; *ptr != '\0'; ptr++)
294 {
295 MPFSGet(0, &c);
296 if(*ptr != c)
297 break;
298 }
299  
300 MPFSGet(0, &c);
301  
302 if(c == '\0' && *ptr == '\0')
303 {// Filename matches, so return true
304 MPFSStubs[hMPFS].addr = fatCache.data;
305 MPFSStubs[hMPFS].bytesRem = fatCache.len;
306 MPFSStubs[hMPFS].fatID = i;
307 return hMPFS;
308 }
309 }
310 }
311  
312 // No file name matched, so return nothing
313 return MPFS_INVALID_HANDLE;
314 }
315  
316 /*****************************************************************************
317 Function:
318 MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile)
319  
320 Description:
321 Opens a file in the MPFS2 file system.
322  
323 Precondition:
324 None
325  
326 Parameters:
327 cFile - a null terminated file name to open
328  
329 Returns:
330 An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE
331 if the file could not be found or no free handles exist.
332  
333 Remarks:
334 This function is aliased to MPFSOpen on non-PIC18 platforms.
335 ***************************************************************************/
336 #if defined(__18CXX)
337 MPFS_HANDLE MPFSOpenROM(ROM BYTE* cFile)
338 {
339 MPFS_HANDLE hMPFS;
340 WORD nameHash, i;
341 WORD hashCache[8];
342 ROM BYTE *ptr;
343 BYTE c;
344  
345 // Make sure MPFS is unlocked and we got a filename
346 if(*cFile == '\0' || isMPFSLocked == TRUE)
347 return MPFS_INVALID_HANDLE;
348  
349 // Calculate the name hash to speed up searching
350 for(nameHash = 0, ptr = cFile; *ptr != '\0'; ptr++)
351 {
352 nameHash += *ptr;
353 nameHash <<= 1;
354 }
355  
356 // Find a free file handle to use
357 for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++)
358 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
359 break;
360 if(hMPFS == MAX_MPFS_HANDLES)
361 return MPFS_INVALID_HANDLE;
362  
363 // Read in hashes, and check remainder on a match. Store 8 in cache for performance
364 for(i = 0; i < numFiles; i++)
365 {
366 // For new block of 8, read in data
367 if((i & 0x07) == 0u)
368 {
369 MPFSStubs[0].addr = 8 + i*2;
370 MPFSStubs[0].bytesRem = 16;
371 MPFSGetArray(0, (BYTE*)hashCache, 16);
372 }
373  
374 // If the hash matches, compare the full filename
375 if(hashCache[i&0x07] == nameHash)
376 {
377 _LoadFATRecord(i);
378 MPFSStubs[0].addr = fatCache.string;
379 MPFSStubs[0].bytesRem = 255;
380  
381 // Loop over filename to perform comparison
382 for(ptr = cFile; *ptr != '\0'; ptr++)
383 {
384 MPFSGet(0, &c);
385 if(*ptr != c)
386 break;
387 }
388  
389 MPFSGet(0, &c);
390  
391 if(c == '\0' && *ptr == '\0')
392 {// Filename matches, so return true
393 MPFSStubs[hMPFS].addr = fatCache.data;
394 MPFSStubs[hMPFS].bytesRem = fatCache.len;
395 MPFSStubs[hMPFS].fatID = i;
396 return hMPFS;
397 }
398 }
399 }
400  
401 // No file name matched, so return nothing
402 return MPFS_INVALID_HANDLE;
403 }
404 #endif
405  
406 /*****************************************************************************
407 Function:
408 MPFS_HANDLE MPFSOpenID(WORD hFatID)
409  
410 Summary:
411 Quickly re-opens a file.
412  
413 Description:
414 Quickly re-opens a file in the MPFS2 file system. Use this function
415 along with MPFSGetID() to quickly re-open a file without tying up
416 a permanent MPFSStub.
417  
418 Precondition:
419 None
420  
421 Parameters:
422 hFatID - the ID of a previous opened file in the FAT
423  
424 Returns:
425 An MPFS_HANDLE to the opened file if found, or MPFS_INVALID_HANDLE
426 if the file could not be found or no free handles exist.
427 ***************************************************************************/
428 MPFS_HANDLE MPFSOpenID(WORD hFatID)
429 {
430 MPFS_HANDLE hMPFS;
431  
432 // Make sure MPFS is unlocked and we got a valid id
433 if(isMPFSLocked == TRUE || hFatID > numFiles)
434 return MPFS_INVALID_HANDLE;
435  
436 // Find a free file handle to use
437 for(hMPFS = 1; hMPFS <= MAX_MPFS_HANDLES; hMPFS++)
438 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
439 break;
440 if(hMPFS == MAX_MPFS_HANDLES)
441 return MPFS_INVALID_HANDLE;
442  
443 // Load the FAT record
444 _LoadFATRecord(hFatID);
445  
446 // Set up the file handle
447 MPFSStubs[hMPFS].fatID = hFatID;
448 MPFSStubs[hMPFS].addr = fatCache.data;
449 MPFSStubs[hMPFS].bytesRem = fatCache.len;
450  
451 return hMPFS;
452 }
453  
454 /*****************************************************************************
455 Function:
456 void MPFSClose(MPFS_HANDLE hMPFS)
457  
458 Summary:
459 Closes a file.
460  
461 Description:
462 Closes a file and releases its stub back to the pool of available
463 handles.
464  
465 Precondition:
466 None
467  
468 Parameters:
469 hMPFS - the file handle to be closed
470  
471 Returns:
472 None
473 ***************************************************************************/
474 void MPFSClose(MPFS_HANDLE hMPFS)
475 {
476 if(hMPFS != 0u && hMPFS <= MAX_MPFS_HANDLES)
477 MPFSStubs[hMPFS].addr = MPFS_INVALID;
478 }
479  
480  
481 /****************************************************************************
482 Section:
483 Data Reading Functions
484 ***************************************************************************/
485  
486 /*****************************************************************************
487 Function:
488 BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c)
489  
490 Description:
491 Reads a byte from a file.
492  
493 Precondition:
494 The file handle referenced by hMPFS is already open.
495  
496 Parameters:
497 hMPFS - the file handle from which to read
498 c - Where to store the byte that was read
499  
500 Return Values:
501 TRUE - The byte was successfully read
502 FALSE - No byte was read because either the handle was invalid or
503 the end of the file has been reached.
504 ***************************************************************************/
505 BOOL MPFSGet(MPFS_HANDLE hMPFS, BYTE* c)
506 {
507 // Make sure we're reading a valid address
508 if(hMPFS > MAX_MPFS_HANDLES)
509 return FALSE;
510 if( MPFSStubs[hMPFS].addr == MPFS_INVALID ||
511 MPFSStubs[hMPFS].bytesRem == 0u)
512 return FALSE;
513  
514 if(c == NULL)
515 {
516 MPFSStubs[hMPFS].addr++;
517 MPFSStubs[hMPFS].bytesRem--;
518 return TRUE;
519 }
520  
521  
522 // Read function for EEPROM
523 #if defined(MPFS_USE_EEPROM)
524 // For performance, cache the last read address
525 if(MPFSStubs[hMPFS].addr != lastRead+1)
526 XEEBeginRead(MPFSStubs[hMPFS].addr + MPFS_HEAD);
527 *c = XEERead();
528 lastRead = MPFSStubs[hMPFS].addr;
529 MPFSStubs[hMPFS].addr++;
530 #elif defined(MPFS_USE_SPI_FLASH)
531 SPIFlashReadArray(MPFSStubs[hMPFS].addr + MPFS_HEAD, c, 1);
532 MPFSStubs[hMPFS].addr++;
533 #else
534 #if defined(__C30__)
535 {
536 DWORD addr;
537 DWORD_VAL read;
538 BYTE i;
539  
540 // MPFS Images are addressed by the byte; Program memory by the word.
541 //
542 // Flash program memory is 24 bits wide and only even words are
543 // implemented. The upper byte of the upper word is read as 0x00.
544 // Address in program memory of any given byte is (MPFSAddr * 2) / 3
545 //
546 // We will read 24 bits at a time, but need to support using only
547 // fractions of the first and last byte.
548  
549 // Find the beginning address in program memory.
550 addr = (MPFSStubs[hMPFS].addr / 3) << 1;
551  
552 // Find where to start in that first 3 bytes
553 read.Val = (addr * 3) >> 1;
554 if(read.Val == MPFSStubs[hMPFS].addr)
555 i = 0;
556 else if(read.Val+1 == MPFSStubs[hMPFS].addr)
557 i = 1;
558 else
559 i = 2;
560  
561 // Add in the MPFS starting address offset
562 addr += MPFS_HEAD;
563  
564 // Update the MPFS Handle
565 MPFSStubs[hMPFS].addr++;
566  
567 // Read the DWORD
568 read.Val = ReadProgramMemory(addr & 0x00FFFFFF);
569 *c = read.v[i];
570  
571 }
572 #else
573 {
574 DWORD dwHITECHWorkaround = MPFS_HEAD;
575 *c = *((ROM BYTE*)(MPFSStubs[hMPFS].addr+dwHITECHWorkaround));
576 MPFSStubs[hMPFS].addr++;
577 }
578 #endif
579 #endif
580  
581 MPFSStubs[hMPFS].bytesRem--;
582 return TRUE;
583 }
584  
585 /*****************************************************************************
586 Function:
587 WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
588  
589 Description:
590 Reads a series of bytes from a file.
591  
592 Precondition:
593 The file handle referenced by hMPFS is already open.
594  
595 Parameters:
596 hMPFS - the file handle from which to read
597 cData - where to store the bytes that were read
598 wLen - how many bytes to read
599  
600 Returns:
601 The number of bytes successfully read. If this is less than wLen,
602 an EOF occurred while attempting to read.
603 ***************************************************************************/
604 WORD MPFSGetArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
605 {
606 // Make sure we're reading a valid address
607 if(hMPFS > MAX_MPFS_HANDLES)
608 return 0;
609  
610 // Determine how many we can actually read
611 if(wLen > MPFSStubs[hMPFS].bytesRem)
612 wLen = MPFSStubs[hMPFS].bytesRem;
613  
614 // Make sure we're reading a valid address
615 if(MPFSStubs[hMPFS].addr == MPFS_INVALID || wLen == 0u)
616 return 0;
617  
618 if(cData == NULL)
619 {
620 MPFSStubs[hMPFS].addr += wLen;
621 MPFSStubs[hMPFS].bytesRem -= wLen;
622 return wLen;
623 }
624  
625 // Read the data
626 #if defined(MPFS_USE_EEPROM)
627 XEEReadArray(MPFSStubs[hMPFS].addr+MPFS_HEAD, cData, wLen);
628 MPFSStubs[hMPFS].addr += wLen;
629 MPFSStubs[hMPFS].bytesRem -= wLen;
630 lastRead = MPFS_INVALID;
631 #elif defined(MPFS_USE_SPI_FLASH)
632 SPIFlashReadArray(MPFSStubs[hMPFS].addr+MPFS_HEAD, cData, wLen);
633 MPFSStubs[hMPFS].addr += wLen;
634 MPFSStubs[hMPFS].bytesRem -= wLen;
635 #else
636 #if defined(__C30__)
637 {
638 DWORD addr;
639 DWORD_VAL read;
640 WORD count;
641 BYTE i;
642  
643 // MPFS Images are addressed by the byte; Program memory by the word.
644 //
645 // Flash program memory is 24 bits wide and only even words are
646 // implemented. The upper byte of the upper word is read as 0x00.
647 // Address in program memory of any given byte is (MPFSAddr * 2) / 3
648 //
649 // We will read 24 bits at a time, but need to support using only
650 // fractions of the first and last byte.
651  
652 // Find the beginning address in program memory.
653 addr = (MPFSStubs[hMPFS].addr / 3) << 1;
654  
655 // Find where to start in that first 3 bytes
656 read.Val = (addr * 3) >> 1;
657 if(read.Val == MPFSStubs[hMPFS].addr)
658 i = 0;
659 else if(read.Val+1 == MPFSStubs[hMPFS].addr)
660 i = 1;
661 else
662 i = 2;
663  
664 // Add in the MPFS starting address offset
665 addr += MPFS_HEAD;
666  
667 // Update the MPFS Handle
668 MPFSStubs[hMPFS].addr += wLen;
669 MPFSStubs[hMPFS].bytesRem -= wLen;
670  
671 // Read the first DWORD
672 read.Val = ReadProgramMemory(addr & 0x00FFFFFF);
673 addr += 2;
674  
675 // Copy values as needed
676 for(count = wLen; count > 0; cData++, count--)
677 {
678 // Copy the next value in
679 *cData = read.v[i++];
680  
681 // Check if a new DWORD is needed
682 if(i == 3 && count != 1)
683 {// Read in a new DWORD
684 read.Val = ReadProgramMemory(addr & 0x00FFFFFF);
685 addr += 2;
686 i = 0;
687 }
688 }
689  
690 }
691 #else
692 {
693 DWORD dwHITECHWorkaround = MPFS_HEAD;
694 memcpypgm2ram(cData, (ROM void*)(MPFSStubs[hMPFS].addr + dwHITECHWorkaround), wLen);
695 MPFSStubs[hMPFS].addr += wLen;
696 MPFSStubs[hMPFS].bytesRem -= wLen;
697 }
698 #endif
699 #endif
700  
701 return wLen;
702 }
703  
704 /*****************************************************************************
705 Function:
706 BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul)
707  
708 Description:
709 Reads a DWORD or Long value from the MPFS.
710  
711 Precondition:
712 The file handle referenced by hMPFS is already open.
713  
714 Parameters:
715 hMPFS - the file handle from which to read
716 ul - where to store the DWORD or long value that was read
717  
718 Returns:
719 TRUE - The byte was successfully read
720 FALSE - No byte was read because either the handle was invalid or
721 the end of the file has been reached.
722 ***************************************************************************/
723 BOOL MPFSGetLong(MPFS_HANDLE hMPFS, DWORD* ul)
724 {
725 return ( MPFSGetArray(hMPFS, (BYTE*)ul, 4) == 4u );
726 }
727  
728 /*****************************************************************************
729 Function:
730 BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode)
731  
732 Description:
733 Moves the current read pointer to a new location.
734  
735 Precondition:
736 The file handle referenced by hMPFS is already open.
737  
738 Parameters:
739 hMPFS - the file handle to seek with
740 dwOffset - offset from the specified position in the specified direction
741 tMode - one of the MPFS_SEEK_MODE constants
742  
743 Returns:
744 TRUE - the seek was successful
745 FALSE - either the new location or the handle itself was invalid
746 ***************************************************************************/
747 BOOL MPFSSeek(MPFS_HANDLE hMPFS, DWORD dwOffset, MPFS_SEEK_MODE tMode)
748 {
749 DWORD temp;
750  
751 // Make sure a valid file is open
752 if(hMPFS > MAX_MPFS_HANDLES)
753 return FALSE;
754 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
755 return FALSE;
756  
757 switch(tMode)
758 {
759 // Seek offset bytes from start
760 case MPFS_SEEK_START:
761 temp = MPFSGetSize(hMPFS);
762 if(dwOffset > temp)
763 return FALSE;
764  
765 MPFSStubs[hMPFS].addr = MPFSGetStartAddr(hMPFS) + dwOffset;
766 MPFSStubs[hMPFS].bytesRem = temp - dwOffset;
767 return TRUE;
768  
769 // Seek forwards offset bytes
770 case MPFS_SEEK_FORWARD:
771 if(dwOffset > MPFSStubs[hMPFS].bytesRem)
772 return FALSE;
773  
774 MPFSStubs[hMPFS].addr += dwOffset;
775 MPFSStubs[hMPFS].bytesRem -= dwOffset;
776 return TRUE;
777  
778 // Seek backwards offset bytes
779 case MPFS_SEEK_REWIND:
780 temp = MPFSGetStartAddr(hMPFS);
781 if(MPFSStubs[hMPFS].addr < temp + dwOffset)
782 return FALSE;
783  
784 MPFSStubs[hMPFS].addr -= dwOffset;
785 MPFSStubs[hMPFS].bytesRem += dwOffset;
786 return TRUE;
787  
788 // Seek so that offset bytes remain in file
789 case MPFS_SEEK_END:
790 temp = MPFSGetSize(hMPFS);
791 if(dwOffset > temp)
792 return FALSE;
793  
794 MPFSStubs[hMPFS].addr = MPFSGetEndAddr(hMPFS) - dwOffset;
795 MPFSStubs[hMPFS].bytesRem = dwOffset;
796 return TRUE;
797  
798 default:
799 return FALSE;
800 }
801 }
802  
803  
804 /****************************************************************************
805 Section:
806 Data Writing Functions
807 ***************************************************************************/
808  
809 /*****************************************************************************
810 Function:
811 MPFS_HANDLE MPFSFormat(void)
812  
813 Summary:
814 Prepares the MPFS image for writing.
815  
816 Description:
817 Prepares the MPFS image for writing and locks the image so that other
818 processes may not access it.
819  
820 Precondition:
821 None
822  
823 Parameters:
824 None
825  
826 Returns:
827 An MPFS handle that can be used for MPFSPut commands, or
828 MPFS_INVALID_HANDLE when the EEPROM failed to initialize for writing.
829  
830 Remarks:
831 In order to prevent misreads, the MPFS will be inaccessible until
832 MPFSClose is called. This function is not available when the MPFS
833 is stored in internal Flash program memory.
834 ***************************************************************************/
835 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH)
836 MPFS_HANDLE MPFSFormat(void)
837 {
838  
839 BYTE i;
840  
841 // Close all files
842 for(i = 0; i < MAX_MPFS_HANDLES; i++)
843 MPFSStubs[i].addr = MPFS_INVALID;
844  
845 // Lock the image
846 isMPFSLocked = TRUE;
847  
848 #if defined(MPFS_USE_EEPROM)
849 // Set FAT ptr for writing
850 MPFSStubs[0].addr = 0;
851 MPFSStubs[0].fatID = 0xffff;
852 MPFSStubs[0].bytesRem = MPFS_WRITE_PAGE_SIZE - ( ((BYTE)MPFSStubs[0].addr+MPFS_HEAD) & (MPFS_WRITE_PAGE_SIZE-1) );
853  
854 // Set up EEPROM for writing
855 if( XEEBeginWrite(MPFSStubs[0].addr+MPFS_HEAD) == XEE_SUCCESS )
856 return 0x00;
857  
858 return MPFS_INVALID_HANDLE;
859 #else
860 // Set up SPI Flash for writing
861 SPIFlashBeginWrite(MPFS_HEAD);
862 return 0x00;
863 #endif
864 }
865 #endif
866  
867 /*****************************************************************************
868 Function:
869 WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE *cData, WORD wLen)
870  
871 Description:
872 Writes an array of data to the MPFS image.
873  
874 Precondition:
875 MPFSFormat was sucessfully called.
876  
877 Parameters:
878 hMPFS - the file handle for writing
879 cData - the array of bytes to write
880 wLen - how many bytes to write
881  
882 Returns:
883 The number of bytes successfully written.
884  
885 Remarks:
886 For EEPROM, the actual write may not initialize until the internal write
887 page is full. To ensure that previously written data gets stored,
888 MPFSPutEnd must be called after the last call to MPFSPutArray.
889 ***************************************************************************/
890 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH)
891 WORD MPFSPutArray(MPFS_HANDLE hMPFS, BYTE* cData, WORD wLen)
892 {
893 #if defined(MPFS_USE_EEPROM)
894 // Write to the EEPROM
895 WORD count;
896  
897 for(count = 0; count < wLen; count++)
898 {
899 XEEWrite(cData[count]);
900  
901 MPFSStubs[hMPFS].addr++;
902 MPFSStubs[hMPFS].bytesRem--;
903  
904 if(MPFSStubs[hMPFS].bytesRem == 0u)
905 {
906 MPFSPutEnd(FALSE);
907 isMPFSLocked = TRUE;
908 XEEBeginWrite(MPFSStubs[hMPFS].addr+MPFS_HEAD);
909 MPFSStubs[hMPFS].bytesRem = MPFS_WRITE_PAGE_SIZE;
910 }
911 }
912  
913 return count;
914  
915 #else
916 // Write to the SPI Flash
917 SPIFlashWriteArray(cData, wLen);
918 return wLen;
919 #endif
920 }
921 #endif
922  
923 /*****************************************************************************
924 Function:
925 void MPFSPutEnd(void)
926  
927 Description:
928 Finalizes an MPFS writing operation.
929  
930 Precondition:
931 MPFSFormat and MPFSPutArray were sucessfully called.
932  
933 Parameters:
934 final - TRUE if the application is done writing, FALSE if MPFS2 called
935 this function locally.
936  
937 Returns:
938 None
939 ***************************************************************************/
940 #if defined(MPFS_USE_EEPROM) || defined(MPFS_USE_SPI_FLASH)
941 void MPFSPutEnd(BOOL final)
942 {
943 isMPFSLocked = FALSE;
944  
945 #if defined(MPFS_USE_EEPROM)
946 XEEEndWrite();
947 while(XEEIsBusy());
948 #endif
949  
950 if(final)
951 _Validate();
952 }
953 #endif
954  
955  
956 /****************************************************************************
957 Section:
958 Meta Data Accessors
959 ***************************************************************************/
960  
961 /*****************************************************************************
962 Function:
963 static void _LoadFATRecord(WORD fatID)
964  
965 Description:
966 Loads the FAT record for a specified handle.
967  
968 Precondition:
969 None
970  
971 Parameters:
972 fatID - the ID of the file whose FAT is to be loaded
973  
974 Returns:
975 None
976  
977 Remarks:
978 The FAT record will be stored in fatCache.
979 ***************************************************************************/
980 static void _LoadFATRecord(WORD fatID)
981 {
982 if(fatID == fatCacheID || fatID >= numFiles)
983 return;
984  
985 // Read the FAT record to the cache
986 MPFSStubs[0].bytesRem = 22;
987 MPFSStubs[0].addr = 8 + numFiles*2 + fatID*22;
988 MPFSGetArray(0, (BYTE*)&fatCache, 22);
989 fatCacheID = fatID;
990 }
991  
992 /*****************************************************************************
993 Function:
994 DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS)
995  
996 Description:
997 Reads the timestamp for the specified file.
998  
999 Precondition:
1000 The file handle referenced by hMPFS is already open.
1001  
1002 Parameters:
1003 hMPFS - the file handle from which to read the metadata
1004  
1005 Returns:
1006 The timestamp that was read as a DWORD
1007 ***************************************************************************/
1008 DWORD MPFSGetTimestamp(MPFS_HANDLE hMPFS)
1009 {
1010 // Make sure a valid file is open
1011 if(hMPFS > MAX_MPFS_HANDLES)
1012 return 0x00000000;
1013 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1014 return 0x00000000;
1015  
1016 // Move to the point for reading
1017 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1018 return fatCache.timestamp;
1019 }
1020  
1021 /*****************************************************************************
1022 Function:
1023 DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS)
1024  
1025 Description:
1026 Reads the microtime portion of a file's timestamp.
1027  
1028 Precondition:
1029 The file handle referenced by hMPFS is already open.
1030  
1031 Parameters:
1032 hMPFS - the file handle from which to read the metadata
1033  
1034 Returns:
1035 The microtime that was read as a DWORD
1036 ***************************************************************************/
1037 DWORD MPFSGetMicrotime(MPFS_HANDLE hMPFS)
1038 {
1039 // Make sure a valid file is open
1040 if(hMPFS > MAX_MPFS_HANDLES)
1041 return 0x00000000;
1042 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1043 return 0x00000000;
1044  
1045 // Move to the point for reading
1046 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1047 return fatCache.microtime;
1048 }
1049  
1050 /*****************************************************************************
1051 Function:
1052 WORD MPFSGetFlags(MPFS_HANDLE hMPFS)
1053  
1054 Description:
1055 Reads a file's flags.
1056  
1057 Precondition:
1058 The file handle referenced by hMPFS is already open.
1059  
1060 Parameters:
1061 hMPFS - the file handle from which to read the metadata
1062  
1063 Returns:
1064 The flags that were associated with the file
1065 ***************************************************************************/
1066 WORD MPFSGetFlags(MPFS_HANDLE hMPFS)
1067 {
1068 // Make sure a valid file is open
1069 if(hMPFS > MAX_MPFS_HANDLES)
1070 return 0x0000;
1071 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1072 return 0x0000;
1073  
1074 //move to the point for reading
1075 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1076 return fatCache.flags;
1077 }
1078  
1079 /*****************************************************************************
1080 Function:
1081 DWORD MPFSGetSize(MPFS_HANDLE hMPFS)
1082  
1083 Description:
1084 Reads the size of a file.
1085  
1086 Precondition:
1087 The file handle referenced by hMPFS is already open.
1088  
1089 Parameters:
1090 hMPFS - the file handle from which to read the metadata
1091  
1092 Returns:
1093 The size that was read as a DWORD
1094 ***************************************************************************/
1095 DWORD MPFSGetSize(MPFS_HANDLE hMPFS)
1096 {
1097 // Make sure a valid file is open
1098 if(hMPFS > MAX_MPFS_HANDLES)
1099 return 0x00000000;
1100 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1101 return 0x00000000;
1102  
1103 // Move to the point for reading
1104 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1105 return fatCache.len;
1106 }
1107  
1108 /*****************************************************************************
1109 Function:
1110 DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS)
1111  
1112 Description:
1113 Determines how many bytes remain to be read.
1114  
1115 Precondition:
1116 The file handle referenced by hMPFS is already open.
1117  
1118 Parameters:
1119 hMPFS - the file handle from which to read the metadata
1120  
1121 Returns:
1122 The number of bytes remaining in the file as a DWORD
1123 ***************************************************************************/
1124 DWORD MPFSGetBytesRem(MPFS_HANDLE hMPFS)
1125 {
1126 // Make sure a valid file is open
1127 if(hMPFS > MAX_MPFS_HANDLES)
1128 return 0x00000000;
1129 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1130 return 0x00000000;
1131  
1132 return MPFSStubs[hMPFS].bytesRem;
1133 }
1134  
1135 /*****************************************************************************
1136 Function:
1137 MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS)
1138  
1139 Description:
1140 Reads the starting address of a file.
1141  
1142 Precondition:
1143 The file handle referenced by hMPFS is already open.
1144  
1145 Parameters:
1146 hMPFS - the file handle from which to read the metadata
1147  
1148 Returns:
1149 The starting address of the file in the MPFS image
1150 ***************************************************************************/
1151 MPFS_PTR MPFSGetStartAddr(MPFS_HANDLE hMPFS)
1152 {
1153 // Make sure a valid file is open
1154 if(hMPFS > MAX_MPFS_HANDLES)
1155 return 0;
1156 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1157 return MPFS_INVALID;
1158  
1159 // Move to the point for reading
1160 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1161 return fatCache.data;
1162 }
1163  
1164 /*****************************************************************************
1165 Function:
1166 MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS)
1167  
1168 Description:
1169 Determines the ending address of a file.
1170  
1171 Precondition:
1172 The file handle referenced by hMPFS is already open.
1173  
1174 Parameters:
1175 hMPFS - the file handle from which to read the metadata
1176  
1177 Returns:
1178 The address just after the file ends (start address of next file)
1179 ***************************************************************************/
1180 MPFS_PTR MPFSGetEndAddr(MPFS_HANDLE hMPFS)
1181 {
1182 // Make sure a valid file is open
1183 if(hMPFS > MAX_MPFS_HANDLES)
1184 return MPFS_INVALID;
1185 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1186 return MPFS_INVALID;
1187  
1188 // Move to the point for reading
1189 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1190 return fatCache.data + fatCache.len;
1191 }
1192  
1193 /*****************************************************************************
1194 Function:
1195 BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen)
1196  
1197 Description:
1198 Reads the file name of a file that is already open.
1199  
1200 Precondition:
1201 The file handle referenced by hMPFS is already open.
1202  
1203 Parameters:
1204 hMPFS - the file handle from which to determine the file name
1205 cName - where to store the name of the file
1206 wLen - the maximum length of data to store in cName
1207  
1208 Return Values:
1209 TRUE - the file name was successfully located
1210 FALSE - the file handle provided is not currently open
1211 ***************************************************************************/
1212 BOOL MPFSGetFilename(MPFS_HANDLE hMPFS, BYTE* cName, WORD wLen)
1213 {
1214 DWORD addr;
1215  
1216 // Make sure a valid file is open
1217 if(hMPFS > MAX_MPFS_HANDLES)
1218 return FALSE;
1219 if(MPFSStubs[hMPFS].addr == MPFS_INVALID)
1220 return FALSE;
1221  
1222 // Move to the point for reading
1223 _LoadFATRecord(MPFSStubs[hMPFS].fatID);
1224 addr = fatCache.string;
1225 MPFSStubs[0].addr = addr;
1226 MPFSStubs[0].bytesRem = 255;
1227  
1228 // Read the value and return
1229 MPFSGetArray(0, cName, wLen);
1230 return TRUE;
1231 }
1232  
1233 /*****************************************************************************
1234 Function:
1235 DWORD MPFSGetPosition(MPFS_HANDLE hMPFS)
1236  
1237 Description:
1238 Determines the current position in the file
1239  
1240 Precondition:
1241 The file handle referenced by hMPFS is already open.
1242  
1243 Parameters:
1244 hMPFS - the file handle for which to determine position
1245  
1246 Returns:
1247 The position in the file as a DWORD (or MPFS_PTR)
1248  
1249 Remarks:
1250 Calling MPFSSeek(hMPFS, pos, MPFS_SEEK_START) will return the pointer
1251 to this position at a later time. (Where pos is the value returned by
1252 this function.)
1253 ***************************************************************************/
1254 DWORD MPFSGetPosition(MPFS_HANDLE hMPFS)
1255 {
1256 return MPFSStubs[hMPFS].addr - MPFSGetStartAddr(hMPFS);
1257 }
1258  
1259 /*****************************************************************************
1260 Function:
1261 WORD MPFSGetID(MPFS_HANDLE hMPFS)
1262  
1263 Description:
1264 Determines the ID in the FAT for a file.
1265  
1266 Precondition:
1267 The file handle referenced by hMPFS is already open.
1268  
1269 Parameters:
1270 hMPFS - the file handle from which to read the metadata
1271  
1272 Returns:
1273 The ID in the FAT for this file
1274  
1275 Remarks:
1276 Use this function in association with MPFSOpenID to quickly access file
1277 without permanently reserving a file handle.
1278 ***************************************************************************/
1279 WORD MPFSGetID(MPFS_HANDLE hMPFS)
1280 {
1281 return MPFSStubs[hMPFS].fatID;
1282 }
1283  
1284  
1285 /****************************************************************************
1286 Section:
1287 Utility Functions
1288 ***************************************************************************/
1289  
1290 /*****************************************************************************
1291 Function:
1292 void _Validate(void)
1293  
1294 Summary:
1295 Validates the MPFS Image
1296  
1297 Description:
1298 Verifies that the MPFS image is valid, and reads the number of
1299 available files from the image header. This function is called on
1300 boot, and again after any image is written.
1301  
1302 Precondition:
1303 None
1304  
1305 Parameters:
1306 None
1307  
1308 Returns:
1309 None
1310 ***************************************************************************/
1311 static void _Validate(void)
1312 {
1313 // If this function causes an Address Error Exception on 16-bit
1314 // platforms with code stored in internal Flash, make sure your
1315 // compiler memory model settings are correct.
1316 //
1317 // In MPLAB, choose Project Menu > Build Options > Project.
1318 // Select the MPLAB C30 tab and change Cagetory to Memory Model.
1319 // Ensure that Large Code Model is selected, and that the remaining
1320 // options are set to Default.
1321  
1322 // Validate the image and update numFiles
1323 MPFSStubs[0].addr = 0;
1324 MPFSStubs[0].bytesRem = 8;
1325 MPFSGetArray(0, (BYTE*)&fatCache, 6);
1326 if(!memcmppgm2ram((void*)&fatCache, (ROM void*)"MPFS\x02\x01", 6))
1327 MPFSGetArray(0, (BYTE*)&numFiles, 2);
1328 else
1329 numFiles = 0;
1330 fatCacheID = MPFS_INVALID_FAT;
1331 }
1332 #endif //#if defined(STACK_USE_MPFS2)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3