Skip to content

Commit db95dd0

Browse files
committed
Fix i2c scan bug with ports/analog/ BUSIO.
- Probe function caused infinite loops / unreliable ACK values - Replaced with probe-function with low-level routines Signed-off-by: Brandon Hurst <[email protected]>
1 parent c3ea182 commit db95dd0

File tree

1 file changed

+16
-26
lines changed
  • ports/analog/common-hal/busio

1 file changed

+16
-26
lines changed

ports/analog/common-hal/busio/I2C.c

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,8 @@
3434

3535
#define I2C_PRIORITY 1
3636

37-
typedef enum {
38-
I2C_FREE = 0,
39-
I2C_BUSY,
40-
I2C_NEVER_RESET,
41-
} i2c_status_t;
42-
4337
// Set each bit to indicate an active I2c
4438
static uint8_t i2c_active = 0;
45-
static i2c_status_t i2c_status[NUM_I2C];
4639
static volatile int i2c_err;
4740

4841
// I2C struct for configuring GPIO pins
@@ -68,7 +61,9 @@ void common_hal_busio_i2c_construct(busio_i2c_obj_t *self,
6861
self->i2c_regs = MXC_I2C_GET_I2C(temp);
6962
}
7063

64+
// Check for valid I2C controller
7165
assert((self->i2c_id >= 0) && (self->i2c_id < NUM_I2C));
66+
assert(!(i2c_active & (1 << self->i2c_id)));
7267

7368
// Init I2C as main / controller node (0x00 is ignored)
7469
if ((scl != NULL) && (sda != NULL)) {
@@ -132,48 +127,43 @@ void common_hal_busio_i2c_deinit(busio_i2c_obj_t *self) {
132127

133128
// Probe device in I2C bus
134129
bool common_hal_busio_i2c_probe(busio_i2c_obj_t *self, uint8_t addr) {
135-
int32_t flags = 0x0;
136-
bool ret = false;
130+
uint32_t int_fl0, int_fl1;
131+
bool ret = 0;
137132

138-
MXC_I2C_ClearFlags(self->i2c_regs, 0xFF, 0xFF);
139-
MXC_I2C_EnableInt(self->i2c_regs, 0xFF, 0xFF);
133+
// Clear FIFOs & all interrupt flags
134+
MXC_I2C_ClearRXFIFO(self->i2c_regs);
135+
MXC_I2C_ClearTXFIFO(self->i2c_regs);
136+
MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF);
140137

141138
// Pre-load target address into transmit FIFO
142139
addr = (addr << 1);
143140
self->i2c_regs->fifo = addr;
144141

145142
// Set start bit & wait for it to clear
146-
self->i2c_regs->mstctrl |= MXC_F_I2C_MSTCTRL_START;
143+
MXC_I2C_Start(self->i2c_regs);
147144

148145
// wait for ACK/NACK
149-
// if tx_lockout occurs, clear the error and re-load the target address
150146
while (!(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_ACK) &&
151147
!(self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_ADDR_NACK_ERR)) {
152-
if (self->i2c_regs->intfl0 & MXC_F_I2C_INTFL0_TX_LOCKOUT) {
153-
self->i2c_regs->intfl0 |= MXC_F_I2C_INTFL0_TX_LOCKOUT;
154-
self->i2c_regs->fifo = addr;
155-
}
156148
}
157-
flags = self->i2c_regs->intfl0;
158-
self->i2c_regs->intfl0 = MXC_F_I2C_INTFL0_ADDR_ACK | MXC_F_I2C_INTFL0_ADDR_NACK_ERR
159149

160-
// Set / Wait for stop
161-
self->i2c_regs->mstctrl |= MXC_F_I2C_MSTCTRL_STOP;
162-
while ((self->i2c_regs->mstctrl & MXC_F_I2C_MSTCTRL_STOP)) {
163-
;
164-
}
150+
// Save interrupt flags for ACK/NACK checking
151+
int_fl0 = self->i2c_regs->intfl0;
152+
153+
// Set / Wait for stop
154+
MXC_I2C_Stop(self->i2c_regs);
165155

166156
// Wait for controller not busy, then clear flags
167157
while (self->i2c_regs->status & MXC_F_I2C_STATUS_BUSY) {
168158
;
169159
}
160+
MXC_I2C_ClearFlags(self->i2c_regs, 0xFFFFFF, 0xFFFFFF);
170161

171-
if (flags & MXC_F_I2C_INTFL0_ADDR_ACK) {
162+
if (int_fl0 & MXC_F_I2C_INTFL0_ADDR_ACK) {
172163
ret = true;
173164
} else {
174165
ret = false;
175166
}
176-
MXC_I2C_ClearFlags(self->i2c_regs, 0xff, 0xff);
177167
return ret;
178168
}
179169

0 commit comments

Comments
 (0)