Fix EEPROM access error for WinAVR

Fix EEPROM access error for WinAVR

the following example is popular use in WinAVR:

uchar EEMEM epmem[8] = {"12345678"};
uchar ram[8];
eeprom_write_block(ram,epmem, 8);
eeprom_read_block(ram,epmem, 8);

but I found there is an bug in it!
In some complex application, it will result in system reset for AV error.
So, do not use "eeprom.h". And use my code to replace it.

#define EEMEM __attribute__((section(".eeprom")))

uchar EEPROMRead(uint addr)
{
  uchar c, s;
  // wait write completed
  while (EECR & (1<  s = SREG;
  cli();
  // set address
  EEAR = addr;
  // start write
  EECR |= (1<  // read result
  c = EEDR;
  SREG = s;
  return c;
}

void EEPROMWrite(uint addr, uchar c)
{
    uchar s;
  // wait write completed
  while (EECR & (1<  s = SREG;
  cli();
  // set address
  EEAR = addr;
  EEDR = c;
  /* set EEMWE
  EECR |= (1<  // start write, but this should be done in 4 CPU cycles, use assembler can avoid this
  EECR |= (1<  __asm__ __volatile__ (
        //* START EEPROM WRITE *
        //"in    r0, %[__sreg]        \n\t"
        //"cli                \n\t"
        "sbi    %[__eecr], %[__eemwe]    \n\t"
        "sbi    %[__eecr], %[__eewe]    \n\t"
        //"out    %[__sreg], r0        \n\t"
        //* END EEPROM WRITE *
        :
        : [__eecr]  "i" (_SFR_IO_ADDR(EECR)),
         // [__sreg]  "i" (_SFR_IO_ADDR(SREG)),
          [__eemwe] "i" (EEMWE),
          [__eewe]  "i" (EEWE)
        : "r0"
    );
  SREG = s;
}

WinAVR的eeprom读写有Bug的,用我的代码就可以避免这个问题
很多人都用
EECR |= (1<EECR |= (1<来写EEPROM,却发现数据没写入,因为置位EEMWE后必须在4个时钟周期内置位EEWE,但WinAVR等编译工具没有如此的优化,故使用嵌入汇编来解决此问题

[本日志由 lysoft 于 2009-06-21 06:23 PM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: AVR EEPROM WinAVR
相关日志:
评论: 0 | 引用: 0 | 查看次数: 3264
发表评论
昵 称:
密 码: 游客发言不需要密码.
邮 箱: 支持Gravatar头像.
网 址: 输入网址便于回访.
内 容:
验证码:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 关闭 | [img]标签 开启