]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - keystone-rtos/ibl.git/blob - src/util/i2cWrite/i2cWrite.c
f6e6576e63f3f347a1b19bec33ae473a3e24e011
[keystone-rtos/ibl.git] / src / util / i2cWrite / i2cWrite.c
1 /*
2  *
3  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ 
4  * 
5  * 
6  *  Redistribution and use in source and binary forms, with or without 
7  *  modification, are permitted provided that the following conditions 
8  *  are met:
9  *
10  *    Redistributions of source code must retain the above copyright 
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  *    Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the 
15  *    documentation and/or other materials provided with the   
16  *    distribution.
17  *
18  *    Neither the name of Texas Instruments Incorporated nor the names of
19  *    its contributors may be used to endorse or promote products derived
20  *    from this software without specific prior written permission.
21  *
22  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34 */
38 /****************************************************************************************************
39  * FILE PURPOSE: Write an I2C eeprom
40  ****************************************************************************************************
41  * @file i2cWrite.c
42  *
43  * @brief
44  *   Writes bytes to an i2c eeprom. The bytes are stored in word format, and written out
45  *   in big endian format, regardless of the endianness of the device.
46  *
47  ****************************************************************************************************/
49 #include "types.h"
50 #include "i2c.h"
51 #include "target.h"
52 #include "pllapi.h"
53 #include <stdio.h>
54 #include <string.h>
56 #ifndef I2C_SIZE_BYTES
57  #define I2C_SIZE_BYTES  0x20000
58 #endif
60 /* Run time configuration */
61 unsigned int   deviceFreqMhz = 1000;
62 unsigned int   prediv        = 1;       /* Pre-divider  */
63 unsigned int   mult          = 20;      /* Multiplier   */
64 unsigned int   postdiv       = 1;       /* Post-divider */
66 unsigned int   busAddress    = 0x50;
67 unsigned int   i2cBlockSize  = 64;
68 unsigned int   nbytes        = I2C_SIZE_BYTES;
69 unsigned int   dataAddress   = 0;
71 #define I2C_DATA_ADDRESS_MASK   0x0fffff        /* 20 bits specifiy the address (4 msb roll into dev address) */
74 #pragma DATA_SECTION(i2cData, ".i2cData")
75 unsigned int i2cData[I2C_SIZE_BYTES >> 2];
77 #pragma DATA_SECTION(i2cRead, ".i2cRead")
78 unsigned int i2cRead[I2C_SIZE_BYTES >> 2];
80 #define I2C_MAX_BLOCK_SIZE_BYTES    256
81 unsigned char i2cBlock[I2C_MAX_BLOCK_SIZE_BYTES+4];  /* need 2 bytes for the address */
84 /**
85  * @brief
86  *  Get a single byte of data from i2cData based on big endian ordering
87  */
89 UINT8 getByte(int idx)
90 {
91     int    word;
92     int    byte;
93     UINT8  u;
94     unsigned int v;
96     word = idx >> 2;
97     byte = idx & 0x3;
99     v = i2cData[word];
101     u = (v >> ((3 - byte) << 3)) & 0xff;
103     return (u);
108 /** 
109  *  @brief
110  *      Form a block of data to write to the i2c. The block is 
111  *      created as a byte stream from the 4 byte stream in which
112  *      the MSB is always sent first.
113  */
114 int formBlock (unsigned int addr, int byteIndex, int n)
116     int p;
117     int i;
119     /* Must start on a word aligned boundary */
120     if ((n & 0x3) != 0)  {
121         printf ("Error: Invalid block base offset specified\n");
122         return (-1);
123     }
125     /* The 1st two bytes are the address */
126     i2cBlock[0] = (addr >> 8) & 0xff;
127     i2cBlock[1] = (addr >> 0) & 0xff;
129     p = byteIndex >> 2;
132     for (i = 0; i < i2cBlockSize; i += 4, p++)  {
134         i2cBlock[i+2+0] = (i2cData[p] >> 24) & 0xff;
135         i2cBlock[i+2+1] = (i2cData[p] >> 16) & 0xff;
136         i2cBlock[i+2+2] = (i2cData[p] >>  8) & 0xff;
137         i2cBlock[i+2+3] = (i2cData[p] >>  0) & 0xff;
139     }
142     return (n+2);
145     
147 /**
148  *  @brief
149  *     Display the error returned by the i2c driver 
150  */
151 void showI2cError (I2C_RET iret)
153     char *ecode;
155     switch (iret)  {
156         case I2C_RET_LOST_ARB:        ecode = "I2C master lost an arbitration battle";
157                                       break;
159         case I2C_RET_NO_ACK:          ecode = "I2C master detected no ack from slave";
160                                       break;
162         case I2C_RET_IDLE_TIMEOUT:    ecode = "I2C timed out";
163                                       break;
165         case I2C_RET_BAD_REQUEST:     ecode = "I2C driver detected a bad data request";
166                                       break;
168         case I2C_RET_CLOCK_STUCK_LOW: ecode = "I2C driver found the bus stuck low";
169                                       break;
171         case I2C_RET_GEN_ERROR:       ecode = "I2C driver reported a general error";
172                                       break;
174     }
176     printf ("I2C reported error: %s\n", ecode);
181 void main (void)
183     I2C_RET i2cRet;
184     int     n, m, p;
185     int     remain;
186     int     progBytes;
187     int     eCount;
189     unsigned int bAddress;
191     UINT8  *iData;
192     UINT8   writeByte;
193     int     j;
195     volatile int i;
198     /* Program the main system PLL */
199     hwPllSetPll (0,              /* Main PLL     */
200                  prediv,         /* Pre-divider  */
201                  mult,           /* Multiplier   */
202                  postdiv);       /* Post-divider */
204     hwI2Cinit (deviceFreqMhz,
205                DEVICE_I2C_MODULE_DIVISOR,
206                25,                              /* Run the bus at 25 kHz */
207                10);
211     for (n = 0; n < nbytes; n += i2cBlockSize)  {
213         remain = nbytes - n;
214         if (remain > i2cBlockSize)
215             remain = i2cBlockSize;
217         /* formBlock sets up the address as well as the data */
218         progBytes = formBlock (dataAddress + n, n, remain);
220         /* Form the i2c bus address. Bits from the i2c address can roll into the bus address field */
221         bAddress = (((busAddress << 16) & ~I2C_DATA_ADDRESS_MASK) + dataAddress + n) >> 16;
223         if (progBytes < 0)
224             return;
226         /* Write the block */
227         i2cRet = hwI2cMasterWrite (bAddress,
228                                    i2cBlock,
229                                    progBytes,
230                                    I2C_RELEASE_BUS,
231                                    FALSE);
232         
234         if (i2cRet != I2C_RET_OK)  {
235             showI2cError (i2cRet);
236             return;
237         }
241         /* Some delay */
242         for (i = 0; i < 600000; i++);
244     }
246     printf ("I2C write complete, reading data\n");
248     memset (i2cRead, 0xffffffff, sizeof(i2cRead));
250     iData = (UINT8 *)i2cRead;
252     for (p = 0, n = nbytes; n > 0;  n = n - m, p = p + m)  {
254       /* bAddress is the complete address, device address in bits 31:16 */
255       bAddress = ((busAddress << 16) & ~I2C_DATA_ADDRESS_MASK) + dataAddress + p;
257       /* m is the number of bytes that can be read from the current device address */
258       m = (bAddress + 0x10000) - bAddress;
259       if (m > n) m = n;
261       /* Read the data back */
262       i2cRet = hwI2cMasterRead (bAddress & 0xffff,
263                                 m,
264                                 &iData[p],
265                                 bAddress >> 16,
266                                 0x100);
269       if (i2cRet != I2C_RET_OK)  {
270           showI2cError (i2cRet);
271           return;
272       }
274     }
276     printf ("I2C read complete, comparing data\n");
278     /* The data received was simply packed bytes, but the data sent was in big endian mode,
279      * so the compare must get the ordering correct */
280     iData  = (UINT8 *)i2cRead;
281     eCount = 0;
282     for (j = 0; j < nbytes; j++)  {
283       
284         writeByte = getByte(j);
285         if (writeByte != iData[j])  {
286             printf ("Error at data byte %d: expected 0x%02x, read 0x%02x\n", j, writeByte, iData[j]);
287             eCount += 1;
288         }
290         if (eCount >= 20)  {
291           printf ("Too many errors, stopping compare\n");
292           break;
293         }
295     }
297     if (eCount == 0)
298         printf ("Data compare passed\n");
299     else
300         printf ("Data compare failed\n");
305