Hi!

I've modified the bit banging i2c code found on the Acme website to
work with port B.
I have gotten a strange behavior from ioctl that I cannot understand.
When my application starts up, it scans the i2c-bus to see what
devices are connected to it, and prints out a list of the connected
devices.
When the pull-up resistors for the bus are in place, everything works
perfectly, but if I remove them, my code hangs.
Since the inputs are floating without the pull-ups, I was expecting
the reads from the port pins to return  random values, but the fact
that the code hangs makes no sense to me.
I also noticed the messages: "err: timer0 irq for gpio" and "err: PA
irq for gpio" in the boot log, but I don't know if my problem has
anything to do with it.

I really want to know what's going on, because this might cause me
serious trouble later on.

I'm attaching the i2c routines below.

Regards
/Tobias Reneskog


/**********************************************************/
#define I2C_DATA_LINE   1<<6    //on GPIOB
#define I2C_CLOCK_LINE  1<<0    //on GPIOB

int i2c_getbit(void);
void i2c_dir_out(void);
void i2c_dir_in(void);
void i2c_data(int state);
void i2c_clk(int state);
void ReadDataAck(unsigned char *ucdata);
void ReadDataNack(unsigned char *ucdata);
void Start(void);
void Stop(void);
int WriteData(unsigned char x);

void i2c_open(void);
void i2c_close(void);

/************************** I2C-bus 1
***************************************/
// Get the SDA line state
int i2c_getbit(void) {
        unsigned int value;
        value=ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS));
        if ((value&(I2C_DATA_LINE))==0) return 0;
        else return 1;
}

// Set the SDA line as output
void i2c_dir_out(void){
        int iomask;
        iomask = I2C_DATA_LINE;
        ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), &iomask);
}

// Set the SDA line as input
void i2c_dir_in(void){
        int iomask;
        iomask = I2C_DATA_LINE;
        ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), &iomask);
}

// Set the SDA line state
void i2c_data(int state){
        if (state==1) {
                i2c_dir_in();
        } else {
                i2c_dir_out();
        }
}

// Set the SCL line state
void i2c_clk(int state){
        int iomask;
        iomask = I2C_CLOCK_LINE;
        if (state==1) ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE,
IO_SETGET_INPUT), &iomask);
        else ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), &iomask);
}


/*************************  I2C bus 1 
***********************************/
// Open the GPIO dev
void i2c_open(void){
        int iomask;

        //I2C-1
        iomask = I2C_CLOCK_LINE;
        ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), &iomask);
        ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_CLOCK_LINE);
        iomask = I2C_DATA_LINE;
        ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), &iomask);
        ioctl(fd_gpiob, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_DATA_LINE);
}

// Close the GPIO dev
void i2c_close(void){
   i2c_dir_in();
   i2c_clk(1);
}

// Send a start sequence to I2C bus
void Start(void){
        i2c_data(1);
        i2c_clk(1);
        i2c_data(0);
        i2c_clk(0);//Added by TR:
}

// Send a stop sequence to I2C bus
void Stop(void){
        i2c_clk(0);
        i2c_data(0);
        i2c_clk(1);
        i2c_data(1);
}

void ReadDataAck(unsigned char *ucdata){
        unsigned char value = 0;
        int bitvalue;
        int i;

        // Read data byte
        i2c_dir_in();

        for (i=0;i<8;i++){
                i2c_clk(1);
                bitvalue = i2c_getbit();
                value |= bitvalue;
                if(i<7) value <<= 1;

                i2c_clk(0);
        }

        // Send Ack
        i2c_data(0);
        i2c_clk(1);
        i2c_clk(0);
        i2c_dir_in();
   *ucdata = value;
}


void ReadDataNack(unsigned char *ucdata){
        unsigned char value = 0;
        int bitvalue;
        int i;

        // Read data byte
        i2c_dir_in();

        for (i=0;i<8;i++) {
                i2c_clk(1);
                bitvalue = i2c_getbit();
                value |= bitvalue;
                if (i<7) value <<= 1;

                i2c_clk(0);
        }

        i2c_clk(1);
        i2c_clk(0);
   *ucdata = value;
}


// Send a byte to the I2C bus and return the ack sequence from slave
// 0 = Nack, 1=Ack
int WriteData(unsigned char x){
        int i;
        int ack;

        for (i=0;i<8;i++) {
                if (x & 0x80) i2c_data(1);
                else    i2c_data(0);
                i2c_clk(1);
                i2c_clk(0);
                x <<= 1;
        }

        i2c_dir_in();
        i2c_clk(1);
        ack=i2c_getbit();
        i2c_clk(0);

        if (ack==0) return 0;
        else return 1;
}

/*******************************/
int scani2c(char verbose){
        unsigned char cntr;
        int nbr_devices=0;
        char devicename[40];

        if(verbose) flogf("\nScanning I2C-bus 1:\n");
        for(cntr = 2; cntr < 252; cntr += 2){
                Start();
                if(!WriteData(cntr)){
                        if(verbose){
                                resolvei2c(cntr, devicename);
                                flogf("Found device @ 0x%X - ", cntr);
                                flogf("%s\n", devicename);
                        }
                        nbr_devices++;
                }
                Stop();
        }
        if(verbose){
                flogf("_____________________________________\n");
                flogf("Found %i devices\n\n", nbr_devices);
        }
        return nbr_devices;
}


int resolvei2c(int deviceid, char *devicename){
        int deviceid2;
   int cnt;
        FILE *f_i2cbase;

        f_i2cbase =     fopen(file_i2cbase, "r");
        do{
                fscanf(f_i2cbase, "%x,%s", &deviceid2, devicename);
                if(deviceid2 == deviceid) break;
        }while(!feof(f_i2cbase));

        fclose(f_i2cbase);

        if(deviceid2 == deviceid){
                for(cnt = 0; cnt < strlen(devicename); cnt++){
                if(devicename[cnt] == '_') devicename[cnt] = ' ';
                }
                return 0;
        }
        else{
                sprintf(devicename, "Unknown device");
                return 1;
        }
}


Reply via email to