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 }
100 /**
101 * @brief
102 * Display the error returned by the i2c driver
103 */
104 void showI2cError (I2C_RET iret)
105 {
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);
131 }
134 void main (void)
135 {
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);
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++) {
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");
232 }