Перейти к содержанию
    

Зависает TWI в SAM7

Использую TWI для работы с еепром и ртц. Все работает как положено. Параллельно работает тамер 0, в обработчике прерывания которого выполняю некоторую работу. Вот что заметил - если прерывание таймера длится относительно долго (точный предел не знаю, у меня около 80мкс), то после выхода из него и возврата к продолжению работы с еепром TWI зависает на проверке статуса готовности принятых данных. Если длительность прерывания таймера маленькая, то все нормально.

Программа выглядит примерно так:

 

main()
{
//.......
    while (1)
    {
         EEPR_ReadData(...);
    }

}

void Timer0IRQ(void)
{
// что-то делаю (~80 мкс)
}

int AT91F_TWI_ReadData(LPVOID Data, int Size)
{
    int Error=0;
    int Status,Count=0;
    AT91PS_TWI pTwi = AT91C_BASE_TWI;
    BYTE *pData = (BYTE*)Data;

    pTwi->TWI_MMR |= AT91C_TWI_MREAD;

    {
         pTwi->TWI_CR = AT91C_TWI_START;
         for(Count=0; Count<Size; Count++)
         {
            if (Count == (Size - 1))    pTwi->TWI_CR = AT91C_TWI_STOP;

            Status = pTwi->TWI_SR;
            while (!(Status & AT91C_TWI_RXRDY))
            {
                Status = pTwi->TWI_SR;       //  <---------- В этом цикле происходит зависание
            }
            *pData++ = pTwi->TWI_RHR;
        }
    }

    return 0;
}

 

Т.е. получается что TWI не любит когда его прерывают на длительное время? Как с этим бороться, ведь теоретически прерывания могут длиться любое время.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я Делать так! не на саме7 а на рм9200, думаю тут таже бага. У Вас происходит переполнение твй.

 

Это при чтении

 

//do read

try_again:

 

length = 9;

not_success=0;

if(try_count==10) goto cleanUp; //stop our try's

 

/* Set the TWI Master Mode Register */

twi->TWI_MMR = ((RTC8564_ADDRESS << 16) | AT91C_TWI_IADRSZ_1_BYTE | AT91C_TWI_MREAD);

 

 

// Set TWI Internal Address Register

twi->TWI_IADR = 0x0;

 

// Start transfer

twi->TWI_CR = AT91C_TWI_START;

 

status = twi->TWI_SR;

 

 

 

for(ii=0;ii<length;ii++){

tmp=0;

 

// Wait RHR Holding register is full

while ((tmp & AT91C_TWI_RXRDY)==0)

{

tmp = twi->TWI_SR;

buffer_misc[ii]=tmp;

if(tmp&AT91C_TWI_OVRE) {not_success=1; break;}

}

 

// Read byte

buffer[ii] = twi->TWI_RHR;

 

}

 

twi->TWI_CR = AT91C_TWI_STOP;

 

status = twi->TWI_SR;

 

// Wait transfer is finished

while (!(twi->TWI_SR & AT91C_TWI_TXCOMP));

// Read last byte

buffer[ii] = twi->TWI_RHR;

 

//inc my try count

try_count++;

if(not_success) goto try_again;

 

cleanUp:

 

 

 

 

Это при записи

 

while ((tmp & AT91C_TWI_TXRDY)==0)

{

tmp = twi->TWI_SR;

buffer_misc[ii]=tmp;

if(tmp&AT91C_TWI_UNRE) {not_success=1; break;}

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

MemoryTest

Действительно, проблема была в overrun error. Нужно было отлавливать это событие.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...