1. 程式人生 > >24系列EEPROM/FRAM通用介面

24系列EEPROM/FRAM通用介面

1.寫在前面
  “24系列”的EEPROM,一般地我們認為是以i2c為通訊介面的一系列序列EEPROM,各大半導體廠商出產的該系列EEPROM都遵循這個規則,而且電路和控制程式上也相容。如AT24C02、ST24C02等。

  FRAM(鐵電儲存器)是近幾年來比較熱門的一項儲存技術,並且有相關實際產品的應用。FRAM具有ROM和RAM的特點,擦寫壽命長、讀寫速度快、讀寫功耗極低。24系列的FRAM在電路和程式設計師相容24系列的EEPROM,但由於FRAM寫速度遠高於EEPROM,因此不再需要傳統EEPROM“頁寫”之間的延時或者匯流排空閒檢查的操作,這也是兩者程式的主要差別。當然存在延時也可以,並不影響資料的正確性,只是降低寫效率。

  除此之外,還有“25系列”的EEPROM,該系列則是以spi序列控制介面,在讀寫時序上稍有差別,具體頁寫演算法可以和24系列的一致。相應地,也有25系列的FRAM,這塊用得少,具體差別還有待驗證。說個題外話,個人覺得spi介面的EEPROM並無太大優勢,甚至有點浪費資源。雖然spi傳輸速度可以高於i2c,但EEPROM的寫速度實在太低了,像i2c這樣的低速匯流排仍需“等待”,所以使用spi並無優勢,還佔用多個IO口。但,spi介面的FRAM就有優勢了,FRAM讀寫速度遠高於EEPROM,儲存資料量較大時,可以優先考慮spi介面的FRAM。

2.介面抽象


2.1 目的
  統一介面,遮蔽底層差異,方便移植。使用時只需設定好具體EEPROM型號、從地址、頁寫延時函式、防寫函式等即可驅動起來,讓使用者將更多時間花在業務功能上。

2.2 使用範圍
 1)MCU裸機程式上。
 2)RTOS(實時系統)上。
 3)其他。

2.3 實現功能
 1)根據型號自動識別頁大小、片容量大小。
 2)帶頁寫演算法,自動翻頁,自動識別非整齊頁。
 3)相容EEPROM和FRAM。

2.4 API
2.4.1 裝置物件
  在介紹API前,有個關鍵的結構體“_24cxx_dev_t”,在“_24cxx_dev.h”中,每個EEPROM外設必須對應一個該結構體,一般地我們參考Linux的叫法稱為“裝置物件”或者“檔案控制代碼”。該結構體需要程式設計師初始化,指定相關引數或者函式指標例項化。後面的讀、寫、擦除函式介面的第一個引數必須都是傳入該物件地址(指標),如果物件為空或者未初始化,則返回錯誤。

/*24cxx eeprom devcie struct*/
typedef struct 
{
	struct i2c_dev_device 	*i2c_dev;	/*i2c bus device struct*/
	uint8_t					slave_addr;	/*eeprom i2c addr*/
	_24_model_t				model;		/*eeprom model*/
	void(*wp)(uint8_t ctrl);			/*protect of write function*/
	void(*page_write_delay)(void);		/*there is a delay in continuous writin for EEPROM,FRAM not need*/
}_24cxx_dev_t;

1)引數一“i2c_dev”,為控制EEPROM的i2c匯流排裝置,可參考“i2c抽象/模擬i2c”文章,使用的是模擬i2c ,也可以根據定義使用硬體i2c;
2)引數二“slave_addr”,為EEPROM的器件從地址,7bit地址,不包括讀寫位;
3)引數三“model”,為具體EEPROM的型號,該型別為自定義的列舉型,枚舉了24c01—24c1024的型號的EEPROM/FRAM;
4)引數四“wp”,為防寫函式,如果EEPROM的防寫引腳“WP”通過MCU控制,則需實現該函式;實現“WP”引腳IO翻轉即可;
5)引數五“page_write_delay”,為頁寫延時函式,程式中採用了頁寫演算法,EEPROM如果連續頁寫,則需要實現該函式, 否則寫會出錯;FRAM則不需要。

2.4.2 讀EEPROM

