- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The datasheet states that a noise-triggered start condition could cause the bus to be in a "busy" state forever. What's the best way to detect this state and get back on-track?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just had another thought....
Assuming a single bus master and that a slave is holding SDA low waiting for a clock, rather than the messy low-level-hardware firmware wiggling of SCL, what do you think about creating a special "SCB_I2CMasterWriteBuf" routine by copying the code from SBC_I2C_MASTER.c after the bus-busy check? Then perform the following steps:
1. SCB_I2CMasterWriteBuf detects bus busy
2. Call the "special" created routine using an unused address (ideally 0xFF) to wiggle just the clock
3. Wait for completion using this code
for (y=0; y<WR_LIMIT; y++) { // then wait for completed transfer
i2c_status = I2C_I2CMasterStatus();
if (0u != (i2c_status & I2C_I2C_MSTAT_WR_CMPLT)) // are we done?
break;
}
which will complete with I2C_I2C_MSTAT_ERR_XFER flag set since there is no slave to ACK
4. Repeat step 3 x number of times for 8x clock pulses
5. Hopefully device releases SDA and bus is back to the idle state
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
Can the following topic be a hint?
Regarding PSoC4 I2C reset for I2C slave hang up(SDA is low)
moto
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Just had another thought....
Assuming a single bus master and that a slave is holding SDA low waiting for a clock, rather than the messy low-level-hardware firmware wiggling of SCL, what do you think about creating a special "SCB_I2CMasterWriteBuf" routine by copying the code from SBC_I2C_MASTER.c after the bus-busy check? Then perform the following steps:
1. SCB_I2CMasterWriteBuf detects bus busy
2. Call the "special" created routine using an unused address (ideally 0xFF) to wiggle just the clock
3. Wait for completion using this code
for (y=0; y<WR_LIMIT; y++) { // then wait for completed transfer
i2c_status = I2C_I2CMasterStatus();
if (0u != (i2c_status & I2C_I2C_MSTAT_WR_CMPLT)) // are we done?
break;
}
which will complete with I2C_I2C_MSTAT_ERR_XFER flag set since there is no slave to ACK
4. Repeat step 3 x number of times for 8x clock pulses
5. Hopefully device releases SDA and bus is back to the idle state
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi WaPi_297581,
If you are the only master in the bus and you get the SCB_I2C_MSTR_BUS_BUSY flag, this definitely means that it is an error. You can straight away reset the SCB block by calling the SCB_Stop() and SCB_Start() functions.
But in a multi- master system, this can not be differentiated. So, if you get a SCB_I2C_MSTR_BUS_BUSY flag it could mean an on-going transaction or it could be due to the ESD event triggered start condition. In that case, you can implement a counter to see how many times your read/ write function returns SCB_I2C_MSTR_BUS_BUSY. If certain counter value is crossed, you can reset the block and try again. Or you can implement a timeout (max time taken to complete a transaction) and reset the block by calling SCB_Stop() and SCB_Start() functions.
In general, it is highly recommended that the ESD events should not strike your device through the I2C lines.
Hope this helps.
Regards,
Bragadeesh
Bragadeesh