Wear Levelling EEPROM

Ref: atmel.com/images/doc2526.pdf
Jika kita mempunyai sistem yang secara berkala write data EEPROM, maka hal itu akan mengurangi lifespan dari EERPOM itu sendiri, mengingat bahwa EEPROM mempunyai kapasitas 100.000 erase/write cycle. Dengan menggunakan circular buffer (O-buffer), hal ini memungkinkan untuk meningkatkan lifespan dari penggunaan EEPROM. Caranya adalah dengan mendistribusikan media penyimpanan pada cell EEPROM lainnya. Jika kita memakai 2 cell yang digunakan sebagai parameter yang akan kita simpan, maka kita mempunyai kemungkian lifespan 200.000 erase/write. Akan tetapi, untuk mengetahui dimana letak terakhir dari EEPROM yang kita simpan, maka kita memerlukan sebuah pointer. Untuk mencover posisi pointer, setelah power off, maka kita memerlukan O-buffer kedua.

Setiap kali kita akan memperbarui parameter EEPROM, kita geser pointer ke cell selanjutnya. Dengan demikian penulisan EEPROM akan terdistribusi. Dan untuk pembacaan kita baca dimana terakhir pointer itu berada. Salah satu kendalanya, ialah ketika setelah power off, maka pointer akan kembali ke-reset. Untuk itu kita perlu mencari suatu algoritma yang akan mengecek dimana pointer terkhir dengan menggunakan data dari status buffer. Algoritmanya yaitu dengan mengecek nilai selisih antara nilai status buffer ke-n dikurangi status buffer ke-n+1 harus mempunyai selisih > 1. Dengan menggunakan algoritma ini dan sedikit modifikasi kita sudah bisa mendeteksi dimana pointer terakhir berada. Akan tetapi perlu diingat, penggunaan metode ini akan memerlukan penggunaan memory EEPROM yang boros. Salah satu cara untuk mengurangi pemborosan ini adalah menggunakan metode ini untuk multiple parameter yang akan menyimpan data secara bersamaan dan beroperasi secara paralel.
Berikut gambaran sederhana dari algoritma tersebut yang terdiri dari beberapa prosedur: findCurrentEepromAddr() yang mengidentifikasi dimana letak pointer setelah reset device. EeReadBuffer() membaca parameter dari buffer. EeWriteBuffer() menyimpan parameter pada Parameter Buffer.

Berikut contoh sourcecodenya:

#define SIZE_EEPROM_LEVELLING 64                                        //This algorithm to make long usage of eeprom

eeprom unsigned char status_memory_shift[SIZE_EEPROM_LEVELLING];     //wear levelling
eeprom unsigned char parameter_memory_shift[SIZE_EEPROM_LEVELLING];  //http://www.atmel.com/images/doc2526.pdf

unsigned char pointer_memory_shift;                                  //This algorithm to make long usage of eeprom
unsigned char counter_pointer_shift;                                 //wear levelling  http://www.atmel.com/images/doc2526.pdf
.
.
.
.
.
.
//-------------Wear Levelling EEPROM shift------------------
void eeprom_init_shift()//inisialisasi di awal program
{
    int i = 0;
    for(i=0;i<SIZE_EEPROM_LEVELLING;i++)
    {
        status_memory_shift[i]    = 0;
        parameter_memory_shift[i] = 1;
    }
}

void find_eeprom_pointer_shift()//mencari letak pointer terakhir, dipakai di awal program
{
    int i = 0;             
    int next_addr = 1;
    for(i=0;i<SIZE_EEPROM_LEVELLING;i++)
    {                
        next_addr = i+1;
        if(next_addr >= SIZE_EEPROM_LEVELLING)
        {
            next_addr = 0;
        }
        if((abs((int)status_memory_shift[next_addr]-(int)status_memory_shift[i])>1)||(((int)status_memory_shift[i] == 1)&&((int)status_memory_shift[next_addr] == 0))||(((int)status_memory_shift[i] == 0)&&((int)status_memory_shift[next_addr] == 0)))
        {         
            pointer_memory_shift = i;
            counter_pointer_shift = status_memory_shift[i];
            i = (int)SIZE_EEPROM_LEVELLING;
        }
    }    
}

void write_eeprom_levelling_shift(unsigned char value)//contoh: unsigned char NilaiVar = 47;
{                                                      //write_eeprom_levelling_shift(NilaiVar);
    int i;
    unsigned char prev_counter_pointer_shift = counter_pointer_shift;
    pointer_memory_shift++;  
    counter_pointer_shift++;
    if(pointer_memory_shift >= SIZE_EEPROM_LEVELLING)      
    {
        pointer_memory_shift = 0;    
    }       
    if((prev_counter_pointer_shift == 255)&& (counter_pointer_shift == 0)) 
    {
        for(i=0;i<SIZE_EEPROM_LEVELLING;i++)
        {
            status_memory_shift[i] = 0;    
        } 
        pointer_memory_shift = 0;       
    }           
    status_memory_shift[pointer_memory_shift] = counter_pointer_shift;
    parameter_memory_shift[pointer_memory_shift] = value;      
}

unsigned char read_eeprom_levelling_shift()        //contoh: unsigned char NilaiVar;
{                                                //NilaiVar = read_eeprom_levelling_shift(); 
    return(parameter_memory_shift[pointer_memory_shift]);
}

Leave a comment