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

byteman · · 2030 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

# 用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开发了多款用于工业和商用的嵌入式物联网设备了。

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2030 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
2 回复  |  直到 2019-06-30 14:52:51
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传