内核dma_cache_maint介绍

搞idm(internal DMA)模块时,看到数据从主芯片传输到WiFi芯片之前,会有一个idm_invalid_cache的动作,该函数里封装着dma_cache_maint,这也就是我们平时经常说的刷cache,那这个内核函数作用是怎么样的呢?从以下几点展开说下:

1、为什么做缓存cache

我们都知道CPU的运算速度远高于内存的读写速度,CPU如果直接去操作DDR,会使得CPU花费很长时间等待数据到来,或者把数据写入内存。
这时就引入了cache,CPU缓存(Cache Memory)是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多。
缓存中存放着内存中很小一部分的数据,但这一小部分是短时间内CPU即将访问使用的;如果CPU调用大量数据,就可避开内存直接从缓存中调用,从而加快读取速度。

2、cache一致性的问题

也正是由于缓存存在于CPU与内存中间,使得外设对内存的修改并不能保证cache中也得到同样的更新,同样的CPU对缓存中内容的修改也不能保证内存中的数据得到更新。
这种与DDR中的数据和cache中数据的不同步和不一致现象就是引入cache带来的一致性问题,最终可能导致使传输数据时或CPU运行改代码时产生出错。

3、DMA与cache

DMA(Direct Memory Access,直接存储器访问),将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。(DMA更多原理自行研究学习)

在进行DMA 操作时,如果没有对Cache 进行适当的操作,将可能产生以下两种错误:

  • 1.DMA 从外设读取数据到供CPU使用。DMA 将外部数据直接传到内存中,但cache 中仍然保留的是旧数据,这样处理器在访问数据时直接访问缓存将得到错误的数据。

  • 2.DMA 向外设写入由CPU提供的数据。处理器在处理数据时数据会先存放到cache 中,此时cache 中的数据有可能还没来得及写回到内存中的数据。如果这时DMA 直接从内存中取出数据传送到外设,外设将可能得到错误的数据。

为了正确进行DMA 传输,必须要对cache进行操作。 cache 操作主要分为 invalidate (作废) 和 writeback (写回) ,有时也将两着放在一起使用。

linux内核DMA 操作的函数如下:

  • 路径:linux/arch/arm/mm/dma-mapping.c
  • 源码:
/*
 * Make an area consistent for devices.
 * Note: Drivers should NOT use this function directly, as it will break
 * platforms with CONFIG_DMABOUNCE.
 * Use the driver DMA support - see dma-mapping.h (dma_sync_*)
 */
void dma_cache_maint(const void *start, size_t size, int direction)
{
        void (*inner_op)(const void *, size_t  ,int);
        void (*outer_op)(unsigned long, unsigned long);

        BUG_ON(!virt_addr_valid(start) || !virt_addr_valid(start + size - 1));

        switch (direction) {
        case DMA_FROM_DEVICE:           /* invalidate only */
                inner_op = dmac_map_area;
                outer_op = outer_inv_range;
                break;
        case DMA_TO_DEVICE:             /* writeback only */
                inner_op = dmac_map_area;//dmac_unmap_area;
                outer_op = outer_clean_range;
                break;
        case DMA_BIDIRECTIONAL:         /* writeback and invalidate */
                inner_op = dmac_flush_range;
                outer_op = outer_flush_range;
                break;
        default:
                BUG();
        }

        inner_op(start, size,direction);
        outer_op(__pa(start), __pa(start) + size);
}
EXPORT_SYMBOL(dma_cache_maint);

direction有三种情况,一是DMA从外设中读取数据,二是将数据送入外设,还有就是外设和CPU交互数据。

  • 1.DMA 从外设读取数据到供CPU使用时,使用invalidate 操作。这样将迫使CPU在读取cache中的数据时,先将数据从内存读取数据到缓存,保证缓存和内存中数据的一致性。

  • 2.DMA 向外设写入由CPU传输的数据时,进行writeback 操作。这样可以DMA传输数据之前先将缓存中的数据写回到内存中。

  • 3.我们在不清楚DMA 操作的方向时,也可先同时进行invalidate 和writeback 操作。操作的结果等同于invalidate 和 writeback 操作效果的叠加。

使用dma_cache_maint刷新cache之后,再对数据进行传输处理,这样便不会出错。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值