Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions drivers/i2c/i2c_ll_stm32_v1.c
Original file line number Diff line number Diff line change
Expand Up @@ -597,27 +597,54 @@ int i2c_stm32_error(const struct device *dev)
I2C_TypeDef *i2c = cfg->i2c;

#if defined(CONFIG_I2C_TARGET)
if (data->slave_attached && !data->master_active) {
/* No need for a slave error function right now. */
return 0;
i2c_target_error_cb_t error_cb = NULL;

if (data->slave_attached && !data->master_active &&
data->slave_cfg != NULL && data->slave_cfg->callbacks != NULL) {
error_cb = data->slave_cfg->callbacks->error;
}
#endif

if (LL_I2C_IsActiveFlag_AF(i2c)) {
LL_I2C_ClearFlag_AF(i2c);
LL_I2C_GenerateStopCondition(i2c);
data->current.is_nack = 1U;
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_GENERIC);
}
#endif
goto end;
}
if (LL_I2C_IsActiveFlag_ARLO(i2c)) {
LL_I2C_ClearFlag_ARLO(i2c);
data->current.is_arlo = 1U;
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_ARBITRATION);
}
#endif
goto end;
}

if (LL_I2C_IsActiveFlag_BERR(i2c)) {
LL_I2C_ClearFlag_BERR(i2c);
data->current.is_err = 1U;
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_GENERIC);
}
#endif
goto end;
}

if (LL_I2C_IsActiveFlag_OVR(i2c)) {
LL_I2C_ClearFlag_OVR(i2c);
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_GENERIC);
}
#endif
goto end;
}

Expand All @@ -632,7 +659,13 @@ int i2c_stm32_error(const struct device *dev)
#endif
return 0;
end:
#if defined(CONFIG_I2C_TARGET)
if (!data->slave_attached || data->master_active) {
i2c_stm32_master_mode_end(dev);
}
#else
i2c_stm32_master_mode_end(dev);
#endif
return -EIO;
}

Expand Down
28 changes: 25 additions & 3 deletions drivers/i2c/i2c_ll_stm32_v1_rtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -452,31 +452,53 @@ int i2c_stm32_error(const struct device *dev)

#if defined(CONFIG_I2C_TARGET)
struct i2c_stm32_data *data = dev->data;
i2c_target_error_cb_t error_cb = NULL;

if (data->slave_attached && !data->master_active) {
/* No need for a target error function right now. */
return 0;
if (data->slave_attached && !data->master_active &&
data->slave_cfg != NULL && data->slave_cfg->callbacks != NULL) {
error_cb = data->slave_cfg->callbacks->error;
}
#endif

if (LL_I2C_IsActiveFlag_AF(i2c)) {
LL_I2C_ClearFlag_AF(i2c);
LL_I2C_GenerateStopCondition(i2c);
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_GENERIC);
}
#endif
goto error;
}
if (LL_I2C_IsActiveFlag_ARLO(i2c)) {
LL_I2C_ClearFlag_ARLO(i2c);
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_ARBITRATION);
}
#endif
goto error;
}

if (LL_I2C_IsActiveFlag_BERR(i2c)) {
LL_I2C_ClearFlag_BERR(i2c);
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_GENERIC);
}
#endif
goto error;
}

return 0;
error:
#if defined(CONFIG_I2C_TARGET)
if (!data->slave_attached || data->master_active) {
i2c_stm32_master_mode_end(dev, -EIO);
}
#else
i2c_stm32_master_mode_end(dev, -EIO);
#endif
return -EIO;

}
Expand Down
24 changes: 21 additions & 3 deletions drivers/i2c/i2c_ll_stm32_v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,15 +593,22 @@ int i2c_stm32_error(const struct device *dev)
I2C_TypeDef *i2c = cfg->i2c;

#if defined(CONFIG_I2C_TARGET)
if (data->slave_attached && !data->master_active) {
/* No need for a slave error function right now. */
return 0;
i2c_target_error_cb_t error_cb = NULL;

if (data->slave_attached && !data->master_active &&
data->slave_cfg != NULL && data->slave_cfg->callbacks != NULL) {
error_cb = data->slave_cfg->callbacks->error;
}
#endif

if (LL_I2C_IsActiveFlag_ARLO(i2c)) {
LL_I2C_ClearFlag_ARLO(i2c);
data->current.is_arlo = 1U;
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_ARBITRATION);
}
#endif
goto end;
}

