Added a read back to the i2c write utility
[keystone-rtos/ibl.git] / src / util / i2cWrite / i2cWrite.c
1 /****************************************************************************************************
2  * FILE PURPOSE: Write an I2C eeprom
3  ****************************************************************************************************
4  * @file i2cWrite.c
5  *
6  * @brief
7  *   Writes bytes to an i2c eeprom. The bytes are stored in word format, and written out
8  *   in big endian format, regardless of the endianness of the device.
9  *
10  ****************************************************************************************************/
12 #include "types.h"
13 #include "i2c.h"
14 #include "target.h"
15 #include <stdio.h>
16 #include <string.h>
18 #define I2C_SIZE_BYTES  0x10000
20 /* Run time configuration */
21 unsigned int   deviceFreqMhz = 1000;
22 unsigned short busAddress    = 0x50;
23 unsigned int   i2cBlockSize  = 64;
24 unsigned int   nbytes        = I2C_SIZE_BYTES;
25 unsigned int   dataAddress   = 0;
28 #pragma DATA_SECTION(i2cData, ".i2cData")
29 unsigned int i2cData[I2C_SIZE_BYTES >> 2];
31 #pragma DATA_SECTION(i2cRead, ".i2cRead")
32 unsigned int i2cRead[I2C_SIZE_BYTES >> 2];
34 #define I2C_MAX_BLOCK_SIZE_BYTES    256
35 unsigned char i2cBlock[I2C_MAX_BLOCK_SIZE_BYTES+4];  /* need 2 bytes for the address */
38 /**
39  * @brief
40  *  Get a single byte of data from i2cData based on big endian ordering
41  */
43 UINT8 getByte(int idx)
44 {
45     int    word;
46     int    byte;
47     UINT8  u;
48     unsigned int v;
50     word = idx >> 2;
51     byte = idx & 0x3;
53     v = i2cData[word];
55     u = (v >> ((3 - byte) << 3)) & 0xff;
57     return (u);
59 }
62 /** 
63  *  @brief
64  *      Form a block of data to write to the i2c. The block is 
65  *      created as a byte stream from the 4 byte stream in which
66  *      the MSB is always sent first.
67  */
68 int formBlock (unsigned int addr, int byteIndex, int n)
69 {
70     int p;
71     int i;
73     /* Must start on a word aligned boundary */
74     if ((n & 0x3) != 0)  {
75         printf ("Error: Invalid block base offset specified\n");
76         return (-1);
77     }
79     /* The 1st two bytes are the address */
80     i2cBlock[0] = (addr >> 8) & 0xff;
81     i2cBlock[1] = (addr >> 0) & 0xff;
83     p = byteIndex >> 2;
86     for (i = 0; i < i2cBlockSize; i += 4, p++)  {
88         i2cBlock[i+2+0] = (i2cData[p] >> 24) & 0xff;
89         i2cBlock[i+2+1] = (i2cData[p] >> 16) & 0xff;
90         i2cBlock[i+2+2] = (i2cData[p] >>  8) & 0xff;
91         i2cBlock[i+2+3] = (i2cData[p] >>  0) & 0xff;
93     }
95     return (n+2);
97 }
98     
100 /**
101  *  @brief
102  *     Display the error returned by the i2c driver 
103  */
104 void showI2cError (I2C_RET iret)
106     char *ecode;
108     switch (iret)  {
109         case I2C_RET_LOST_ARB:        ecode = "I2C master lost an arbitration battle";
110                                       break;
112         case I2C_RET_NO_ACK:          ecode = "I2C master detected no ack from slave";
113                                       break;
115         case I2C_RET_IDLE_TIMEOUT:    ecode = "I2C timed out";
116                                       break;
118         case I2C_RET_BAD_REQUEST:     ecode = "I2C driver detected a bad data request";
119                                       break;
121         case I2C_RET_CLOCK_STUCK_LOW: ecode = "I2C driver found the bus stuck low";
122                                       break;
124         case I2C_RET_GEN_ERROR:       ecode = "I2C driver reported a general error";
125                                       break;
127     }
129     printf ("I2C reported error: %s\n", ecode);
134 void main (void)
136     I2C_RET i2cRet;
137     int     n;
138     int     remain;
139     int     progBytes;
140     int     eCount;
142     UINT8  *iData;
143     UINT8   writeByte;
144     int     j;
146     volatile int i;
148     hwI2Cinit (deviceFreqMhz,
149                DEVICE_I2C_MODULE_DIVISOR,
150                25,                              /* Run the bus at 25 kHz */
151                10);
155     for (n = 0; n < nbytes; n += i2cBlockSize)  {
157         remain = nbytes - n;
158         if (remain > i2cBlockSize)
159             remain = i2cBlockSize;
161         /* formBlock sets up the address as well as the data */
162         progBytes = formBlock (dataAddress + n, n, remain);
164         if (progBytes < 0)
165             return;
167         /* Write the block */
168         i2cRet = hwI2cMasterWrite (busAddress,
169                                    i2cBlock,
170                                    progBytes,
171                                    I2C_RELEASE_BUS,
172                                    FALSE);
173         
175         if (i2cRet != I2C_RET_OK)  {
176             showI2cError (i2cRet);
177             return;
178         }
182         /* Some delay */
183         for (i = 0; i < 600000; i++);
185     }
187     printf ("I2C write complete, reading data\n");
189     memset (i2cRead, 0xffffffff, sizeof(i2cRead));
191     /* Read the data back */
192     i2cRet = hwI2cMasterRead (dataAddress,
193                               nbytes,
194                               (UINT8 *)i2cRead,
195                               busAddress,
196                               0x100);
199     if (i2cRet != I2C_RET_OK)  {
200         showI2cError (i2cRet);
201         return;
202     }
204     printf ("I2C read complete, comparing data\n");
206     /* The data received was simply packed bytes, but the data sent was in big endian mode,
207      * so the compare must get the ordering correct */
208     iData  = (UINT8 *)i2cRead;
209     eCount = 0;
210     for (j = 0; j < nbytes; j++)  {
211       
212         writeByte = getByte(j);
213         if (writeByte != iData[j])  {
214             printf ("Error at data byte %d: expected 0x%02x, read 0x%02x\n", j, writeByte, iData[j]);
215             eCount += 1;
216         }
218         if (eCount >= 20)  {
219           printf ("Too many errors, stopping compare\n");
220           break;
221         }
223     }
225     if (eCount == 0)
226         printf ("Data compare passed\n");
227     else
228         printf ("Data compare failed\n");
233