NIOS II/f Data Cache and Tightly-Coupled Memory

这个问题困扰了我n久n久了(2天)...

IOWR 写数据总结出郁闷的问题 

http://www.cnblogs.com/crazybingo/archive/2010/11/26/1888731.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的image

Data Cache被屏蔽了,不存在Data Cache(数据缓存)的问题

下面是nios/f的image (可以在这里把它关掉,防止后面的一系列问题)

nios/f为CPU开辟了2KB的32字节的Date Cache(数据缓存),问题就出在这里

 

Data Cache 数据缓存相当于电脑的一级缓存,二级缓存,是为了提高系统速度,因为这样就可以一直发送数据,一直接收数据了。

根据Nios II Processor Handbook 上关于Cache and Tightly-Coupled Memory的解说:

image

image

 

可见,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,我一直这样写

 

image

以前这样写从没出现过问题是因为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 寄存器映射方法

image

在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

image

(1)可以改善系统系能

(2)保证装在和存储指令或数据的时间确定

紧耦合所存器使NIOS II性能提高,又能获得可预测的实时响应,有以下特点:

(1)性能类似于高速缓存

(2)软件能够保存讲关键性能的代码或数据存放在紧耦合存储器中

(3)代码执行的确定性——装载和存储指令或者数据的时间是可预测的

NIOS II节后指令和数据访问都支持耦合存储器

如果应用程序和存储器需要组后小,能够完全在片内实现,可以使用专门针对代码和数据的紧耦合器,可是怎么用捏???

 

 

反正,问题都解决, 静态地址 主端和从端的地址映射也差不多知道了。。。。

养成对Cache Bit31位操作的习惯,便于移植

总结出一点,好好看handbook!!!

发现问题--问问题--无果--看handbook--while(1){冷静,问题总能被解决的………}

posted on 2010-11-26 21:44  CrazyBingo  阅读(4529)  评论(5编辑  收藏  举报

导航