[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