Skip to content

Commit

Permalink
Make it possible to get i2c abort reason
Browse files Browse the repository at this point in the history
Currently we're returning PICO_ERROR_GENERIC for an i2c abort such as
"No ack". Add a new PICO_ERROR_ABORT and use this if
PICO_I2C_RETURN_ABORT_REASON is true.

The abort reason comes from tx_abrt_source
(I2C_IC_TX_ABRT_SOURCE_ABRT_*_BITS) so take the zero count from
PICO_ERROR_ABORT, so the reason can be determined from the return code.

Fixes #1049
  • Loading branch information
peterharperuk committed Nov 11, 2024
1 parent f642b76 commit 4ac16d6
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/common/pico_base_headers/include/pico/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ enum pico_error_codes {
PICO_ERROR_UNSUPPORTED_MODIFICATION = -18, ///< Write is impossible based on previous writes; e.g. attempted to clear an OTP bit
PICO_ERROR_LOCK_REQUIRED = -19, ///< A required lock is not owned
PICO_ERROR_VERSION_MISMATCH = -20, ///< A version mismatch occurred (e.g. trying to run PIO version 1 code on RP2040)
PICO_ERROR_RESOURCE_IN_USE = -21 ///< The call could not proceed because requires resourcesw were unavailable
PICO_ERROR_RESOURCE_IN_USE = -21, ///< The call could not proceed because requires resourcesw were unavailable
PICO_ERROR_ABORT = -22, ///< The call could not proceed so was aborted
};

#endif // !__ASSEMBLER__
Expand Down
17 changes: 13 additions & 4 deletions src/rp2_common/hardware_i2c/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ void i2c_set_slave_mode(i2c_inst_t *i2c, bool slave, uint8_t addr) {
i2c->hw->enable = 1;
}

// PICO_CONFIG: PICO_I2C_RETURN_ABORT_REASON, change i2c functions to return the abort reason via a return code less than or equal to PICO_ERROR_ABORT, type=bool, default=0, group=harware_i2c
#if PICO_I2C_RETURN_ABORT_REASON
// if (ret <= PICO_ERROR_ABORT) abort_reason = PICO_ERROR_ABORT - ret; // one of I2C_IC_TX_ABRT_SOURCE_ABRT_*_LSB
#define PICO_I2C_MAKE_ABORT_ERROR(A) (PICO_ERROR_ABORT - __builtin_ctz(A))
#else
// By default, for compatibility, return PICO_ERROR_GENERIC if an abort occurs
#define PICO_I2C_MAKE_ABORT_ERROR(A) PICO_ERROR_GENERIC
#endif

static int i2c_write_blocking_internal(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, bool nostop,
check_timeout_fn timeout_check, struct timeout_state *ts) {
invalid_params_if(HARDWARE_I2C, addr >= 0x80); // 7-bit addresses
Expand Down Expand Up @@ -225,13 +234,13 @@ static int i2c_write_blocking_internal(i2c_inst_t *i2c, uint8_t addr, const uint
else if (!abort_reason || abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS) {
// No reported errors - seems to happen if there is nothing connected to the bus.
// Address byte not acknowledged
rval = PICO_ERROR_GENERIC;
rval = PICO_I2C_MAKE_ABORT_ERROR(I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS);
} else if (abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_TXDATA_NOACK_BITS) {
// Address acknowledged, some data not acknowledged
rval = byte_ctr;
} else {
//panic("Unknown abort from I2C instance @%08x: %08x\n", (uint32_t) i2c->hw, abort_reason);
rval = PICO_ERROR_GENERIC;
rval = PICO_I2C_MAKE_ABORT_ERROR(abort_reason);
}
} else {
rval = byte_ctr;
Expand Down Expand Up @@ -319,10 +328,10 @@ static int i2c_read_blocking_internal(i2c_inst_t *i2c, uint8_t addr, uint8_t *ds
else if (!abort_reason || abort_reason & I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS) {
// No reported errors - seems to happen if there is nothing connected to the bus.
// Address byte not acknowledged
rval = PICO_ERROR_GENERIC;
rval = PICO_I2C_MAKE_ABORT_ERROR(I2C_IC_TX_ABRT_SOURCE_ABRT_7B_ADDR_NOACK_BITS);
} else {
// panic("Unknown abort from I2C instance @%08x: %08x\n", (uint32_t) i2c->hw, abort_reason);
rval = PICO_ERROR_GENERIC;
rval = PICO_I2C_MAKE_ABORT_ERROR(abort_reason);
}
} else {
rval = byte_ctr;
Expand Down

0 comments on commit 4ac16d6

Please sign in to comment.