00001 00002 00003 00015 /********************************************************************* 00016 * Software License Agreement 00017 * 00018 * Copyright (C) 2002-2008 Microchip Technology Inc. All rights 00019 * reserved. 00020 * 00021 * Microchip licenses to you the right to use, modify, copy, and 00022 * distribute: 00023 * (i) the Software when embedded on a Microchip microcontroller or 00024 * digital signal controller product ("Device") which is 00025 * integrated into Licensee's product; or 00026 * (ii) ONLY the Software driver source files ENC28J60.c and 00027 * ENC28J60.h ported to a non-Microchip device used in 00028 * conjunction with a Microchip ethernet controller for the 00029 * sole purpose of interfacing with the ethernet controller. 00030 * 00031 * You should refer to the license agreement accompanying this 00032 * Software for additional information regarding your rights and 00033 * obligations. 00034 * 00035 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT 00036 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT 00037 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A 00038 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL 00039 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR 00040 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF 00041 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS 00042 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE 00043 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER 00044 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT 00045 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE. 00046 * 00047 * 00048 * Author Date Comment 00049 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00050 * Nilesh Rajbharti 5/20/02 Original (Rev. 1.0) 00051 * Howard Schlunder 9/01/04 Rewritten for SPI EEPROMs 00052 * Howard Schlunder 8/10/06 Modified to control SPI module 00053 * frequency whenever EEPROM accessed 00054 * to allow bus sharing with different 00055 * frequencies. 00056 ********************************************************************/ 00057 #define __SPIEEPROM_C 00058 00059 #include "TCPIP.h" 00060 00062 // Local Defines 00064 00065 // SPI Serial EEPROM buffer size. To enhance performance while 00066 // cooperatively sharing the SPI bus with other peripherals, bytes 00067 // read and written to the memory are locally buffered. Legal 00068 // sizes are 1 to the EEPROM page size. 00069 #define EEPROM_BUFFER_SIZE (32) 00070 00071 // EEPROM SPI opcodes 00072 #define READ 0x03 // Read data from memory array beginning at selected address 00073 #define WRITE 0x02 // Write data to memory array beginning at selected address 00074 #define WRDI 0x04 // Reset the write enable latch (disable write operations) 00075 #define WREN 0x06 // Set the write enable latch (enable write operations) 00076 #define RDSR 0x05 // Read Status register 00077 #define WRSR 0x01 // Write Status register 00078 00079 #define EEPROM_CS_IO (LATFbits.LATF5) 00080 00081 00083 // Local function prototypes 00085 00086 static void DoWrite(void); 00087 // MODIFIX: Moved the following prototypes from the header file to this 00088 // location and made them static. 00089 static XEE_RESULT XEEBeginWrite(XEE_ADDR address); 00090 static XEE_RESULT XEEWrite(unsigned char val); 00091 static XEE_RESULT XEEEndWrite(void); 00092 static BOOL XEEIsBusy(void); 00093 00094 00096 // Local Variables 00098 00099 static XEE_ADDR EEPROMAddress; 00100 static BYTE EEPROMBuffer[EEPROM_BUFFER_SIZE]; 00101 static BYTE EEPROMBytesToWrite; 00102 static BYTE EEPROMPageSpace; 00103 00104 00105 // MODIFIX: Removed the functions XEEInit, XEEBeginRead, XEERead and 00106 // XEEEndRead. 00107 00108 /********************************************************************* 00109 * Function: XEE_RESULT XEEReadArray(XEE_ADDR address, 00110 * BYTE *buffer, 00111 * BYTE length) 00112 * 00113 * PreCondition: None. 00114 * 00115 * Input: address - Address from where array is to be read 00116 * buffer - Caller supplied buffer to hold the data 00117 * length - Number of bytes to read. 00118 * 00119 * Output: XEE_SUCCESS 00120 * 00121 * Side Effects: None 00122 * 00123 * Overview: Reads desired number of bytes in sequential mode. 00124 * This function performs all necessary steps 00125 * and releases the bus when finished. 00126 * 00127 * Note: None 00128 ********************************************************************/ 00129 00130 void _startReading(XEE_ADDR Address) 00131 { 00132 BYTE tmp; 00133 00134 // SPI-Configuration for EEPROM: 00135 // SPI Master / Clock = Fosc/16 / Enable / Clock idle state is low 00136 SSP1CON1 = 0x21; 00137 SSP1STAT = 0x40; // CKE = 1 00138 00139 // Send READ opcode 00140 PIR1bits.SSP1IF = 0; 00141 EEPROM_CS_IO = 0; 00142 SSPBUF = READ; 00143 while(PIR1bits.SSP1IF == 0); 00144 tmp = SSPBUF; 00145 00146 // Send address (WORD) 00147 PIR1bits.SSP1IF = 0; 00148 SSPBUF = ((WORD_VAL*)&Address)->v[1]; 00149 while( PIR1bits.SSP1IF == 0 ); 00150 tmp = SSPBUF; 00151 PIR1bits.SSP1IF = 0; 00152 SSPBUF = ((WORD_VAL*)&Address)->v[0]; 00153 while( PIR1bits.SSP1IF == 0 ); 00154 tmp = SSPBUF; 00155 } 00156 00159 00160 00161 XEE_RESULT XEEReadArray(XEE_ADDR address, BYTE *buffer, BYTE length) 00162 { 00163 BYTE Dummy; 00164 BYTE len = length; 00165 BYTE * pBuf = buffer; 00166 00167 _startReading(address); 00168 00169 while(len--) 00170 { 00171 PIR1bits.SSP1IF = 0; 00172 SSPBUF = 0; 00173 while(PIR1bits.SSP1IF == 0); 00174 *pBuf++ = SSPBUF; 00175 } 00176 00177 EEPROM_CS_IO = 1; 00178 00179 return XEE_SUCCESS; 00180 } 00181 00182 00183 /********************************************************************* 00184 * Function: XEE_RESULT XEEBeginWrite(XEE_ADDR address) 00185 * 00186 * PreCondition: None (MODIFIX) 00187 * 00188 * Input: address - address to be set for writing 00189 * 00190 * Output: XEE_SUCCESS 00191 * 00192 * Side Effects: None 00193 * 00194 * Overview: Starts the writing of content to EEPROM to the 00195 * given address. 00196 * 00197 ********************************************************************/ 00198 XEE_RESULT XEEBeginWrite(XEE_ADDR address) 00199 { 00200 EEPROMAddress = address; 00201 EEPROMBytesToWrite = 0; 00202 EEPROMPageSpace = EEPROM_BUFFER_SIZE-(address % EEPROM_BUFFER_SIZE); 00203 return XEE_SUCCESS; 00204 } 00205 00206 00207 /********************************************************************* 00208 * Function: XEE_RESULT XEEWrite(BYTE val) 00209 * 00210 * PreCondition: XEEBeginWrite() are already called. 00211 * 00212 * Input: val - Byte to be written 00213 * 00214 * Output: XEE_SUCCESS 00215 * 00216 * Side Effects: None 00217 * 00218 * Overview: Adds a byte to the current page to be writen when 00219 * XEEEndWrite() is called. 00220 * 00221 * Note: Page boundary cannot be exceeded or the byte 00222 * to be written will be looped back to the 00223 * beginning of the page. 00224 ********************************************************************/ 00225 XEE_RESULT XEEWrite(BYTE val) 00226 { 00227 EEPROMBuffer[EEPROMBytesToWrite++] = val; 00228 EEPROMPageSpace--; 00229 00230 if(EEPROMPageSpace==0) 00231 DoWrite(); 00232 00233 return XEE_SUCCESS; 00234 } 00235 00236 00237 /********************************************************************* 00238 * Function: XEE_RESULT XEEEndWrite(void) 00239 * 00240 * PreCondition: XEEBeginWrite() is already called. 00241 * 00242 * Input: None 00243 * 00244 * Output: XEE_SUCCESS if successful 00245 * other value if failed. 00246 * 00247 * Side Effects: None 00248 * 00249 * Overview: Instructs EEPROM to begin write cycle. 00250 * 00251 * Note: Call this function after either page full of bytes 00252 * written or no more bytes are left to load. 00253 * This function initiates the write cycle. 00254 * User must call for XEEIsBusy() to ensure that write 00255 * cycle is finished before calling any other 00256 * routine. 00257 ********************************************************************/ 00258 XEE_RESULT XEEEndWrite(void) 00259 { 00260 if(EEPROMBytesToWrite) 00261 DoWrite(); 00262 00263 return XEE_SUCCESS; 00264 } 00265 00266 static void DoWrite(void) 00267 { 00268 BYTE Dummy; 00269 BYTE i; 00270 00271 // SPI-Configuration for EEPROM: 00272 // SPI Master / Clock = Fosc/16 / Enable / Clock idle state is low (CKP=0) 00273 SSP1CON1 = 0x21; 00274 SSP1STAT = 0x40; // CKE = 1 00275 00276 // Set the Write Enable latch 00277 PIR1bits.SSP1IF = 0; 00278 EEPROM_CS_IO = 0; 00279 SSPBUF = WREN; 00280 while( PIR1bits.SSP1IF == 0 ); 00281 Dummy = SSPBUF; 00282 EEPROM_CS_IO = 1; 00283 00284 // Send WRITE opcode 00285 EEPROM_CS_IO = 0; 00286 PIR1bits.SSP1IF = 0; 00287 SSPBUF = WRITE; 00288 while(PIR1bits.SSP1IF == 0); 00289 Dummy = SSPBUF; 00290 00291 // Send address (WORD) 00292 PIR1bits.SSP1IF = 0; 00293 SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[1]; 00294 while(PIR1bits.SSP1IF == 0); 00295 Dummy = SSPBUF; 00296 PIR1bits.SSP1IF = 0; 00297 SSPBUF = ((WORD_VAL*)&EEPROMAddress)->v[0]; 00298 while(PIR1bits.SSP1IF == 0); 00299 Dummy = SSPBUF; 00300 00301 EEPROMAddress += EEPROMBytesToWrite; 00302 00303 for (i=0; i<EEPROMBytesToWrite;i++) 00304 { 00305 // Send the byte to write 00306 PIR1bits.SSP1IF = 0; 00307 SSPBUF = EEPROMBuffer[i]; 00308 while(PIR1bits.SSP1IF == 0); 00309 Dummy = SSPBUF; 00310 } 00311 00312 // Begin the write 00313 EEPROM_CS_IO = 1; 00314 00315 EEPROMBytesToWrite = 0; 00316 EEPROMPageSpace = EEPROM_BUFFER_SIZE; 00317 00318 00319 // Wait for write to complete 00320 while( XEEIsBusy() ); 00321 } 00322 00323 00324 /********************************************************************* 00325 * Function: BOOL XEEIsBusy(void) 00326 * 00327 * PreCondition: None. 00328 * 00329 * Input: None 00330 * 00331 * Output: FALSE if EEPROM is not busy 00332 * TRUE if EEPROM is busy 00333 * 00334 * Side Effects: None 00335 * 00336 * Overview: Reads the status register 00337 * 00338 * Note: None 00339 ********************************************************************/ 00340 static BOOL XEEIsBusy(void) 00341 { 00342 BYTE_VAL result; 00343 00344 // SPI-Configuration for EEPROM: 00345 // SPI Master / Clock = Fosc/16 / Enable / Clock idle state is low 00346 SSP1CON1 = 0x21; 00347 SSP1STAT = 0x40; // CKE = 1 00348 00349 PIR1bits.SSP1IF = 0; 00350 EEPROM_CS_IO = 0; 00351 // Send RDSR - Read Status Register opcode 00352 SSPBUF = RDSR; 00353 while(PIR1bits.SSP1IF == 0); 00354 result.Val = SSPBUF; 00355 00356 // Get register contents 00357 PIR1bits.SSP1IF = 0; 00358 SSPBUF = 0; 00359 while(PIR1bits.SSP1IF == 0); 00360 result.Val = SSPBUF; 00361 EEPROM_CS_IO = 1; 00362 00363 return result.bits.b0; 00364 } 00365 00368 00369 void XEEEraseEEPROM(void) 00370 { 00371 int i = 0; 00372 XEEBeginWrite(0); 00373 00374 for (; i < EEPROM_SIZE; i++) 00375 { 00376 XEEWrite(0xFF); 00377 } 00378 00379 XEEEndWrite(); 00380 } 00381 00384 00385 void XEEWriteArray(WORD address, BYTE * pData, BYTE len) 00386 { 00387 BYTE i; 00388 00389 XEEBeginWrite(address); 00390 00391 for (i = 0; i < len; i++) 00392 XEEWrite(pData[i]); 00393 00394 XEEEndWrite(); 00395 } 00396
1.5.5