This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software:
Hi everyone,
I'm working on an I2C driver to meet a client's application requirements. I've broken down the I2C Controller operations into several phases:
i2c_start_write
i2c_start_read
i2c_write
i2c_read
i2c_stop
Currently, the write operations (start_write
→ write
) are functioning correctly. However, I'm encountering issues with the read operations (start_read
→ read
→ stop
). Here's what's happening:
Issue:
When I execute the following sequence:
start_write > write > start_read > read > stop
During the start_read
phase, the function DL_I2C_startControllerTransferAdvanced
automatically triggers a data read operation. This results in the read data clock being generated unexpectedly. Although the target address (addr
) is being sent out, the data read should not start automatically at this stage.
Expected Behavior:
In the start_read
phase, the system should:
addr
).read
phase.Relevant Code Snippet:
static bool i2c_start_read(void) { // Wait until I2C controller is idle if (!retry_until_condition(BUS0_I2C_INST, MAX_RETRIES, 10, is_i2c_idle)) { uart_printf("%s I2C not idle; retry limit reached before starting read transfer\n", TAG); return false; } // Flush RX FIFO and reset transfer DL_I2C_flushControllerRXFIFO(BUS0_I2C_INST); DL_I2C_resetControllerTransfer(BUS0_I2C_INST); // Set only the START condition, print debug message #if DEBUG_START uart_printf("%s Starting I2C read transfer (START only)\n", TAG); #endif DL_I2C_startControllerTransferAdvanced( BUS0_I2C_INST, addr, DL_I2C_CONTROLLER_DIRECTION_RX, 0, // Transmission length set to 0 DL_I2C_CONTROLLER_START_ENABLE, DL_I2C_CONTROLLER_STOP_DISABLE, DL_I2C_CONTROLLER_ACK_ENABLE ); // Check for transfer errors if (DL_I2C_getControllerStatus(BUS0_I2C_INST) & DL_I2C_CONTROLLER_STATUS_ERROR) { uart_printf("%s Read start transfer error\n", TAG); return false; } return true; }
Additional Context:
According to the I2C Controller documentation:
START
bit in the MCTR
register to generate the START condition. The controller should then send the START condition followed by the target address once it detects the bus is free.MBLEN
field specifies the number of bytes to transmit. Setting MBLEN
to 0
may prevent the address from being sent correctly.What I've Tried:
Ensuring MBLEN
is Set Correctly:
MBLEN
field is set to at least 1
to guarantee the address is sent.BURSTRUN
to start the operation.Adjusting i2c_start_read
Function:
Despite these changes, the issue persists where DL_I2C_startControllerTransferAdvanced
still automatically triggers a data read during the i2c_start_read
phase, causing the read data clock to be generated unexpectedly.
Normal Behavior Example:
When executing i2c_start_read
, the system should:
addr
).read
phase.Any Suggestions or Solutions?
How can I modify the I2C controller operations to ensure that during the start_read
phase, only the START condition is generated without automatically initiating a data read? Is there a specific register setting or sequence of operations I might be missing?
Thanks in advance for your help!
Best regards,
Eason Tsai
Hi, Eason
Stop without generating the read data clock.
How this Stop works?
Just stop sending clock and then waiting for i2c_read is called and then sending the read clock one byte by one byte?
During thestart_read
phase, the functionDL_I2C_startControllerTransferAdvanced
automatically triggers a data read operation. This results in the read data clock being generated unexpectedly. Although the target address (addr
) is being sent out, the data read should not start automatically at this stage.
So in your test result, set len = 1 and MSPM0's I2C can not only send the I2C address but also first read byte included?
What's the test result of setting len = 0? I2C won't send anything include address?
Regards,
Helic
Hi Helic,
Thank you for your prompt response and suggestions.
Regarding your questions:
1. How the Stop works:
Stop condition should terminate the I2C transaction after sending the START condition and the address. It shouldn't generate any read data clock until the i2c_read function is called to manually initiate data reading.
2. Testing len settings:
Setting len = 1:
The I2C controller successfully sends out the target address (addr).
However, it immediately triggers the read data clock, initiating a data read operation automatically, which is not desired at this stage.
Setting len = 0:
Surprisingly, the I2C controller still sends out the target address (addr).
It also automatically triggers the read data clock, just like when len = 1. I expected that setting len = 0 might prevent the address from being sent, but it doesn't.
Is there a way to configure the I2C controller so that during the start_read
phase, it only generates the START condition and sends the target address without automatically initiating the data read? Are there specific register settings or a sequence of operations I might be missing?
Thank you for your assistance!
Best regards,
Eason Tsai
Hi, Eason
I have tried some method to avoid the first byte to be read from Target, all of them not work.
Regards,
Helic