Expand All @@ -613,6 +620,12 @@ int i2c_stm32_error(const struct device *dev)
if (LL_I2C_IsActiveFlag_BERR(i2c)) {
LL_I2C_ClearFlag_BERR(i2c);
data->current.is_err = 1U;
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_GENERIC);
}
#endif
goto end;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end sequence must be updated:

 end:
+#if defined(CONFIG_I2C_TARGET)
+	if (data->slave_attached && !data->master_active) {
+		return -EIO;
+	}
+#endif
 	i2c_stm32_disable_transfer_interrupts(dev);
 	/* Wakeup thread */
 	k_sem_give(&data->device_sync_sem);
 	return -EIO;
}

(with indentation updates)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

#if defined(CONFIG_SMBUS_STM32_SMBALERT)
Expand All @@ -627,6 +640,11 @@ int i2c_stm32_error(const struct device *dev)

return 0;
end:
#if defined(CONFIG_I2C_TARGET)
if (data->slave_attached && !data->master_active) {
return -EIO;
}
#endif
i2c_stm32_disable_transfer_interrupts(dev);
/* Wakeup thread */
k_sem_give(&data->device_sync_sem);
Expand Down
19 changes: 16 additions & 3 deletions drivers/i2c/i2c_ll_stm32_v2_rtio.c
Original file line number Diff line number Diff line change
Expand Up @@ -428,17 +428,30 @@ int i2c_stm32_error(const struct device *dev)
int ret = 0;

#if defined(CONFIG_I2C_TARGET)
if (data->slave_attached && !data->master_active) {
/* No need for a target error function right now. */
return 0;
i2c_target_error_cb_t error_cb = NULL;

if (data->slave_attached && !data->master_active &&
data->slave_cfg != NULL && data->slave_cfg->callbacks != NULL) {
error_cb = data->slave_cfg->callbacks->error;
}
#endif

if (LL_I2C_IsActiveFlag_ARLO(i2c)) {
LL_I2C_ClearFlag_ARLO(i2c);
#if defined(CONFIG_I2C_TARGET)
if (error_cb != NULL) {
error_cb(data->slave_cfg, I2C_ERROR_ARBITRATION);
}
#endif
ret = -EIO;
}

#if defined(CONFIG_I2C_TARGET)
if (data->slave_attached && !data->master_active) {
return ret;
}
#endif

if (ret) {
i2c_stm32_master_mode_end(dev);
if (i2c_rtio_complete(ctx, ret)) {
Expand Down
29 changes: 29 additions & 0 deletions include/zephyr/drivers/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,34 @@ typedef int (*i2c_target_buf_read_requested_cb_t)(
*/
typedef int (*i2c_target_stop_cb_t)(struct i2c_target_config *config);

/**
* @brief I2C error reasons.
*
* Values that correspond to events or errors responsible for stopping
* an I2C transfer.
*/
enum i2c_error_reason {
I2C_ERROR_TIMEOUT = 0, /* Timeout error */
I2C_ERROR_ARBITRATION, /* Bus arbitration size */
I2C_ERROR_SIZE, /* Bad frame size */
I2C_ERROR_DMA, /* DMA transfer error */
I2C_ERROR_GENERIC, /* Any other bus error */
};

/** @brief Function called when an error is detected on the I2C bus
* while acting as a target.
*
* This function is invoked by the controller when a bus error,
* arbitration lost, or other critical error is detected during
* a transaction addressed to this device.
*
* @param config the configuration structure associated with the
* device to which the operation is addressed.
* @param error_code an integer code identifying the error type.
*/
typedef void (*i2c_target_error_cb_t)(struct i2c_target_config *config,
enum i2c_error_reason error_code);

/** @brief Structure providing callbacks to be implemented for devices
* that supports the I2C target API.
*
Expand All @@ -430,6 +458,7 @@ struct i2c_target_callbacks {
i2c_target_buf_read_requested_cb_t buf_read_requested;
#endif
i2c_target_stop_cb_t stop;
i2c_target_error_cb_t error;
};

/** @brief Structure describing a device that supports the I2C
Expand Down