关于DSP外扩存储器的几个问题

[复制链接]
 楼主| cruby 发表于 2007-7-8 22:07 | 显示全部楼层 |阅读模式
我用的芯片是2407,在外扩存储器时有几个问题搞不清楚,请各位帮我看看:<br /><br />1.&nbsp;假设我要外扩程序存储器,现在我将PS#跟存储器Flash的CE#连接(这里用#表示“反/非”的意思),要使Flash使能就必须使CE#为0,也就是要使PS#为0,那么怎么才能使PS#为0呢?<br /><br />2.&nbsp;如果我令MP/MC#&nbsp;=&nbsp;0(从内部读取复位向量),那么能访问外部的存储器吗?如果能,那么假设我要读外部存储器0x0010地址处的值时,我应该用什么指令呢?<br />是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;&nbsp;//定义一个内部变量<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)0x0010;<br />还是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000);呢?<br /><br />3.&nbsp;如果我令MP/MC#&nbsp;=&nbsp;1(从外部读取复位向量),那么怎么才能访问外部的存储器呢?<br />是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)0x0010;<br />还是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000);呢?<br /><br />4.&nbsp;接着第3个问题,此时还能访问内部的存储器吗?如果能的话怎么访问内部的存储器呢?如果不能的话,那么内部32K的Flash不是没用了吗;外扩的时候内部32K的Flash是不是始终都有用还是说外扩后就没用了?<br />
wowow 发表于 2007-7-9 13:03 | 显示全部楼层

提一下思路

C2000的我不熟,提一下在其它5000系列中的思路供参考:<br />接到PS#说明是程序空间,如果是汇编就用相关的指令,如果是C,*(unsigned&nbsp;int*)0x0010这种方法肯定不行,这是数据指针,是访问数据空间用的。函数指针才会指向程序空间,但用函数指针来访问数据肯定也不恰当.<br /><br />能想到的办法中有通过变量,确保它分配到程序空间<br />1.对于const变量,定义:<br />const&nbsp;int&nbsp;x;<br />然后将.const段(前面的.不要漏了)分配到程序空间的Section里面。(C2000里也应该有Page0/Page1吧?前面争了半天的,呵呵)<br />这个方法只能用于全局变量,因为局部变量是在stack里,不会分配到.const段。还有前面不能加volatile,因为volatile变量处理方法不一样。<br /><br /><br />2.自定义一个section,比如取名叫mysect,将其也分配到程序空间的Section里。然后在定义变量的前面加上#pragma&nbsp;DATA_SECTION编译指示:<br />#pragma&nbsp;DATA_SECTION&nbsp;(y,&nbsp;&quot;mysect&quot;)<br />int&nbsp;y;<br /><br />但这种方法访问数据估计会比较慢,因为程序空间的寻址方式很少,你可以看一一反汇编的代友,一般要先把数据先复制到寄存器或数据空间里再参与运算。不划算吧?所以除常量以外的数据最好都放在数据空间。
Cruby 发表于 2007-7-9 14:19 | 显示全部楼层

如果外接的数据存储器呢?

谢谢楼上提醒,但是如果我接的是数据存储器呢?比如DS#接外部数据存储器的片选信号CE#,那么怎么才能使DS#变为0呢?<br /><br />另外,我访问外部数据存储器地址的0x0010时,我用<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;&nbsp;//定义一个内部变量<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)0x0010;<br />还是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000);呢?
wowow 发表于 2007-7-9 16:25 | 显示全部楼层

看样子你是想把外部flash的0地址对应DSP的0x8000吧?

1.要想DS#变低,就要访问外部地址空间,<br />比如将0x8000地址以上映射到extern&nbsp;memory,<br />访问*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000)就可以使DS#变低<br /><br />如果你想外部flash的0地址对应DSP的0x8000,就要将高位地址线A15取反,再跟DS#脚相或,再接到Flash的CE#,低地址A14-A0线一一对应接。这样你访问0x8010时,A15为低,跟DS#相或后仍然是低,选中Flash。但实际操作的是Flash的0x0010地址。<br /><br />其实也不复杂,只要想好:DSP的引脚输出什么电平,外部芯片需要输入什么电平才能选中,中间加个组合逻辑匹配一下就行了。<br /><br />如果你用的是32k*16的Flash,只能这样接了。如果是64k或更大的,反正只能用到32k,总是有浪费的。可以直接DS#接Flash的CE#,并将低32k的数据空间由于是映射到内部空间,高32k数据空间映射到外部空间,那么flash的低32k是访问不到的了,高32k与程序中的地址是一一对应的。这样以浪费flash的代价节省接口逻辑。
 楼主| cruby 发表于 2007-7-9 19:14 | 显示全部楼层