int16_t _24cxx_read(_24cxx_dev_t *pdev,uint32_t addr, uint8_t *pbuf, uint32_t size);
引數 功能描述
pdev EEPROM/FRAM裝置物件
addr 起始地址
pbuf 讀取的資料(快取)
size 讀取資料大小(位元組)
2.4.3 寫EEPROM
_24cxx_write(_24cxx_dev_t *pdev,uint32_t addr,uint8_t *pbuf,uint32_t size);
引數 功能描述
pdev EEPROM/FRAM裝置物件
addr 起始地址
pbuf 待寫的資料
size 待寫資料大小(位元組)
2.4.4 擦除EEPROM

  原則上EEPROM並不存在“擦除”操作,“擦除”一般指用於flash寫入前的操作。但特殊場合下,需賦予EEPROM預設值,如賦值0或者0xff,此時可以使用擦除操作。為了節約記憶體,該函式內部使用的是單位元組擦除,效率不高,如有需擦除大片空間,建議直接呼叫寫函式進行擦除。

int16_t _24cxx_erase(_24cxx_dev_t *pdev,uint32_t addr,uint8_t data, uint32_t size);
引數 功能描述
pdev EEPROM/FRAM裝置物件
addr 起始地址
data 擦除為預設值
size 待擦除空間大小(位元組)
2.4.5 狀態返回

  呼叫函式時,都會返回一個狀態碼,無錯誤返回0。具體狀態碼可以檢視“_24cxx_dev.h”中的定義。

/*operation state*/
enum _24CXX_ERROR
{
	_24CXX_OK 				= 0,	
	_24CXX_ERR_I2C_WR 		= 1,
	_24CXX_ERR_DEV_NONE 	= 2,
	_24CXX_ERR_PAGE_WRITE	= 3,
	_24CXX_ERR_PAGE_SIZE	= 4,
	_24CXX_ERR_CHIP_SIZE	= 5,
};
3.使用例子

  目前測試並且通過的EEPROM/FRAM型號有AT24C02、AT24C16、FM24C16。其他型號暫未測試過,如廣大網友測試發現問題歡迎指出。

3.1 EEPROM系列
  在測試工程下的“drivers”目錄下,原始碼檔案是“at24cxx.c”,主要初始化實現一個“_24cxx_dev_t”裝置物件。

static void page_write_delay(void) 
{
	uint16_t i;
	
	i = 0xFFFF;
	while(i--);
}

/**
 * @brief  device init
 */
const _24cxx_dev_t at24cxx_dev =
{
	&i2c1_dev,					/*i2c device*/
	0x50,						/*eeprom address*/
	_24C16_E,					/*eeprom model,eg AT24C16*/
	0,							/*no write protect*/
	page_write_delay,			/*delay function,must!*/	
};

1)“i2c1_dev”為i2c匯流排裝置物件,在“i2c抽象/模擬i2c”文章提及,不再贅述;
2)0x50為器件從地址,不包括讀寫位;
3)器件具體型號;
4)防寫函式,這裡無,賦值NULL(0);
5)頁寫延時函式。

  這一步完成,即可通過上述的API介面讀、寫EEPROM,具體demo檢視工程原始碼。

3.1.1 防寫函式
  常見的使用方式都是直接將EEPROM的WP引腳拉低,沒有保護功能。如果WP引腳通過MCU控制,則需要使用上防寫函式。以為STM32為例,假設PA0控制器件的WP引腳,防寫函式實現如下,IO口時鐘、方式、狀態等暫存器需在初始化時配置。在初始化裝置物件時,賦值到防寫函式指標。

static void wp_fun(uint8_t ctrl)
{
	if(ctrl == 0)
	{
		GPIO_ResetBits(GPIOA,GPIO_Pin_0);
	}
	else
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_0);
	}
}

3.2 FRAM系列
  FRAM控制介面相容傳統EEPROM,程式上差異不大,主要是頁寫函式可以去掉,設定為NULL(0)即可。以FM24CL16為例,實現如下。

/**
 * @brief  device init
 */
const _24cxx_dev_t fm24clxx_dev =
{
	&i2c1_dev,			/*i2c device*/
	0x50,				/*fram address*/
	_24C16_E,			/*eeprom model,eg FM24C16*/
	0,					/*no write protect*/
	0,					/*delay fun,FRAM no need*/
};
4.相關文章

[1] i2c抽象/模擬i2c:
https://blog.csdn.net/qq_20553613/article/details/78878211

[2] EEPROM頁寫演算法:
https://blog.csdn.net/qq_20553613/article/details/78550427

5.原始碼

[1] https://github.com/Prry/_24Cxx-EEPROM-FRAM-Dev