Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++
12603 Discussions

Nios 2 I2c timeout altera_avalon_i2c.c - timeout never occurs

Jacob11
New Contributor II
1,202 Views

Hi gang.

 

I am using the altera avalon i2c driver for communication to peripheral devices on my board.

 

I want to read from different i2c addresses to determine if a device is present.

 

For instance a small code snippet:

 

rt = i2c_read_reg(I2C_EXT, 0x00, 0x00, &i2cRead, 8);
//i2c_read_reg(i2cBus, i2cAddress, register, *data buffer, bitwidth)
 
if (rt == ALT_AVALON_I2C_SUCCESS)
{
printf("INFO: Device found at address 0x00);
}
else
{
printf("INFO: no device exists at address 0x00");
}
 
 
The issue is that when a device is at the address, everything works.
 
But if the device does not exist at the given address, the program
just freezes. It doesn't actually timeout and return an error code
like it is supposed to.
 
Is there any workaround?? I need to test 127 addresses. I can already
accomplish this with a write operation, but I do not want to write anything
since some of these are memory chips with specific functions. A simple
read allows me to accomplish this much better.
 
Any ideas here??
 
What I have already tried is to lower the timeout variables in the driver
from 10000 to 100 and that also did not seem to do anything. The program just
freezes when trying to read from an address with no hardware attached.
 
Thanks
Jacob
0 Kudos
11 Replies
Jacob11
New Contributor II
1,193 Views

Well, solved this issue, but I did not like editing the intel avalon driver.

 

on line 581 of the driver I changed retry from 100000 to 100.

 

This times out in about 10 seconds. i think 100000 is just way too many and takes forever.

 

 

Now the problem is that I need to read some registers beyond 0xFF.

 

I need to read registers 0x149 and a few other register addresses higher than that. It seems the driver ALSO limits this even though the register variable passed into i2c_read_reg is an alt_u16.

 

So this is my real question.....how to read registers past 0xFF. I can read up until there, but once I try 0x100 there are errors.

0 Kudos
JingyangTeh
Employee
1,181 Views

Hi Jacob


The feature that you are looking for is the i2c probe.

Unfortunately the library does not support this feature.


As for the addressing, did you change the addressing mode from 7Bit to 10Bit addressing?

You could search for "ALT_AVALON_I2C_ADDR_MODE_10_BIT "


Regards

Jingyang, Teh


0 Kudos
Jacob11
New Contributor II
1,173 Views

Good morning Jingyang,

 

I tried this but so far no success. Actually now I cannot read anything at all.

 

I think the issue is that my devices have normal, 7/8 bit addresses. 0x57, for example. But the registers that I need to read in these devices are anywhere from 0x000 to 0x145. 

 

with address mode at default(7 bit), I can read any registers from 0x00 to 0xFF at address 0x57. 

 

By using the below code to try and set 10 bit addressing, I lose the ability to read everything. It just returns with a NACK error.

 

is it possible with this driver to have 7 bit addresses, but 10 bit registers??

 

I have this code now for configuration. Is this the correct way to do this??

 

ALT_AVALON_I2C_DEV_t *gp_i2c3 = NULL;
gp_i2c3 = alt_avalon_i2c_open(I2C_MASTER_3_NAME);
gp_i2c3->address_mode = ALT_AVALON_I2C_ADDR_MODE_10_BIT;
 
ALT_AVALON_I2C_STATUS_CODE status;
ALT_AVALON_I2C_MASTER_CONFIG_t cfg;
memset(&cfg, 0, sizeof(cfg));

alt_avalon_i2c_master_config_get(gp_i2c3, &cfg);
cfg.scl_hcnt -= ALT_AVALON_I2C_DIFF_LCNT_HCNT;
cfg.scl_lcnt += ALT_AVALON_I2C_DIFF_LCNT_HCNT;

alt_avalon_i2c_master_config_set(gp_i2c3, &cfg);

// Set bus speed to 400Hz
alt_avalon_i2c_master_config_speed_set(gp_i2c3, &cfg, 400);
 
0 Kudos
Jacob11
New Contributor II
1,137 Views

I have managed to find in the i2c driver from intel (i2c_interface.c) the following code inside the i2c_read_reg function:

 

 

if (reg > 0xff) {
txbuf[0] = reg;
txbuf[1] = reg >> 8;
txsize = 2;
} else {
txbuf[0] = reg;
txsize = 1;
}

 

So there is at least some attempt to control the tx buffer when the value of the register is greater than 0xFF.

This TX buffer is sent to the function

alt_avalon_i2c_master_tx_rx(pdev, txbuf, txsize, rxbuf, rxsize, 0);
 
This function can be found in the file altera_avalon_i2c.c:
 
 
 
Something about this process is broken. As long as we remain in "else" everything works. As soon as
the register goes above oxFF and we need this txsize = 2 we have issues.
0 Kudos
Jacob11
New Contributor II
1,156 Views

Were there any updates on this issue?

 

Thanks

Jacob

0 Kudos
JingyangTeh
Employee
1,133 Views

Hi Jacob


Sorry that I have suggested you to change the addressing mode from 7 to 10bit.

I misunderstood that your addressing is greater than 7 Bit.


For the register address in the device, if it is greater that FF, then you would need to send another extra byte for the register address.

It is normal in this case, because all data send in the i2c bus are byte size.

In your case if you would like to read a register address greater than 0xFF then you would need to send a total of 3 bytes to initiate the read.

e.g.


<device address byte> <register address byte 1> <register address byte 2> ... <remaining bytes>


Could you share the datasheet of the device that you are trying to read from?


Regards

Jingyang, Teh



0 Kudos
Jacob11
New Contributor II
1,128 Views

Hello Jingyang,

 

I understand this point. However, in the driver provided by Intel there is already functionality for this that seems to not function. See the code snippet i posted above:

 

if (reg > 0xff) {
txbuf[0] = reg;
txbuf[1] = reg >> 8;
txsize = 2;
} else {
txbuf[0] = reg;
txsize = 1;
}
 
Lets say the register is 0x0318.
 
txbuf is an array of alt_u8 integers. So we have:
 
alt_u8 data = 0xDD;
alt_u8 txbuff[2];
 
if (reg > 0xff) ----YES
   so,
         txbuf[0] = 0x18   (this is 0x318 converted to alt_u8.
         txbuff[1] = 0x03  (0x0318 >> = 0x03;
         txsize = 2;
 
So now I send the txbuf with the register as the first 2 bytes.
 
The intel driver takes care of the rest with this function calls:
 
alt_avalon_i2c_master_transmit(i2c_dev, txbuff, txsize, ALT_AVALON_I2C_NO_RESTART, ALT_AVALON_I2C_NO_STOP);
 
with this function call 0x03 then 0x18 are sent over the i2c bus sequentially....so this point should already exist in the driver. But it isn't working. I can try something manually, but it would be nice to just use the intel functions since we are already using them for everything.
 
Thanks,
Jacob
 
0 Kudos
JingyangTeh
Employee
1,094 Views

Hi Jacob


Could you share me the github link to i2c_interface.c that you are referring too?

Are you using the "i2c_interface.c" or the" alt_avalon_i2c.c"?

From the "alt_avalon_i2c_master_tx_rx" function you need to enter the register as part of the buffer.

The "alt_avalon_i2c_master_transmit" will loop through the buffer to transmit the whole array.

I do not see a problem in this implementation.


Regards

Jingyang, Teh





0 Kudos
Jacob11
New Contributor II
1,028 Views

Hello Jingyang.

 

Sorry, we have been closed for the Christmas break so I am only seeing your response today.

 

I agree this should work fine since the buffer holds the entire register address and loops through the whole buffer. But it is not working for whatever reason.

 

The i2c_interface.c is provided to us as confidential from Intel so I cannot publicly share that. Maybe you can poke around at Intel and find it. 

 

I cannot find any flaw in this implementation. I will check again the datasheets of the hardware to make sure I am not missing something.

 

Thanks,

Jacob

0 Kudos
JingyangTeh
Employee
1,072 Views

Hi


Any update on this case?


Regards

Jingyang, Teh


0 Kudos
JingyangTeh
Employee
1,048 Views

Hi


Since there are no feedback for this thread, I shall set this thread to close pending. Please login to ‘https://supporttickets.intel.com’, view details of the desire request, and post a feed/response within the next 15 days to allow me to continue to support you. After 15 days, this thread will be transitioned to community support. The community users will be able to help you on your follow-up questions.


If you happened to close this thread you might receive a survey. If you think you would rank your support experience less than 10 out of 10, please allow me to correct it before closing or if the problem can’t be corrected, please let me know the cause so that I may improve your future service experience.


Regards

Jingyang, Teh


0 Kudos
Reply