NIOS II/f Data Cache and Tightly-Coupled Memory
0赞这个问题困扰了我n久n久了(2天)...
IOWR 写数据总结出郁闷的问题
http://blog.chinaaet.com/detail/14241.html
上篇博文中我提出了问题,对于
#define LED_DATA *(volatile unsigned char*) LED_PIO_BASE
直接操作没有效果,但后面加一句printf()后可执行,一直想不通这个问题,现在终于解决了…
最后在牙缝哥哥的“不情愿”的教导下,又baidu google了一下,加上手册和书,我终于悟出来了。。。。。
下面我图文并茂,handbook+ZLG_BOOK+BMP+txt 来解决问题
在SOPC创建CPU的时候,nios/e、nios/s、nios/f有个地方有所不同:
下面是nios/e、nios/s的,
Data Cache被屏蔽了,不存在Data Cache(数据缓存)的问题
下面是nios/f的(可以在这里把它关掉,防止后面的一系列问题)
nios/f为CPU开辟了2KB的32字节的Date Cache(数据缓存),问题就出在这里
Data Cache 数据缓存相当于电脑的一级缓存,二级缓存,是为了提高系统速度,因为这样就可以一直发送数据,一直接收数据了。
根据Nios II Processor Handbook 上关于Cache and Tightly-Coupled Memory的解说:
可见,ldio/stio类指令明确指明了第31位地址对旁路数据缓存提供了一个可选的方法
如果第31为地址被拉高- 1 -:数据缓存区被旁路
如果第31为地址被拉低- 0 -:数据缓存区被打开
因此在nios/f中又可以通过软件的方法吧Data Cache关掉
第31位地址只能在处理器内部使用,所以最大的地址空间只有31位,及2G寻址空间
后面又说到,对于nios/e、nios/s也是31位及2G寻址空间,这样便于不同等级的NIOS II核之间的代码移植
下面摘录ZLG的《SOPC嵌入式系统基础教程》P68、P69中的几句话:
“NIOS II结构的指令主端口和数据主端口都支持高速缓存
高速缓存使用片内存储器
nios/f中指令和数据高速缓存在运行时移植使能,但可以使用软件方法来旁路数据高速缓存
NIOS II处理器出城部分的高速缓存在SOPC Bulider中式可选的,取决于用户对系统欧冠存储性能的要求
NIOS II处理器 数据指令缓存 可有可无
NIOS II 高速缓存改善心梗的功效基础
(1)常规存储器位于片外,方为时间>片内存储器
(2)循环执行的、最大的、关键性能的指令序列长度小于指令高速缓存
(3)关键性能数据的最大规模小于数据高速缓存
NIOS II 高速缓存缺点
(1)只有片内存储器时,高速缓存没优势
(2)程序循环2KB,高速缓存1KB,没作用(上述(3))
(3)使得程序执行时间不可预测
NIOS II处理器内核支持一种称作31为高速缓存旁路的机制,根据最高有效位的值来旁路高速缓存
NIOS II内核地址都限制在31为,及2G地址空间
”
至此,我恍然大悟,记得当年我的另外一块开发板因为画的是在太戳了,nios/f跑步起来,所以一直用的是nios/e、nios/s,我一直这样写
以前这样写从没出现过问题是因为nios/e,nios/s不存在数据缓存区,Bit31无效
但nios/f存在数据缓存区,Bit31有效,所以如果要直接通过地址映射操作,必须把最高位屏蔽掉
#define LED_DATA *(volatile unsigned int*) (LED_PIO_BASE| (1<<31)) //把Bit31拉高
这样就能操作了
而上述我在LED_DATA = 1;后面加了一句printf()就可以了原因,
因为把给LED_DATA发出的数据放在了数据缓存区,没有及时处理,
个人觉得printf是电脑在执行操作,这个同事刚好FPGA CPU空闲,所以缓存区释放,IO有效(如果有不到之处,看到的人请提出,谢谢)
下面放映一下我Master的SPI 寄存器映射方法
在nios/f中 要寄存器映射都必须bypass cache,否则会出错,这个要铭记了。。。
。。。。。。。。。
#define LED_DATA *(volatile unsigned int*) (LED_PIO_BASE| (1<<31))
int main()
{
unsigned char table[]={0x00,0x01,0x02,0x03};
unsigned char i;
printf("Time is flying...\n");
printf("我要吐血了。。。\n");
while(1)
{
for(i=0;i<4;i++)
{
LED_DATA = table[i];
Delay_Ms(500);
}
}
return 0;
}
但是Cache存在缺陷,就是 不能及时处理数据,执行代码时间变的不可确定,降低了实时性
在此,有更好的解决方案,那就是Tigtly-Coupled Memory,紧耦合锁存器:是一种紧挨着内核的快速SRAM
(1)可以改善系统系能
(2)保证装在和存储指令或数据的时间确定
紧耦合所存器使NIOS II性能提高,又能获得可预测的实时响应,有以下特点:
(1)性能类似于高速缓存
(2)软件能够保存讲关键性能的代码或数据存放在紧耦合存储器中
(3)代码执行的确定性——装载和存储指令或者数据的时间是可预测的
NIOS II节后指令和数据访问都支持耦合存储器
如果应用程序和存储器需要组后小,能够完全在片内实现,可以使用专门针对代码和数据的紧耦合器,可是怎么用捏???
反正,问题都解决, 静态地址 主端和从端的地址映射也差不多知道了。。。。
养成对Cache Bit31位操作的习惯,便于移植
总结出一点,好好看handbook!!!
发现问题--问问题--无果--看handbook--while(1){冷静,问题总能被解决的………}