Linux Kernel之flush_cache_all在ARM平台下是如何实现的

发布者:SecretWhisper最新更新时间:2024-11-11 来源: cnblogs关键字:Linux  Kernel  ARM平台 手机看文章 扫描二维码
随时随地手机看文章

在驱动程序的设计中,我们可能会用到flush_cache_all将ARM cache的内容刷新到RAM,这是因为ARM Linux中cache一般会被设定为write back的。而通常象DMA是访问不了cache,所以如果我们需要启动DMA将RAM中的内容写到Flash中或LCD framebuffer,那么我们就需要调用flush_cache_all将cache中最新的内容刷新到RAM中。如果不这样做在LCD中可能会出现花屏。本文主要分析在ARM平台上到底如何实现的。

1.1                   flush_cache_all在ARM Linux中的实现

在include/asm-arm/cacheflush.h中:

#define flush_cache_all()             __cpuc_flush_kern_all()

#define __cpuc_flush_kern_all            cpu_cache.flush_kern_all

 

在setup_processor():

list = lookup_processor_type(processor_id);

//根据processor id找到对应ARM CPU(常见的如ARM926)相关的信息,存在list中。如果想把事情彻底搞清楚,必然要问processor_id是怎么来。它是在Linux Kernel启动时候从ARM chip中读出来。如果以后有机会大家一起讨论ARM Linux的启动全过程,可以详细分析。

      cpu_cache = *list->cache;

 

而lookup_processor_type定义在arch/arm/kernel/head-comman.S中:相应的assembler code如下:

     .type __lookup_processor_type, %function

__lookup_processor_type:

   adr   r3, 3f

   ldmda       r3, {r5 - r7}

   sub  r3, r3, r7                      @ get offset between virt&phys

   add  r5, r5, r3                      @ convert virt addresses to

   add  r6, r6, r3                      @ physical address space

1:         ldmia        r5, {r3, r4}                    @ value, mask

   and  r4, r4, r9                      @ mask wanted bits

   teq    r3, r4

   beq  2f

   add  r5, r5, #PROC_INFO_SZ            @ sizeof(proc_info_list)

   cmp r5, r6

   blo    1b

   mov  r5, #0                                    @ unknown processor

2:         mov  pc, lr

 

/*

 * This provides a C-API version of the above function.

 */

ENTRY(lookup_processor_type)

   stmfd        sp!, {r4 - r7, r9, lr}

   mov  r9, r0

   bl      __lookup_processor_type

   mov  r0, r5

   ldmfd        sp!, {r4 - r7, r9, pc}

 

/*

 * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for

 * more information about the __proc_info and __arch_info structures.

 */

   .long          __proc_info_begin

   .long          __proc_info_end

3:         .long          .

   .long          __arch_info_begin

   .long          __arch_info_end

 

它其实就是到__proc_info_begin开始的section中去找到对应当前SOC中用的CPU Cache相关的operation list

再由arch/arm/kernel/vmlinux.lds.S可以__proc_info_begin就是section *(.proc.info.init)的开始地址。

            __proc_info_begin = .;

                   *(.proc.info.init)

            __proc_info_end = .;

而我们知道我们所用是ARM926,所以其定义在arch/arm/mm/proc-arm926.S:

     .section '.proc.info.init', #alloc, #execinstr

     .type       __arm926_proc_info,#object

__arm926_proc_info:

  .long       0x41069260                  @ ARM926EJ-S (v5TEJ)

  .long       0xff0ffff0

  .long   PMD_TYPE_SECT |

         PMD_SECT_BUFFERABLE |

         PMD_SECT_CACHEABLE |

         PMD_BIT4 |

         PMD_SECT_AP_WRITE |

         PMD_SECT_AP_READ

  .long   PMD_TYPE_SECT |

         PMD_BIT4 |

         PMD_SECT_AP_WRITE |

         PMD_SECT_AP_READ

  b     __arm926_setup

  .long       cpu_arch_name

  .long       cpu_elf_name

  .long         HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP|HWCAP_JAVA

  .long       cpu_arm926_name

  .long       arm926_processor_functions

  .long       v4wbi_tlb_fns

  .long       v4wb_user_fns

  .long       arm926_cache_fns

     .size       __arm926_proc_info, . - __arm926_proc_info

