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.
I am doing some experiments with the I2C peripheral to understand it better. When in repeat mode master transmitter, I enable STT bit and then put data in TX FIFO. The code is as follows:
//Set as master transmitter in Repeat mode I2C_setConfig(I2CA_BASE, (I2C_MASTER_SEND_MODE|I2C_REPEAT_MODE)); I2C_sendStartCondition(I2CA_BASE); //Configure FIFO data for EEPROM address I2C_putData(I2CA_BASE, (address>>8) & 0xFF); I2C_putData(I2CA_BASE, address & 0xFF); //wait for the data to be sent //ARDY is low when data is not yet sent. ARDY gets set when all data in FIFO has been sent attemptCount = 1; extern volatile uint32_t externcount; attemptCount = 0; while(attemptCount < 160) { if((I2C_getStatus(I2CA_BASE) & I2C_STR_ARDY) != 0U) { //all data in FIFO has been sent along with START, Device Address //so break out of the loop break; } else { //all data in FIFO is yet to be sent //wait inside loop attemptCount++; externcount = attemptCount; DEVICE_DELAY_US(10); } } //Outside the loop, if ARDY is still low, that means data hasn't been sent yet and timeout has occurred //Exit function and return timeout error if((I2C_getStatus(I2CA_BASE) & I2C_STR_ARDY) == 0U) return ERROR_TIMEOUT;
If the microcontroller recieves NACK from slave receiver, I see that NACK goes high and ARDY goes high as seen from the snapshot below:
I could not find any mention of such behaviour in the TRM.
I only found the following information regarding behaviour of ARDY in the document:
Behaviour of ARDY under NACK reception is not clear from above. Is my understanding that ARDY bit is set when TX or RX is successful or NACK is received correct?
Could anyone please give a clarification regarding this behaviour?
Apran,
ARDY bit behavior is mentioned below. It doesn't explicitly talk about NACK vs ACK because the behavior of ARDY bit is the same whether NACK (or) ACK is received. So, yes ARDY bit does get set irrespective ACK / NACK condition.
Regards,
Manoj
Hi Manoj,
ARDY bit behavior is mentioned below.
I think you missed to add something.
ARDY bit does get set irrespective ACK / NACK condition.
Let's say there are 3 bytes to be transmitted in TX FIFO in REPEAT MASTER mode. NACK is received on the first byte itself. What happens next? Will it set ARDY immediately? Or it will try to send all 3 bytes one by one and get NACKed 3 times and then set ARDY in the end?
Regards,
Arpan
Hi Manoj,
Let's say in Repeat mode as master transmitter, if there is no data in TX FIFO and we set STT. Does ARDY get set after START condition is sent? Similarly, if we raise STP, is ARDY set after STOP condition gets sent?
Regards,
Arpan
Arpan,
Let's say in Repeat mode as master transmitter, if there is no data in TX FIFO and we set STT. Does ARDY get set after START condition is sent?
Yes, ARDY bit does get set
Similarly, if we raise STP, is ARDY set after STOP condition gets sent?
No, ARDY doesn't get set when STOP condition is set. You can wait for I2caRegs.I2CSTR.SCD bit to set to detect whether STOP condition got generated.
Regards,
Manoj
Hi Manoj,
Okay. Understood. Could you please add these to the documentation. All these are not at all clear from the present documentation.
Regards,
Arpan
Hi Manoj,
Could you please reply to the message quoted below?
Hi Manoj,
ARDY bit behavior is mentioned below.I think you missed to add something.
ARDY bit does get set irrespective ACK / NACK condition.Let's say there are 3 bytes to be transmitted in TX FIFO in REPEAT MASTER mode. NACK is received on the first byte itself. What happens next? Will it set ARDY immediately? Or it will try to send all 3 bytes one by one and get NACKed 3 times and then set ARDY in the end?
Regards,
Arpan
Regards,
Arpan
Hi Manoj,
The vrious aspects of ARDY are not clear from the available information in TRM. Could it be expanded so that it's clearer?
Hi Manoj,
In the example provided by you in a different thread e2e.ti.com/.../3909865
Arpan,
In I2C master receiver configuration in repeat mode, you should be knowing when you are receiving the last byte. Before you receive last byte you need to enable NACKMOD = 1. There is a code snippet which demonstrates that.
#define WAIT_TILL_REGISTERS_ARE_READY !(I2C_getStatus(I2CA_BASE) & I2C_STS_REG_ACCESS_RDY)
I2C_disableFIFO(I2CA_BASE);
I2C_setConfig(I2CA_BASE, (I2C_MASTER_SEND_MODE | I2C_REPEAT_MODE));
I2C_sendStartCondition(I2CA_BASE);
I2C_putData(I2CA_BASE, 0); while(WAIT_TILL_REGISTERS_ARE_READY);
I2C_putData(I2CA_BASE, 0); while(WAIT_TILL_REGISTERS_ARE_READY);
I2C_setConfig(I2CA_BASE, (I2C_MASTER_RECEIVE_MODE | I2C_REPEAT_MODE));
I2C_sendStartCondition(I2CA_BASE);
for(i=1;i<=5;i++)
{
status = I2C_getData(I2CA_BASE);while(WAIT_TILL_REGISTERS_ARE_READY);
}
I2C_sendNACK(I2CA_BASE);
status = I2C_getData(I2CA_BASE);while(WAIT_TILL_REGISTERS_ARE_READY);
I2C_sendStopCondition(I2CA_BASE);Regards,
Manoj
After configuring it in receive mode and sending Start condition, if we call I2C_getData() immediately, we are not giving time to microcontroller to receive the data from slave. Should we add ARDY and NACK check in between. If yes, then how many times ARDY check is needed? Twice? Once for STP bit and then for RX?
Regards,
Arpan
Hi Manoj,
I have written the following code to Receive 1 byte as Master in Repeat mode:
//Set as master receiver in Repeat mode I2C_setConfig(I2CA_BASE, (I2C_MASTER_RECEIVE_MODE|I2C_REPEAT_MODE)); I2C_sendStartCondition(I2CA_BASE); //NACK would be sent on next byte received from slave //I2C mandates NACK be sent upon reading the last byte before STOP I2C_sendNACK(I2CA_BASE); //wait for the START condition to be sent. It will also send the slave address with R/W bit //ARDY is low when START, slave address+R/W bit is not yet sent. ARDY gets set when START, slave address+R/W bit has been sent or NACK is received attemptCount = 1U; while(attemptCount < 100U) { DEVICE_DELAY_US(10); if((I2C_getStatus(I2CA_BASE) & I2C_STR_ARDY) != 0U) { //START, Device Address has been sent or NACK has been received //so break out of the loop break; } else { //START, Device Address is yet to be sent //stay inside loop attemptCount++; } } //Outside the loop, if ARDY is still low, that means START, Device Address hasn't been sent yet and timeout has occurred //Exit function and return timeout error if((I2C_getStatus(I2CA_BASE) & I2C_STR_ARDY) == 0U) { return ERROR_TIMEOUT; } //check if NACK has been sent by EEPROM if(I2C_getStatus(I2CA_BASE) & I2C_STR_NACK) { //NACK received from EEPROM //Slave did not respond I2C_clearStatus(I2CA_BASE, I2C_STS_NO_ACK); I2C_sendStopCondition(I2CA_BASE); I2C_disableFIFO(I2CA_BASE); I2C_enableFIFO(I2CA_BASE); //wait for the STOP condition to be set //MST is high when STOP is not yet sent. MST gets reset when STOP has been sent. It provides the essential delay between 2 consecutive I2C transfers (read or write operations) attemptCount = 1U; while(attemptCount < 100U) { DEVICE_DELAY_US(10); if((HWREGH(I2CA_BASE + I2C_O_MDR) & I2C_MDR_MST) == 0U) { //MST has been reset, so STOP has been sent and delay between 2 consecutive transfers is over //so break out of the loop break; } else { //MST is yet to be reset //stay inside loop attemptCount++; } } //Check MST, STP bytes to ensure Stop condition has been sent (both bits should be low) if(((HWREGH(I2CA_BASE + I2C_O_MDR) & I2C_MDR_MST) != 0U) || (I2C_getStopConditionStatus(I2CA_BASE) != 0U)) { //If MST or STP is still high, that means STOP bit hasn't been sent yet and it times out above //return error code //enable write protect GPIO_writePin(39, 1); //TODO: Add Stop condition recovery sequence return ERROR_TIMEOUT; } //enable write protect GPIO_writePin(39, 1); return I2C_NACK_ERROR; } //wait for the data to be received (with NACK) //ARDY is low when data is not yet received. ARDY gets set when data has been received attemptCount = 1U; while(attemptCount < 100U) { DEVICE_DELAY_US(10); if((I2C_getStatus(I2CA_BASE) & I2C_STR_ARDY) != 0U) { //data has been received //so break out of the loop break; } else { //data yet to be received //stay inside loop attemptCount++; } } //Outside the loop, if ARDY is still low, that means data hasn't been received yet and timeout has occurred //Exit function and return timeout error if((I2C_getStatus(I2CA_BASE) & I2C_STR_ARDY) == 0U) { return ERROR_TIMEOUT; } //read the received data and store in the pointer supplied as fucntion argument *byte = I2C_getData(I2CA_BASE); //send STOP condition to finish I2C transaction I2C_sendStopCondition(I2CA_BASE);
I need your feedback regarding this code:
I2C_setConfig(I2CA_BASE, (I2C_MASTER_RECEIVE_MODE|I2C_REPEAT_MODE));
I2C_sendStartCondition(I2CA_BASE);
I2C_sendNACK(I2CA_BASE);
//wait for START and slave address+R/W to be sent
while(WAIT_TILL_REGISTERS_ARE_READY);
//wait for 1 byte data to be clocked in
while(WAIT_TILL_REGISTERS_ARE_READY);
//read the 1 byte data received
*byte = I2C_getData(I2CA_BASE);
I2C_sendStopCondition(I2CA_BASE);
Regards,
Arpan
Arpan,
After configuring it in receive mode and sending Start condition, if we call I2C_getData() immediately, we are not giving time to microcontroller to receive the data from slave. Should we add ARDY and NACK check in between.
ARDY and NACK condition needs on START condition, each time a byte is transmitted / received. For STOP condition, you can wait for I2CSTR.SCD bit to go high to ensure STOP condition is generated.
What do you think of the following seuence to receive 1 byte ? The sequence used in the above code is summarised below:I2C_setConfig(I2CA_BASE, (I2C_MASTER_RECEIVE_MODE|I2C_REPEAT_MODE));
I2C_sendStartCondition(I2CA_BASE);
I2C_sendNACK(I2CA_BASE);
//wait for START and slave address+R/W to be sent
while(WAIT_TILL_REGISTERS_ARE_READY);
//wait for 1 byte data to be clocked in
while(WAIT_TILL_REGISTERS_ARE_READY);
//read the 1 byte data received
*byte = I2C_getData(I2CA_BASE);
I2C_sendStopCondition(I2CA_BASE);
You don't need two while(WAIT_TILL_REGISTERS_ARE_READY) loops. You just need one.
After setting STP bit, I am waiting till MST bit is reset and then checking for MST and STP bites to ensure that STOP condition has been sent. In this code, I am doing this after sending STOP if NACK is received from slave (lines 38 to 81). Do you think it's a correct approach after NACK has been received and when I want to send STOP at the end of any I2C operation?
To check whether STOP condition has been successfully generated, you need to use I2CSTR.SCD bit. You seem to be using I2CMDR.MST bit. I wouldn't do that when there is specifically a SCD bit to tell whether STOP condition got generated.
Regards,
Manoj
The vrious aspects of ARDY are not clear from the available information in TRM. Could it be expanded so that it's clearer?
All the contents regarding ARDY bit is provided in current TRM. It is just that it is little bit scattered all over the place. I will review and try to consolidate it next TRM release.
You don't need two while(WAIT_TILL_REGISTERS_ARE_READY) loops. You just need one.
When does ARDY go high? Because you had said earlier that ARDY goes high after START condition is sent out by master.
I think then again ARDY will go high after 1 byte is received. Is it not so?
Regards,
Arpan
To check whether STOP condition has been successfully generated, you need to use I2CSTR.SCD bit. You seem to be using I2CMDR.MST bit. I wouldn't do that when there is specifically a SCD bit to tell whether STOP condition got generated.
This is according to I2C tips recommendation :
Arpan,
In my previous post, I had said ARDY does get SET even if the slave NACK the transaction on a START condition. Below, code will work file for 1 byte receive transaction.
I2C_setConfig(I2CA_BASE, (I2C_MASTER_RECEIVE_MODE | I2C_REPEAT_MODE));
I2C_sendStartCondition(I2CA_BASE);
I2C_sendNACK(I2CA_BASE);
while(WAIT_TILL_REGISTERS_ARE_READY); //check ARDY bit is set (or) not.
RX_MsgBuffer[0] = I2C_getData(I2CA_BASE);
I2C_sendStopCondition(I2CA_BASE);
Regards,
Manoj