RISC cpu cache管理总结

花了些时间,了解了一下 嵌入式中 cache的一些问题
总结一下,贴出来共享一下. 写得不好,或者有什么问题 欢迎提出.

ps: 也算是原创帖子了,欢迎讨论. 不知道怎么把帖子变成原创呢?
本文以MIPS R4000系列cpu为例.
假如使用的MIPS 4KEC (MIPSr232):
D cache & I cache 的结构都是4组并联的 cache,
每组为4KB,因此 I cache & D cache都是 16KB.
cacheline 是 16字节.


一. cache管理中,特别注意的2点:
1.DMA 控制器的操作内存的问题:
DMA 控制器的操作是直接操作内存的,并不经过cpu的cache.

2. 写指令问题.也就是flash驱动驱动load指令代码到内存中要注意的问题:
在MIPS中Data cache 与 Instrution cache 是相互独立的.因此,从内存中读取指令数据到内存,有可能数据读取到了D cache中,
没有实际回写到实际物理内存里面. 如果这个时候,执行刚才拷贝到内存的代码,就会有问题.
解释如下:
因为假如指令代码处于Data cache中(实际物理内存中,没有相应指令),此时,执行刚刚load进内存
的指令, cpu 只会 透过 Instrution cache 去执行指令,I cache里面没有对应的索引,会到内存里面去读.
但是由于指令数据还在D cache中,就出现问题了.
结论是:假如flash 驱动从介质读取指令代码到内存中时候,
必须保证 指令代码 已经回写到物理内存中,而不能留在Data cache中.

在MIPS cpu下有两种方法去保证:
MIPS下
处于kseg0的物理地址,也就是0x8000 0000 - 0x9FFF FFFF(512M)地址,进行内存访问是经过cache,但不经过MMU的
(也就是访问该内存地址后,会在cache中留有数据)
处于kseg1的物理地址,也就是0xA000 0000 - 0xBFFF FFFF(512M)地址,进行内存访问是不经过cache,也不经过MMU的
(也就是访问该内存地址后,不会在cache中留有数据)

1). 假如传入flash驱动的内存地址是处于kseg0的物理地址,也就是0x8000 0000 - 0x9FFF FFFF(512M).
a.若flash 驱动以CPU 方式通过D cache 读取数据到内存后, 最后需要将D cache中的数据回写到物理内存里面.
b.若flash 驱动以DMA驱动读取指令数据到内存,因为数据已经直接写到物理内存,不会残留在D cache中,因此DMA读取flash数据后不需要回写cache.
不过,使用DMA进行访问前,需要先将内存对应的cache无效.--->参看DMA设备写数据到内存
      但是还是有一点要注意,若此时读取出来的数据,然后cpu根据硬件ECC校验结果对内存数据进行修正.也就是使用CPU方式修改了内存.
此时,还是需要重新将D cache中的数据回写到物理内存里面.
2). 将传入flash驱动的内存地址 统一转换为 kseg1的物理地址,也就是0xA000 0000 - 0xBFFF FFFF(512M).
因为,在MIPS中,kseg1的物理地址空间是不通过cache 存取的.因此,在flash驱动里面无论使用cpu方式还是DMA方式读取数据,
都不用将D cache中的数据回写到物理内存里面.

二 . cache管理中,要注意3点问题.
1).在DMA设备从内存取数据之前. (回写cache操作)
        必须先回写cache,也就是将D cache的数据回写到物理内存中,否则DMA 直接从 内存中取数据,会取到错误的数据
        
2).DMA设备写数据到内存.(无效cache 操作)
        必须将物理内存对应的D cache索引无效掉. 

3). 写指令,也就是特别注意的一.中的第2点.所谓,写指令,也就是从介质透过D cache load 指令代码到内存中,然后 cpu 执行指令
(MIPS cpu 下执行指令必须透过I cache进行执行指令) 
a.写回 D cache的 数据
b. 无效I cache 相应的数据

在linux中 的一个例子,就是加载驱动模块时候,shell下执行 insmode XXX.drv
会调用内核函数load_module
load_module函数最后会执行
        flush_icache_range((unsigned long)mod->module_core,
                           (unsigned long)mod->module_core + mod->core_size);                           
注意flush_icache_range 其实是做了先回写D cache然后在无效I cache
//对于R4K mips cpu
flush_icache_range其实是执行了local_r4k_flush_icache_range.
static inline void local_r4k_flush_icache_range(unsigned long start, unsigned long end)
{
..
                if (end - start >= dcache_size) {
                        r4k_blast_dcache();//回写全部D cache
                } else {
                        protected_blast_dcache_range(start, end);//回写相应D cache
                }


        if (end - start > icache_size)
                r4k_blast_icache();//无效全部I cache
        else
                protected_blast_icache_range(start, end);//无效相应I cache
}

三. cache 操作要注意的问题
1.cache 操作最常用的几种为:
        1). 无效cache (invalidate)
        2). 回写cache (writeback),对于MIPS cpu 回写cache 一般都是回写D cache. 我没有看见过
        什么时候需要回写I cache的.还望 大牛 指点.
        3). 回写并且无效cache.
无效cache时候,要注意无效的地址是否是cache line对齐的,
因为不是cache line 对齐的话,有可能将其他有用的数据清除了.
比如: cpu的cache line 是16字节. 
假如要无效0x8000 1004 的地址,也就是要无效 物理地址为 0x8000 1000 -  0x8000 100F ,这16 字节的cache line
这个时候, 程序的本意应该是 无效0x8000 1004 之后的一条 cahche内存.
但是,由于cache line 要对齐的原因, 却无效了0x8000 1000 - 0x8000 1003    4字节的数据.
也就是将这4字节的内存毁坏了.
很有可能这4字节的数据在之前并没有回写到物理内存里面. 
最终结论是: 假如要对 cache line不对齐的内存进行无效时候,对于边界不对齐的内存,要进行
先回写,然后再无效的动作, 也就是回写并且无效cache. 不能单单是无效cache.

2. cache操作的例子
DMA拷贝的一些例子,使用DMA 从src 内存地址,将数据搬运到 dst 内存地址:
INT32S am_memcpy_dma(void* dst, void* src, INT32U count)
{
...
                r4k_dma_cache_wback((INT32U)src,count);//回写DMA源地址
                r4k_dma_cache_wback_inv((INT32U)dst,count);//无效DMA目的地址,
                // 这里要注意,由于dst 的地址可能不是cache line
                //对齐,因此,需要先回写边界部分cache line,然后再无效边界的cache line,否则,边界数据有可能丢失.
                start_dma(src,dst,count);
        ...
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值