Chinaunix首页 | 论坛 | 博客
  • 博客访问: 55694
  • 博文数量: 9
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 80
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-16 22:03
个人简介

Small thing follow your head, big thing follow your heart.

文章分类

全部博文(9)

文章存档

2015年(4)

2014年(5)

我的朋友

分类: 嵌入式

2015-03-18 17:12:21

MMU,用于虚拟地址和物理地址的转换。当使用mmu时,cpu发出地址给MMU,MMU再转换成物理地址传给存储管理器,再获取需要的信息。
(cpu是不管虚拟地址还是物理地址的,它只管发送给MMU(使用MMU时)或者存储管理器(没有使用MMU时))

实验步骤:

1.建立表格(图片右上角,表格中填写的是物理地址的   起始地址!!!)
2.告诉mmu表格地址
3.运行mmu。


代码步骤:
1.设置栈指针,以调用c函数
2.关闭看门狗
3.设置存储管理控制器(13个寄存器,不懂!!!)
4.复制代码到sdram(事先把部分代码放到片内4k内存的2048处,把这部分代码复制到0x30004000处,此处为sdram的地址,映射为0xb0004000)
5.设置页表(steppingstone一个,sdram一个,gpio寄存器一个,至少三个页表)
6.重新设置栈指针(ldr sp, =0xb4000000,指向sdram的顶端?!!!![改成0xb0000000也可以,底端才是0xb000000吗???])   (不懂!!!!)(实践的结果是:不要这步也可以!!!)
7.跳到sdram中继续执行(ldr pc, =0xb0004000,物理地址为0x30004000)


视频中推荐的书籍:linux内核完全注释(教怎么嵌入汇编到c)

建表代码:(注意映射时,是段映射,就是说最小单位是1m!!!!!!!)
以及开启mmu:

