您的位置:首页 > 其它

FPGA学习心得及(flash读写,+lwip+数据发送等问题)

2011-10-13 23:49 375 查看
前段时间应老板的项目需求,对硬件丝毫不懂得我开始接触edk硬件编程,感觉这段时间跟硬件打交道,自己都老了不少。首先,硬件编程编译很慢,编译一次有时候得10-20分钟,尤其是用verilog写得程序比较大的时候。其次,调试非常麻烦,不能像利用c或者c#那样断点调试了,只能通过chipscope看波形调试。有时候一个小小的错误竟然花一两天还找不出来,初学的我上不起啊。总体感觉写verilog程序时序非常重要,一定要保证时序不出一点差错,才能保证程序运行如自己所愿。下面主要记录下在写flash控制器与通过网络传输数据程序时的一些心得。

关于falsh的读写

学习FPGA一个月后,老板就让我们写flash控制器,我们用的板子是virtex 5,falsh是intel的strata p30,内嵌在FPGA中.在这个过程中确实感觉datasheet非常重要,先前没看datasheet的时候写得程序只能读数据,但是不能写数据,化了几天时间都没弄明白,后来看了下datasheet,才发现在写数据之前必须将数据块解锁并擦除,然后才可以写。对flash读与写步骤如下:

读一个数据的流程:

1写 x00ff,表示要读数据了

2读取数据

3写0x70 ,表示读状态寄存器,判断读数据是否完成

写数据的过程:

1:读寄存器状态(write0x70,read rs[7])

2:对当前写数据所属内存块解锁write 0x60,write 0xD0

3:擦除数据所属块 write 0x20, write 0xD0

4:读寄存器状态

5:往指定地址写数据

6:读寄存器状态

关于lwip的数据传输。

在板子上做基于网络的数据传输的目的是想:在远程控制板子的一些外围设备的参数,这就需要将参数通过网络传输到板子,并在板子上部署一个微型网络服务器,对这些数据进行接收,并存储在flash中,当板子掉电重启后,从flash中读取参数,以使板子外围设备正常运行。

当老板提出这个需求的时候,我就傻眼了,客户端是高级语言c#或c++,flash读写是硬件描述语言,如何进行通信啊?后来经过王工大牛的指点,才知道xinlinx都为我们想好了,有个sdk可以编软件,并且是c语言的,只要在xps中将硬件设计好,然后在sdk中编写网络传输以及flash读写的程序即可了,这样客户端发来的数据就可以被板子的服务器接收并存储起来了。到了这一步,又遇到问题了,如何利用c语言对flash进行读写呢?以前写的可是用verilog写得啊!正当我无望的时候,又是王工大牛出现了,这才知道,通过xps设计好硬件后,xps会为每个外围设备(包括flash)分配一个地址范围,我们对flash进行读写,就是对相对基地址读写。由于ise11.4中没有读写flash的ip核,起初准备自己写个flash读写的ip核,没想到这个过程是出奇的复杂。搞了一周都没搞出来,后来一次偶然试验,直接向总线写类似在verilog中读写flash的命令就可实现flash读写及擦出操作。以下是对flash中地址blockAddr的各种操作

对Blockaddr地址所属块擦除

int EraseBlock(u32 Blockaddr)

{

u8 reg_status;

//unlock

XIo_Out16(FlashBaseAddr+2*Blockaddr,0x0060);

XIo_Out16(FlashBaseAddr+2*Blockaddr,0x00D0);

//erase

XIo_Out16(FlashBaseAddr+2*Blockaddr,0x0020);

XIo_Out16(FlashBaseAddr+2*Blockaddr,0x00D0);

//read register status

while(1)

{

XIo_Out16(FlashBaseAddr,0x0070);

reg_status = XIo_In16(FlashBaseAddr);

//xil_printf("%x\r\n",reg_status);

if(reg_status == 0x0080)

break;

}

return 1;

}

对Blockaddr地址写数据data

int WriteDataToBlockAddr(u32 Blockaddr,u16 data)

{

u8 reg_status;

XIo_Out16(FlashBaseAddr+2*Blockaddr,0x0040);

XIo_Out16(FlashBaseAddr+2*Blockaddr,data);

while(1)

{

XIo_Out16(FlashBaseAddr,0x0070);

reg_status = XIo_In16(FlashBaseAddr);

//xil_printf("%x\r\n",reg_status);

if(reg_status == 0x0080)

break;

}

return 1;

}

读取地址blockAddr中的数据

u16 ReadDataByWord(u32 dataAddr)

{

XIo_Out16(FlashBaseAddr+2*dataAddr,0x00ff);

u16 value = XIo_In16(FlashBaseAddr+2*dataAddr);

return value;

}

在c中对flash读写可以实现了,下面就是网络服务器的构建了,这里用到了lwip协议栈,据说是瑞典科学院一般人弄的,很适合在嵌入式系统中做网络传输。只要在服务器端监听客户端连接并解析客户端传来的数据就行了。比如,客户端传一个read/addr,命令给服务器,flash中地址addr的数据就被读取出来传给客户端,客户端传一个write/addr/data命令给服务器端,那么flash中地址为addr就被写上数据data。由于flash写操作的特性,在写之前需要将此块先擦除,所以利用这种方式写一个数据,那么此块中以前的数据都被擦除了。由于要保证原有在flash中的数据在写一个数据后还存在,就必须将此块的数据全部读取出来,然后再与要写的数据一起写回去,就可以保证写一个数据后原有数据不被擦除。在写这一部分的时候遇到了郁闷一周的问题:就是当在服务器端读取数据发送给客户端时,发了200多bytes就出现tcp_write
errror!试了很多方法,包括改pbuf的大小都不行,后来想在服务器端建一个大数组,将读取的数据存储在其中,这就不要传给客户端,但是结果还是不行,因为系统内存资源太小不可能分配一个能存储128kB的空间。后来呢才想到,发送命令给服务器,让读取的数据不断地传回来,是不是也会使空间不够啊?然后试着发送一个命令只获取块中512个数据,不断地发送命令直至此块数据获取完毕,竟然成功了!喜悦啊!

这就是今晚弄成功的,心情愉悦,故记之。

以上内容可能可能语言组织不好,有些问题没说清,今天实在很晚了,下次有时间按再来改!敬请各位谅解
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: