QG8 IIC busy flag not being cleared

cancel
Showing results for 
Search instead for 
Did you mean: 

QG8 IIC busy flag not being cleared

4,113 Views
Contributor III
Hi,
 
I cannot figure out why the IIC bus busy flag is not getting cleared.  The flag remains at 1 when the below code is executed a third time.
 
 
// Turns on or off a specified display LED connected to the MAX7658
void write_LEDs(unsigned char LED_number, unsigned char LED_status)
{
 
 if (LED_status == on)
   set_bit(current_Segments, LED_number);
 else
   clear_bit(current_Segments, LED_number);
 
 while(IICS_BUSY);   // wait for bus to free
 
 START_BIT;       // send start signal
 IICD = max6958_slave_address; // send calling address (write bit is included)
 while(!IICS_TCF);   // wait for byte transfer to complete
 acknowledge = check_ACK();
 if (acknowledge == DEVICE_NO_ACK )
   return;
  
 IICD = Segments;    // Segments register
 while(!IICS_TCF);   // wait for byte transfer to complete
 acknowledge = check_ACK();
 if (acknowledge == DEVICE_NO_ACK )
   return;
 
 IICD = current_Segments; // LED x on
 while(!IICS_TCF);   // wait for byte transfer to complete
 acknowledge = check_ACK();
 if (acknowledge == DEVICE_NO_ACK)
   return;
 STOP_BIT;       // send stop signal

}
Labels (1)
0 Kudos
6 Replies

53 Views
Contributor I
Update:  I have determined the cause of the problem.  Since mine is a single master system, I was not checking to see if the bus is busy before attempting to send a start bit (MST 0->1).   Sending a start bit before the stop bit completes apparently prevents the module from detecting its own stop, which is apparently required for the BUSY flag to get cleared.  That is likely how the busy flag locks up.  Polling for BUSY=0 before transmitting a start solves the problem.

I still believe this is an issue that should be addressed in hardware.  The idle bus should eventually clear the BUSY flag. 

Hope this helps someone else having similar problems.
0 Kudos

53 Views
Contributor I

I've been fighting this for awhile and was very happy to see your post with the cause - but, I went back through my code and everywhere I set a START the BUSY bit is checked:

 

while( (IIC1S_BUSY == TRUE) && !TimerHasExpired(TimerIIC))

{

  __RESET_WATCHDOG();

 

I don't see the BUSY bit locked up every time - it has actually gone weeks without locking up, but it will eventually lock up and I have to toggle the IIC_EN bit off and on to get it un-wedged.

 

Has there ever been any official reply from Freescale? 

0 Kudos

53 Views
Senior Contributor II
Dear FC,

As you require an answer, please DO submit a Service Request.
See the link in my address.

In the descripotion of the issue, include your investigations + the URL of your thread on the Forum.
You can send me, via Private Message, the SR# you receive back from the system and I can make sure you have filed the detail correctly to ensure a faster resolution and prevent the request to be mis-directed.

Alban.
0 Kudos

53 Views
Contributor III
PLEASE HELP;
 
After a few hard hours of testing, a conclusion is made:
 
1.  The QG8 datasheet is not correct for the IIC module
2.  The mcu on the QG8 demo board has a problem
 
Despite this, I figured a soluton to the IICS_BUSY flag not clearing.
 
Between successive bus transfers, I added this to reset the IIC bus:
 
IICC_IICEN = 0;
IICC_IICEN = 1;
 
Now all my code works as expected.  But this was a frustrating and troublesome problem to resolve especially with no scope to see the IIC bus activity.
 
 
 
0 Kudos

53 Views
Contributor I
I have recently discovered this issue with the IIC BUSY flag not getting cleared.  I have a single master-single slave system.  Logic analyzer shows the bus is idle, but the IIC module has the busy flag set.  Only way to clear it is to disable, reenable the IIC module as suggested.  The code works perfectly after this change, though it is not a clean solution. 

Does anyone know if this issue has been resolved.  This is a very old thread, yet I can find no resolution either way.  I have also checked the errata for the QG8 and found nothing. 
0 Kudos

53 Views
Contributor III
I forgot to add:
 
// Checks if IIC device sends ACK signal
unsigned char check_ACK(void)
{
 
 unsigned char delay = 10;
 
 while(delay--);
 if (IICS_RXAK == 1)   // check for ACK
 {
   STOP_BIT;       // device did not send ACK , set SDA high, and return error
   return(DEVICE_NO_ACK);
 }
 else
   return(DEVICE_ACK);
}
 
 
0 Kudos