| Welcome to AT91SAM Community Forum http://www.at91.com/samphpbb/ |
|
| AT91F_TWI_WriteByte & AT91F_TWI_ReadByte infinite loop http://www.at91.com/samphpbb/viewtopic.php?f=15&t=1988 |
Page 1 of 1 |
| Author: | Satanic [ Tue Jul 11, 2006 6:47 pm ] |
| Post subject: | AT91F_TWI_WriteByte & AT91F_TWI_ReadByte infinite loop |
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. |
|
| Author: | seulater [ Tue Jul 11, 2006 7:11 pm ] |
| Post subject: | |
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...... |
|
| Author: | Satanic [ Wed Jul 12, 2006 1:21 pm ] |
| Post subject: | |
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++; } |
|
| Author: | seulater [ Wed Jul 12, 2006 5:39 pm ] |
| Post subject: | |
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. |
|
| Page 1 of 1 | All times are UTC + 1 hour [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|



Forum