啊,这可怎么办?

如果不用A15取反的话,就永远不能访问前32k了是吗?<br /><br />因为如果我直接将DS#与Flash的CE#连起来的话,用*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000)访问的就是存储器的0x8010的地址;而用*(unsigned&nbsp;int*)(0x0010)的话就是访问数据存储器内部的0x0100地址而不是Flash的0x0010地址,是这样吗?<br /><br />我现在碰到的情况是用DS#接外部一个4M的Flash(共22根地址线)的CE#,地址线A0-A15连Flash的A0-A15,剩下的地址线不够用就用IO口PE0-PE5代替;另外,DSP的RD#接Flash的OE#,WE#接WE#;如果这样的话,是不是说这4M的Flash的前32K也是不能用了?另外,这IO口能代替数据线访问Flash的空间吗?
wowow 发表于 2007-7-9 19:35 | 显示全部楼层

可以把Flash的A15也用IO来控制

只把A0-A14跟DSP总线相联,这样一次可中32k
 楼主| cruby 发表于 2007-7-9 22:09 | 显示全部楼层

我的硬件已经成型了,怎么办呢

非常感谢wowow指点,现在我的硬件已经成型了,地址线A0-A15已经跟Flash的A0-A15连接了,应该怎么办呢?<br /><br />我往Flash上写东西时,要先往0x555、0x2aa等地址上写一些数据,按照现有的硬件条件怎么才能访问到这些地址呢?
wowow 发表于 2007-7-10 01:59 | 显示全部楼层

要么浪费,要么飞线

有的flash的0x555、0x2aa写命令不在意A15是高还是低,这个要看datasheet。<br /><br />Address&nbsp;format&nbsp;A14-A0&nbsp;(Hex):<br />Address&nbsp;A15&nbsp;is&nbsp;“Don’t&nbsp;Care”&nbsp;for&nbsp;the&nbsp;Command&nbsp;sequence&nbsp;for&nbsp;SST39LF/VF512.<br />Address&nbsp;A15&nbsp;and&nbsp;A16&nbsp;are&nbsp;“Don’t&nbsp;Care”&nbsp;for&nbsp;the&nbsp;Command&nbsp;sequence&nbsp;for&nbsp;SST39LF/VF010.<br />Address&nbsp;A15,&nbsp;A16&nbsp;and&nbsp;A17&nbsp;are&nbsp;“Don’t&nbsp;Care”&nbsp;for&nbsp;the&nbsp;Command&nbsp;sequence&nbsp;for&nbsp;SST39LF/VF020.<br />Address&nbsp;A15,&nbsp;A16,&nbsp;A17&nbsp;and&nbsp;A18&nbsp;are&nbsp;“Don’t&nbsp;Care”&nbsp;for&nbsp;the&nbsp;Command&nbsp;sequence&nbsp;for&nbsp;SST39LF/VF040.<br /><br /><br />SST39LF/VF200A SST39LF/VF400A&nbsp;SST39LF/VF800A:<br />Address&nbsp;format&nbsp;A14-A0&nbsp;(Hex),&nbsp;Addresses&nbsp;AMS-A15&nbsp;can&nbsp;be&nbsp;VIL&nbsp;or&nbsp;VIH,&nbsp;but&nbsp;no&nbsp;other&nbsp;value,&nbsp;for&nbsp;the&nbsp;Command&nbsp;sequence.<br />
tjsheep 发表于 2007-7-10 11:14 | 显示全部楼层

简单解答,呵呵

1.&nbsp;假设我要外扩程序存储器,现在我将PS#跟存储器Flash的CE#连接(这里用#表示“反/非”的意思),要使Flash使能就必须使CE#为0,也就是要使PS#为0,那么怎么才能使PS#为0呢?<br /><br />----mp/mc设为mp模式,访问程序时候ps有效,就是外部空间<br /><br />2.&nbsp;如果我令MP/MC#&nbsp;=&nbsp;0(从内部读取复位向量),那么能访问外部的存储器吗?如果能,那么假设我要读外部存储器0x0010地址处的值时,我应该用什么指令呢?<br />是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;&nbsp;//定义一个内部变量<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)0x0010;<br />还是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000);呢?<br /><br />--------访问外部什么空间?数据还是程序?<br /><br />3.&nbsp;如果我令MP/MC#&nbsp;=&nbsp;1(从外部读取复位向量),那么怎么才能访问外部的存储器呢?<br />是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)0x0010;<br />还是<br />unsigned&nbsp;int&nbsp;getValue&nbsp;=&nbsp;0;<br />getValue&nbsp;=&nbsp;*(unsigned&nbsp;int*)(0x0010&nbsp;+&nbsp;0x8000);呢?<br /><br />------8000以后的数据空间自动访问外部的,c语言里的变量分配用cmd文件指定,一般不用绝对地址<br /><br />4.&nbsp;接着第3个问题,此时还能访问内部的存储器吗?如果能的话怎么访问内部的存储器呢?如果不能的话,那么内部32K的Flash不是没用了吗;外扩的时候内部32K的Flash是不是始终都有用还是说外扩后就没用了?<br /><br />------内部外部程序空间是重叠的,一般来说是不能同时用的,但是用手动的办法来访问也是可以的,但是不符合c的编译器,不能自动编译出这样的代码
 楼主| cruby 发表于 2007-7-10 11:27 | 显示全部楼层

看来是大大地浪费了

今天早上考虑了一下,把DS#接个反相器直接与存储器连了,这样我就只用了4M闪存的32k(心痛啊,好浪费!),暂时不管别的了,先把芯片调通了再说;<br /><br />另外,我用的Flash是AMD(Spansion?)的Am29DL640D,数据手册好大,有六十多页,回去找找看看高位引脚跟命令字节有没有关系?<br /><br />PS:wowow人品很不错~
iversonma 发表于 2007-7-10 15:28 | 显示全部楼层

理论上应该可以

command命令寄存器是不会占用存储空间的,你给具体的地址写数据系统不会识别是写命令或者写数据。不过提供了两个方法防止这种错误<br />首先一般写数据都要求先写一个命令字,下一个周期写入的数据才能写入,注意memory的集中mode<br />normal&nbsp;mode似乎写数据之前是需要命令字的,还有一种autoselect&nbsp;mode似乎不用,具体可以详细看看memory的datasheet。<br />再者一般的命令字都是连续好几个的,闲着没事估计没有人写地址数据刚好和命令字相同。<br /><br />这个问题倒是问得不错,支持你按你的想法试一下,别忘了在这里说一下结果<br />
 楼主| cruby 发表于 2007-7-12 22:08 | 显示全部楼层

To iversonma:

今天试了一下,向Flash编程时可以用0x8555代替0x555,我可以往Flash上写一个字,不过也就一个字;紧接着往第二个字写的时候发现没有用,可能是我的写时序有点问题,明天再看看~<br /><br />不知道有谁写过读写Flash存储器Am29DL640D类似的程序,如果有的话我想参考一下。我的邮箱为:veshid@gmail.com
iversonma 发表于 2007-7-12 22:23 | 显示全部楼层

re

没有看明白什么意思?<br />命令可以替代,写数据什么意思?<br />am29dl是异步的吧,如果是的话找别的异步器件参考就行<br />别人的程序不会那么轻易就送出去的
随风飘2008 发表于 2007-7-12 23:07 | 显示全部楼层

re

我也没看明白
 楼主| cruby 发表于 2007-7-12 23:43 | 显示全部楼层

不明白吗

说得不够明白是吧<br />简单地说就是写命令字节进A22-A11的状态是无所谓的,这样<br />*(unsigned&nbsp;int*)(0x0A555)&nbsp;=&nbsp;0xAA;<br />*(unsigned&nbsp;int*)(0x0B2AA)&nbsp;=&nbsp;0x55;<br />*(unsigned&nbsp;int*)(0x0C555)&nbsp;=&nbsp;0xA0;<br />就等价与<br />*(unsigned&nbsp;int*)(0x0555)&nbsp;=&nbsp;0xAA;<br />*(unsigned&nbsp;int*)(0x02AA)&nbsp;=&nbsp;0x55;<br />*(unsigned&nbsp;int*)(0x0555)&nbsp;=&nbsp;0xA0;了,<br /><br />因为我现在板子的硬件设置访问不了外部Flash&nbsp;0x8000前的空间,而要往Flash里写数据的话必须写几个命令字节(在555,2aa,555等地址,注意:这些地址都在0x8000前);所以一开始我以为访问不了Flash的8000前地址,也就不能往这些地址写上东西,但是后来看到A22-A21无关后,就试了一下,发现在555,2aa之类的地址加上8000也无所谓(为什么我要加8000呢?&nbsp;因为访问8000以上地址,WE#才能变低,所以......)<br />
iversonma 发表于 2007-7-13 09:24 | 显示全部楼层

这不就是datasheet上面的原话吗

看来是你自己没有说清楚<br />另外你说的那个第二次写不进去的问题,应该是flash不支持页模式,或者你只设置为async模式,这样情况下写一次命令字只允许写一个数据位(如果falsh为16位就是16位)。和时序没有关系<br />
 楼主| cruby 发表于 2007-7-13 11:27 | 显示全部楼层

继续

估计我不止没说清楚,也没有弄清楚,所以稀里糊涂的~<br />继续说几句吧,看看有没有人搞过类似的芯片,想交流一下:<br /><br />1.&nbsp;芯片名字叫Am29DL640D,现在好像已经停产了,官方推荐用S29JL064H代替~<br />2.&nbsp;读芯片没什么特殊的,直接读地址就可以了<br />3.&nbsp;“写”芯片(program&nbsp;flash)就麻烦了:首先要先命令字节,另外还有两种写的模式,一个是常规的,需四个周期,还有一种叫bypass模式,只需2个周期;<br />4.&nbsp;有两种擦除模式,一个是Chip&nbsp;Erase,另一个是Sector&nbsp;Erase,是不是在写之前都要擦除一下呢?<br />5.&nbsp;另外还有个引脚叫WP#/ACC,好像可以加速读写速度的,具体不清楚,都是英文,看得头都大了,相关中文资料找了好久也没找到什么有价值的,痛苦啊~<br /><br />我只是奇怪,为什么我用<br />ProgramFlash(0x8888,&nbsp;0x1111);&nbsp;//往8888地址写1111<br />ProgramFlash(0x9999,&nbsp;0x2222);<br />getValue1&nbsp;=&nbsp;ReadFlash(0x8888);//读取8888地址的值<br />getValue2&nbsp;=&nbsp;ReadFlash(0x9999);<br />后,getValue1的值正确,而getValue2的值就不正确呢?<br />是不是每次读或者写后都必须得验证一下呢?<br />回去还得好好看看手册~
iversonma 发表于 2007-7-13 20:32 | 显示全部楼层

胡乱解释一下

<br /><br /><br />1.&nbsp;芯片名字叫Am29DL640D,现在好像已经停产了,官方推荐用S29JL064H代替~<br />这个没有问题,基本软件是全部兼容的,而且速度肯定要上去一些,因为采用了更高级的制造工艺,这样spansion的成本也降下来了。<br />2.&nbsp;读芯片没什么特殊的,直接读地址就可以了<br />因为不会破坏内部数据,所以不用写命令。<br />3.&nbsp;“写”芯片(program&nbsp;flash)就麻烦了:首先要先命令字节,另外还有两种写的模式,一个是常规的,需四个周期,还有一种叫bypass模式,只需2个周期;<br />模式不止这两种,<br />4.&nbsp;有两种擦除模式,一个是Chip&nbsp;Erase,另一个是Sector&nbsp;Erase,是不是在写之前都要擦除一下呢?<br />在nor&nbsp;flash里面,是由好多sector(块)组成的,擦除的时候可以选择Chip&nbsp;Erase(整片擦除)和sector&nbsp;erase(块擦除)写之前不一定必须擦除,如果你不确定memory里面是否有数据,写之前擦除一下也是很必要的。取决于你自己<br /><br />5.&nbsp;另外还有个引脚叫WP#/ACC,好像可以加速读写速度的,具体不清楚,都是英文,看得头都大了,相关中文资料找了好久也没找到什么有价值的,痛苦啊~<br /><br />wp#/acc管脚也有可能是两个分开,wp#是硬件写保护信号(write&nbsp;protect)有效时软件写操作被屏蔽,可以起到保护的作用。acc是加速的意思,一般烧写器或者工厂大批量烧写的时候用到,比普通的软件在线编程速度快一倍多(不同的器件可能有差异,大致是这个意思)。<br /><br />其实对于做软件驱动而言,只要关心操作数和时序就可以了,好多种的保护模式实际很少用刀,除非作烧写器或者要大批量生产。<br /><br /><br />关于资料,memory的资料一般都是英文的,没有办法,技术更新的太快,目前中文有一本译文的,名字好像是《半导体存储器-结构&nbsp;&nbsp;&nbsp;》不确定,不过你网上搜,也只有一本,讲的比较基础,目前市面上常用的memory都有详细介绍。
 楼主| cruby 发表于 2007-7-13 22:35 | 显示全部楼层

看了一下午手册

看了一下午手册,有点弄明白了,不过晚上上机一试发现还是调不出来,郁闷,明天得加班继续了~
zhangmangui 发表于 2013-12-9 12:20 | 显示全部楼层
好贴  帮忙顶
您需要登录后才可以回帖 登录 | 注册

本版积分规则

10

主题

64

帖子

0

粉丝
快速回复 返回顶部 返回列表