arm926_cache_fns定义在同一个文件中,如下:

ENTRY(arm926_cache_fns)

  .long       arm926_flush_kern_cache_all

  .long       arm926_flush_user_cache_all

  .long       arm926_flush_user_cache_range

  .long       arm926_coherent_kern_range

  .long       arm926_coherent_user_range

  .long       arm926_flush_kern_dcache_page

  .long       arm926_dma_inv_range

  .long       arm926_dma_clean_range

  .long       arm926_dma_flush_range

 

它所对应的struct的定义:(include/asm-arm/cacheflush.h)

struct cpu_cache_fns {

  void (*flush_kern_all)(void);

  void (*flush_user_all)(void);

  void (*flush_user_range)(unsigned long, unsigned long, unsigned int);

 

  void (*coherent_kern_range)(unsigned long, unsigned long);

  void (*coherent_user_range)(unsigned long, unsigned long);

  void (*flush_kern_dcache_page)(void *);

 

  void (*dma_inv_range)(const void *, const void *);

  void (*dma_clean_range)(const void *, const void *);

  void (*dma_flush_range)(const void *, const void *);

};

所以其实flush_cache_all 在我们的项目中就是arm926_flush_kern_cache_all:其实现在同一个文件中:

/*

 *   flush_kern_cache_all()

*  Clean and invalidate the entire cache.

 */

ENTRY(arm926_flush_kern_cache_all)

  mov r2, #VM_EXEC

  mov ip, #0

__flush_whole_cache:

#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH

  mcr  p15, 0, ip, c7, c6, 0              @ invalidate D cache

#else

1:      mrc  p15, 0, r15, c7, c14, 3   @ test,clean,invalidate

  bne  1b

#endif

  tst   r2, #VM_EXEC

  mcrne     p15, 0, ip, c7, c5, 0              @ invalidate I cache

  mcrne     p15, 0, ip, c7, c10, 4            @ drain WB

  mov pc, lr

 

最后我们它不仅仅flush 所有的cache(包括ICache和DCache),也flush了Write Buffer。


关键字:Linux  Kernel  ARM平台 引用地址:Linux Kernel之flush_cache_all在ARM平台下是如何实现的

上一篇:ARM、Intel、MIPS处理器啥区别?看完全懂了
下一篇:ARM Linux 3.x的设备树(Device Tree)

推荐阅读最新更新时间:2024-11-12 22:07

今天使用crosstool制作了arm-linux交叉编译工具链
今天使用crosstool制作了arm-linux交叉编译工具链,并且成功编译和运行u-boot-1.3.0。 通过http://www.kegel.com/crosstool/了解crosstool。 要制作的交叉编译工具链版本为3.3.2。 具体步骤如下: 下载crosstool-0.43.tar.gz mkdir /home/wxm/crosstool cp crosstool-0.43.tar.gz /home/wxm/crosstool cd /home/wxm/crosstool tar -jxvf crosstool-0.43.tar.gz mkdir downloads 下载源码包: binuti
[单片机]
基于嵌入式Linux 的I2C设备驱动程序的分析
  0 引言   由于I2C总线的通用性,Linux作为一款优秀的嵌入式操作系统,也必须要对其要有很好的支持。在Linux内核源码中对I2C总线的驱动是基于总线设备驱动模型的,其驱动程序用到了特殊的几个数据结构,对I2C总线协议进行了更抽象更通用的定义,极大的增加了设备驱动的可移植性。要编写出自己的I2C 设备驱动程序,必须对这种内核I2C总线驱动的架构有深刻的理解。   1 I2C总线的硬件构成   I2C 总线协议只有两条总线线路,一条是串行数据线(SDA),一条是串行时钟线(SCL)。SDA 负责数据的传输,SCL 负责数据传输的时钟同步。I2C 设备通过这两条总线连接到处理器的I2C总线控制器上,不同设备之间通过7
[单片机]
基于嵌入式<font color='red'>Linux</font> 的I2C设备驱动程序的分析
建立ARM+Linux运行环境
前一个阶段主要是在Windowsxp下,通过ADS1.2、H-JTAG和DNW来对代码进行编辑和调试。现在转到Linux下,利用RedHat9.0+虚拟机作为开发环境,这里将这两天来对环境的配置及其遇到的问题总结一下。 开发板为GEC2410,在Linux下的环境搭建相对于Windows来说要麻烦一些。原先再Windows下,利用广嵌提供的Bootloader(GEC2410_BIOS_320240.bin)、kernel(zImage-gec2410-linux-2.6.8.tar.bz2)、fs(gec2410_demo.cramfs),能够直接烧写运行,可是将bootloader换成vivi后,对广嵌所提供的内核通
[单片机]
移植MySQL到嵌入式ARM平台
因为MySQL5.5之后,编译是用的cmake不再使用./configure,因此,只好倒回支持./configure的版本来用,这里使用了文档上的5.1.51版本。进行如下步骤完成移植: 1) 下载mysql5.1.51: http://www.mirrorservice.org/sites/ftp.mysql.com/Downloads/MySQL-5.1/mysql-5.1.51.tar.gz 2) 安装编译器:用的是4.3.2的交叉编译器。gcc之类的都是ubuntu10.10自带的。 3) 编译PC版本的mysql备用 a) 解压mysql-5.1.51到/opt/mysql-5.1.51: tar zxv
[单片机]
交叉编译Python-2.7.13到ARM(aarch64)平台
方法跟交叉编译Python-2.7.13到ARM(aarch32)平台基本一样, 不同的地方只是把工具链换成编译aarch64的工具链,这里可以参考用qemu搭建aarch64学习环境. 创建目录: mkdir python2_7_13_for_aarch64 下面是配置、编译和安装的脚本: 1、配置: mk1_conf.sh 1 #!/bin/bash 2 3 export PATH=/home/pengdonglin/src/qemu/aarch64/gcc-linaro-aarch64-linux-gnu-4.9-2014.07_linux/bin:$PATH 4 5 ../Python-2.7.13
[单片机]
从零开始at91sam9263的linux编程----内核编译
内核的编译。 linux的新内核一般功能都会更强大,且都会相对稳定些,所以优选最新版本的内核。现 在最先的内核应该是2.6.34了,不过atmle官网上还没有该版本对应的补丁,所以就使用 2.6.33。 首先从官网下载 linux-2.6.33.tar.bz2和补丁2.6.33-at91.patch 先解压缩linux-2.6.33.tar.bz2,然后打上补丁,如下 # sudo tar xjvf ./linux-2.6.33.tar.bz2 然后 # sudo gunzip 2.6.33-at91.patch.gz gzip: 2.6.33-at91.patch.gz: not in gzip forma
[单片机]
LINUX下使用简单的中断程序使单片机精确计时
在程序开始时需要对定时器及中断寄存器做初始化设置: 对TMOD——定时器/计数器工作方式寄存器赋值,以确定T0和T1的工作方式。 计算初值,并将初值写入TH0,TL0或TH1,TL1。 对IE——中断允许寄存器的EA和ET0或ET1赋值,打开T0或T1。 使TR0或TR1置位,启动定时器/计数器定时或计数。 详细说明如下 一、TMOD是工作方式寄存器,D0~D3是定时器T0,D4~D7是定时器T1。D0~D3含义如下: D0:M0。 D1:M1——M0和M1的四种组合方式决定了定时器/计数器的4种工作方式。当M1=0,M0=1时是16位定时器/计数器。 D2:C/T——定时器模式和计时器模式选择位,1为计数器模式,
[单片机]
linux设备树-按键中断驱动
---------------------------------------------------------------------------------------------------------------------------- 内核版本:linux 5.2.8 根文件系统:busybox 1.25.0 u-boot:2016.05 ---------------------------------------------------------------------------------------------------------------------------- 回到顶部 一、修改设备树
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved