Программирование AVR: решение проблем, FAQ Глюк при чтении EEPROM у ATmega8, ATmega32, ATmega128 Thu, March 28 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Глюк при чтении EEPROM у ATmega8, ATmega32, ATmega128 Печать
Добавил(а) microsin   

В библиотеке avr-libc WinAVR (релиз 20080610) есть глюк, связанный с чтением EEPROM. В новых версиях WinAVR (например, релиз 20090313) этот глюк уже исправлен.

Глюк связан с неучтенным ERRATA "Reading EEPROM by using ST or STS to set EERE bit triggers unexpected interrupt request". Глюк проявляется на микроконтроллерах ATmega8, ATmega32, ATmega128 (на ATmega16 такого глюка почему-то нет). Проявляется глюк в непредсказуемом переходе в младшие адреса при вызовах подпрограмм c:\WinAVR-20080610\avr\include\avr\eeprom.h -> eeprom_read_byte, eeprom_read_word, eeprom_read_dword, eeprom_read_block. Несколько вызовов могут пройти нормально, но на каком-то определенном адресе может произойти сбой. Я с этой проблемой проковырялся долго, так как сначала думал, что ошибка у меня в программе.

Глюк таится в одной-единственной функции eeprom_read_byte (все остальные, как я понял, используют её вызовы, поэтому глюк наследуется). Код, на C, который есть в подпрограмме eeprom_read_byte (этот код устанавливает бит EERE), компилируется в ассемблерную инструкцию ST, которая и вызывает сбой. Старый глючный код eeprom.h: 

__ATTR_PURE__ static __inline__ uint8_t eeprom_read_byte (const uint8_t *__p)
{
    do {} while (!eeprom_is_ready ());
#if E2END <= 0xff="" br="">     EEARL = (unsigned)__p;
#else
    EEAR = (unsigned)__p;
#endif
  EECR |= (1 << EERE);
  return EEDR;
}

Исправить проблему можно, если обновить WinAVR. Можно просто вручную поправить код, написав это место на ассемблере (для установки бита EERE надо использовать инструкцию OUT или SBI), например вот так: 

__ATTR_PURE__ static __inline__ uint8_t eeprom_read_byte (const uint8_t *__p)
{
    do {} while (!eeprom_is_ready ());
#if    E2END <= 0xff="" br="">     EEARL = (unsigned)__p;
#else
    EEAR = (unsigned)__p;
#endif
 ////////////////////////////////////////////////////////////
  // here fixed ERRATA Bug "Reading EEPROM by using ST or STS
  // to set EERE bit triggers unexpected interrupt request"
  // EECR |= (1 << EERE);
  __asm__ __volatile__ (
        "sbi    %[__eecr], %[__eere]    \n\t"
        :
        : [__eecr] "i" (_SFR_IO_ADDR(EECR)),
         [__eere] "i" (EERE)
    );
  return EEDR;
}
 

Добавить комментарий


Защитный код
Обновить

Top of Page