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) |
Powered by WebSVN v2.8.3