zoukankan      html  css  js  c++  java
  • 跟着韦老师学Linux学习笔记(三)-MMU

    (1)、MMU介绍

             a、权限管理

             不同地址空间的程序是无法相互访问的,否则会发生错误。

             b、地址映射

        老师在视频中关于MMU讲解不是很多,要求也只是了解MMU这个概念就行了,可以参考书上或者下面这个文章了解MMU

             http://www.cnblogs.com/bigbear1385/p/5325344.html

          1、  建立表格,就是建立虚拟地址到物理地址的映射

          2、  把表格地址告诉MMU

          3、  启动MMU

    (2)、程序代码

    首先我们看汇编代码,因为我们的主要程序都在汇编代码里面了。

    .text
    .global _start
    _start:
        ldr sp, =4096                       @ 设置栈指针,以下都是C函数,调用前需要设好栈
        bl  disable_watch_dog               @ 关闭WATCHDOG,否则CPU会不断重启
        bl  memsetup                        @ 设置存储控制器以使用SDRAM
        bl  copy_2th_to_sdram               @ 将第二部分代码复制到SDRAM
        bl  create_page_table               @ 设置页表
        bl  mmu_init                        @ 启动MMU
        ldr sp, =0xB4000000                 @ 重设栈指针,指向SDRAM顶端(使用虚拟地址)
        ldr pc, =0xB0004000                 @ 跳到SDRAM中继续执行第二部分代码
        @ ldr pc, =main
    halt_loop:
        b   halt_loop

    ldr sp, =4096

    bl  disable_watch_dog

    bl  memsetup

    这三句代码和前几集课的功能是一样的,设置栈、关看门狗、初始化SDRAM。

    接下来是拷贝代码到SDRAM里面去,这个代码和之前不太一样,需要涉及到连接脚本的内容。

    1 firtst    0x00000000 : { head.o init.o }
    2 
    3 second    0xB0004000 : AT(2048) { leds.o }

    首先第一段代码是从0x00000000开始的执行的没问题,但是我们的主函数的代码的地址是被放在了2048,并重定位地址为0xB0004000(这个是虚拟地址,在后面需要把它映射到一个物理地址上去)。

     1 void copy_2th_to_sdram(void)
     2 {
     3     unsigned int *pdwSrc  = (unsigned int *)2048;
     4     unsigned int *pdwDest = (unsigned int *)0x30004000;
     5     
     6     while (pdwSrc < (unsigned int *)4096)
     7     {
     8         *pdwDest = *pdwSrc;
     9         pdwDest++;
    10         pdwSrc++;
    11     }
    12 }

    这段代码是拷贝第二段代码到SDRAM里面去,因为第二段代码是从个2048开始的,并且我们的内部RAM只有4096,所以我们把从2048到4096的代码全部拷贝到0x30004000处。并留出0x30000000~0x30004000的地址空间用来存放一级页表的设置内容,一级页表的基地址就是0x30000000。

    设置页表:

    1     virtuladdr = 0;
    2     physicaladdr = 0;
    3     *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | 
    4                                             MMU_SECDESC_WB;

    这几句代码是把物理地址起始位置为0的1M地址空间映射到虚拟地址的起始地址位0的1M地址空间去。

    目的是为了在开启MMU后仍然能够运行第一段代码。

    为什么是1M:因为我们采用的是段描述的页表。

    1     virtuladdr = 0xA0000000;
    2     physicaladdr = 0x56000000;
    3     *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | 
    4                                             MMU_SECDESC;

    这几句代码是把GPIO的起始物理地址为0x56000000的1M地址空间映射到虚拟地址0xA0000000,记住,后面要使用到。

    1     virtuladdr = 0xB0000000;
    2     physicaladdr = 0x30000000;
    3     while (virtuladdr < 0xB4000000)
    4     {
    5         *(mmu_tlb_base + (virtuladdr >> 20)) = (physicaladdr & 0xFFF00000) | 
    6                                                 MMU_SECDESC_WB;
    7         virtuladdr += 0x100000;
    8         physicaladdr += 0x100000;
    9 }

    这里是完全把SDRAM的64M的地址空间完全映射到起始地址为0xB0000000虚拟地址空间里去。

    设置完页表后,接着启动MMU,重设栈指针到SDRAM的顶端。最后跳到0xB0004000里去执行第二段代码。

    不知道是没完全弄懂,还是怎么回事?这节课听的迷迷糊糊的。嘛,以后进入linux后再结合相关内容深入研究一下。

     

  • 相关阅读:
    EF6学习笔记二十五:分布式事务
    EF6学习笔记二十四:事务
    EF6学习笔记二十三:拦截器异常、耗时监控
    EF6学习笔记二十二:初识NLog日志框架
    EF6学习笔记二十一:格式化日志输出
    EF6学习笔记二十:简单日志记录
    EF6学习笔记十九:不一样的复杂类型
    EF6学习笔记十八:DetectChanges
    EF6学习笔记十七:快照追踪与代理追踪性能测试
    EF6学习笔记十六:变更追踪
  • 原文地址:https://www.cnblogs.com/tianhaoyuan/p/6490637.html
Copyright © 2011-2022 走看看