搜尋此網誌

2014年9月15日 星期一

Embedded Linux I2C application -- I2C Sample Code

/****************************************************/

**makefile

/****************************************************/

CROSS_COMPILE = arm-linux-gnueabi-

CFLAGS = -static

CC = $(CROSS_COMPILE)gcc

 

all : main.o

        $(CC) $(CFLAGS) -o test main.o

 

main.o : main.c i2c.h

        $(CC) -c main.c

 

clean :

        rm main.o test

 

/****************************************************/

**delay.h

/****************************************************/

static inline void udelay(volatile int us) 

{ 

    volatile int i; 

    while(us--) 

        for(i = 30; i > 0; i--); 

} 

 

static inline void mdelay(volatile int ms) 

{ 

    while(ms--) { 

        udelay(700); 

    } 

} 

 

/****************************************************/

**main.c

/****************************************************/

#include <stdio.h>

#include <linux/types.h>

#include <stdlib.h>

#include <fcntl.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/ioctl.h>

#include <errno.h>

#include "delay.h"

 

#define I2C_RETRIES 0x0701

#define I2C_TIMEOUT 0x0702

#define I2C_RDWR 0x0707

 

#include <string.h>

 

#define STORAGE_DEV (0xA8 >> 1) /*Slave Device Address*/

 

struct i2c_msg {

    unsigned short addr;

    unsigned short flags;

    #define I2C_M_TEN 0x0010

    #define I2C_M_RD 0x0001

    unsigned short len;

    unsigned char *buf;

};

 

struct i2c_rdwr_ioctl_data{

    struct i2c_msg *msgs;

    int nmsgs;

};

 

struct i2c_rdwr_ioctl_data storage_data;

struct i2c_msg storage_msg[2];

 

 

int i2c_write(int fd, unsigned char slvAddr, unsigned short index, unsigned char * const data, unsigned char len )

{

        int ret;

        unsigned char *tmp = (unsigned char*) malloc(1024);

 

        if (tmp == NULL) {

            perror("memory allocate error(write)!!");

            return -1;

        }

 

        memcpy(tmp, (unsigned char *)&index, sizeof(unsigned short));

        memcpy((tmp + sizeof(unsigned short)), data, len);

        len += sizeof(unsigned short);

 

        /***write data to storage**/

        storage_data.nmsgs = 1;

        (storage_data.msgs[0]).len = len; // Data length

        (storage_data.msgs[0]).addr = slvAddr;//Device Addr

        (storage_data.msgs[0]).flags = 0; //write

        (storage_data.msgs[0]).buf = tmp;

        ret = ioctl(fd, I2C_RDWR, &storage_data);

 

        if (tmp)

          free(tmp);

 

        return (ret < 0) ? -1 : 0;

}

 

int i2c_read(int fd, unsigned char slvAddr, unsigned short index, unsigned char *data, int len)

{

        storage_data.nmsgs = 2;

        (storage_data.msgs[0]).len = sizeof(unsigned short);

        (storage_data.msgs[0]).addr = slvAddr;

        (storage_data.msgs[0]).flags = 0;  //Dummy write

        (storage_data.msgs[0]).buf = (unsigned char *)&index;

       

        (storage_data.msgs[1]).len = len;

        (storage_data.msgs[1]).addr = slvAddr;

        (storage_data.msgs[1]).flags = 1;

        (storage_data.msgs[1]).buf = data;

 

        if(ioctl(fd,I2C_RDWR, &storage_data) < 0){

            perror("ioctl error");

                return -1;

        }

 

        return 0;

}

 

int

i2c_transmit_data(int fd, unsigned char *data_ptr, unsigned short start_word_address ,unsigned short write_data_length)

{

        int i, ret = 0;

        unsigned char write_data_buffer[1024];      

        unsigned short transmit_legth = 16;

 

        memset(write_data_buffer, 0, 1024);

        write_data_length = ((write_data_length > 1024) ? 1024 : write_data_length);

        memcpy(write_data_buffer, data_ptr, write_data_length);

 

        for (i = 0; i < write_data_length; i ++) {

                if ((i % transmit_legth) == 0) {

                        int retry = 5;

                        do {

                                ret = i2c_write(fd, STORAGE_DEV, (start_word_address + i), (write_data_buffer + i), transmit_legth);

                                if(ret == 0) {

                                        break;

                                }

                               mdelay(1);

                        } while (-- retry);

 

                        if (ret) {

                            printf("i2c write %i error!!!\n", i);

                        }

                }

        }

        return ret;

}

 

int

i2c_receive_data(int fd, unsigned char *data_ptr, unsigned short start_word_address ,unsigned short read_data_length)

