/[H8]/trunk/docs/Microchip TCP_IP stack/TCPIP Stack/SPIEEPROM.c
ViewVC logotype

Contents of /trunk/docs/Microchip TCP_IP stack/TCPIP Stack/SPIEEPROM.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations) (download)
Thu Apr 19 09:01:15 2007 UTC (17 years, 1 month ago) by hedin
File MIME type: text/plain
File size: 16259 byte(s)
added the TCP/IP stack, source code.
1 /*********************************************************************
2 *
3 * Data SPI EEPROM Access Routines
4 *
5 *********************************************************************
6 * FileName: SPIEEPROM.c
7 * Dependencies: Compiler.h
8 * XEEPROM.h
9 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
10 * Complier: Microchip C18 v3.02 or higher
11 * Microchip C30 v2.01 or higher
12 * Company: Microchip Technology, Inc.
13 *
14 * Software License Agreement
15 *
16 * Copyright © 2002-2007 Microchip Technology Inc. All rights
17 * reserved.
18 *
19 * Microchip licenses to you the right to use, modify, copy, and
20 * distribute:
21 * (i) the Software when embedded on a Microchip microcontroller or
22 * digital signal controller product (“Device”) which is
23 * integrated into Licensee’s product; or
24 * (ii) ONLY the Software driver source files ENC28J60.c and
25 * ENC28J60.h ported to a non-Microchip device used in
26 * conjunction with a Microchip ethernet controller for the
27 * sole purpose of interfacing with the ethernet controller.
28 *
29 * You should refer to the license agreement accompanying this
30 * Software for additional information regarding your rights and
31 * obligations.
32 *
33 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED “AS IS” WITHOUT
34 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
35 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
36 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
37 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
38 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
39 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
40 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
41 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
42 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
43 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
44 *
45 *
46 * Author Date Comment
47 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
48 * Nilesh Rajbharti 5/20/02 Original (Rev. 1.0)
49 * Howard Schlunder 9/01/04 Rewritten for SPI EEPROMs
50 * Howard Schlunder 8/10/06 Modified to control SPI module
51 * frequency whenever EEPROM accessed
52 * to allow bus sharing with different
53 * frequencies.
54 ********************************************************************/
55 #define __SPIEEPROM_C
56
57 #include "TCPIP Stack/TCPIP.h"
58
59 #if defined(MPFS_USE_EEPROM) && defined(EEPROM_CS_TRIS) && defined(STACK_USE_MPFS)
60
61 // IMPORTANT SPI NOTE: The code in this file expects that the SPI interrupt
62 // flag (EEPROM_SPI_IF) be clear at all times. If the SPI is shared with
63 // other hardware, the other code should clear the EEPROM_SPI_IF when it is
64 // done using the SPI.
65
66 // SPI Serial EEPROM buffer size. To enhance performance while
67 // cooperatively sharing the SPI bus with other peripherals, bytes
68 // read and written to the memory are locally buffered. Legal
69 // sizes are 1 to the EEPROM page size.
70 #define EEPROM_BUFFER_SIZE (32)
71
72 // EEPROM SPI opcodes
73 #define READ 0x03 // Read data from memory array beginning at selected address
74 #define WRITE 0x02 // Write data to memory array beginning at selected address
75 #define WRDI 0x04 // Reset the write enable latch (disable write operations)
76 #define WREN 0x06 // Set the write enable latch (enable write operations)
77 #define RDSR 0x05 // Read Status register
78 #define WRSR 0x01 // Write Status register
79
80 static void DoWrite(void);
81
82 static WORD EEPROMAddress;
83 static BYTE EEPROMBuffer[EEPROM_BUFFER_SIZE];
84 static BYTE *EEPROMBufferPtr;
85
86 /*********************************************************************
87 * Function: void XEEInit(unsigned char speed)
88 *
89 * PreCondition: None
90 *
91 * Input: speed - not used (included for compatibility only)
92 *
93 * Output: None
94 *
95 * Side Effects: None
96 *
97 * Overview: Initialize SPI module to communicate to serial
98 * EEPROM.
99 *
100 * Note: Code sets SPI clock to Fosc/16.
101 ********************************************************************/
102 #if defined(HPC_EXPLORER) && !defined(__18F87J10)
103 #define PROPER_SPICON1 (0x20) /* SSPEN bit is set, SPI in master mode, FOSC/4, IDLE state is low level */
104 #elif defined(__PIC24F__)
105 #define PROPER_SPICON1 (0x0013 | 0x0120) /* 1:1 primary prescale, 4:1 secondary prescale, CKE=1, MASTER mode */
106 #elif defined(__dsPIC30F__)
107 #define PROPER_SPICON1 (0x0017 | 0x0120) /* 1:1 primary prescale, 3:1 secondary prescale, CKE=1, MASTER mode */
108 #elif defined(__dsPIC33F__) || defined(__PIC24H__)
109 #define PROPER_SPICON1 (0x0003 | 0x0120) /* 1:1 primary prescale, 8:1 secondary prescale, CKE=1, MASTER mode */
110 #else
111 #define PROPER_SPICON1 (0x21) /* SSPEN bit is set, SPI in master mode, FOSC/16, IDLE state is low level */
112 #endif
113
114 void XEEInit(void)
115 {
116 EEPROM_CS_IO = 1;
117 EEPROM_CS_TRIS = 0; // Drive SPI EEPROM chip select pin
118
119 EEPROM_SCK_TRIS = 0; // Set SCK pin as an output
120 EEPROM_SDI_TRIS = 1; // Make sure SDI pin is an input
121 EEPROM_SDO_TRIS = 0; // Set SDO pin as an output
122
123 EEPROM_SPICON1 = PROPER_SPICON1; // See PROPER_SPICON1 definition above
124 #if defined(__C30__)
125 EEPROM_SPICON2 = 0;
126 EEPROM_SPISTAT = 0; // clear SPI
127 EEPROM_SPISTATbits.SPIEN = 1;
128 #elif defined(__18CXX)
129 EEPROM_SPI_IF = 0;
130 EEPROM_SPISTATbits.CKE = 1; // Transmit data on rising edge of clock
131 EEPROM_SPISTATbits.SMP = 0; // Input sampled at middle of data output time
132 #endif
133 }
134
135
136 /*********************************************************************
137 * Function: XEE_RESULT XEEBeginRead(unsigned char control,
138 * XEE_ADDR address)
139 *
140 * PreCondition: XEEInit() is already called.
141 *
142 * Input: control - EEPROM control and address code.
143 * address - Address at which read is to be performed.
144 *
145 * Output: XEE_SUCCESS if successful
146 * other value if failed.
147 *
148 * Side Effects: None
149 *
150 * Overview: Sets internal address counter to given address.
151 * Puts EEPROM in sequential read mode.
152 *
153 * Note: This function does not release I2C bus.
154 * User must call XEEEndRead() when read is not longer
155 * needed; I2C bus will released after XEEEndRead()
156 * is called.
157 ********************************************************************/
158 XEE_RESULT XEEBeginRead(XEE_ADDR address)
159 {
160 // Save the address and emptry the contents of our local buffer
161 EEPROMAddress = address;
162 EEPROMBufferPtr = EEPROMBuffer + EEPROM_BUFFER_SIZE;
163 return XEE_SUCCESS;
164 }
165
166
167 /*********************************************************************
168 * Function: XEE_RESULT XEERead(void)
169 *
170 * PreCondition: XEEInit() && XEEBeginRead() are already called.
171 *
172 * Input: None
173 *
174 * Output: XEE_SUCCESS if successful
175 * other value if failed.
176 *
177 * Side Effects: None
178 *
179 * Overview: Reads next byte from EEPROM; internal address
180 * is incremented by one.
181 *
182 * Note: This function does not release I2C bus.
183 * User must call XEEEndRead() when read is not longer
184 * needed; I2C bus will released after XEEEndRead()
185 * is called.
186 ********************************************************************/
187 unsigned char XEERead(void)
188 {
189 // Check if no more bytes are left in our local buffer
190 if( EEPROMBufferPtr == EEPROMBuffer + EEPROM_BUFFER_SIZE )
191 {
192 // Get a new set of bytes
193 XEEReadArray(EEPROMAddress, EEPROMBuffer, EEPROM_BUFFER_SIZE);
194 EEPROMAddress += EEPROM_BUFFER_SIZE;
195 EEPROMBufferPtr = EEPROMBuffer;
196 }
197
198 // Return a byte from our local buffer
199 return *EEPROMBufferPtr++;
200 }
201
202 /*********************************************************************
203 * Function: XEE_RESULT XEEEndRead(void)
204 *
205 * PreCondition: XEEInit() && XEEBeginRead() are already called.
206 *
207 * Input: None
208 *
209 * Output: XEE_SUCCESS if successful
210 * other value if failed.
211 *
212 * Side Effects: None
213 *
214 * Overview: Ends sequential read cycle.
215 *
216 * Note: This function ends sequential cycle that was in
217 * progress. It releases I2C bus.
218 ********************************************************************/
219 XEE_RESULT XEEEndRead(void)
220 {
221 return XEE_SUCCESS;
222 }
223
224
225 /*********************************************************************
226 * Function: XEE_RESULT XEEReadArray(unsigned char control,
227 * XEE_ADDR address,
228 * unsigned char *buffer,
229 * unsigned char length)
230 *
231 * PreCondition: XEEInit() is already called.
232 *
233 * Input: control - Unused
234 * address - Address from where array is to be read
235 * buffer - Caller supplied buffer to hold the data
236 * length - Number of bytes to read.
237 *
238 * Output: XEE_SUCCESS if successful
239 * other value if failed.
240 *
241 * Side Effects: None
242 *
243 * Overview: Reads desired number of bytes in sequential mode.
244 * This function performs all necessary steps
245 * and releases the bus when finished.
246 *
247 * Note: None
248 ********************************************************************/
249 XEE_RESULT XEEReadArray(XEE_ADDR address,
250 unsigned char *buffer,
251 unsigned char length)
252 {
253 BYTE Dummy;
254 #if defined(__18CXX)
255 BYTE SPICON1Save;
256 #else
257 WORD SPICON1Save;
258 #endif
259
260 // Save SPI state (clock speed)
261 SPICON1Save = EEPROM_SPICON1;
262 EEPROM_SPICON1 = PROPER_SPICON1;
263
264 EEPROM_CS_IO = 0;
265
266 // Send READ opcode
267 EEPROM_SSPBUF = READ;
268 while(!EEPROM_SPI_IF);
269 Dummy = EEPROM_SSPBUF;
270 EEPROM_SPI_IF = 0;
271
272 // Send address
273 EEPROM_SSPBUF = ((WORD_VAL*)&address)->v[1];
274 while(!EEPROM_SPI_IF);
275 Dummy = EEPROM_SSPBUF;
276 EEPROM_SPI_IF = 0;
277 EEPROM_SSPBUF = ((WORD_VAL*)&address)->v[0];
278 while(!EEPROM_SPI_IF);
279 Dummy = EEPROM_SSPBUF;
280 EEPROM_SPI_IF = 0;
281
282 while(length--)
283 {
284 EEPROM_SSPBUF = 0;
285 while(!EEPROM_SPI_IF);
286 *buffer++ = EEPROM_SSPBUF;
287 EEPROM_SPI_IF = 0;
288 };
289
290 EEPROM_CS_IO = 1;
291
292 // Restore SPI state
293 EEPROM_SPICON1 = SPICON1Save;
294
295 return XEE_SUCCESS;
296 }
297
298
299 /*********************************************************************
300 * Function: XEE_RESULT XEESetAddr(unsigned char control,
301 * XEE_ADDR address)
302 *
303 * PreCondition: XEEInit() is already called.
304 *
305 * Input: control - data EEPROM control code
306 * address - address to be set for writing
307 *
308 * Output: XEE_SUCCESS if successful
309 * other value if failed.
310 *
311 * Side Effects: None
312 *
313 * Overview: Modifies internal address counter of EEPROM.
314 *
315 * Note: Unlike XEESetAddr() in xeeprom.c for I2C EEPROM
316 * memories, this function is used only for writing
317 * to the EEPROM. Reads must use XEEBeginRead(),
318 * XEERead(), and XEEEndRead().
319 * This function does not release the SPI bus.
320 ********************************************************************/
321 XEE_RESULT XEEBeginWrite(XEE_ADDR address)
322 {
323 EEPROMAddress = address;
324 EEPROMBufferPtr = EEPROMBuffer;
325 return XEE_SUCCESS;
326 }
327
328
329 /*********************************************************************
330 * Function: XEE_RESULT XEEWrite(unsigned char val)
331 *
332 * PreCondition: XEEInit() && XEEBeginWrite() are already called.
333 *
334 * Input: val - Byte to be written
335 *
336 * Output: XEE_SUCCESS
337 *
338 * Side Effects: None
339 *
340 * Overview: Adds a byte to the current page to be writen when
341 * XEEEndWrite() is called.
342 *
343 * Note: Page boundary cannot be exceeded or the byte
344 * to be written will be looped back to the
345 * beginning of the page.
346 ********************************************************************/
347 XEE_RESULT XEEWrite(unsigned char val)
348 {
349 *EEPROMBufferPtr++ = val;
350 if( EEPROMBufferPtr == EEPROMBuffer + EEPROM_BUFFER_SIZE )
351 {
352 DoWrite();
353 }
354
355 return XEE_SUCCESS;
356 }
357
358
359 /*********************************************************************
360 * Function: XEE_RESULT XEEEndWrite(void)
361 *
362 * PreCondition: XEEInit() && XEEBeginWrite() are already called.
363 *
364 * Input: None
365 *
366 * Output: XEE_SUCCESS if successful
367 * other value if failed.
368 *
369 * Side Effects: None
370 *
371 * Overview: Instructs EEPROM to begin write cycle.
372 *
373 * Note: Call this function after either page full of bytes
374 * written or no more bytes are left to load.
375 * This function initiates the write cycle.
376 * User must call for XEEIsBusy() to ensure that write
377 * cycle is finished before calling any other
378 * routine.
379 ********************************************************************/
380 XEE_RESULT XEEEndWrite(void)
381 {
382 if( EEPROMBufferPtr != EEPROMBuffer )
383 {
384 DoWrite();
385 }
386
387 return XEE_SUCCESS;
388 }
389
390 static void DoWrite(void)
391 {
392 BYTE Dummy;
393 BYTE BytesToWrite;
394 #if defined(__18CXX)
395 BYTE SPICON1Save;
396 #else
397 WORD SPICON1Save;
398 #endif
399
400 // Save SPI state (clock speed)
401 SPICON1Save = EEPROM_SPICON1;
402 EEPROM_SPICON1 = PROPER_SPICON1;
403
404 // Set the Write Enable latch
405 EEPROM_CS_IO = 0;
406 EEPROM_SSPBUF = WREN;
407 while(!EEPROM_SPI_IF);
408 Dummy = EEPROM_SSPBUF;
409 EEPROM_SPI_IF = 0;
410 EEPROM_CS_IO = 1;
411
412 // Send WRITE opcode
413 EEPROM_CS_IO = 0;
414 EEPROM_SSPBUF = WRITE;
415 while(!EEPROM_SPI_IF);
416 Dummy = EEPROM_SSPBUF;
417 EEPROM_SPI_IF = 0;
418
419 // Send address
420 EEPROM_SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[1];
421 while(!EEPROM_SPI_IF);
422 Dummy = EEPROM_SSPBUF;
423 EEPROM_SPI_IF = 0;
424 EEPROM_SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[0];
425 while(!EEPROM_SPI_IF);
426 Dummy = EEPROM_SSPBUF;
427 EEPROM_SPI_IF = 0;
428
429 BytesToWrite = (BYTE)(EEPROMBufferPtr - EEPROMBuffer);
430
431 EEPROMAddress += BytesToWrite;
432 EEPROMBufferPtr = EEPROMBuffer;
433
434 while(BytesToWrite--)
435 {
436 // Send the byte to write
437 EEPROM_SSPBUF = *EEPROMBufferPtr++;
438 while(!EEPROM_SPI_IF);
439 Dummy = EEPROM_SSPBUF;
440 EEPROM_SPI_IF = 0;
441 }
442
443 // Begin the write
444 EEPROM_CS_IO = 1;
445
446 EEPROMBufferPtr = EEPROMBuffer;
447
448 // Restore SPI State
449 EEPROM_SPICON1 = SPICON1Save;
450
451 // Wait for write to complete
452 while( XEEIsBusy() );
453 }
454
455
456 /*********************************************************************
457 * Function: BOOL XEEIsBusy(void)
458 *
459 * PreCondition: XEEInit() is already called.
460 *
461 * Input: None
462 *
463 * Output: FALSE if EEPROM is not busy
464 * TRUE if EEPROM is busy
465 *
466 * Side Effects: None
467 *
468 * Overview: Reads the status register
469 *
470 * Note: None
471 ********************************************************************/
472 BOOL XEEIsBusy(void)
473 {
474 BYTE_VAL result;
475 #if defined(__18CXX)
476 BYTE SPICON1Save;
477 #else
478 WORD SPICON1Save;
479 #endif
480
481 // Save SPI state (clock speed)
482 SPICON1Save = EEPROM_SPICON1;
483 EEPROM_SPICON1 = PROPER_SPICON1;
484
485 EEPROM_CS_IO = 0;
486 // Send RDSR - Read Status Register opcode
487 EEPROM_SSPBUF = RDSR;
488 while(!EEPROM_SPI_IF);
489 result.Val = EEPROM_SSPBUF;
490 EEPROM_SPI_IF = 0;
491
492 // Get register contents
493 EEPROM_SSPBUF = 0;
494 while(!EEPROM_SPI_IF);
495 result.Val = EEPROM_SSPBUF;
496 EEPROM_SPI_IF = 0;
497 EEPROM_CS_IO = 1;
498
499 // Restore SPI State
500 EEPROM_SPICON1 = SPICON1Save;
501
502 return result.bits.b0;
503 }
504
505
506 #endif //#if defined(MPFS_USE_EEPROM) && defined(EEPROM_CS_TRIS) && defined(STACK_USE_MPFS)

  ViewVC Help
Powered by ViewVC 1.1.20