From 54bcbdae625ffba45c22acbdf3267dd9482275f7 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Tue, 21 Nov 2023 08:21:18 -0800 Subject: [PATCH 1/2] Fix STM32 I2C v2 async transfer not doing a repeated start --- targets/TARGET_STM/i2c_api.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/targets/TARGET_STM/i2c_api.c b/targets/TARGET_STM/i2c_api.c index 266eeaa5772..74ca2b8dce4 100644 --- a/targets/TARGET_STM/i2c_api.c +++ b/targets/TARGET_STM/i2c_api.c @@ -1389,7 +1389,7 @@ void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) if(obj->rx_buff.length > 0) { // This is a write-then-read transaction, switch to reading. - uint32_t xferOptions = obj_s->stop ? I2C_FIRST_AND_LAST_FRAME : I2C_FIRST_FRAME; + uint32_t xferOptions = get_hal_xfer_options(obj_s, obj_s->stop); HAL_I2C_Master_Seq_Receive_IT(hi2c, obj_s->address, (uint8_t *) obj->rx_buff.buffer, obj->rx_buff.length, xferOptions); obj_s->state = STM_I2C_ASYNC_READ_IN_PROGRESS; @@ -1784,7 +1784,11 @@ void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length, void *rx, prep_for_restart_if_needed(obj_s); - uint32_t xferOptions = get_hal_xfer_options(obj_s, stop); + // If we are doing both a tx and an rx, then we never want to send a stop on the + // first transfer. + bool sendStopOnFirstTransfer = stop && ((tx_length == 0) || (rx_length == 0)); + + uint32_t xferOptions = get_hal_xfer_options(obj_s, sendStopOnFirstTransfer); if(!i2c_is_ready_for_transaction_start(obj_s->state)) { From 4866b8deddf8e371bbb149041053ae28e3270d64 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Tue, 21 Nov 2023 08:30:41 -0800 Subject: [PATCH 2/2] Clarify docs --- drivers/include/drivers/I2C.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/include/drivers/I2C.h b/drivers/include/drivers/I2C.h index 541ca362a43..27e8cd1a8b3 100644 --- a/drivers/include/drivers/I2C.h +++ b/drivers/include/drivers/I2C.h @@ -377,7 +377,8 @@ class I2C : private NonCopyable { * * The %I2C peripheral will begin a transmit and/or receive operation in the background. If only a transmit * or receive buffer is specified, only a transmit or receive will be done. If both buffers are specified, - * first the transmission is done to the given slave address, then the specified number of bytes are received. + * first the transmission is done to the given slave address, then the MCU performs a repeated start + * and the specified number of bytes are received. * * If you wish to find out when the transfer is done, pass a callback function to the callback argument * and set the event argument to the events you wish to receive. @@ -400,7 +401,7 @@ class I2C : private NonCopyable { * of the flags I2C_EVENT_ERROR, I2C_EVENT_ERROR_NO_SLAVE, I2C_EVENT_TRANSFER_COMPLETE, or I2C_EVENT_TRANSFER_EARLY_NACK * @param callback The event callback function * @param repeated Set up for a repeated start. If true, the Mbed processor does not relinquish the bus after - * this write operation. You may then call write(), read(), or start() again to start another operation. + * this operation. You may then call write(), read(), start(), or transfer() again to start another operation. * * @returns Zero if the transfer has started, or -1 if I2C peripheral is busy */ @@ -415,7 +416,8 @@ class I2C : private NonCopyable { * * The %I2C peripheral will begin a transmit and/or receive operation in the background. If only a transmit * or receive buffer is specified, only a transmit or receive will be done. If both buffers are specified, - * first the transmission is done to the given slave address, then the specified number of bytes are received. + * first the transmission is done to the given slave address, then the MCU performs a repeated start + * and the specified number of bytes are received. * * Internally, the chip vendor may implement this function using either DMA or interrupts. * @@ -428,7 +430,7 @@ class I2C : private NonCopyable { * @param rx_length The length of RX buffer in bytes If 0, no reception is done. * @param timeout timeout value. Use #rtos::Kernel::wait_for_u32_forever to wait forever (the default). * @param repeated Set up for a repeated start. If true, the Mbed processor does not relinquish the bus after - * this operation. You may then call write(), read(), or start() again to start another operation. + * this operation. You may then call write(), read(), start(), or transfer() again to start another operation. * * @returns Result code describing whether the transfer succeeded or not. */