点击(此处)折叠或打开

  1. //设置页表(十分重要,建立三个表:
  2. //steppingstone[片内4k],gpio寄存器,sdram)
  3. void create_page_table(void)
  4. {
  5.     //用于段描述符的一些宏定义(注意时段描述符)
  6. #define MMU_FULL_ACCESS (3 << 10) //访问权限
  7. #define MMU_DOMAIN (0 << 5) //属于哪个域
  8. #define MMU_SPECIAL (1 << 4) //必须是1
  9. #define MMU_CACHEABLE (1 << 3) //cacheable
  10. #define MMU_BUFFERABLE (1 << 2) //bufferable
  11. #define MMU_SECTION (2) //表示这是段描述符

  12. #define MMU_SECDESC (MMU_FULL_ACCESS | MMU_DOMAIN| \
  13.                          MMU_SPECIAL | MMU_SECTION)

  14. #define MMU_SECDESC_WB (MMU_FULL_ACCESS | MMU_DOMAIN | \
  15.                          MMU_SPECIAL | MMU_CACHEABLE | \
  16.                          MMU_BUFFERABLE | MMU_SECTION)

  17. #define MMU_SECTION_SIZE 0x00100000 //1mb

  18.     unsigned long virtuladdr ;
  19.     unsigned long physicaladdr;
  20.     unsigned long *mmu_tlb_base = (unsigned long *)0x30000000;

  21. /*建立steppingstone的表,起始地址(虚拟,物理)都是0*/
  22.     virtuladdr = 0;
  23.     physicaladdr = 0;
  24.     *(mmu_tlb_base + (virtuladdr >> 20))
  25.         = (physicaladdr & 0xfff00000) | MMU_SECDESC_WB; //这句不太懂

  26. /*0x56000000是GPIO寄存器的起始物理地址,对应虚拟地址0xa0000000*/
  27.     virtuladdr = 0xa0000000;
  28.     physicaladdr = 0x56000000;
  29.     //为什么要加上mmu_tlb_base?相当于0?等号后面也不懂.//
  30.     *(mmu_tlb_base + (virtuladdr >> 20))
  31.         = (physicaladdr & 0xfff00000) | MMU_SECDESC; //不太懂;

  32. /*sdram的物理地址范围是:0x30000000~0x33ffffff,*/
  33. /*将虚拟地址0xB0000000 ~ 0xB3ffffff映射到sdram的物理地址*/
  34. /*总共64M,涉及64个段描述符*/

  35.     virtuladdr = 0xb0000000;
  36.     physicaladdr = 0x30000000;

  37.     while (virtuladdr < 0xb4000000)
  38.     {
  39.         *(mmu_tlb_base + (virtuladdr >> 20))
  40.             = (physicaladdr & 0xfff00000 ) | MMU_SECDESC_WB;
  41.         
  42.         virtuladdr += 0x100000;
  43.         physicaladdr += 0x100000;
  44.     }
  45. }


  46. /*启动mmu*/
  47. void mmu_init(void)
  48. {
  49.     unsigned long ttb = 0x30000000;
  50.     
  51.     __asm__
  52.     (
  53.      "mov r0, #0\n"
  54.      "mcr p15, 0, r0, c7, c7, 0\n" //使无效ICaches和DCaches
  55.      "mcr p15, 0, r0, c7, c10, 4\n" /* drain write buffer on v4 */
  56.      "mcr p15, 0, r0, c8, c7, 0\n" /* 使无效指令、数据TLB */
  57.     
  58.     "mov r4, %0\n" /* r4 = 页表基址 */
  59.     "mcr p15, 0, r4, c2, c0, 0\n" /* 设置页表基址寄存器 */
  60.     
  61.     "mvn r0, #0\n"
  62.     "mcr p15, 0, r0, c3, c0, 0\n" /* 域访问控制寄存器设为0xFFFFFFFF,
  63.                                          * 不进行权限检查
  64.                                          */
  65.     /*
  66.      * 对于控制寄存器,先读出其值,在这基础上修改感兴趣的位,
  67.      * 然后再写入
  68.      */
  69.     "mrc p15, 0, r0, c1, c0, 0\n" /* 读出控制寄存器的值 */
  70.     
  71.     /* 控制寄存器的低16位含义为:.RVI ..RS B... .CAM
  72.      * R : 表示换出Cache中的条目时使用的算法,
  73.      * 0 = Random replacement;1 = Round robin replacement
  74.      * V : 表示异常向量表所在的位置,
  75.      * 0 = Low addresses = 0x00000000;1 = High addresses = 0xFFFF0000
  76.      * I : 0 = 关闭ICaches;1 = 开启ICaches
  77.      * R、S : 用来与页表中的描述符一起确定内存的访问权限
  78.      * B : 0 = CPU为小字节序;1 = CPU为大字节序
  79.      * C : 0 = 关闭DCaches;1 = 开启DCaches
  80.      * A : 0 = 数据访问时不进行地址对齐检查;1 = 数据访问时进行地址对齐检查
  81.      * M : 0 = 关闭MMU;1 = 开启MMU
  82.      */
  83.     
  84.     /*
  85.      * 先清除不需要的位,往下若需要则重新设置它们
  86.      */
  87.                                         /* .RVI ..RS B... .CAM */
  88.     "bic r0, r0, #0x3000\n" /* ..11 .... .... .... 清除V、I位 */
  89.     "bic r0, r0, #0x0300\n" /* .... ..11 .... .... 清除R、S位 */
  90.     "bic r0, r0, #0x0087\n" /* .... .... 1... .111 清除B/C/A/M */

  91.     /*
  92.      * 设置需要的位
  93.      */
  94.     "orr r0, r0, #0x0002\n" /* .... .... .... ..1. 开启对齐检查 */
  95.     "orr r0, r0, #0x0004\n" /* .... .... .... .1.. 开启DCaches */
  96.     "orr r0, r0, #0x1000\n" /* ...1 .... .... .... 开启ICaches */
  97.     "orr r0, r0, #0x0001\n" /* .... .... .... ...1 使能MMU */
  98.     
  99.     "mcr p15, 0, r0, c1, c0, 0\n" /* 将修改的值写入控制寄存器 */
  100.     : /* 无输出 */
  101.     : "r" (ttb)
  102.      );
  103. }

阅读(2777) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~