?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 * Data SPI EEPROM Access Routines
4 *
5 *********************************************************************
6 * FileName: SPIEEPROM.c
7 * Dependencies: None
8 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
9 * Compiler: Microchip C32 v1.05 or higher
10 * Microchip C30 v3.12 or higher
11 * Microchip C18 v3.30 or higher
12 * HI-TECH PICC-18 PRO 9.63PL2 or higher
13 * Company: Microchip Technology, Inc.
14 *
15 * Software License Agreement
16 *
17 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
18 * reserved.
19 *
20 * Microchip licenses to you the right to use, modify, copy, and
21 * distribute:
22 * (i) the Software when embedded on a Microchip microcontroller or
23 * digital signal controller product ("Device") which is
24 * integrated into Licensee's product; or
25 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
26 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
27 * used in conjunction with a Microchip ethernet controller for
28 * the sole purpose of interfacing with the ethernet controller.
29 *
30 * You should refer to the license agreement accompanying this
31 * Software for additional information regarding your rights and
32 * obligations.
33 *
34 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
35 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
36 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
37 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
38 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
39 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
40 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
41 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
42 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
43 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
44 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
45 *
46 *
47 * Author Date Comment
48 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49 * Nilesh Rajbharti 5/20/02 Original (Rev. 1.0)
50 * Howard Schlunder 9/01/04 Rewritten for SPI EEPROMs
51 * Howard Schlunder 8/10/06 Modified to control SPI module
52 * frequency whenever EEPROM accessed
53 * to allow bus sharing with different
54 * frequencies.
55 ********************************************************************/
56 #define __SPIEEPROM_C
57  
58 #include "HardwareProfile.h"
59  
60 // If the CS line is not defined, SPIEEPROM.c's content will not be compiled.
61 // If you are using a serial EEPROM please define the CS pin as EEPROM_CS_TRIS
62 // in HardwareProfile.h
63 #if defined(EEPROM_CS_TRIS)
64  
65 #include "TCPIP Stack/TCPIP.h"
66  
67 // IMPORTANT SPI NOTE: The code in this file expects that the SPI interrupt
68 // flag (EEPROM_SPI_IF) be clear at all times. If the SPI is shared with
69 // other hardware, the other code should clear the EEPROM_SPI_IF when it is
70 // done using the SPI.
71  
72 // SPI Serial EEPROM buffer size. To enhance performance while
73 // cooperatively sharing the SPI bus with other peripherals, bytes
74 // read and written to the memory are locally buffered. Legal
75 // sizes are 1 to the EEPROM page size.
76 #define EEPROM_BUFFER_SIZE (32)
77  
78 // Must be the EEPROM write page size, or any binary power of 2 divisor. If
79 // using a smaller number, make sure it is at least EEPROM_BUFFER_SIZE big for
80 // max performance. Microchip 25LC256 uses 64 byte page size, 25LC1024 uses
81 // 256 byte page size, so 64 is compatible with both.
82 #define EEPROM_PAGE_SIZE (64)
83  
84 // EEPROM SPI opcodes
85 #define OPCODE_READ 0x03 // Read data from memory array beginning at selected address
86 #define OPCODE_WRITE 0x02 // Write data to memory array beginning at selected address
87 #define OPCODE_WRDI 0x04 // Reset the write enable latch (disable write operations)
88 #define OPCODE_WREN 0x06 // Set the write enable latch (enable write operations)
89 #define OPCODE_RDSR 0x05 // Read Status register
90 #define OPCODE_WRSR 0x01 // Write Status register
91  
92 #define EEPROM_MAX_SPI_FREQ (10000000ul) // Hz
93  
94 #if defined (__18CXX)
95 #define ClearSPIDoneFlag() {EEPROM_SPI_IF = 0;}
96 #define WaitForDataByte() {while(!EEPROM_SPI_IF); EEPROM_SPI_IF = 0;}
97 #define SPI_ON_BIT (EEPROM_SPICON1bits.SSPEN)
98 #elif defined(__C30__)
99 #define ClearSPIDoneFlag()
100 static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
101 {
102 while ((EEPROM_SPISTATbits.SPITBF == 1) || (EEPROM_SPISTATbits.SPIRBF == 0));
103 }
104  
105 #define SPI_ON_BIT (EEPROM_SPISTATbits.SPIEN)
106 #elif defined( __PIC32MX__ )
107 #define ClearSPIDoneFlag()
108 static inline __attribute__((__always_inline__)) void WaitForDataByte( void )
109 {
110 while (!EEPROM_SPISTATbits.SPITBE || !EEPROM_SPISTATbits.SPIRBF);
111 }
112  
113 #define SPI_ON_BIT (EEPROM_SPICON1bits.ON)
114 #else
115 #error Determine SPI flag mechanism
116 #endif
117  
118 static void DoWrite(void);
119  
120 static DWORD EEPROMAddress;
121 static BYTE EEPROMBuffer[EEPROM_BUFFER_SIZE];
122 static BYTE vBytesInBuffer;
123  
124 /*********************************************************************
125 * Function: void XEEInit(unsigned char speed)
126 *
127 * PreCondition: None
128 *
129 * Input: speed - not used (included for compatibility only)
130 *
131 * Output: None
132 *
133 * Side Effects: None
134 *
135 * Overview: Initialize SPI module to communicate to serial
136 * EEPROM.
137 *
138 * Note: Code sets SPI clock to Fosc/16.
139 ********************************************************************/
140 #if (defined(HPC_EXPLORER) || defined(PIC18_EXPLORER)) && !defined(__18F87J10) && !defined(__18F87J11) && !defined(__18F87J50)
141 #define PROPER_SPICON1 (0x20) /* SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level */
142 #elif defined(__PIC24F__) || defined(__PIC24FK__)
143 #define PROPER_SPICON1 (0x0013 | 0x0120) /* 1:1 primary prescale, 4:1 secondary prescale, CKE=1, MASTER mode */
144 #elif defined(__dsPIC30F__)
145 #define PROPER_SPICON1 (0x0017 | 0x0120) /* 1:1 primary prescale, 3:1 secondary prescale, CKE=1, MASTER mode */
146 #elif defined(__dsPIC33F__) || defined(__PIC24H__)
147 #define PROPER_SPICON1 (0x0003 | 0x0120) /* 1:1 primary prescale, 8:1 secondary prescale, CKE=1, MASTER mode */
148 #elif defined(__PIC32MX__)
149 #define PROPER_SPICON1 (_SPI2CON_ON_MASK | _SPI2CON_FRZ_MASK | _SPI2CON_CKE_MASK | _SPI2CON_MSTEN_MASK)
150 #else
151 #define PROPER_SPICON1 (0x21) /* SSPEN bit is set, SPI in master mode, FOSC/16, IDLE state is low level */
152 #endif
153  
154 void XEEInit(void)
155 {
156 EEPROM_CS_IO = 1;
157 EEPROM_CS_TRIS = 0; // Drive SPI EEPROM chip select pin
158  
159 EEPROM_SCK_TRIS = 0; // Set SCK pin as an output
160 EEPROM_SDI_TRIS = 1; // Make sure SDI pin is an input
161 EEPROM_SDO_TRIS = 0; // Set SDO pin as an output
162  
163 ClearSPIDoneFlag();
164 #if defined(__C30__)
165 EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
166 EEPROM_SPICON2 = 0;
167 EEPROM_SPISTAT = 0; // clear SPI
168 EEPROM_SPISTATbits.SPIEN = 1;
169 #elif defined(__C32__)
170 EEPROM_SPIBRG = (GetPeripheralClock()-1ul)/2ul/EEPROM_MAX_SPI_FREQ;
171 EEPROM_SPICON1 = PROPER_SPICON1;
172 #elif defined(__18CXX)
173 EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
174 EEPROM_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock
175 EEPROM_SPISTATbits.SMP = 0; // Input sampled at middle of data output time
176 #endif
177 }
178  
179  
180 /*********************************************************************
181 * Function: XEE_RESULT XEEBeginRead(DWORD address)
182 *
183 * PreCondition: None
184 *
185 * Input: address - Address at which read is to be performed.
186 *
187 * Output: XEE_SUCCESS
188 *
189 * Side Effects: None
190 *
191 * Overview: Sets internal address counter to given address.
192 *
193 * Note: None
194 ********************************************************************/
195 XEE_RESULT XEEBeginRead(DWORD address)
196 {
197 // Save the address and emptry the contents of our local buffer
198 EEPROMAddress = address;
199 vBytesInBuffer = 0;
200 return XEE_SUCCESS;
201 }
202  
203  
204 /*********************************************************************
205 * Function: BYTE XEERead(void)
206 *
207 * PreCondition: XEEInit() && XEEBeginRead() are already called.
208 *
209 * Input: None
210 *
211 * Output: BYTE that was read
212 *
213 * Side Effects: None
214 *
215 * Overview: Reads next byte from EEPROM; internal address
216 * is incremented by one.
217 *
218 * Note: None
219 ********************************************************************/
220 BYTE XEERead(void)
221 {
222 // Check if no more bytes are left in our local buffer
223 if(vBytesInBuffer == 0u)
224 {
225 // Get a new set of bytes
226 XEEReadArray(EEPROMAddress, EEPROMBuffer, EEPROM_BUFFER_SIZE);
227 EEPROMAddress += EEPROM_BUFFER_SIZE;
228 vBytesInBuffer = EEPROM_BUFFER_SIZE;
229 }
230  
231 // Return a byte from our local buffer
232 return EEPROMBuffer[EEPROM_BUFFER_SIZE - vBytesInBuffer--];
233 }
234  
235 /*********************************************************************
236 * Function: XEE_RESULT XEEEndRead(void)
237 *
238 * PreCondition: None
239 *
240 * Input: None
241 *
242 * Output: XEE_SUCCESS
243 *
244 * Side Effects: None
245 *
246 * Overview: This function does nothing.
247 *
248 * Note: Function is used for backwards compatability with
249 * I2C EEPROM module.
250 ********************************************************************/
251 XEE_RESULT XEEEndRead(void)
252 {
253 return XEE_SUCCESS;
254 }
255  
256  
257 /*********************************************************************
258 * Function: XEE_RESULT XEEReadArray(DWORD address,
259 * BYTE *buffer,
260 * WORD length)
261 *
262 * PreCondition: XEEInit() is already called.
263 *
264 * Input: address - Address from where array is to be read
265 * buffer - Caller supplied buffer to hold the data
266 * length - Number of bytes to read.
267 *
268 * Output: XEE_SUCCESS
269 *
270 * Side Effects: None
271 *
272 * Overview: Reads desired number of bytes in sequential mode.
273 * This function performs all necessary steps
274 * and releases the bus when finished.
275 *
276 * Note: None
277 ********************************************************************/
278 XEE_RESULT XEEReadArray(DWORD address,
279 BYTE *buffer,
280 WORD length)
281 {
282 volatile BYTE Dummy;
283 BYTE vSPIONSave;
284 #if defined(__18CXX)
285 BYTE SPICON1Save;
286 #elif defined(__C30__)
287 WORD SPICON1Save;
288 #else
289 DWORD SPICON1Save;
290 #endif
291  
292 // Save SPI state (clock speed)
293 SPICON1Save = EEPROM_SPICON1;
294 vSPIONSave = SPI_ON_BIT;
295  
296 // Configure SPI
297 SPI_ON_BIT = 0;
298 EEPROM_SPICON1 = PROPER_SPICON1;
299 SPI_ON_BIT = 1;
300  
301 EEPROM_CS_IO = 0;
302  
303 // Send READ opcode
304 EEPROM_SSPBUF = OPCODE_READ;
305 WaitForDataByte();
306 Dummy = EEPROM_SSPBUF;
307  
308 // Send address
309 #if defined(USE_EEPROM_25LC1024)
310 EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[2];
311 WaitForDataByte();
312 Dummy = EEPROM_SSPBUF;
313 #endif
314  
315 EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[1];
316 WaitForDataByte();
317 Dummy = EEPROM_SSPBUF;
318  
319 EEPROM_SSPBUF = ((DWORD_VAL*)&address)->v[0];
320 WaitForDataByte();
321 Dummy = EEPROM_SSPBUF;
322  
323 while(length--)
324 {
325 EEPROM_SSPBUF = 0;
326 WaitForDataByte();
327 Dummy = EEPROM_SSPBUF;
328 if(buffer != NULL)
329 *buffer++ = Dummy;
330 };
331  
332 EEPROM_CS_IO = 1;
333  
334 // Restore SPI state
335 SPI_ON_BIT = 0;
336 EEPROM_SPICON1 = SPICON1Save;
337 SPI_ON_BIT = vSPIONSave;
338  
339  
340 return XEE_SUCCESS;
341 }
342  
343  
344 /*********************************************************************
345 * Function: XEE_RESULT XEEBeginWrite(DWORD address)
346 *
347 * PreCondition: None
348 *
349 * Input: address - address to be set for writing
350 *
351 * Output: XEE_SUCCESS
352 *
353 * Side Effects: None
354 *
355 * Overview: Modifies internal address counter of EEPROM.
356 *
357 * Note: Unlike XEESetAddr() in xeeprom.c for I2C EEPROM
358 * memories, this function is used only for writing
359 * to the EEPROM. Reads must use XEEBeginRead(),
360 * XEERead(), and XEEEndRead().
361 * This function does not use the SPI bus.
362 ********************************************************************/
363 XEE_RESULT XEEBeginWrite(DWORD address)
364 {
365 vBytesInBuffer = 0;
366 EEPROMAddress = address;
367 return XEE_SUCCESS;
368 }
369  
370  
371 /*********************************************************************
372 * Function: XEE_RESULT XEEWrite(BYTE val)
373 *
374 * PreCondition: XEEInit() && XEEBeginWrite() are already called.
375 *
376 * Input: val - Byte to be written
377 *
378 * Output: XEE_SUCCESS
379 *
380 * Side Effects: None
381 *
382 * Overview: Writes a byte to the write cache, and if full,
383 * commits the write. Also, if a write boundary is
384 * reached the write is committed. When finished
385 * writing, XEEEndWrite() must be called to commit
386 * any unwritten bytes from the write cache.
387 *
388 * Note: None
389 ********************************************************************/
390 XEE_RESULT XEEWrite(BYTE val)
391 {
392 EEPROMBuffer[vBytesInBuffer++] = val;
393 if(vBytesInBuffer >= sizeof(EEPROMBuffer))
394 DoWrite();
395 else if((((BYTE)EEPROMAddress + vBytesInBuffer) & (EEPROM_PAGE_SIZE-1)) == 0u)
396 DoWrite();
397  
398 return XEE_SUCCESS;
399 }
400  
401  
402 /*****************************************************************************
403 Function:
404 XEE_RESULT XEEWriteArray(BYTE *val, WORD wLen)
405  
406 Summary:
407 Writes an array of bytes to the EEPROM part.
408  
409 Description:
410 This function writes an array of bytes to the EEPROM at the address
411 specified when XEEBeginWrite() was called. Page boundary crossing is
412 handled internally.
413  
414 Precondition:
415 XEEInit() was called once and XEEBeginWrite() was called.
416  
417 Parameters:
418 vData - The array to write to the next memory location
419 wLen - The length of the data to be written
420  
421 Returns:
422 None
423  
424 Remarks:
425 The internal write cache is flushed at completion, so it is unnecessary
426 to call XEEEndWrite() after calling this function. However, if you do
427 so, no harm will be done.
428 ***************************************************************************/
429 void XEEWriteArray(BYTE *val, WORD wLen)
430 {
431 while(wLen--)
432 XEEWrite(*val++);
433  
434 XEEEndWrite();
435 }
436  
437  
438 /*********************************************************************
439 * Function: XEE_RESULT XEEEndWrite(void)
440 *
441 * PreCondition: XEEInit() && XEEBeginWrite() are already called.
442 *
443 * Input: None
444 *
445 * Output: XEE_SUCCESS
446 *
447 * Side Effects: None
448 *
449 * Overview: Commits any last uncommitted bytes in cache to
450 * physical storage.
451 *
452 * Note: Call this function when you no longer need to
453 * write any more bytes at the selected address.
454 ********************************************************************/
455 XEE_RESULT XEEEndWrite(void)
456 {
457 if(vBytesInBuffer)
458 DoWrite();
459  
460 return XEE_SUCCESS;
461 }
462  
463 static void DoWrite(void)
464 {
465 BYTE i;
466 volatile BYTE vDummy;
467 BYTE vSPIONSave;
468 #if defined(__18CXX)
469 BYTE SPICON1Save;
470 #elif defined(__C30__)
471 WORD SPICON1Save;
472 #else
473 DWORD SPICON1Save;
474 #endif
475  
476 // Save SPI state
477 SPICON1Save = EEPROM_SPICON1;
478 vSPIONSave = SPI_ON_BIT;
479  
480 // Configure SPI
481 SPI_ON_BIT = 0;
482 EEPROM_SPICON1 = PROPER_SPICON1;
483 SPI_ON_BIT = 1;
484  
485 // Set the Write Enable latch
486 EEPROM_CS_IO = 0;
487 EEPROM_SSPBUF = OPCODE_WREN;
488 WaitForDataByte();
489 vDummy = EEPROM_SSPBUF;
490 EEPROM_CS_IO = 1;
491  
492 // Send WRITE opcode
493 EEPROM_CS_IO = 0;
494 EEPROM_SSPBUF = OPCODE_WRITE;
495 WaitForDataByte();
496 vDummy = EEPROM_SSPBUF;
497  
498 // Send address
499 #if defined(USE_EEPROM_25LC1024)
500 EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[2];
501 WaitForDataByte();
502 vDummy = EEPROM_SSPBUF;
503 #endif
504  
505 EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[1];
506 WaitForDataByte();
507 vDummy = EEPROM_SSPBUF;
508  
509 EEPROM_SSPBUF = ((DWORD_VAL*)&EEPROMAddress)->v[0];
510 WaitForDataByte();
511 vDummy = EEPROM_SSPBUF;
512  
513  
514 for(i = 0; i < vBytesInBuffer; i++)
515 {
516 // Send the byte to write
517 EEPROM_SSPBUF = EEPROMBuffer[i];
518 WaitForDataByte();
519 vDummy = EEPROM_SSPBUF;
520 }
521  
522 // Begin the write
523 EEPROM_CS_IO = 1;
524  
525 // Update write address and clear write cache
526 EEPROMAddress += vBytesInBuffer;
527 vBytesInBuffer = 0;
528  
529 // Restore SPI State
530 SPI_ON_BIT = 0;
531 EEPROM_SPICON1 = SPICON1Save;
532 SPI_ON_BIT = vSPIONSave;
533  
534  
535 // Wait for write to complete
536 while( XEEIsBusy() );
537 }
538  
539  
540 /*********************************************************************
541 * Function: BOOL XEEIsBusy(void)
542 *
543 * PreCondition: XEEInit() is already called.
544 *
545 * Input: None
546 *
547 * Output: FALSE if EEPROM is not busy
548 * TRUE if EEPROM is busy
549 *
550 * Side Effects: None
551 *
552 * Overview: Reads the status register
553 *
554 * Note: None
555 ********************************************************************/
556 BOOL XEEIsBusy(void)
557 {
558 volatile BYTE_VAL result;
559 BYTE vSPIONSave;
560 #if defined(__18CXX)
561 BYTE SPICON1Save;
562 #elif defined(__C30__)
563 WORD SPICON1Save;
564 #else
565 DWORD SPICON1Save;
566 #endif
567  
568 // Save SPI state
569 SPICON1Save = EEPROM_SPICON1;
570 vSPIONSave = SPI_ON_BIT;
571  
572 // Configure SPI
573 SPI_ON_BIT = 0;
574 EEPROM_SPICON1 = PROPER_SPICON1;
575 SPI_ON_BIT = 1;
576  
577 EEPROM_CS_IO = 0;
578 // Send RDSR - Read Status Register opcode
579 EEPROM_SSPBUF = OPCODE_RDSR;
580 WaitForDataByte();
581 result.Val = EEPROM_SSPBUF;
582  
583 // Get register contents
584 EEPROM_SSPBUF = 0;
585 WaitForDataByte();
586 result.Val = EEPROM_SSPBUF;
587 EEPROM_CS_IO = 1;
588  
589 // Restore SPI State
590 SPI_ON_BIT = 0;
591 EEPROM_SPICON1 = SPICON1Save;
592 SPI_ON_BIT = vSPIONSave;
593  
594 return result.bits.b0;
595 }
596  
597  
598 #endif //#if defined(EEPROM_CS_TRIS)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3