source: PlatformSupport/CustomPeripherals/pcores/eeprom_onewire_v1_10_a/src/EEPROM_l.c

Last change on this file was 1166, checked in by murphpo, 15 years ago

adding updated EEPROM core/driver with better clocking

File size: 33.7 KB
Line 
1/* Copyright (c) 2006 Rice University */
2/* All Rights Reserved */
3/* This code is covered by the Rice-WARP license */
4/* See http://warp.rice.edu/license/ for details */
5
6
7//////////////////////////////////////////////////////////////////////////////
8// Filename:          C:\EDK_User_Repository\WARP\drivers\EEPROM_v1_00_a\src\EEPROM_l.c
9// Version:           1.00.a
10// Description:       EEPROM Driver Source File
11// Date:              July 28, 2006
12//////////////////////////////////////////////////////////////////////////////
13
14
15/***************************** Include Files *******************************/
16
17#include "EEPROM_l.h"
18#include "xparameters.h"
19#include <stdlib.h>
20
21/****************************WARP LIBRARIES**************************/
22
23// Initialize the EEPROM master for communication. Required before any communication
24// can be made on the 1wire bus.  Performs a master reset, and must be done before any
25// communication can happen on the 1-wire bus.
26// Assumes a EEPROM_select call has already been made.  Defaults to the FPGA board.
27// Sets the clock divisor based on the host bus speed (usually 40 or 80MHz)
28// baseaddr is the base address of the EEPROM device.
29// CLK_DIV_RATIO defined in EEPROM_l.h determines which clock division should be made
30
31char WarpEEPROM_Initialize(unsigned int* baseaddr)
32{
33   //Xuint8 CMD_REG;
34   Xuint8 CMD_REG, EEPROM_select;
35   
36   // Save current EEPROM selected.
37   EEPROM_select = (EEPROM_mReadReg((volatile)baseaddr, 0x0) & 0x70);
38
39   // For selecting the appropriate EEPROM
40   CMD_REG = EEPROM_mReadReg((volatile)baseaddr, 0x0);
41   EEPROM_mWriteReg((volatile)baseaddr, 0x0, (CMD_REG & 0x8F) + EEPROM_select);   
42     
43   switch(CLK_DIV_RATIO)
44   {
45      case(1) : 
46      {
47         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x8); // Set divisor ratio
48         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x88); // Enable clock
49         break;
50      }
51      case(2) : 
52      {
53         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x2); // Set divisor ratio
54         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x82); // Enable clock
55         break;
56      }
57      case(3) : 
58      {
59         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x5); // Set divisor ratio
60         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x85); // Enable clock
61         break;
62      }
63      case(4) : 
64      {
65         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x3); // Set divisor ratio
66         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x83); // Enable clock
67         break;
68      }
69      case(5) : 
70      {
71         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0xC); // Set divisor ratio
72         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x8C); // Enable clock
73         break;
74      }
75      case(6) : 
76      {
77         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x6); // Set divisor ratio
78         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x86); // Enable clock
79         break;
80      }
81      case(7) : 
82      {
83         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x9); // Set divisor ratio
84         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x89); // Enable clock
85         break;
86      }
87      case(8) : 
88      {
89         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0x7); // Set divisor ratio
90         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x87); // Enable clock
91         break;
92      }
93      case(9) : 
94      {
95         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x10); // Set divisor ratio
96         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x90); // Enable clock
97         break;
98      }
99      case(10) : 
100      {
101         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0xA); // Set divisor ratio
102         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x8A); // Enable clock
103         break;
104      }
105      case(11) : 
106      {
107         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0xD); // Set divisor ratio
108         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x8D); // Enable clock
109         break;
110      }
111      case(12) : 
112      {
113         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0xB); // Set divisor ratio
114         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x8B); // Enable clock
115         break;
116      }
117      case(13) : 
118      {
119         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x14); // Set divisor ratio
120         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x94); // Enable clock
121         break;
122      }
123      case(14) : 
124      {
125         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0xE); // Set divisor ratio
126         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x8E); // Enable clock
127         break;
128      }
129      case(15) : 
130      {
131         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x11); // Set divisor ratio
132         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x91); // Enable clock
133         break;
134      }
135      case(16) : 
136      {
137         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET,  0xF); // Set divisor ratio
138         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x8F); // Enable clock
139         break;
140      }
141      case(17) : 
142      {
143         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x18); // Set divisor ratio
144         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x98); // Enable clock
145         break;
146      }
147      case(18) : 
148      {
149         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x12); // Set divisor ratio
150         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x92); // Enable clock
151         break;
152      }
153      case(19) : 
154      {
155         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x15); // Set divisor ratio
156         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x95); // Enable clock
157         break;
158      }
159      case(20) : 
160      {
161         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x13); // Set divisor ratio
162         EEPROM_mWriteReg((volatile)baseaddr, CLKDIV_REG_OFFSET, 0x93); // Enable clock
163         break;
164      }
165      default :
166      {
167         print("\r\nNo or invalid clock speed specified.\r\n");
168      }
169   }
170   
171   // Detect EEPROM on 1-wire bus and ready for a command
172   Xuint8 check;
173
174   check = WarpEEPROM_Detect(baseaddr); // Detect device on 1-wire line
175   
176   if(check == NO_DEVICE)                  // Quit w/ message if no device found
177   {
178      print("\r\nNo device found on the line.\r\n");
179      return NO_DEVICE;
180   }
181
182   return SUCCESS;
183}
184   
185// Send a Reset out on the 1-wire device and wait for a presence detect. 
186// Assumes previous initialization
187// baseaddr is the base address of the EEPROM device
188// Returns SUCCESS if device found
189// Else returns FAILURE
190char WarpEEPROM_Detect(unsigned int* baseaddr)
191{
192   Xuint8 datareg;
193    int checkCount = 0;
194   
195   // Send reset pulse on 1-wire
196   datareg = EEPROM_mReadReg((volatile)baseaddr, COMMAND_REG_OFFSET);
197   EEPROM_mWriteReg((volatile)baseaddr, COMMAND_REG_OFFSET, (datareg & 0xFE)+ 0x01);
198   
199   // Wait for presence detect window
200   while((EEPROM_mReadReg((volatile)baseaddr, INTERRUPT_REG_OFFSET) & 0x01) == 0)
201   {
202        //Give up after a while, so we don't get stuck here forever if the EEPROM is broken
203        if(checkCount++ > 100000)
204            break;
205   }
206   
207   // If device a device was found on 1-Wire, return SUCCESS, else FAILURE
208   if((EEPROM_mReadReg((volatile)baseaddr, INTERRUPT_REG_OFFSET) & 0x02) == 0)
209      return SUCCESS;
210   else
211      return NO_DEVICE;
212}
213
214// Writes a byte to the transmit buffer
215// Waits until Tx buffer/shift registers are empty before writing.
216// Waits until Rx buffer is full to continue. This is indicative of
217// completion of the sending.
218// Assumes previous Initialization and Detect
219// baseaddr is the base address of the EEPROM device
220// data is the byte to be written
221void WarpEEPROM_WriteByte(unsigned int* baseaddr, char data)
222{
223   // Wait until Tx buffer/shift register are empty
224   while((EEPROM_mReadReg((volatile)baseaddr, INTERRUPT_REG_OFFSET) & 0x3C) != 0xC)
225   {
226      EEPROM_mReadReg((volatile)baseaddr, TXRXBUFFER_OFFSET); 
227   }
228   
229   // Write to the Tx buffer
230   EEPROM_mWriteReg((volatile)baseaddr, TXRXBUFFER_OFFSET, data);
231   
232   // Wait until Rx buffer is full -- indicates all has sent
233   while((EEPROM_mReadReg((volatile)baseaddr, INTERRUPT_REG_OFFSET) & 0x10) == 0)
234   {
235   }
236}
237
238// Reads a data byte from the EEPROM
239// Assumes the EEPROM is ready to trasmit based on other commands.
240// Also assumes no other information is needing to be read.
241// Returns a byte.  Default value is FF.
242// baseaddr is the base address of the EEPROM device
243char WarpEEPROM_ReadByte(unsigned int* baseaddr)
244{
245   Xuint8 data;
246   // Wait until Rx buffer/shift registers are clear.
247   while((EEPROM_mReadReg((volatile)baseaddr, INTERRUPT_REG_OFFSET) & 0x30) != 0)
248   {
249      EEPROM_mReadReg((volatile)baseaddr, TXRXBUFFER_OFFSET);   
250   }   
251   
252   // Write to EEPROM to retrieve byte
253   WarpEEPROM_WriteByte(baseaddr, 0xFF);
254     
255   // Wait until Rx buffer is full
256   while((EEPROM_mReadReg((volatile)baseaddr, INTERRUPT_REG_OFFSET) & 0x10) == 0)
257   {
258   }
259   
260   // Read and return byte
261   data = EEPROM_mReadReg((volatile)baseaddr, TXRXBUFFER_OFFSET);
262   
263   return data;
264}
265
266// Given a 64 bit ROM from an EEPROM, checks to see that the family code
267// and serial number flies with the CRC.
268// Returns SUCCESS if no error, otherwise FAILURE
269char WarpEEPROM_VerifyROM(unsigned char *Serial)
270{
271    // Initialize registers
272    Xboolean   reg0 = 0,
273               reg1 = 0,
274               reg2 = 0,
275               reg3 = 0,
276               reg4 = 0,
277               reg5 = 0,
278               reg6 = 0,
279               reg7 = 0,
280               reg8 = 0,
281               reg8old = 0;
282           
283   Xuint8 i,bitsel,j, nextbit;
284   
285   for(i=0; i<8 ; i++)
286   {
287      for(bitsel=0; bitsel<8 ; bitsel++)
288      {         
289         // Mask and shift to choose next bit
290         nextbit = (Xboolean)((Serial[i] & (1 << bitsel)) >> bitsel); 
291         
292         // Shift Algorithm to check CRC
293         // Polynomial = X^8 + X^5 + X^4 + 1
294         reg8old = reg8;       
295         reg8 = reg7;
296         reg7 = reg6;
297         reg6 = reg5 ^ (nextbit ^ reg8old);
298         reg5 = reg4 ^ (nextbit ^ reg8old);
299         reg4 = reg3;
300         reg3 = reg2;
301         reg2 = reg1;
302         reg1 = reg8old ^ nextbit;     
303      }
304   }
305   
306   // If all registers are = 0, then the information was received correctly.
307   if((reg1==0)&&(reg2==0)&&(reg3==0)&&(reg4==0)&&(reg5==0)&&(reg6==0)&&(reg7==0)&&(reg8==0))
308      return SUCCESS;
309   else 
310      return FAILURE;     
311}
312
313// This function verifies that the 16bit-CRC produced by the EEPROM
314// jives with the information sent over the 1-wire bus during
315// Read/Write Scratchpad commands.
316// array is the 13-byte (11 + 2-byte CRC) or 14-byte (12 + 2-byte CRC)
317// array of information
318// The function expects that the last 2 bytes of the array will be the
319// complement of the CRC sent over the 1-wire bus (that is the actual CRC).
320// RNW: 0 - if checking a write command, 1 -- if checking a read command
321// Returns SUCCESS if no error, otherwise FAILURE
322char WarpEEPROM_VerifyScratchpad(unsigned char *array, unsigned char RNW)
323{
324    // Initialize registers
325    Xboolean   reg1     = 0,
326               reg2     = 0,
327               reg3     = 0,
328               reg4     = 0,
329               reg5     = 0,
330               reg6     = 0,
331               reg7     = 0,
332               reg8     = 0,
333               reg9     = 0,
334               reg10    = 0,
335               reg11    = 0,
336               reg12    = 0,
337               reg13    = 0,
338               reg14    = 0,
339               reg15    = 0,
340               reg16    = 0,
341               reg16old = 0;
342           
343   Xuint8 i,bitsel,j, nextbit;
344   
345   
346   for(i=0; i < (13 + RNW) ; i++)
347   {
348      for(bitsel=0; bitsel<8 ; bitsel++)
349      {         
350         // Mask and shift to choose next bit
351         nextbit = (Xboolean)((array[i] & (1 << bitsel)) >> bitsel); 
352         
353         // Shift Algorithm to check CRC
354         // Polynomial = X^16 + X^15 + X^2 + 1
355         reg16old = reg16;       
356         reg16 = reg15 ^ (nextbit ^ reg16old);
357         reg15 = reg14;
358         reg14 = reg13;
359         reg13 = reg12;
360         reg12 = reg11;
361         reg11 = reg10;
362         reg10 = reg9;
363         reg9 = reg8;
364         reg8 = reg7;
365         reg7 = reg6;
366         reg6 = reg5; 
367         reg5 = reg4;
368         reg4 = reg3;
369         reg3 = reg2 ^ (nextbit ^ reg16old);
370         reg2 = reg1;
371         reg1 = reg16old ^ nextbit;     
372      }
373   }
374   
375   // If all registers are = 0, then the information was received correctly.
376   if((reg1==0)&&(reg2==0)&&(reg3==0)&&(reg4==0)&&(reg5==0)&&(reg6==0)&&(reg7==0)&&(reg8==0)&&(reg9==0)&&(reg10==0)&&(reg11==0)&&(reg12==0)&&(reg13==0)&&(reg14==0)&&(reg15==0)&&(reg16==0))
377      return SUCCESS;
378   else 
379      return FAILURE;     
380}
381
382// Given an array of information and addressing information, this function writes
383// the given information to the memory of the EEPROM. 
384// baseaddr is the base address of the EEPROM device
385// page must be 0-3, and refers to memory pages on the device
386// sector must be 0-3, and refers to the appropriate sector on the device
387// array must be an 8 byte array
388char WarpEEPROM_WriteScratch(unsigned int* baseaddr, char page, char sector, unsigned char *array)
389{
390   
391   // Check to see that user gave valid location
392   
393   if((page > 3))// || (page < 0))
394   {
395      print("\r\nInvalid Page Number\r\n");
396      return;
397   }
398   else if((sector > 3))// || (sector < 0))
399   {
400      print("\r\nInvalid Sector Number\r\n");
401      return FAILURE;
402   }
403
404   ///////////////////////////////////////////////////////////////////////////////
405   // INITIALIZATION SEQUENCE
406   Xuint8 check, mem_address;
407   
408   WarpEEPROM_Initialize(baseaddr); // Set Clock
409
410   WarpEEPROM_WriteByte(baseaddr, 0xCC); // Bypass ROM access
411
412   ///////////////////////////////////////////////////////////////////////////////
413   // COPY ARRAY TO SCRATCHPAD
414   // Produce Array for Verifying Scratchpad Write
415   Xuint8 verify[13];
416   
417   // Send Write Scratchpad command
418   WarpEEPROM_WriteByte(baseaddr, 0x0F);
419   verify[0] = 0x0F;
420   
421   
422   // Set memory address TA1 based on page and sector.
423   mem_address = ((page & 0x03) << 5) + ((sector & 0x03) << 3);
424   WarpEEPROM_WriteByte(baseaddr,mem_address);
425   verify[1] = mem_address;
426   
427   // Second byte is always zero   
428   WarpEEPROM_WriteByte(baseaddr,0x0);
429   verify[2] = 0;
430   
431
432   // Send 8 data bytes of array to scratchpad
433   Xuint8 i;
434   for(i=0;i<8;i++)
435   {
436      WarpEEPROM_WriteByte(baseaddr,array[i]);
437      verify[i + 3] = array[i];
438   }   
439   
440   // Receive 2 bytes of inverted CRC-16
441   // Receive CRC 1st byte
442   Xuint8 CRC_n;
443   CRC_n = WarpEEPROM_ReadByte(baseaddr);
444   verify[11] = ~CRC_n;
445   
446   // Receive CRC 2nd byte
447   CRC_n = WarpEEPROM_ReadByte(baseaddr);
448   verify[12] = ~CRC_n;
449   
450   check = WarpEEPROM_VerifyScratchpad(verify, 0);
451   //xil_printf("\r\n\r\nWriteSuccess (0)    : %x\r\n", check);
452   if(check == 0)
453      return SUCCESS;
454   else 
455      return FAILURE;
456}
457
458// This will read the current value in the scratchpad.
459// Returns the two memory location bytes and the E/S byte necessary
460// to copy the scratchpad to memory.
461// baseaddr is the base address of the EEPROM device
462// auth_code is a 11-byte array where the 3-byte authcode followed by the 8-byte
463// scratchpad value sent from the EEPROM will be stored
464char WarpEEPROM_ReadScratch(unsigned int* baseaddr, unsigned char* auth_code)
465{
466   ///////////////////////////////////////////////////////////////////////////////
467   // INITIALIZATION SEQUENCE
468   Xuint8 check, mem_address;
469   
470   WarpEEPROM_Initialize(baseaddr); // Set Clock
471
472   WarpEEPROM_WriteByte(baseaddr, 0xCC); // Bypass ROM access
473   
474   ///////////////////////////////////////////////////////////////////////////////
475   // READ SCRATCHPAD
476   
477   // Make array for checking CRC-16 value
478   Xuint8 verify[14];
479   
480   // Send Read Scratchpad Command
481   WarpEEPROM_WriteByte(baseaddr, 0xAA);
482   verify[0] = 0xAA;
483   
484   // Get data bytes from EEPROM
485   Xuint8 i, data;
486   for(i = 0; i < 11; i++)
487   {
488      data = WarpEEPROM_ReadByte(baseaddr);
489      auth_code[i] = data;
490      verify[i+1]  = data;
491   }
492   
493   // Receive 2 bytes of inverted CRC-16
494   // Receive CRC 1st byte
495   Xuint8 CRC_n;
496   CRC_n = WarpEEPROM_ReadByte(baseaddr);
497   verify[12] = ~CRC_n;
498   
499   // Receive CRC 2nd byte
500   CRC_n = WarpEEPROM_ReadByte(baseaddr);
501   verify[13] = ~CRC_n;
502   
503   check = WarpEEPROM_VerifyScratchpad(verify, 1);
504   //xil_printf("Read Success (0)    : %x\r\n", check);
505   if(check == 0)
506      return SUCCESS;
507   else 
508      return FAILURE;
509}
510
511// After the information in the scratchpad has been verified via CRC check, the
512// scratchpad read, and the authorization code returned, this command will copy
513// the scratchpad into the flash memory specified.
514// baseaddr is the base address of the EEPROM device
515// auth_code a 3 byte array containing the 2-byte memory location and
516// 1-byte E/S regsiter value returned during a ReadScratch command.
517// Returns SUCCESS if no error, otherwise FAILURE
518char WarpEEPROM_Scratch2Mem(unsigned int* baseaddr, unsigned char* auth_code)
519{
520   ///////////////////////////////////////////////////////////////////////////////
521   // INITIALIZATION SEQUENCE
522   Xuint8 check;
523   
524   WarpEEPROM_Initialize(baseaddr); // Set Clock
525
526   WarpEEPROM_WriteByte(baseaddr, 0xCC); // Bypass ROM access
527   
528   ///////////////////////////////////////////////////////////////////////////////
529   // COPY SCRATCHPAD TO MEMORY
530   
531   // Give Copy Scratchpad Command
532   WarpEEPROM_WriteByte(baseaddr, 0x55);
533   
534   // Write authorization bytes to EEPROM
535   Xuint8 i;
536   for(i = 0; i < 3; i++)
537   {
538      WarpEEPROM_WriteByte(baseaddr, auth_code[i]);
539   }
540   
541   usleep(12500); // 12.5ms for data transfer
542   
543   check = WarpEEPROM_ReadByte(baseaddr);
544   //xil_printf("AA for success      : %x\r\n", check);
545   
546   if(check == 0xAA)
547      return SUCCESS;
548   else
549      return FAILURE;
550}
551
552// This function reads from a specified memory location in the 1024-bit memory.
553// Returns an 8-byte sector of the EEPROM.
554// baseaddr is the base address of the EEPROM device
555// page must be 0-3, and refers to memory pages on the device
556// sector must be 0-3, and refers to the appropriate sector on the device
557// array must be an 8 byte array
558// Returns SUCCESS if no error, otherwise FAILURE
559char WarpEEPROM_ReadMem(unsigned int* baseaddr, char page, char sector, unsigned char *memory)
560{
561   // Check to see that user gave valid location
562   if((page > 3)) //  || (page < 0))
563   {
564      print("Invalid Page Number");
565      return FAILURE;
566   }
567   else if((sector > 3)) //  || (sector < 0))
568   {
569      print("Invalid Sector Number");
570      return FAILURE;
571   }
572   
573   ///////////////////////////////////////////////////////////////////////////////
574   // INITIALIZATION SEQUENCE
575   Xuint8 check, mem_address;
576   
577   WarpEEPROM_Initialize(baseaddr); // Set Clock
578
579   WarpEEPROM_WriteByte(baseaddr, 0xCC); // Bypass ROM access
580   
581   ///////////////////////////////////////////////////////////////////////////////
582   // READ FROM MEMORY
583         
584   // Send Read Memory command
585   WarpEEPROM_WriteByte(baseaddr, 0xF0);
586
587   
588   // Set memory address TA1 based on page and sector.
589   mem_address = ((page & 0x03) << 5) + ((sector & 0x03) << 3);
590   WarpEEPROM_WriteByte(baseaddr,mem_address);
591
592   // Second byte is always zero
593   WarpEEPROM_WriteByte(baseaddr,0x0);
594
595   // Receive 8 data bytes from memory
596   Xuint8 i;
597   for(i=0;i<8;i++)
598   {
599      memory[i] = WarpEEPROM_ReadByte(baseaddr);
600   }   
601   return SUCCESS;
602}
603
604// Writes a given 8-byte array to a designated location in memory.
605// Essentially a wrapper of the WriteScratch, ReadScratch and Scratch2Mem functions
606// baseaddr is the base address of the EEPROM device
607// page must be 0-3, and refers to memory pages on the device
608// sector must be 0-3, and refers to the appropriate sector on the device
609// array must be an 8 byte array
610char WarpEEPROM_WriteMem(unsigned int* baseaddr, char page, char sector, unsigned char *array)
611{
612   Xuint8 array2[11], check; 
613   
614   check = WarpEEPROM_WriteScratch(baseaddr, page, sector, array);
615   if(check != 0)
616      return FAILURE;
617   check = WarpEEPROM_ReadScratch(baseaddr, array2);
618   if(check != 0)
619      return FAILURE;
620   check = WarpEEPROM_Scratch2Mem(baseaddr, array2);
621   if(check != 0)
622      return FAILURE;
623   
624   return SUCCESS;
625}
626
627// Reads and outputs the values stored in the 5 protection bytes, the factory byte, and the
628// two user bytes.
629void WarpEEPROM_ReadControlBytes(unsigned int* baseaddr, char *control_regs)
630{
631   ///////////////////////////////////////////////////////////////////////////////
632   // INITIALIZATION SEQUENCE
633   Xuint8 check, mem_address;
634   
635   WarpEEPROM_Initialize(baseaddr); // Set Clock
636   
637   WarpEEPROM_WriteByte(baseaddr, 0xCC); // Bypass ROM access
638   
639   ///////////////////////////////////////////////////////////////////////////////
640   // READ FROM MEMORY
641         
642   // Send Read Memory command
643   WarpEEPROM_WriteByte(baseaddr, 0xF0);
644   
645   // Set memory address TA1 based on page and sector.
646   mem_address = 0x80;
647   WarpEEPROM_WriteByte(baseaddr,mem_address);
648
649   // Second byte is always zero
650   WarpEEPROM_WriteByte(baseaddr,0x0);
651
652   // Receive 8 data bytes from memory
653   Xuint8 i;
654   for(i=0;i<8;i++)
655   {
656      control_regs[i] = WarpEEPROM_ReadByte(baseaddr);
657   }   
658   //xil_printf("\r\nProtection Control Byte Page 0:     %x", control_regs[0]);
659   //xil_printf("\r\nProtection Control Byte Page 1:     %x", control_regs[1]);
660   //xil_printf("\r\nProtection Control Byte Page 2:     %x", control_regs[2]);
661   //xil_printf("\r\nProtection Control Byte Page 3:     %x", control_regs[3]);
662   //xil_printf("\r\nCopy Protection Byte:               %x", control_regs[4]);
663   //xil_printf("\r\nFactory Byte:                       %x", control_regs[5]);
664   //xil_printf("\r\nUser Byte:                          %x", control_regs[6]);
665   //xil_printf("\r\nUser Byte:                          %x\r\n", control_regs[7]);
666   
667}
668
669// Retrieves the type of board.  Returns a char.
670// Return values: 0x01 -- FPGA Board
671//                0x02 -- Radio Board               
672char WarpEEPROM_GetDeviceType(unsigned int* baseaddr)
673{
674   Xuint8 memory[8];
675   WarpEEPROM_ReadMem(baseaddr, 0, 0, memory);
676   return memory[0] & 0x1F;
677}
678
679// A utility function for taking ascii input and turning it into a hex number
680char WarpEEPROM_ascii2hex(unsigned char ascii)
681{
682   if((ascii < 48) || ((ascii > 57) && (ascii < 65)) || ((ascii > 70) && (ascii < 97)) || (ascii > 102))
683      return 0x00; // return 0 if bad input.  less harmful than other options
684   else if(ascii <= 57)
685      return (char)(ascii - 48);
686   else if(ascii <= 70)
687      return (char)(ascii - 55);
688   else 
689      return (char)(ascii - 87);
690}
691
692// A utility function for taking two sequential keyboard inputs and
693// returning a single hex byte.  Used for hex input from keyboard
694char WarpEEPROM_ascii2hexbyte(unsigned char MSB, unsigned char LSB)
695{
696   Xuint8 MSBx,LSBx, byte;
697   
698   MSBx = WarpEEPROM_ascii2hex(MSB); 
699   LSBx = WarpEEPROM_ascii2hex(LSB);
700
701   return (char)((MSBx << 4) + LSBx);
702}
703   
704
705/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
706/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
707/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
708//*************************************************************************************************************//
709//*************************************************************************************************************//
710//*************************************************************************************************************//
711// THE FOLLOWING FUNCTION CAN BE USED TO WRITE TO THE WRITE PROTECTION BYTES AND THE TWO USER BYTES            //
712//             SOME WRITES CAN NEVER BE CHANGED.  EVER.  USE AT YOUR OWN RISK.                                 //
713//*************************************************************************************************************//
714//*************************************************************************************************************//
715//*************************************************************************************************************//
716/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
717/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
718/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
719
720//***********************************************************************************************************
721//***********************************************************************************************************
722//**WARNING**: Writing to any of the protection bytes is **IRREVERSIBLE**!
723//             Both the write protect and EPROM mode commands write protect the
724//             register to which they are written.
725//***********************************************************************************************************
726//***********************************************************************************************************
727//
728// Writes to one of the five protection bytes (if not already copy protected) or
729// to one of the User Bytes (if not copy protected).
730// baseaddr is the base address of the EEPROM device
731// ByteSelect:       
732//                0: Protection Control Byte Page 0
733//                1: Protection Control Byte Page 1
734//                2: Protection Control Byte Page 2
735//                3: Protection Control Byte Page 3
736//                4: Copy Protection Byte
737//                5: User Byte #1
738//                6: User Byte #2
739//
740
741char WarpEEPROM_ControlByteWrite(unsigned int* baseaddr, char ByteSelect, char value2store)
742{   
743   Xuint8 choice;
744   if(ByteSelect < 5)
745   {
746      print("\r\nReturning\r\n");
747      return; // Remove in order to enable writing to control bytes.
748      print("\r\nSETTING THE PROTECTION REGISTERS TO WRITE PROTECT OR EPROM MODE IS\r\n");
749      print("\r\n                    ***IRREVERSIBLE***\r\n");
750      print("\r\nDo you wish to continue? (y)\r\n");
751      choice = XUartLite_RecvByte(STDIN_BASEADDRESS);
752      if(choice != 'y')
753         return ABORT;
754     
755      print("\r\nPlease Verify the Control Byte you are Writing\r\n");
756      print("      0: Protection Control Byte Page 0\r\n");     
757      print("      1: Protection Control Byte Page 1\r\n");     
758      print("      2: Protection Control Byte Page 2\r\n");     
759      print("      3: Protection Control Byte Page 3\r\n");     
760      print("      4: Copy Protection Byte\r\n");     
761      print("      5: User Byte #1\r\n");     
762      print("      6: User Byte #2\r\n");
763      choice = XUartLite_RecvByte(STDIN_BASEADDRESS);   
764      if((choice - 48) != ByteSelect)
765         return ABORT;
766         
767      print("\r\nPlease Verify the value you are writing is %x.  (k)\r\n", value2store);
768      choice = XUartLite_RecvByte(STDIN_BASEADDRESS);
769      if(choice != 'k')
770         return ABORT;
771     
772      print("\r\nSETTING THE PROTECTION REGISTERS TO 'WRITE PROTECT' OR 'EPROM MODE' IS\r\n");
773      print("\r\n                    ***IRREVERSIBLE***\r\n");
774      print("\r\nDo you wish to continue? (y)\r\n");
775      choice = XUartLite_RecvByte(STDIN_BASEADDRESS);
776      if(choice != 'y')
777         return ABORT;
778   }
779   
780   // Obtain Current Control Register Values
781   Xuint8 control_regs[8], mem_address;
782   WarpEEPROM_ReadControlBytes(baseaddr, control_regs); 
783   mem_address = 0x80;
784   switch(ByteSelect)
785   {   
786      case(0)  : 
787      {
788         control_regs[0] = value2store; break;
789      }
790      case(1)  : 
791      {
792         control_regs[1] = value2store; break;
793     
794      }
795      case(2)  : 
796      {
797         control_regs[2] = value2store; break;
798     
799      }
800      case(3)  : 
801      {
802         control_regs[3] = value2store; break;
803     
804      }
805      case(4)  : 
806      {
807         control_regs[4] = value2store; break;
808     
809      }
810      case(5)  : 
811      {
812         control_regs[6] = value2store; break;
813     
814      }
815      case(6)  : 
816      {
817         control_regs[7] = value2store; break;
818     
819      }
820      default : return; break;
821   } 
822
823      ////////////////////////////////////////////////////////////////////////////////////
824      // Write Scratchpad
825      Xuint8 CRC_n, check, verify[14];
826      WarpEEPROM_Initialize(baseaddr);
827      WarpEEPROM_WriteByte(baseaddr, 0xCC);     
828     
829      WarpEEPROM_WriteByte(baseaddr, 0x0F);             verify[0] = 0x0F;
830     
831      WarpEEPROM_WriteByte(baseaddr, mem_address);      verify[1] = mem_address;
832      WarpEEPROM_WriteByte(baseaddr, 0x0);              verify[2] = 0x0;
833     
834      WarpEEPROM_WriteByte(baseaddr, control_regs[0]);  verify[3] = control_regs[0];
835      WarpEEPROM_WriteByte(baseaddr, control_regs[1]);  verify[4] = control_regs[1];
836      WarpEEPROM_WriteByte(baseaddr, control_regs[2]);  verify[5] = control_regs[2];
837      WarpEEPROM_WriteByte(baseaddr, control_regs[3]);  verify[6] = control_regs[3];
838      WarpEEPROM_WriteByte(baseaddr, control_regs[4]);  verify[7] = control_regs[4];
839      WarpEEPROM_WriteByte(baseaddr, control_regs[5]);  verify[8] = control_regs[5];
840      WarpEEPROM_WriteByte(baseaddr, control_regs[6]);  verify[9] = control_regs[6];
841      WarpEEPROM_WriteByte(baseaddr, control_regs[7]); verify[10] = control_regs[7];
842     
843      CRC_n = WarpEEPROM_ReadByte(baseaddr); 
844      verify[11] = ~CRC_n;
845      CRC_n = WarpEEPROM_ReadByte(baseaddr); 
846      verify[12] = ~CRC_n;
847     
848      check = WarpEEPROM_VerifyScratchpad(verify, 0);
849      if(check != 0)
850         return FAILURE;   
851     
852      ////////////////////////////////////////////////////////////////////////////////////
853      // Read Scratchpad
854      WarpEEPROM_Initialize(baseaddr);
855      WarpEEPROM_WriteByte(baseaddr, 0xCC);     
856     
857      WarpEEPROM_WriteByte(baseaddr, 0xAA); verify[0] = 0xAA;
858     
859       verify[1] = WarpEEPROM_ReadByte(baseaddr);
860       verify[2] = WarpEEPROM_ReadByte(baseaddr);
861       verify[3] = WarpEEPROM_ReadByte(baseaddr); 
862       
863       verify[4] = WarpEEPROM_ReadByte(baseaddr);
864       verify[5] = WarpEEPROM_ReadByte(baseaddr);
865       verify[6] = WarpEEPROM_ReadByte(baseaddr);
866       verify[7] = WarpEEPROM_ReadByte(baseaddr);
867       verify[8] = WarpEEPROM_ReadByte(baseaddr);
868       verify[9] = WarpEEPROM_ReadByte(baseaddr);
869      verify[10] = WarpEEPROM_ReadByte(baseaddr);
870      verify[11] = WarpEEPROM_ReadByte(baseaddr);
871     
872      CRC_n = WarpEEPROM_ReadByte(baseaddr); verify[12] = ~CRC_n;
873      CRC_n = WarpEEPROM_ReadByte(baseaddr); verify[13] = ~CRC_n;
874     
875      check = WarpEEPROM_VerifyScratchpad(verify, 1);
876      if(check != 0)
877         return FAILURE;
878     
879      ////////////////////////////////////////////////////////////////////////////////////
880      // Copy Scratchpad
881      WarpEEPROM_Initialize(baseaddr);
882      WarpEEPROM_WriteByte(baseaddr, 0xCC);     
883     
884      WarpEEPROM_WriteByte(baseaddr, 0x55);
885      WarpEEPROM_WriteByte(baseaddr, verify[1]);
886      WarpEEPROM_WriteByte(baseaddr, verify[2]);
887      WarpEEPROM_WriteByte(baseaddr, verify[3]);
888      usleep(12500);
889     
890      check = WarpEEPROM_ReadByte(baseaddr);
891      if(check == 0xAA)
892      {
893         return SUCCESS;
894      }
895      else 
896         return FAILURE;
897}
898
899/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
900/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
901/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
902//*************************************************************************************************************//
903//*************************************************************************************************************//
904//*************************************************************************************************************//
905// THE ABOVE FUNCTION CAN BE USED TO WRITE TO THE WRITE PROTECTION BYTES AND THE TWO USER BYTES                //
906//             SOME WRITES CAN NEVER BE CHANGED.  EVER.  USE AT YOUR OWN RISK.                                 //
907//*************************************************************************************************************//
908//*************************************************************************************************************//
909//*************************************************************************************************************//
910/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
911/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
912/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Note: See TracBrowser for help on using the repository browser.