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: Code Composer Studio
Hi, I'm using F28377 to communicate with MSP430FR2XXX by I2C, F28377 as master.
In 28377 master Tx mode, after Tx condition(MDR) setting, I wait ARDY to 1, and check ACK for data transmit, however, it is usually stall ARDY check.
ARDY is always 0 no matter how long I wait, all I can do is to reset the I2C modele (IRS = 0).
here's the question:
1. If ARDY is 0 after setting Tx MDR, does it means the start bit, slave address, direction, one of them is fail during transmit?
2. While stall on ARDY( = 0), the STR.BB is 0, is that means the start bit is fail? or because ARDY == 0, all I2C register is unreachable?
3. Does MSP430 hold SDA low may make ARDY stall at 0?
Hi Willie,
Is the ARDY stall happening after you set the STT bit (start condition) and the slave address is sent? Can you share your I2C init and setup code for the F2837x master device? Checking the I2C waveforms with a logic analyzer would likely help debug this further as well.
You should be able to do something like the below for a master transmitter:
// // Wait until the STP bit is cleared from any previous master communication // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. // if (I2caRegs.I2CMDR.bit.STP == 1) { return I2C_STP_NOT_READY_ERROR; } // // Setup slave address // I2caRegs.I2CSAR = slave_addr; // // Check if bus busy // if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; } // // Set up as master transmitter // FREE + MST + TRX + IRS // I2caRegs.I2CMDR.all = 0x4620; // // Setup number of bytes to send // == (# of register bytes) + (# of data[] buffer bytes) // I2caRegs.I2CCNT = reg_size + data_size; I2caRegs.I2CMDR.bit.STT = 0x1; // Send START condition I2caRegs.I2CMDR.bit.STP = 0x1; // STOP condition will be // generated when I2CCNT is zero while(!I2caRegs.I2CSTR.bit.ARDY) // Wait for slave address to be sent { if(I2caRegs.I2CSTR.bit.XSMT == 0) { break; // ACK received on slave address } } #if I2C_NACK_CHECK // check if NACK was received if(I2caRegs.I2CSTR.bit.NACK == 1) { I2caRegs.I2CMDR.bit.STP = 1; I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; return I2C_NACK_ERROR; } #endif
Best,
Kevin
hi, Kevin
ARDY stall after setting MDR = 0x26A0, here's my setup code
int I2C_MSP430_Tx(Uint16 Slave_address, Uint16 TransBuffer[], Uint16 Trans_DataBytes) { int index_byte = 0; // in bytes Uint16 NACK_retryCnt = 0; Uint32 ClearSTP_retryCnt = 0; I2caRegs.I2CSAR.all = Slave_address; do { NACK_retryCnt++; if( NACK_retryCnt > MAXRETRY_NACK ) { I2caRegs.I2CMDR.bit.STP = 1; // Send Stop cmd return TxFAIL; } I2caRegs.I2CSTR.bit.NACK = 1; // Clear NACK condition DELAY_US(10); if( ClearSTPTimeout() == TimeOut_Happen ) { return TxFAIL; } // Setup I2C Tx Command Byte I2caRegs.I2CMDR.all = 0x26A0; // IRS, RM, TRX, MST, STT On while( I2caRegs.I2CSTR.bit.ARDY != 1 ); ////////////////////ARDY stalls HERE } while( I2caRegs.I2CSTR.bit.NACK == 1 ); // Clear if NACK received // Send Tx buffer for( index_byte = 0; index_byte < Trans_DataBytes; index_byte++ ) { while( I2caRegs.I2CSTR.bit.XRDY == 0 ); I2caRegs.I2CDXR.all = TransBuffer[index_byte]; } // Send Stop cmd I2caRegs.I2CMDR.bit.STP = 1; // Detect stop condition if( ClearSTPTimeout() == TimeOut_Happen ) { return TxFAIL; } } int ClearSTPTimeout(void) { Uint32 ClearSTP_retryCnt = 0; // Detect a stop bit while( I2caRegs.I2CMDR.bit.STP != 0 ) { ClearSTP_retryCnt++; I2caRegs.I2CSTR.bit.SCD = 1; DELAY_US(5); if( ClearSTP_retryCnt > TIMEOUTCNT_STP ) { SendSTOP(); return TimeOut_Happen; } } return TimeOut_Pass; }
Hi Willie,
Are you able to probe the I2CI2C bus and provide screenshots of the waveforms? That would help debug if there's an issue more.
Try replacing line 25 above with the below:
while(!I2caRegs.I2CSTR.bit.ARDY) // Wait for slave address to be sent { if(I2caRegs.I2CSTR.bit.XSMT == 0) { break; // ACK received on slave address } }
Best,
Kevin
Hi Kevin,
Because of PCB layout, it is hard to probe I2C bus, I'll try to do it.
However, can you explain why "XSMT == 0" means received ACK on address? why not detect NACK?
Also, please answer the following question on my first post:
1. If ARDY is 0 after setting Tx MDR, does it means the start bit, slave address, direction, one of them is fail during transmit?
2. While stall on ARDY( = 0), the STR.BB is 0, is that means the start bit is fail? or because ARDY == 0, all I2C register is unreachable?
Hi Willie,
OK, probing the bus will be the easiest way to understand what is going on.
Willie LAi said:However, can you explain why "XSMT == 0" means received ACK on address? why not detect NACK?
I think it should be XRDY flag, not XSMT actually. See the wiki article below. The NACK bit may be able to be used for ACK checking, but you'd need to include a delay since NACK is 0 on reset (i.e. wait some time for slave address to be sent out).
https://processors.wiki.ti.com/index.php/I2C_Tips#Detecting_and_handling_NACK
The NACK handling method described in the Wiki article is the following:
while(!(I2caRegs.I2CSTR.bit.ARDY | I2caRegs.I2CSTR.bit.XRDY)); // Wait for slave address to be sent if(I2caRegs.I2CSTR.bit.NACK == 1) // Check for NACK { I2caRegs.I2CMDR.bit.STP = 1; I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; return I2C_NACK_ERROR; }
Willie LAi said:1. If ARDY is 0 after setting Tx MDR, does it means the start bit, slave address, direction, one of them is fail during transmit?
2. While stall on ARDY( = 0), the STR.BB is 0, is that means the start bit is fail? or because ARDY == 0, all I2C register is unreachable?
I don't think so for either of these, ARDY is zero at reset which may have something to do with what you're seeing. The correct method is to check XRDY as well as ARDY as described in that wiki page I linked.
Please try the above out and let me know how it works.
Best,
Kevin
Hi Kevin,
Kevin Allen18 said:I think it should be XRDY flag, not XSMT actually.
I said XMST because your reply say so on Sep.28. Which one is correct?
From the wiki you post, it says " // Wait for "XRDY" flag to transmit data or "ARDY" if we get NACKed "
Does it means ARDY make sense only on NACK detection? Here's the 28377 spec on page 2221
ARDY at spec says I2C module registers, is it include any register? or just for NACK? if ARDY == 0 but XRDY == 1, can we trust XRDY?
Should we wait for ARDY before access any I2C module registers?
Hi Willie,
Willie LAi said:I said XMST because your reply say so on Sep.28. Which one is correct?
XRDY is the correct one for the NACK checking scheme. XSMT was my mistake earlier.
Willie LAi said:Does it means ARDY make sense only on NACK detection? Here's the 28377 spec on page 2221
I tested your original code (below) on the F2806x device and ARDY got set to 1 for both the NACK and ACK cases of the slave address actually. Let me test the same on F2837x and get back to you soon.
while( I2caRegs.I2CSTR.bit.ARDY != 1 );
Best,
Kevin
Hi Willie,
I just tried the below code on a F28379D LaunchPad and ARDY got set to 1 for both the NACK and ACK cases, try with the STP and Bus busy checks I included. Something else must be wrong with your SW or HW. Please try probing the I2C lines to debug this further.
// // Wait until the STP bit is cleared from any previous master communication // Clearing of this bit by the module is delayed until after the SCD bit is // set. If this bit is not checked prior to initiating a new message, the // I2C could get confused. // if (I2caRegs.I2CMDR.bit.STP == 1) { return I2C_STP_NOT_READY_ERROR; } // // Setup slave address // I2caRegs.I2CSAR.all = slave_addr; // // Check if bus busy // if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; } I2caRegs.I2CMDR.all = 0x26A0; while( I2caRegs.I2CSTR.bit.ARDY != 1 ); #if I2C_NACK_CHECK // check if NACK was received if(I2caRegs.I2CSTR.bit.NACK == 1) { ESTOP0; I2caRegs.I2CMDR.bit.STP = 1; I2caRegs.I2CSTR.all = I2C_CLR_NACK_BIT; return I2C_NACK_ERROR; } #endif
Best,
Kevin