43

用go语言来做嵌入式-读写铁电存储器

 4 years ago
source link: https://www.tuicool.com/articles/jIBVRfQ
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用go语言来做嵌入式-读写铁电存储器

存储器介绍

在嵌入式设备中使用的存储芯片一般多用的Flash芯片或者EEPROM芯片的,它们的擦写次数大概是10万-100万次,而且写入时间也是毫秒级别,再一些对关键参数存储要求较高的场景下,就需要使用铁电存储器了,铁电存储器的读写次数以亿级来算,而且写入时间可以达到纳秒级,存储非常可靠。

项目背景

我最近在我们一款采集设备上应用到了一款FM24CL64的8KB的铁电存储器,该芯片是I2C接口的,该设备是基于mtk7688主芯片,linux内核的openwrt系统,应用程序采用go语言开发,研究了一下该芯片的手册后,基于linux的标准i2c接口,编写了go语言版本的铁电存储器读写代码,并成功应用到产品中。

驱动和测试程序

const(
	I2C_SLAVE_FORCE=1798    //标准i2c接口提供的设置i2c从机地址的命令号
	I2C_TIMEOUT=1794        //标准i2c接口提供的设置i2c总线操作超时命令号
	I2C_RETRIES=1793        //标准i2c接口提供的设置i2c总线重试次数的命令号
)
type FM24xxFram struct{
	Fd 		int //i2c设备接口文件句柄
	Bus 	int //i2c总线编号 从0开始
	Addr 	int //i2c从机地址
	Timeout int //超时时间
	Retry 	int  //重试次数
}
func NewFM24cxxFram(bus,addr,timeout,retry int)*FM24xxFram{
	return &FM24xxFram{
		Fd:-1,
		Bus:bus,
		Addr:addr,
		Timeout:timeout,
		Retry,retry,
	}
}
//返回尺寸大小,以字节为单位 8192
func (f *FM24xxFram)Size()int  {
	return 8192
}
//打开铁电存储器总线设备
func (f *FM24xxFram)Open()error{
	fd,err:=syscall.Open(fmt.Sprintf("/dev/i2c-%d",f.Bus),os.O_RDWR,0777)
	if err!=nil{
		return err
	}
	f.Fd = fd
	syscall.Syscall(syscall.SYS_IOCTL,uintptr(fd),I2C_SLAVE_FORCE,uintptr(f.Addr))
	syscall.Syscall(syscall.SYS_IOCTL,uintptr(fd),I2C_TIMEOUT,f.Timeout)
	syscall.Syscall(syscall.SYS_IOCTL,uintptr(fd),I2C_RETRIES,f.Retry)
	return nil
}
//关闭设备
func (f *FM24xxFram)Close(){
	if f.Fd != -1{
		syscall.Close(f.Fd)
	}
	f.Fd = -1
}

/*
往铁电某个地址写入数据
addr: 铁电的存储地址 从0 - 8K
p :需要写入的数据内容
 */
func (f *FM24xxFram)Write(addr int,p []byte)(n int, err error){
	writeBuf :=make([]byte,2)
	writeBuf[0]=byte((addr>>8)&0xff)
	writeBuf[1]=byte(addr&0xff)
	if len(p) > 0{
		writeBuf=append(writeBuf,p...)

	}

	return syscall.Write(f.Fd,writeBuf)

	//return f.File.Write(writeBuf)
}

/**
从铁电读取某个地址的数据
addr: 铁电的存储地址
p: 存放读取的数据
 */
func (f *FM24xxFram)Read(addr int,p []byte)(n int, err error){

	//先定位到存储器的某个地址.
	if n,err=f.Write(addr,[]byte{});err!=nil{
		return
	}
	return syscall.Read(f.Fd,p)
}

测试程序如下:

package main

import "testing"

const FM24XX_I2C_ADDR=0x50

func TestRead(t *testing.T) {
	
	fm:=NewFM24cxxFram(0,FM24XX_I2C_ADDR, 3, 10 )
	if err:=fm.Open();err!=nil{
		t.Errorf("Open Fm failed %v",err)
		return
	}
	if _,err:=fm.Write(0,[]byte{1,2,3,4,5});err!=nil{
		t.Errorf("Write Fm failed %v",err)
		return
	}
	buf:=make([]byte,5)
	if _,err:=fm.Read(0,buf);err!=nil{
		t.Errorf("Read Fm failed %v",err)
		return
	}
	t.Logf("Read Data=%v",buf)

}

怎么来玩

有兴趣研究go在嵌入式下应用的朋友,可以在淘宝上买一块mt7688的开发板,上面有很多硬件资源【wifi/以太网/i2c/spi/usb/sd卡/gpio等等】可以用go来操作,我们已经用mt7688+go开发了多款用于工业和商用的嵌入式物联网设备了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK