Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 写入EEPROM的算法?_C_Memory_Memory Management - Fatal编程技术网

C 写入EEPROM的算法?

C 写入EEPROM的算法?,c,memory,memory-management,C,Memory,Memory Management,我有一个内存,它是一列4字节的行。我只能用16个字节写入,用I2C用4个字节(即逐行)读取 我对如何将数据写入EEPROM很感兴趣:正在写入的数据由几个不同的部分组成,其中两个部分可以是可变长度的。例如,我可以使用XYYZ或XYYYYYZZZZZ,其中每个字母是4个字节 我的问题是,我应该如何解决这个问题,以获得一种使用16字节写入将消息写入内存的通用方法,以适应这两个部分的可变性质?不是专门针对您的示例定制的,完全未经测试,依赖于“从EEPROM读取4字节”和“将16字节写入EEPROM”封装

我有一个内存,它是一列4字节的行。我只能用16个字节写入,用I2C用4个字节(即逐行)读取

我对如何将数据写入EEPROM很感兴趣:正在写入的数据由几个不同的部分组成,其中两个部分可以是可变长度的。例如,我可以使用XYYZ或XYYYYYZZZZZ,其中每个字母是4个字节


我的问题是,我应该如何解决这个问题,以获得一种使用16字节写入将消息写入内存的通用方法,以适应这两个部分的可变性质?

不是专门针对您的示例定制的,完全未经测试,依赖于“从EEPROM读取4字节”和“将16字节写入EEPROM”封装在适当的函数中

void write_to_eeprom(uint32_t start, size_t len, uint8_t *data) {
  uint32_t eeprom_dst = start & 0xfffffff0;
  uint8_t buffer[16];
  ssize_t data_offset;

  for (data_offset = (start - eeprom_dst); data_offset < len; data_offset += 16, eeprom_dst+= 16) {
    if (data_offset < 0) || ((len - data_offset) < 16) {
      // we need to fill our buffer with EEPROM data
      read_from_eeprom(eeprom_dst, buffer); // read 4 bytes, place at ptr
      read_from_eeprom(eeprom_dst+4, buffer+4);
      read_from_eeprom(eeprom_dst+8, buffer+8);
      read_from_eeprom(eeprom_dst+12, buffer+12);
      for (int buf_ix=0, ssize_t tmp_offset = data_offset; buf_ix < 16; buf_ix++, offset++) {
        if ((offset >= 0) && (buf_ix < 16)) {
          // We want to copy actual data
          buffer[buf_ix] = data[offset];
        }
      }
    } else {
      // We don't need to cater for edge cases and can simply shift
      // 16 bytes into our tmp buffer.
      for (int ix = 0; ix < 16; ix++) {
         buffer[ix] = data[data_offset + ix];
      }
    }
    write_to_eeprom(eeprom_dst, buffer);
  }
}
无效写入eeprom(uint32启动、大小透镜、uint8*数据){
uint32_t eeprom_dst=启动&0xfffffff0;
uint8_t缓冲器[16];
ssize_t data_offset;
对于(数据偏移量=(启动-eeprom dst);数据偏移量=0)和&(buf_ix<16)){
//我们想复制实际数据
缓冲区[buf_ix]=数据[offset];
}
}
}否则{
//我们不需要迎合边缘情况,可以简单地改变
//16个字节进入我们的tmp缓冲区。
对于(int-ix=0;ix<16;ix++){
缓冲区[ix]=数据[data_offset+ix];
}
}
写入eeprom(eeprom dst,缓冲器);
}
}

<>代码>而不是尝试以4字节或16字节单位工作,您可以考虑使用一个小的(21字节)静态缓存用于EEPROM。让我们假设你有

void eeprom_read16(uint32_t page, uint8_t *data);
void eeprom_write16(uint32_t page, const uint8_t *data);
其中,
page
是地址除以16,并且始终对16字节块进行操作。缓存本身及其初始化函数(通电时调用一次)将

只有当您希望确保某些数据存储在eeprom中时,才需要使用
eeprom\u flush()
功能,基本上是在每次完成事务之后。你可以随时安全地呼叫它

要访问EEPROM中的任何内存,请使用访问器功能

static inline uint8_t eeprom_get(const uint32_t address)
{
    const uint32_t page = address >> 4;
    if (page != eeprom_page) {
        if (eeprom_dirty) {
            eeprom_write(eeprom_page, eeprom_cache);
            eeprom_dirty = 0;
        }
        eeprom_read(page, eeprom_cache);
        eeprom_page = page;
    }
    return eeprom_cache[address % 0xFU];
}

static inline void eeprom_set(const uint32_t address, const uint8_t value)
{
    const uint32_t page = address >> 4;
    if (page != eeprom_page) {
        if (eeprom_dirty) {
            eeprom_write(eeprom_page, eeprom_cache);
            eeprom_dirty = 0;
        }
        eeprom_read(page, eeprom_cache);
        eeprom_page = page;
    }
    eeprom_dirty = 1;
    eeprom_cache[address % 0xFU] = value;
}
如果愿意,可以省略
内联
;这只是一个优化。上面的
静态内联
告诉C99编译器尽可能内联函数。它可能会增加您的代码大小,但它会生成更快的代码(因为当这样的小函数内联到代码中时,编译器可以进行更好的优化)

请注意,您不应在中断处理程序中使用上述代码,因为eeprom页面未准备正常代码以更改mid操作

您可以混合读写操作,但这可能会导致EEPROM不必要的磨损。当然,如果混合读写,您可以将读写端拆分为单独的缓存。这还允许您从中断上下文安全地执行EEPROM读取(尽管I2C访问的延迟/延迟可能会在其他地方造成严重破坏)

static inline uint8_t eeprom_get(const uint32_t address)
{
    const uint32_t page = address >> 4;
    if (page != eeprom_page) {
        if (eeprom_dirty) {
            eeprom_write(eeprom_page, eeprom_cache);
            eeprom_dirty = 0;
        }
        eeprom_read(page, eeprom_cache);
        eeprom_page = page;
    }
    return eeprom_cache[address % 0xFU];
}

static inline void eeprom_set(const uint32_t address, const uint8_t value)
{
    const uint32_t page = address >> 4;
    if (page != eeprom_page) {
        if (eeprom_dirty) {
            eeprom_write(eeprom_page, eeprom_cache);
            eeprom_dirty = 0;
        }
        eeprom_read(page, eeprom_cache);
        eeprom_page = page;
    }
    eeprom_dirty = 1;
    eeprom_cache[address % 0xFU] = value;
}