Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix STM32 I2C v2 async transfer not doing a repeated start #197

Merged
Merged
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
10 changes: 6 additions & 4 deletions drivers/include/drivers/I2C.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,8 @@ class I2C : private NonCopyable<I2C> {
*
* 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.
Expand All @@ -400,7 +401,7 @@ class I2C : private NonCopyable<I2C> {
* 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
*/
Expand All @@ -415,7 +416,8 @@ class I2C : private NonCopyable<I2C> {
*
* 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.
*
Expand All @@ -428,7 +430,7 @@ class I2C : private NonCopyable<I2C> {
* @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.
*/
Expand Down
8 changes: 6 additions & 2 deletions targets/TARGET_STM/i2c_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
{
Expand Down