[i2c] i2c Driver for AT91SAM9260

Jean Delvare khali at linux-fr.org
Mon Apr 30 13:55:28 CEST 2007


Hi Paul,

On Wed, 25 Apr 2007 16:26:48 -0500, Paul Kavan wrote:
> I now have my DAC set up and am trying to get some communications between
> the AT91SAM9260 and the DAC. My scope is telling me that the driver is
> sending the start bit, but does not seem to be sending what I send and, inf
> fact, seems to time out quickly after that. In my userspace code, I am
> writing to the i2c with:

We'd need a much more precise description of what you see on your scope
in order to help.

> /**********************CODE********************/
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <sys/ioctl.h>
> #include <unistd.h>
> #include < stdio.h>
> #include <linux/i2c-dev.h>
> #include <linux/i2c.h>

There is no <linux/i2c.h> header file for user-space, so I am quite
surprised that you are even able to compile your code. Remove that
include, it can only harm.

> 
> #define WRITE_FILE      "adc_values.dat"
> #define MAX_SIZE        10
> 
> int main(void)
> {
>   unsigned short adc_vals[MAX_SIZE];
>   unsigned short shift_vals[MAX_SIZE];
>   int len, i, j, adc_fd, i2c_fd;
>   char c;
> 
>   i2c_fd = open("/dev/at91_i2c", O_RDWR);
>   if(i2c_fd == -1)
>   {
>     printf("i2c open error...\n");
>     return 1;
>   }
>   else
>    printf("at91_i2c Opened\n");
> 
>   adc_fd = open("/dev/at91_adc", O_RDWR);
>   if(i2c_fd == -1)

You're testing the wrong thing here.

>   {
>     printf("adc open error...\n");
>     return 1;
>   }

What are these device files?

> 
>   for(i=1 ; i<MAX_SIZE ; i++)
>   {
>     //len = read(adc_fd,&adc_vals[i], sizeof(adc_vals));
>     adc_vals[i] = 0x2AA;
>   }
> 
>   int addr = 0x4C; /* The I2C address */

Declaring a variable in the middle of a C function is bad ;)

>   if (ioctl(i2c_fd,I2C_SLAVE,addr) < 0)
>   {
>     printf("Address Error\n");
>     exit(1);
>   }
>   else

This "else" is not needed and error-prone.

> 
>   for(j=1 ; j<i ; j++)
>   {
>     shift_vals[j] = (adc_vals[j]<<2);
>     write(i2c_fd,&shift_vals[j],2);

This construct isn't byte-ordering safe. It won't send the same thing
on the bus if the host is little-endian or big-endian.

Also, you should first check that the underlying bus driver is capable
of raw I2C transactions. This is done by checking if the I2C_FUNC_I2C
bit is set in the value returned by the I2C_FUNC ioctl.

>     printf("press enter to continue\n");
>     c = getchar();
>   }
> 
>   close(adc_fd);        //Close the adc
>   close(i2c_fd);        //Close the i2c
> }
> 
> /******************END OF CODE********************/

What does the program above do in practice? In particular, where does
it fail and how?

> The DAC I am using (TI DAC6571) has a standard mode that operates in a
> standard mode and a fast mode (100 kHz and 400 kHz respectively)--plus a
> high-speed mode (which I dont really need). It
> expects on the first update a start condition, a valid i2c address, the 2
> bytes I send that contain control information and the 10-bit number for the
> DAC.
> 
> The address is 0b1001100 or 0x4c. To indicate a 'write' it wants a '0', then
> it sends an ack. then the two message bytes follow, separated by an ack, and
> another ack follows the second byte.....I assume this is fairly standard for
> the i2c (It has been about 3 yrs since I used it)

Yes, all you describe here is fairly standard.

> I believe that I am doing everything correctly, but could very well be wrong
> in that assumption. I am going over the i2c driver code now to try and trace
> what is happening...it seems like it should work.
> 
> Does anyone have any ideas or suggestions of possible errors on my part?

I would use i2cdetect (from the lm_sensors package) to probe the i2c
bus and make sure you actually have a responsive chip at address 0x4c.
That would rule out (or point to) a bus driver or hardware problem.

-- 
Jean Delvare



More information about the i2c mailing list