Atmel website | ARM Community | AVR freaks | Technical Support
Banner
 FAQ •  Search •  Register •  Login 

All times are UTC + 1 hour [ DST ]




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: AT91F_TWI_WriteByte & AT91F_TWI_ReadByte infinite loop
PostPosted: Tue Jul 11, 2006 6:47 pm 
Offline

Joined: Wed Jul 06, 2005 6:42 pm
Posts: 73
Location: Spain
Heya, i have been using the next 2 funtions for months, they are included in the basic examples. My application has been working fine while i have been in debugging, debug that i have done usually compiling to flash.

The problem came when i compiled to flash, where i have found that it gets in a loop forever, until the watchdog restarts the program (with watchdog disabled it hangs there forever).

You probably know the next code and maybe you are using it:

Code:

//*=========================================================
//*      WRITE
//*=========================================================
//*----------------------------------------------------------------------------
//* \fn    AT91F_TWI_WriteByte
//* \brief Send a byte to a slave device
//*----------------------------------------------------------------------------
int AT91F_TWI_WriteByte(const AT91PS_TWI pTwi ,int mode, int int_address, char *data2send, int nb)
{
   unsigned int status,counter=0,error=0;

   // Set TWI Internal Address Register
   if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address;

   // Set the TWI Master Mode Register
     pTwi->TWI_MMR = mode & ~AT91C_TWI_MREAD;
   if(nb <2){
      pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN | AT91C_TWI_STOP;
      pTwi->TWI_THR = *data2send;
   }
   else
   {
   // Set the TWI Master Mode Register
     for(counter=0;counter<nb;counter++){
          pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;
          if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP;
          status = pTwi->TWI_SR;
          if ((status & ERROR) == ERROR) error++;
          while (!(status & AT91C_TWI_TXRDY)){
               status = pTwi->TWI_SR;
               if ((status & ERROR) == ERROR) error++;
          }
          pTwi->TWI_THR = *(data2send+counter);
      }
   }
   status = pTwi->TWI_SR;
   if ((status & ERROR) == ERROR) error++;
   while (!(status & AT91C_TWI_TXCOMP)){
          status = pTwi->TWI_SR;
          if ((status & ERROR) == ERROR) error++;
    }
   return error;
}

//*=========================================================
//*      READ
//*=========================================================
//*----------------------------------------------------------------------------
//* \fn    AT91F_TWI_ReadByte
//* \brief Read a byte from a slave device
//*----------------------------------------------------------------------------
int AT91F_TWI_ReadByte(const AT91PS_TWI pTwi ,int mode, int int_address, char *data, int nb)
{
   unsigned int status,counter=0,error=0;


   // Set TWI Internal Address Register
   if ((mode & AT91C_TWI_IADRSZ) != 0) pTwi->TWI_IADR = int_address;

   // Set the TWI Master Mode Register
   pTwi->TWI_MMR = mode | AT91C_TWI_MREAD;

   // Start transfer
   if (nb == 1){
      pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_STOP;
      status = pTwi->TWI_SR;
          if ((status & ERROR) == ERROR) error++;
      while (!(status & AT91C_TWI_TXCOMP)){
             status = pTwi->TWI_SR;
              if ((status & ERROR) == ERROR) error++;
          }
      *(data) = pTwi->TWI_RHR;
   }
   else{
      pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;
      status = pTwi->TWI_SR;
      if ((status & ERROR) == ERROR) error++;

   // Wait transfer is finished
           while (!(status & AT91C_TWI_TXCOMP)){
         status = pTwi->TWI_SR;
         if ((status & ERROR )== ERROR) error++;
          if(status & AT91C_TWI_RXRDY){
         *(data+counter++) = pTwi->TWI_RHR;
         if (counter == (nb - 1)) pTwi->TWI_CR = AT91C_TWI_STOP;
      }
      }
   }
   return 0;
}




I disable interrupts before i call any of those 2 functions and i enable them after. As i said both work fine while i run the code in ram but not when i run it in flash. It doesnt fail always, it happens just some random times, so i though that it was something with interrupts but it is not since i have them disabled.

For example in write funtion it hangs forever here:

Code:
          while (!(status & AT91C_TWI_TXRDY)){
               status = pTwi->TWI_SR;
               if ((status & ERROR) == ERROR) error++;
          }


In that case status has always status = 0x00000008 (that bit is always 1 it seems, even when it works fine).

I have tried everything and i have been not able to fix it, i'm thinking to implement it with soft, instead of using the Peripheral.

Some help would be welcome. Thanks in advance.

_________________
A good friend told me that he would love to live in a nordic country to have a faster inet connection, I told him that i would never change my 250 sunny days / year for a gbit inet.

Who is wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 11, 2006 7:11 pm 
Offline

Joined: Fri Mar 24, 2006 7:33 pm
Posts: 29
I too had this problem, that whole routine is kinda buggy (FYI).
I re-done the whole thing.

in the write routine try putting:

status = pTwi->TWI_SR;
if ((status & ERROR) == ERROR) error++;
while (!(status & AT91C_TWI_TXRDY)){
status = pTwi->TWI_SR;
if ((status & ERROR) == ERROR) error++;
}


after the "pTwi->TWI_THR = *(data2send+counter); "

TWI_SR is supposed to be checked after you update the TWI_THR and not
before.


Atmel, who includes it on their CD should scrutinize the software they use as samples. Tisk, Tisk, Atmel......

_________________
Amateurs built the ark...
Professionals built the Titanic...


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 1:21 pm 
Offline

Joined: Wed Jul 06, 2005 6:42 pm
Posts: 73
Location: Spain
Code:
// Set the TWI Master Mode Register
    for(counter=0;counter<nb;counter++)
      {
       pTwi->TWI_CR = AT91C_TWI_START | AT91C_TWI_MSEN;
       if(counter == (nb - 1))
          pTwi->TWI_CR = AT91C_TWI_STOP;
       pTwi->TWI_THR = *(data2send+counter);
       status = pTwi->TWI_SR;
       if((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
          error++;
       while (!(status & AT91C_TWI_TXRDY))
         {
          status = pTwi->TWI_SR;
          if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
             error++;
         }
      }// end loop for


It makes sense, but I still have the same problem :(


It never exits from:

Code:
       while (!(status & AT91C_TWI_TXRDY))
         {
          status = pTwi->TWI_SR;
          if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
             error++;
         }

_________________
A good friend told me that he would love to live in a nordic country to have a faster inet connection, I told him that i would never change my 250 sunny days / year for a gbit inet.

Who is wrong?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 5:39 pm 
Offline

Joined: Fri Mar 24, 2006 7:33 pm
Posts: 29
replace

status = pTwi->TWI_SR;
if((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
error++;
while (!(status & AT91C_TWI_TXRDY))
{
status = pTwi->TWI_SR;
if ((status & AT91C_TWI_NACK) == AT91C_TWI_NACK)
error++;
}


with

do
{
status = TWI_SR;

if( (status & TWI_SR_TXCOMP) || (status & TWI_SR_NACK) )
{
// printf("Error\r\n");
return 1;
}

}while(!(status & TWI_SR_TXRDY));

return 0;




try that.

_________________
Amateurs built the ark...
Professionals built the Titanic...


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC + 1 hour [ DST ]


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: