用到的设备:嵌入SPI4W模块的主控、SPI Falsh、逻辑分析仪。
啥?你问我SPI4W是啥?
嗯·····SPI协议大伙儿都熟悉:serial peripheral interface、串行外围设备接口,采用四线制,接口有CLK、CS、MISO、MOSI,输入输出可同时存在,要讲起来可以一套一套的。
先来击垮一个误区:SPI一定是四线制吗?
SPI版本是比较混乱的,没有绝对标准的协议,虽然本质上没有差异,但是有多个版本,其中一个版本就是三线制,接口有CLK、CS、SDA,这条SDA线同一时刻只能作为MISO或者MOSI。
什么?这个例子说服力不够?
那再来看看一种少见的——SPI4W。
这是一种与SPI大异小同的功能模块,看清楚,我说的是大异小同。这家伙在游戏开局设定中就有6条信号线CS、CLK、D0、D1、D2、D3,并没有CS、CLK、MOSI和MISO的绝对限定,实际上,每条D1、D2、D3、D4都可以功能复用成MISO或者MOSI。
开局就给了一张任意牌,开发者这样设定有什么用呢,因为无论是SPI还是SPI4W,CLK和CS都只需要一条即可。
的确如此。
SPI4W最主要的用途,在于可以随意扩宽传输数据的宽度,根据不同的位宽,衍生了1bit mode,2bit mode和4bit mode。
1bit mode:之所以是1bit,是因为无论是input还是output,都只占用了1条信号线,数据宽度为1bit;
(1)CS、CLK、SDA (input、output)
(2)CS、CLK、SDI、SDO
2bit mode:之所以是2bit,是因为无论是input还是output,都只占用了2条信号线,数据宽度为2bit;
CS、CLK、SDA0、SDA1
4bit mode:之所以是4bit,是因为无论是input还是output,都占用了4条信号线,数据宽度为4bit;
CS、CLK、SDA0、SDA1、SDA2、SDA3
咦,咋没有3bit mode呢?SPI4W模块很少有3bit的,除非你的硬件上支持。
那为什么1bit mode中有两种接线方式呢,那是因为在该模式中
(1)既可以让1条SDA既当input又当output,
(2)又可以1条SDA0当input,另一条SDA1当output,而又不改变位宽1bit的设定。
这两种方式也是有名号的,(1)称为2-wire mode,(2)称为3-wire mode
而我们大学中见到的SPI,实际上就是SPI4W中的1bit模式中的3-wire mode。
捋清了两者的关系。再来看。
无论是大哥SPI4W,还是小弟SPI,他们的实现方式只要两种:
一种是硬件内部已经做好了SPI模块,我们只需要通过配置相应的寄存器就可以发送对应的SPI波形;
一种是硬件上啥也没有,只能乖乖的用IO口来模拟相应的SPI波形;
由于我使用的主控已经有了SPI4W模块功能,所以我选择使用第一种。
使能寄存器,数据寄存器,地址寄存器配置等初始化配置啥的,网上太多了,大同小异,这里就不说了,说点网上少见的。
以下涉及到的命令,flash性能,都以我现在在用的P25Q80H为例子:
在SPI波形中,数据在什么样的时序中是有效的,什么样的时序在被采样,都跟timing mode的配置有关,这也是配置好SPI4W协议的第一步。
timing mode配置有四种模式:mode 0,mode 1,mode 2,mode 3。
具体支持哪一种,得看主板模块和SPI协议芯片的脸色。
假如主控四种都支持,但是SPI Flash只能支持mode 0和mode 3,那你就只能用这两种了,没办法,甲方是爹。
那这四种模式的时序都是长什么样子的?
关门放图,以下就是mode 0和mode 3的波形:
注意两个点即可,一是空闲的初始状态,二是采样的时间点。
以mode 0 为例:
(1)在空闲状态下,SCLK是呈现低电平的
(2)在上升沿被采样的数据为有效数据
在配置SPI4W协议模块寄存器的时候,只需要配置好这两个点,那么timing时序的运作方式就被确定了,接下来在SPI的内部模块中,内部就会自动在空闲状态是低电平的状态下进行上升沿采样。
如果你是想选用mode 3,那也是可以的:
(1)空闲状态下,SCLK是高电平状态
(2)在上升沿采样
无论是手上用有一些CPU,在SPI4W的传输过程中,时钟的产生都不是一直产生的,只有在发送命令或者数据的时候才会有,只要配置好SPI4W模块,应用开发者只需要发送需要的数据,内部就会自动同时发送CLK,在这一点无论是开发板还是FPGA上并没有什么异样。
可能出现异样的,是接收。因为只有存在时钟CLK的时候,才会有数据传输这档子事,由于此时是接收状态,有些SPI4W模块中,并不会在接收数据的前一瞬间自动发送CLK。
那这个要怎么确定呢,简单,用逻辑分析仪抓一抓就可以知道,就看在接收数据阶段有没有抓取到CLK信号。
没有抓到的话,那就需要自己手动发送CLK,做法也相当简单,在接收状态下,随便发送1份数据,可以说1byte,也可以是2byte,这都无所谓。由于此时是接收状态,所以发送的数据并不会真的被发送出去,发出去的只有CLK而已,如果用逻辑分析仪抓的话,是抓不到任何发出去的信号的,配置没配错的情况下抓到的只会是接收回来的数据。
拿我用的这款25AAxxx的flash来说,先举几个命令:
对应1bit mode的单通道写操作命令——Page Program(0x02);
对应2bit mode的双通道写操作命令—— Dual Page Program(0xA2);
对应4bit mode的四通道写操作命令——Qual Page Program(0x32);
falsh手册上明确指出了,要发送这些命令之前,必须先发送Write Enable(0x06)命令。
那就照着做:
拉低CS——发送0x06命令——拉高CS——拉低CS——发送0x02/0xA2/0x32——
以上命令发送的步骤,省一步,数据就不对了。
从拉低CS的那一瞬间,flash就开始进行工作了,这就是使能。
这就引出了一个需要注意的点——一定要做好一切SPI4W模块配置后再进行CS使能。不然,一切SPI4W寄存器配置引起的引脚电平跳变都会被Flash当成输入信号,进行产生任何可能产生的错误波形。
想在使用Page Program(0x02)、Dual Page Program(0xA2)、Qual Page Program(0x32)这些写操作的命令时,每一次处理都需要一定的执行时间。
温馨提示:如果是program类型的命令,记得先进行擦除才写入。
看,一次page program的操作一般是2ms,最大是3ms。
不同的命令处理具体需要多少时间,得看具体使用的flash配套的手册。
一般情况下,都是加些延时,挺过来所需要的时间再做下一步操作。
可延时函数毕竟不是最保险的做法,因为根本无法统一每个命令执行究竟需要多少时间,最保险的做法就是查询状态寄存器RDSR。
没错,当page program过程被执行完毕后,状态寄存器的某些位的值会发生改变,以这些位的值是否发生了改变为标准才算最准确的。
究竟是那些位会发生改变呢?
先来看看以下两张状态寄存器的命令时序和相关状态位。
要留意的就是(S1)WEL、和(S2)WIP这两bit,page program执行过程中,一旦flash识别到Write Enable,WEL就会被置1,一旦识别到program命令,WIp就会被置1。
只有program操作被完整完成,这两bit才会被清零。
因此可以在进行一段时间延时后,查询这两个位是否被清零,如果是,说明program过程被执行完毕了。
当然,也可以完全不需要延时函数,但是这样的话,就需要持续不断的去查询这两个位的状态,直到查询到为0为止。
除了page program,还有dual program 、qual program、erase等命令,也是做好通过查询寄存器来判断该过程执行完毕没有。
还有一点冷知识,有些flash的WEL这个位,缺省状态就是1,即使完成命令操作,状态也还是1,所以如果图省事的话,状态寄存器仅仅是判断WIP这一个位也是足够的。
在一开始也讲过了,SPI4W可以随意更改数据传输的位宽,那具体表现形式的怎么样的呢?
1bit mode下,8个CLK可以承载8bit数据,也就是1byte;
2bit mode下,8CLK可以承载2byte数据,接收1byte数据只需要4个CLK;
4bit mode下,8个CLk可以承载4byte数据,接收1byte数据只需要2个CLK;
大部分CPU在设计的时候,就是需要凑足8个CLk在进行一次传输的,因为1bit的还好,但是2bit就至少需要传输2byte,4bit就至少需要传输4byte数据才行。
flash的保护机制无非两个方面。
外在保护机制,WP这个引脚只要赋予相应的电平,就能启动写保护机制,一旦启动,即使所有配置和命令都正确的情况下,就是写不进去。但是究竟是高电平有效还是低电平有效,看具体flash款式。
内在保护机制,BP4,BP3,BP2,BP1,BP0一旦被置1,就会启动内在保护机制。
这几个bit,是不是很熟悉,你看。
正是状态寄存器中的S2~S6位,解决保护机制关键在于只要将这几bit清零即可。
直接用写状态寄存器命令——Write Status Register)(WRSR),清零这几个值即可。
如果是仅仅测试flash能不能正常运行,一般我们采用较低的工作频率完全OK。
而一旦在工作应用中,工作频率的上调是一个必经的过程,为了就是要抓取主控和外围能承受的最大工作频率。
在低频率测试无误的情况下,在高频率都被暴露出许多在低频下完全被忽略掉的细节,什么现象都会发生。
频率的调试就是一个头疼问题,一旦你确定了自己的配置无误,程序并没有错误的时候,就可以往频率这方面上去找找问题了。
高频下第一个暴露出来的,就是命令。
每一个命令必须要其支持的频率下才有效果,以我用的flash为例,最后支持频率为104M,高频模式下能用的命令有FAST READ、RDSFDP、PP、SE、BE32K、CE、WREN、RDSR等。
而低频命令只能跑低频率,但是高频命令既能跑高频,也能跑低频。
气不气人,用高频命令跑低频的,就是为了低功耗。
高频下第二个暴露出来的,就是SPI波形。
这里mode 0下用逻辑分析仪抓到的波形。
一看就发现波形不对劲,mode 0下是上升沿采样的,而波形中,应该被采样到的DI信号“完美”避开了上升沿时刻,那采样回来的能是个什么,估计是个球吧。
后来发现,只要DI信号能往前偏移一点波形就正确了。
那么原因就很明显了,这就是由于flash反应跟不上高频的节奏,面对这种情况,往往在SPI模块中会嵌有高频修复功能,这就是面对可能出现这样一种情况的偏移位补偿,只需要找到该寄存器,开启次位修复功能即可。
那我真没有这修复模块,但是还是出错了呢,这咋解决?
哈哈,那可能你这SPI模块在制作的时候,高频情况不在其应用范围之内。
会有这样的人问了:那我抓出来的波形确实发生了偏移,但是Flash却能确证的运行,这是咋回事呢?
我很遗憾的告诉你,恭喜,问题出在你用来抓信号的逻辑分析仪上,可能并不能支持抓到高频的信号,你换一个支持高频抓取的。
那换了能支持高频的,抓回来的波形还是出错,还有一种方法可以一试:
就是调低逻辑分析仪的触发电压。
为什么需要这么试呢,原因是这样的:
芯片的信号获取是从CLK的下降沿到下一个上升沿的时间,记做tCLQV。
这是个重要的时间参数,在这个时间内,数据就被填充完毕了,等上升沿来临就可以读取出数据来。
这个时间段的具体时间可以在falsh手册上明确找到,根据不同电容的差异,时间值大概是6~7ns。
所以我们可以量一下实际抓取到的tCLQV,如果不是这个时间,那就说明有问题。
那那····怎么量?
额,这么量,你看。
逻辑分析仪抓取到的波形,实际上是电压,在有低拉高的过程中,由于高频频率太快,还没来得及拉高,tCLQV时间就过了。
这里有个误区:并不是频率快,拉高的过程就快了,比如高电平是3.3V,就算你频率再怎么快,硬件上从0拉到3.3V需要的时间还是那个时间,而频率快改变了的,是降低了tCLQV时间短范围。
在这个范围内,硬件电平还没拉高,时间就过了。
所以我们才需要修改触发电平,比如3.3V触发改成2.0或者1.6V触发,目的在于降低硬件拉高电平所需要的时间,使拉高的这个过程在cCLQV时间内执行完毕。