{

        int i, ret = 0;

        unsigned char read_data_buffer[1024];       

        unsigned short receive_legth = 16;

 

        memset(read_data_buffer, 0x00, 1024);

        read_data_length = ((read_data_length > 1024) ? 1024 : read_data_length);

 

        for (i = 0; i < read_data_length; i ++) {

                if ((i % receive_legth) == 0) {

                        int retry = 5;

                        do {

                                ret = i2c_read(fd, STORAGE_DEV, (start_word_address + i), (read_data_buffer + i), receive_legth);

                                if(ret == 0) {

                                        break;

                                }

                               mdelay(1);

                        } while (-- retry);

                        if(ret == 0) {

#if 0

                                int count;

                                for (count = i; count < (i + receive_legth); count += 16) {

                                        printf("%d. [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]\n", count

                                                , read_data_buffer[count + 0]

                                                , read_data_buffer[count + 1]

                                                , read_data_buffer[count + 2]

                                                , read_data_buffer[count + 3]

                                                , read_data_buffer[count + 4]

                                                , read_data_buffer[count + 5]

                                                , read_data_buffer[count + 6]

                                                , read_data_buffer[count + 7]

                                                , read_data_buffer[count + 8]

                                                , read_data_buffer[count + 9]

                                                , read_data_buffer[count + 10]

                                                , read_data_buffer[count + 11]

                                                , read_data_buffer[count + 12]

                                                , read_data_buffer[count + 13]

                                                , read_data_buffer[count + 14]

                                                , read_data_buffer[count + 15]

                                        );

                                }

#endif

                        } else {

                            printf("i2c read %i error!!!\n", i);

                        }

                }

        }

 

        if (ret == 0) {

                memcpy(data_ptr, read_data_buffer, read_data_length);

        }

 

        return ret;

}

 

int str_isxdigit(char *tmp)

{

        int i;

        for (i = 0; i < strlen(tmp); i++) {

                if (!isxdigit(tmp[i]))

                        return -1;

        }

        return 0;

}

 

int str_isdigit(char *tmp)

{

        int i;

        for (i = 0; i < strlen(tmp); i++) {

                if (!isdigit(tmp[i]))

                        return -1;

        }

        return 0;

}

 

int main(int argc, char **argv)

{

        int fd = 0, ret = 0;

        int mode_type = 0; /*0: Read, 1: Write*/

        unsigned long test_value = 0;

        if ((argc == 3) && ((argv[1][0] == 'w') || (argv[1][0] == 'W'))) {

                mode_type = 1;  /*0: Read, 1: Write*/

                if (str_isdigit(argv[1]) == 0) {

                        if (str_isxdigit(argv[2]) == 0) {

                                sscanf(argv[2], "%x", &test_value);

                                //printf("test_value = %08x\n", test_value);

                        } else {

                                ret = -1;

                        }

                } else {

                        ret = -1;

                }

        }

        else if ((argc == 2) && ((argv[1][0] == 'r') || (argv[1][0] == 'R'))) {

                mode_type = 0;  /*0: Read, 1: Write*/

        }

        else {

                ret = -1;

        }

 

        if (ret) {

                printf("%s r ==> Read Double Word.\n", argv[0]);

                printf("%s w 0x12345678 ==> Write Double Word.\n", argv[0]);

                return 0;

        }

       

        storage_data.nmsgs = 2;

        storage_data.msgs = storage_msg;

 

 

        fd = open("/dev/i2c-0",O_RDWR);

        if(fd < 0){

                perror("open I2C Dev error!!");

                exit(1);

        }

        ioctl(fd, I2C_TIMEOUT, 1);/*set timeout value*/

        ioctl(fd, I2C_RETRIES, 2);/*set retry times*/

#if 1

        if (mode_type == 1) /*0: Read, 1: Write*/

        {

                //I2C Write

                //Step 1. Transfer data

                unsigned char write_api_cmd_buf[64]={

                /*Byte 0, Byte 1, Byte 2, Byte 3*/

                /*DW00*/       0x00, 0x00, 0x00, 0x00,

                };

                unsigned short i2c_data_length = 4;

                memcpy((write_api_cmd_buf + (0 * 4)), &test_value, 4);

                i2c_transmit_data(fd, write_api_cmd_buf,(0x0000, i2c_data_length);

#if 0

                {

                        int i;

                        unsigned char tmp_buffer[1024]; 

                        memset(tmp_buffer, 0x00, 1024);

                        i2c_receive_data(fd, tmp_buffer, 0x0000, i2c_data_length);

                }

#endif

        }

#endif

 

#if 1

        if (mode_type == 0) /*0: Read, 1: Write*/

        {

                //test Read

                //Step 1. Receive data

                unsigned char write_api_cmd_buf[64]={

                /*Byte 0, Byte 1, Byte 2, Byte 3*/

                /*DW00*/       0x00, 0x00, 0x00, 0x00,

                };

                unsigned short i2c_data_length = 4;

                //i2c_transmit_data(fd, write_api_cmd_buf, 0x0000, i2c_data_length);

                {

                        int i, ret;

                        unsigned char tmp_buffer[64];     

                        memset(tmp_buffer, 0x00, 64);

                        ret = i2c_receive_data(fd, tmp_buffer, 0x0000, i2c_data_length);

                        if (ret == 0) {

                                printf("Data ==> 0x%08X\n", *((unsigned long *)tmp_buffer + 0));

                        }

                }

        }

#endif

 

        if (fd)

                close(fd);

 

        return 0;

}

 

 

 

沒有留言:

張貼留言