?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 * SPI Flash Interface Headers
4 * - Tested with SST 25VF016B
5 * Expected compatibility with all SST 25VFxxxB devices
6 * - Tested with Spansion 25FL040A
7 * Compatible with other Spansion parts with minor modifications
8 *
9 *********************************************************************
10 * FileName: SPIFlash.c
11 * Dependencies: None
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 * E. Wood 3/20/08 Original
54 ********************************************************************/
55 #define __SPIFLASH_C
56  
57 #include "HardwareProfile.h"
58  
59 #if defined(SPIFLASH_CS_TRIS)
60  
61 #include "TCPIP Stack/TCPIP.h"
62  
63 #define READ 0x03 // SPI Flash opcode: Read up up to 25MHz
64 #define READ_FAST 0x0B // SPI Flash opcode: Read up to 50MHz with 1 dummy byte
65 #define ERASE_4K 0x20 // SPI Flash opcode: 4KByte sector erase
66 #define ERASE_32K 0x52 // SPI Flash opcode: 32KByte block erase
67 #define ERASE_SECTOR 0xD8 // SPI Flash opcode: sector block erase
68 #define ERASE_ALL 0x60 // SPI Flash opcode: Entire chip erase
69 #define WRITE 0x02 // SPI Flash opcode: Write one byte
70 #define WRITE_STREAM 0xAD // SPI Flash opcode: Write continuous stream of words (AAI mode)
71 #define RDSR 0x05 // SPI Flash opcode: Read Status Register
72 #define EWSR 0x50 // SPI Flash opcode: Enable Write Status Register
73 #define WRSR 0x01 // SPI Flash opcode: Write Status Register
74 #define WREN 0x06 // SPI Flash opcode: Write Enable
75 #define WRDI 0x04 // SPI Flash opcode: Write Disable / End AAI mode
76 #define RDID 0x90 // SPI Flash opcode: Read ID
77 #define JEDEC_ID 0x9F // SPI Flash opcode: Read JEDEC ID
78 #define EBSY 0x70 // SPI Flash opcode: Enable write BUSY status on SO pin
79 #define DBSY 0x80 // SPI Flash opcode: Disable write BUSY status on SO pin
80  
81 #define BUSY 0x01 // Mask for Status Register BUSY bit
82 #define WEL 0x02 // Mask for Status Register BUSY bit
83 #define BP0 0x04 // Mask for Status Register BUSY bit
84 #define BP1 0x08 // Mask for Status Register BUSY bit
85 #define BP2 0x10 // Mask for Status Register BUSY bit
86 #define BP3 0x20 // Mask for Status Register BUSY bit
87 #define AAI 0x40 // Mask for Status Register BUSY bit
88 #define BPL 0x80 // Mask for Status Register BUSY bit
89  
90 #if defined(__PIC24F__) || defined(__PIC24FK__)
91 #define PROPER_SPICON1 (0x001B | 0x0120) // 1:1 primary prescale, 2:1 secondary prescale, CKE=1, MASTER mode
92 #elif defined(__dsPIC33F__) || defined(__PIC24H__)
93 #define PROPER_SPICON1 (0x000F | 0x0120) // 1:1 primary prescale, 5:1 secondary prescale, CKE=1, MASTER mode
94 #elif defined(__dsPIC30F__)
95 #define PROPER_SPICON1 (0x0017 | 0x0120) // 1:1 primary prescale, 3:1 secondary prescale, CKE=1, MASTER mode
96 #elif defined(__PIC32MX__)
97 #define PROPER_SPICON1 (_SPI2CON_ON_MASK | _SPI2CON_FRZ_MASK | _SPI2CON_CKE_MASK | _SPI2CON_MSTEN_MASK)
98 #else
99 #define PROPER_SPICON1 (0x20) // SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level
100 #endif
101  
102 // Maximum speed of SPI Flash part in Hz
103 // Should theoretically operate at 25MHz, but need to account for level-shifting delays
104 #define SPIFLASH_MAX_SPI_FREQ (16000000ul)
105  
106 #if defined (__18CXX)
107 #define ClearSPIDoneFlag() {SPIFLASH_SPI_IF = 0;}
108 #define WaitForDataByte() {while(!SPIFLASH_SPI_IF); SPIFLASH_SPI_IF = 0;}
109 #define SPI_ON_BIT (SPIFLASH_SPICON1bits.SSPEN)
110 #elif defined(__C30__)
111 #define ClearSPIDoneFlag()
112 static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
113 {
114 while ((SPIFLASH_SPISTATbits.SPITBF == 1) || (SPIFLASH_SPISTATbits.SPIRBF == 0));
115 }
116  
117 #define SPI_ON_BIT (SPIFLASH_SPISTATbits.SPIEN)
118 #elif defined( __PIC32MX__ )
119 #define ClearSPIDoneFlag()
120 static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
121 {
122 while (!SPIFLASH_SPISTATbits.SPITBE || !SPIFLASH_SPISTATbits.SPIRBF);
123 }
124  
125 #define SPI_ON_BIT (SPIFLASH_SPICON1bits.ON)
126 #else
127 #error Determine SPI flag mechanism
128 #endif
129  
130 // Internal pointer to address being written
131 DWORD dwWriteAddr;
132  
133  
134 void _SendCmd(BYTE cmd);
135 void _WaitWhileBusy(void);
136 //void _GetStatus(void);
137  
138  
139 /*****************************************************************************
140 Function:
141 void SPIFlashInit(void)
142  
143 Description:
144 Initializes SPI Flash module.
145  
146 Precondition:
147 None
148  
149 Parameters:
150 None
151  
152 Returns:
153 None
154  
155 Remarks:
156 This function is only called once during the lifetime of the application.
157  
158 Internal:
159 This function sends WRDI to clear any pending write operation, and also
160 clears the software write-protect on all memory locations.
161 ***************************************************************************/
162 void SPIFlashInit(void)
163 {
164 volatile BYTE Dummy;
165 BYTE vSPIONSave;
166 #if defined(__18CXX)
167 BYTE SPICON1Save;
168 #elif defined(__C30__)
169 WORD SPICON1Save;
170 #else
171 DWORD SPICON1Save;
172 #endif
173  
174 SPIFLASH_CS_IO = 1;
175 SPIFLASH_CS_TRIS = 0; // Drive SPI Flash chip select pin
176  
177 SPIFLASH_SCK_TRIS = 0; // Set SCK pin as an output
178 SPIFLASH_SDI_TRIS = 1; // Make sure SDI pin is an input
179 SPIFLASH_SDO_TRIS = 0; // Set SDO pin as an output
180  
181 // Save SPI state (clock speed)
182 SPICON1Save = SPIFLASH_SPICON1;
183 vSPIONSave = SPI_ON_BIT;
184  
185 // Configure SPI
186 SPI_ON_BIT = 0;
187 SPIFLASH_SPICON1 = PROPER_SPICON1;
188 SPI_ON_BIT = 1;
189  
190 ClearSPIDoneFlag();
191 #if defined(__C30__)
192 SPIFLASH_SPICON2 = 0;
193 SPIFLASH_SPISTAT = 0; // clear SPI
194 SPIFLASH_SPISTATbits.SPIEN = 1;
195 #elif defined(__C32__)
196 SPIFLASH_SPIBRG = (GetPeripheralClock()-1ul)/2ul/SPIFLASH_MAX_SPI_FREQ;
197 #elif defined(__18CXX)
198 SPIFLASH_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock
199 SPIFLASH_SPISTATbits.SMP = 0; // Input sampled at middle of data output time
200 #endif
201  
202  
203 // Clear any pre-existing AAI write mode
204 // This may occur if the PIC is reset during a write, but the Flash is
205 // not tied to the same hardware reset.
206 _SendCmd(WRDI);
207  
208 // Execute Enable-Write-Status-Register (EWSR) instruction
209 _SendCmd(EWSR);
210  
211 // Clear Write-Protect on all memory locations
212 SPIFLASH_CS_IO = 0;
213 SPIFLASH_SSPBUF = WRSR;
214 WaitForDataByte();
215 Dummy = SPIFLASH_SSPBUF;
216  
217 SPIFLASH_SSPBUF = 0x00; // Clear all block protect bits
218 WaitForDataByte();
219 Dummy = SPIFLASH_SSPBUF;
220  
221 SPIFLASH_CS_IO = 1;
222  
223 // Restore SPI state
224 SPI_ON_BIT = 0;
225 SPIFLASH_SPICON1 = SPICON1Save;
226 SPI_ON_BIT = vSPIONSave;
227 }
228  
229  
230 /*****************************************************************************
231 Function:
232 void SPIFlashReadArray(DWORD dwAddress, BYTE *vData, WORD wLength)
233  
234 Description:
235 Reads an array of bytes from the SPI Flash module.
236  
237 Precondition:
238 SPIFlashInit has been called, and the chip is not busy (should be
239 handled elsewhere automatically.)
240  
241 Parameters:
242 dwAddress - Address from which to read
243 vData - Where to store data that has been read
244 wLength - Length of data to read
245  
246 Returns:
247 None
248 ***************************************************************************/
249 void SPIFlashReadArray(DWORD dwAddress, BYTE *vData, WORD wLength)
250 {
251 volatile BYTE Dummy;
252 BYTE vSPIONSave;
253 #if defined(__18CXX)
254 BYTE SPICON1Save;
255 #elif defined(__C30__)
256 WORD SPICON1Save;
257 #else
258 DWORD SPICON1Save;
259 #endif
260  
261 // Ignore operations when the destination is NULL or nothing to read
262 if(vData == NULL || wLength == 0)
263 return;
264  
265 // Save SPI state (clock speed)
266 SPICON1Save = SPIFLASH_SPICON1;
267 vSPIONSave = SPI_ON_BIT;
268  
269 // Configure SPI
270 SPI_ON_BIT = 0;
271 SPIFLASH_SPICON1 = PROPER_SPICON1;
272 SPI_ON_BIT = 1;
273  
274 // Activate chip select
275 SPIFLASH_CS_IO = 0;
276 ClearSPIDoneFlag();
277  
278 // Send READ opcode
279 SPIFLASH_SSPBUF = READ;
280 WaitForDataByte();
281 Dummy = SPIFLASH_SSPBUF;
282  
283 // Send address
284 SPIFLASH_SSPBUF = ((BYTE*)&dwAddress)[2];
285 WaitForDataByte();
286 Dummy = SPIFLASH_SSPBUF;
287  
288 SPIFLASH_SSPBUF = ((BYTE*)&dwAddress)[1];
289 WaitForDataByte();
290 Dummy = SPIFLASH_SSPBUF;
291  
292 SPIFLASH_SSPBUF = ((BYTE*)&dwAddress)[0];
293 WaitForDataByte();
294 Dummy = SPIFLASH_SSPBUF;
295  
296 // Read data
297 while(wLength--)
298 {
299 SPIFLASH_SSPBUF = 0;
300 WaitForDataByte();
301 *vData++ = SPIFLASH_SSPBUF;
302 };
303  
304 // Deactivate chip select
305 SPIFLASH_CS_IO = 1;
306  
307 // Restore SPI state
308 SPI_ON_BIT = 0;
309 SPIFLASH_SPICON1 = SPICON1Save;
310 SPI_ON_BIT = vSPIONSave;
311 }
312  
313 /*****************************************************************************
314 Function:
315 void SPIFlashBeginWrite(DWORD dwAddr)
316  
317 Summary:
318 Prepares the SPI Flash module for writing.
319  
320 Description:
321 Prepares the SPI Flash module for writing. Subsequent calls to
322 SPIFlashWrite or SPIFlashWriteArray will begin at this location and
323 continue sequentially.
324  
325 SPI Flash
326  
327 Precondition:
328 SPIFlashInit has been called.
329  
330 Parameters:
331 dwAddr - Address where the writing will begin
332  
333 Returns:
334 None
335  
336 Remarks:
337 Flash parts have large sector sizes, and can only erase entire sectors
338 at once. The SST parts for which this library was written have sectors
339 that are 4kB in size. Your application must ensure that writes begin on
340 a sector boundary so that the SPIFlashWrite functions will erase the
341 sector before attempting to write. Entire sectors need not be written
342 at once, so applications can begin writing to the front of a sector,
343 perform other tasks, then later call SPIFlashBeginWrite and point to an
344 address in this sector that has not yet been programmed. However, care
345 must taken to ensure that writes are not attempted on addresses that are
346 not in the erased state. The chip will provide no indication that the
347 write has failed, and will silently ignore the command.
348 ***************************************************************************/
349 void SPIFlashBeginWrite(DWORD dwAddr)
350 {
351 dwWriteAddr = dwAddr;
352 }
353  
354 /*****************************************************************************
355 Function:
356 void SPIFlashWrite(BYTE vData)
357  
358 Summary:
359 Writes a byte to the SPI Flash part.
360  
361 Description:
362 This function writes a byte to the SPI Flash part. If the current
363 address pointer indicates the beginning of a 4kB sector, the entire
364 sector will first be erased to allow writes to proceed. If the current
365 address pointer indicates elsewhere, it will be assumed that the sector
366 has already been erased. If this is not true, the chip will silently
367 ignore the write command.
368  
369 Precondition:
370 SPIFlashInit and SPIFlashBeginWrite have been called, and the current
371 address is either the front of a 4kB sector or has already been erased.
372  
373 Parameters:
374 vData - The byte to write to the next memory location.
375  
376 Returns:
377 None
378  
379 Remarks:
380 See Remarks in SPIFlashBeginWrite for important information about Flash
381 memory parts.
382 ***************************************************************************/
383 void SPIFlashWrite(BYTE vData)
384 {
385 volatile BYTE Dummy;
386 BYTE vSPIONSave;
387 #if defined(__18CXX)
388 BYTE SPICON1Save;
389 #elif defined(__C30__)
390 WORD SPICON1Save;
391 #else
392 DWORD SPICON1Save;
393 #endif
394  
395 // Save SPI state (clock speed)
396 SPICON1Save = SPIFLASH_SPICON1;
397 vSPIONSave = SPI_ON_BIT;
398  
399 // Configure SPI
400 SPI_ON_BIT = 0;
401 SPIFLASH_SPICON1 = PROPER_SPICON1;
402 SPI_ON_BIT = 1;
403  
404 // If address is a boundary, erase a sector first
405 if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0)
406 SPIFlashEraseSector(dwWriteAddr);
407  
408 // Enable writing
409 _SendCmd(WREN);
410  
411 // Activate the chip select
412 SPIFLASH_CS_IO = 0;
413 ClearSPIDoneFlag();
414  
415 // Issue WRITE command with address
416 SPIFLASH_SSPBUF = WRITE;
417 WaitForDataByte();
418 Dummy = SPIFLASH_SSPBUF;
419  
420 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[2];
421 WaitForDataByte();
422 Dummy = SPIFLASH_SSPBUF;
423  
424 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[1];
425 WaitForDataByte();
426 Dummy = SPIFLASH_SSPBUF;
427  
428 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[0];
429 WaitForDataByte();
430 Dummy = SPIFLASH_SSPBUF;
431  
432 // Write the byte
433 SPIFLASH_SSPBUF = vData;
434 WaitForDataByte();
435 Dummy = SPIFLASH_SSPBUF;
436 dwWriteAddr++;
437  
438 // Deactivate chip select and wait for write to complete
439 SPIFLASH_CS_IO = 1;
440 _WaitWhileBusy();
441  
442 // Restore SPI state
443 SPI_ON_BIT = 0;
444 SPIFLASH_SPICON1 = SPICON1Save;
445 SPI_ON_BIT = vSPIONSave;
446 }
447  
448 /*****************************************************************************
449 Function:
450 void SPIFlashWriteArray(BYTE* vData, WORD wLen)
451  
452 Summary:
453 Writes an array of bytes to the SPI Flash part.
454  
455 Description:
456 This function writes an array of bytes to the SPI Flash part. When the
457 address pointer crosses a sector boundary (and has more data to write),
458 the next sector will automatically be erased. If the current address
459 pointer indicates an address that is not a sector boundary and is not
460 already erased, the chip will silently ignore the write command until the
461 next sector boundary is crossed.
462  
463 Precondition:
464 SPIFlashInit and SPIFlashBeginWrite have been called, and the current
465 address is either the front of a sector or has already been erased.
466  
467 Parameters:
468 vData - The array to write to the next memory location
469 wLen - The length of the data to be written
470  
471 Returns:
472 None
473  
474 Remarks:
475 See Remarks in SPIFlashBeginWrite for important information about Flash
476 memory parts.
477 ***************************************************************************/
478 void SPIFlashWriteArray(BYTE* vData, WORD wLen)
479 {
480 volatile BYTE Dummy;
481 BYTE vSPIONSave;
482 #if defined(__18CXX)
483 BYTE SPICON1Save;
484 #elif defined(__C30__)
485 WORD SPICON1Save;
486 #else
487 DWORD SPICON1Save;
488 #endif
489 BOOL isStarted;
490  
491 // Save SPI state (clock speed)
492 SPICON1Save = SPIFLASH_SPICON1;
493 vSPIONSave = SPI_ON_BIT;
494  
495 // Configure SPI
496 SPI_ON_BIT = 0;
497 SPIFLASH_SPICON1 = PROPER_SPICON1;
498 SPI_ON_BIT = 1;
499  
500 #if defined(SPI_FLASH_SST)
501 // If starting at an odd address, write a single byte
502 if((dwWriteAddr & 0x01) && wLen)
503 {
504 SPIFlashWrite(*vData);
505 vData++;
506 wLen--;
507 }
508  
509 isStarted = FALSE;
510  
511 // Loop over all remaining WORDs
512 while(wLen > 1)
513 {
514 // Don't do anything until chip is ready
515 _WaitWhileBusy();
516  
517 // If address is a sector boundary
518 if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0)
519 SPIFlashEraseSector(dwWriteAddr);
520  
521 // If not yet started, initiate AAI mode
522 if(!isStarted)
523 {
524 // Enable writing
525 _SendCmd(WREN);
526  
527 // Activate the chip select
528 SPIFLASH_CS_IO = 0;
529 ClearSPIDoneFlag();
530  
531 // Issue WRITE_STREAM command with address
532 SPIFLASH_SSPBUF = WRITE_STREAM;
533 WaitForDataByte();
534 Dummy = SPIFLASH_SSPBUF;
535  
536 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[2];
537 WaitForDataByte();
538 Dummy = SPIFLASH_SSPBUF;
539  
540 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[1];
541 WaitForDataByte();
542 Dummy = SPIFLASH_SSPBUF;
543  
544 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[0];
545 WaitForDataByte();
546 Dummy = SPIFLASH_SSPBUF;
547  
548 isStarted = TRUE;
549 }
550 // Otherwise, just write the AAI command again
551 else
552 {
553 // Assert the chip select pin
554 SPIFLASH_CS_IO = 0;
555 ClearSPIDoneFlag();
556  
557 // Issue the WRITE_STREAM command for continuation
558 SPIFLASH_SSPBUF = WRITE_STREAM;
559 WaitForDataByte();
560 Dummy = SPIFLASH_SSPBUF;
561 }
562  
563 // Write the two bytes
564 SPIFLASH_SSPBUF = *vData++;
565 WaitForDataByte();
566 Dummy = SPIFLASH_SSPBUF;
567  
568 SPIFLASH_SSPBUF = *vData++;
569 WaitForDataByte();
570 Dummy = SPIFLASH_SSPBUF;
571  
572 // Release the chip select to begin the write
573 SPIFLASH_CS_IO = 1;
574  
575 // Increment the address, decrement length
576 dwWriteAddr += 2;
577 wLen -= 2;
578  
579 // If a boundary was reached, end the write
580 if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0)
581 {
582 _WaitWhileBusy();
583 _SendCmd(WRDI);
584 isStarted = FALSE;
585 }
586 }
587  
588 // Wait for write to complete, then exit AAI mode
589 _WaitWhileBusy();
590 _SendCmd(WRDI);
591  
592 // If a byte remains, write the odd address
593 if(wLen)
594 SPIFlashWrite(*vData);
595  
596 #elif defined(SPI_FLASH_SPANSION)
597  
598 // Loop over all data to be written
599 while(wLen)
600 {
601 // If address is a sector boundary, erase a sector first
602 if((dwWriteAddr & SPI_FLASH_SECTOR_MASK) == 0)
603 SPIFlashEraseSector(dwWriteAddr);
604  
605 // Enable writing
606 _SendCmd(WREN);
607  
608 // Activate the chip select
609 SPIFLASH_CS_IO = 0;
610 ClearSPIDoneFlag();
611  
612 // Issue WRITE command with address
613 SPIFLASH_SSPBUF = WRITE;
614 WaitForDataByte();
615 Dummy = SPIFLASH_SSPBUF;
616  
617 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[2];
618 WaitForDataByte();
619 Dummy = SPIFLASH_SSPBUF;
620  
621 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[1];
622 WaitForDataByte();
623 Dummy = SPIFLASH_SSPBUF;
624  
625 SPIFLASH_SSPBUF = ((BYTE*)&dwWriteAddr)[0];
626 WaitForDataByte();
627 Dummy = SPIFLASH_SSPBUF;
628  
629 // Write the bytes, up to a page boundary
630 do
631 {
632 SPIFLASH_SSPBUF = *vData++;
633 WaitForDataByte();
634 Dummy = SPIFLASH_SSPBUF;
635  
636 dwWriteAddr++;
637 wLen--;
638 } while(wLen && (dwWriteAddr & SPI_FLASH_PAGE_MASK));
639  
640 // Deactivate chip select and wait for write to complete
641 SPIFLASH_CS_IO = 1;
642 _WaitWhileBusy();
643 }
644 #endif
645  
646 // Restore SPI state
647 SPI_ON_BIT = 0;
648 SPIFLASH_SPICON1 = SPICON1Save;
649 SPI_ON_BIT = vSPIONSave;
650 }
651  
652  
653 /*****************************************************************************
654 Function:
655 void SPIFlashEraseSector(DWORD dwAddr)
656  
657 Summary:
658 Erases a sector.
659  
660 Description:
661 This function erases a sector in the Flash part. It is called
662 internally by the SPIFlashWrite functions whenever a write is attempted
663 on the first byte in a sector.
664  
665 Precondition:
666 SPIFlashInit has been called.
667  
668 Parameters:
669 dwAddr - The address of the sector to be erased.
670  
671 Returns:
672 None
673  
674 Remarks:
675 See Remarks in SPIFlashBeginWrite for important information about Flash
676 memory parts.
677 ***************************************************************************/
678 void SPIFlashEraseSector(DWORD dwAddr)
679 {
680 volatile BYTE Dummy;
681 BYTE vSPIONSave;
682 #if defined(__18CXX)
683 BYTE SPICON1Save;
684 #elif defined(__C30__)
685 WORD SPICON1Save;
686 #else
687 DWORD SPICON1Save;
688 #endif
689  
690 // Save SPI state (clock speed)
691 SPICON1Save = SPIFLASH_SPICON1;
692 vSPIONSave = SPI_ON_BIT;
693  
694 // Configure SPI
695 SPI_ON_BIT = 0;
696 SPIFLASH_SPICON1 = PROPER_SPICON1;
697 SPI_ON_BIT = 1;
698  
699 // Enable writing
700 _SendCmd(WREN);
701  
702 // Activate the chip select
703 SPIFLASH_CS_IO = 0;
704 ClearSPIDoneFlag();
705  
706 // Issue ERASE command with address
707 #if defined(SPI_FLASH_SST)
708 SPIFLASH_SSPBUF = ERASE_4K;
709 #elif defined(SPI_FLASH_SPANSION)
710 SPIFLASH_SSPBUF = ERASE_SECTOR;
711 #endif
712 WaitForDataByte();
713 Dummy = SPIFLASH_SSPBUF;
714  
715 SPIFLASH_SSPBUF = ((BYTE*)&dwAddr)[2];
716 WaitForDataByte();
717 Dummy = SPIFLASH_SSPBUF;
718  
719 SPIFLASH_SSPBUF = ((BYTE*)&dwAddr)[1];
720 WaitForDataByte();
721 Dummy = SPIFLASH_SSPBUF;
722  
723 SPIFLASH_SSPBUF = ((BYTE*)&dwAddr)[0];
724 WaitForDataByte();
725 Dummy = SPIFLASH_SSPBUF;
726  
727 // Deactivate chip select to perform the erase
728 SPIFLASH_CS_IO = 1;
729  
730 // Wait for erase to complete
731 _WaitWhileBusy();
732  
733 // Restore SPI state
734 SPI_ON_BIT = 0;
735 SPIFLASH_SPICON1 = SPICON1Save;
736 SPI_ON_BIT = vSPIONSave;
737 }
738  
739 /*****************************************************************************
740 Function:
741 void _SendCmd(BYTE cmd)
742  
743 Summary:
744 Sends a single-byte command to the SPI Flash part.
745  
746 Description:
747 This function sends a single-byte command to the SPI Flash part. It is
748 used for commands such as WREN, WRDI, and EWSR that must have the chip
749 select activated, then deactivated immediately after the command is
750 transmitted.
751  
752 Precondition:
753 SPIFlashInit has been called.
754  
755 Parameters:
756 cmd - The single-byte command code to send
757  
758 Returns:
759 None
760 ***************************************************************************/
761 void _SendCmd(BYTE cmd)
762 {
763 // Activate chip select
764 SPIFLASH_CS_IO = 0;
765 ClearSPIDoneFlag();
766  
767 // Send Read Status Register instruction
768 SPIFLASH_SSPBUF = cmd;
769 WaitForDataByte();
770 cmd = SPIFLASH_SSPBUF;
771  
772 // Deactivate chip select
773 SPIFLASH_CS_IO = 1;
774 }
775  
776  
777 /*****************************************************************************
778 Function:
779 void _WaitWhileBusy(void)
780  
781 Summary:
782 Waits for the SPI Flash part to indicate it is idle.
783  
784 Description:
785 This function waits for the SPI Flash part to indicate it is idle. It is
786 used in the programming functions to wait for operations to complete.
787  
788 Precondition:
789 SPIFlashInit has been called.
790  
791 Parameters:
792 None
793  
794 Returns:
795 None
796 ***************************************************************************/
797 void _WaitWhileBusy(void)
798 {
799 volatile BYTE Dummy;
800  
801 // Activate chip select
802 SPIFLASH_CS_IO = 0;
803 ClearSPIDoneFlag();
804  
805 // Send Read Status Register instruction
806 SPIFLASH_SSPBUF = RDSR;
807 WaitForDataByte();
808 Dummy = SPIFLASH_SSPBUF;
809  
810 // Poll the BUSY bit
811 do
812 {
813 SPIFLASH_SSPBUF = 0x00;
814 WaitForDataByte();
815 Dummy = SPIFLASH_SSPBUF;
816 } while(Dummy & BUSY);
817  
818 // Deactivate chip select
819 SPIFLASH_CS_IO = 1;
820 }
821  
822 /*****************************************************************************
823 Function:
824 void _GetStatus()
825  
826 Summary:
827 Reads the status register of the part.
828  
829 Description:
830 This function reads the status register of the part. It was written
831 for debugging purposes, and is not needed for normal operation. Place
832 a breakpoint at the last instruction and check the "status" variable to
833 see the result.
834  
835 Precondition:
836 SPIFlashInit has been called.
837  
838 Parameters:
839 None
840  
841 Returns:
842 None
843 ***************************************************************************/
844 //void _GetStatus()
845 //{
846 // volatile BYTE Dummy;
847 // static BYTE statuses[16];
848 // static BYTE *status = statuses;
849 //
850 // // Activate chip select
851 // SPIFLASH_CS_IO = 0;
852 // ClearSPIDoneFlag();
853 //
854 // // Send Read Status Register instruction
855 // SPIFLASH_SSPBUF = RDSR;
856 // WaitForDataByte();
857 // Dummy = SPIFLASH_SSPBUF;
858 //
859 // SPIFLASH_SSPBUF = 0x00;
860 // WaitForDataByte();
861 // *status = SPIFLASH_SSPBUF;
862 // status++;
863 //
864 // // Deactivate chip select
865 // SPIFLASH_CS_IO = 1;
866 //
867 // if(status == &statuses[10])
868 // statuses[15] = 0;
869 //}
870  
871 #endif //#if defined(SPIFLASH_CS_TRIS)
872  
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3