十三、S3C2440 裸机 — 初始化代码及MMU

发布时间:2023-07-11  

13.1 NOR FLASH 搬运

  • 把程序从 nor flash 上搬运到 SDRAM 中

    • 程序存储在 nor flash 上,运行时将程序搬运到 SDRAM 中运行

  • nor flash 启动:nor flash 的地址从 0x0000 0000 开始,CPU 可以直接在 nor flash 上运行程序

    • 在 nor flash 上运行程序很慢

  • SDRAM:地址为 0x3000 0000,程序烧录在 nor flash 上,运行时,将 nor flash 上的代码搬运至 SDRAM 中运行

  • nor flash 启动:

    • 初始化寄存器

    • 关闭看门狗

    • 设置存储控制器

    • 复制代码到 SDRAM 中

    • 跳转 main 运行:使用 BL MAIN,跳转到 main 函数中运行的时候属于相对跳转,若使用 BL 指令,则 main 函数的地址时相对于 nor flash 的基地址的地址,而 SDRAM 的基地址是 0x30000000,当代码搬运到 SDRAM 中之后,程序跳转不到 main。因此要设置栈,并使用 LDR 跳转

  •  代码与前面 SDRAM 中的代码一样,搬运代码就是 COPYING 开头的代码

13.2 MMU介绍

13.2.1 MMU 特性

  内存管理单元(Memory Management Unit)简称MMU,它负责虚拟地址到物理地址的映射,并提供硬件机制的内存访问权限检查。现在的多用户多进程操作系统通过 MMU 使得各个用户进程都拥有自己独立的地址空间。

  地址映射功能使得各进程拥有“看起来”一样的地址空间,内存访问权限的检查可以保护每个进程所用的内存不会被其他进程破坏。

  S3C2440/2410 有如下特性:

  • 与 ARM V4 兼容的映射长度、域、访问权限检查机制

  • 4种映射长度:段(1MB)、大页(64KB)、小页(4KB)、极小页(1KB)

  • 对每段都可以设置访问权限

  • 大页、小页的每个子页(sub-page,即被映射页的 1/4)都可以单独设置访问权限

  • 硬件实现的 16 个域

  • 指令 TLB(含 64 个条目)、数据TLB(含64个条目)

  • 硬件访问页表(地址映射、权限检查由硬件自动进行)

  • TLB 中条目的替换采用 round-robin 算法(也称 cyclic 算法)

  • 可以使无效整个 TLB

  • 可以单独使无效某个 TLB 条目

  • 可以在 TLB 中锁定某个条目,指令 TLB、数据TLB 相互独立  

  一个程序在运行之前,没由必要全部装入内存,而仅需要将那些当前要运行的部分先装入内存,其余部分在用到的时候再从磁盘调入,而当内存耗光时再将暂时不用的部分调出到磁盘。

  再 32 位的CPU系统中,虚拟内存地址范围位 0~ 0xFFFFFFFF,这个地址范围称为虚拟地址空间,其中的某个地址称为虚拟地址。

  与虚拟地址空间、虚拟地址对应的使物理地址空间、物理地址,他们对应实际的内存

  虚拟地址最终需要转换为物理地址才能读写实际的数据,这通过将虚拟地址空间、物理地址空间划分为同样大小的一块块小空间(称为段或页),然后为这两类小空间建立映射关系。由于虚拟地址空间远大于物理空间,有可能多块虚拟地址空间映射到同一块物理地址空间,或者有些虚拟地址空间没有映射到具体的物理地址空间上去(可以在使用到时再映射)。

  • ARM CPU 上的地址转换过程的三个概念

    • VA:Virtual Address,虚拟地址

    • MVA:Modified Virtual Address,变换后的虚拟地址

    • PA:Physical Address,物理地址

  未启动 MMU 时,CPU核、cache、MMU、外设等所有部件使用的都使物理地址

  启动MMU后,CPU核对外发出虚拟地址VA;VA被转换为MVA供cache、MMU使用,再这里 MVA 被转换为 PA;最后使用PA读写实际设备:

  1. CPU核看到的、用到的只是虚拟地址 VA,至于 VA如何最终落实到物理地址 PA 上,CPU核使不理会的

  2. caches 和 MMU 也是看不见 VA 的,他们利用由 MVA 转换得到 PA

  3. 实际设备看不到 VA、MVA,读写它们时使用的是物理地址PA

  MVA 是除 CPU 核外的其他部分看见的虚拟地址

  

13.2.2 地址映射过程

  

  将一个虚拟地址转换为物理地址,由两个办法,用一个确定的数学公式进行转换或用表格存储虚拟地址对应的物理地址。这类表格称为页表(Page table),页面由一个个条目(Entry)组成;每个条目存储了一段虚拟地址对应的物理地址及其访问权限,或者下一级页表的地址。ARM CPU 中使用的是表格。

  S3C2440/2410 最多用到两级页表:以段(Section,1MB)的方式进行转换时只用到一级页表,以页(Page)的方式进行转换时用到两级页表。

  页的大小由 3 种,大页(64KB)、小页(4KB)、极小页(1KB)。

  条目也称为”描述符“(Descriptor),有段描述符、大页描述符、小页描述符、极小页描述符,主要是用来保存相应的段或页的起始物理地址;粗页描述符、细页描述符用来保存二级页表的物理地址。

  转换过程为:

  1. 根据给定的虚拟地址找到一级页表中的条目

  2. 如果此条目是段描述符,则返回物理地址,转换结束

  3. 否则如果此条目是二级页表描述符,继续利用虚拟地址在此二级页表中找到下一个条目

  4. 如果这第二个条目是页描述符,则返回物理地址,转换结束

  5. 其他情况出错

  

  TTB base 代表一级页表的地址,将它写入协处理器 CP15 的寄存器 C2(称为页表基址寄存器)即可。

13.2.3 权限管理 

  MMU对段和页面进行保护,对段和页面进行保护是由几个因素造成的。它由域的访问控制字段和一级描述符或二级描述符中的 AP 字段,以及 C1 寄存器的 S(表示system),R(表示rom)控制位来共同决定的。
  MMU中的域是指的一些段,大页或者小页的集合。ARM支持最多16个域,每个域的访问控制特性由 CP15 中的寄存器 C3 中的两位来控制。CP15 中的寄存器 C3 的格式如下:

  

   其中每两位控制一个域的访问控制特性,其编码及对应的含义如下:

  

  • 当控制位为00时,此域是没有访问权限的;

  • 当控制位为01时,此时域的属性为“用户”域;

    • 当其域为“用户”域时,存储访问权限控制由AP,S,R来决定。

  • 当控制位为11时,此时域的属性为“系统”域。

    • 当其域为“系统”域时,AP,S,R 的值将会忽略,CPU(无论cpu运行在用户级还是在特权级)可以直接访问存储内容,将不进行存储权限检查。

  当域为“用户”域时,AP,S,R控制访问权限的具体规则如下:

  

  当域为“用户”域时,当CPU运行在“特权级”或“用户级”时,AP,S,R 控制段或页的存储访问权限;

  比如:

  当域为“用户”域时,当CPU运行在“用户级”时,AP=00,S=1,R=0,查表可知,这时CPU没有访问权限;

  当域为“用户”域时,当CPU运行在“特权级”时,AP=00,S=1,R=0,这里CPU只能读存储内容,但不能写,如果写的话将产生错误;

  注意:AP,S,R的决定访问权限的作用只用是在其域为“用户”域的状态。

13.2.3 编程地址映射

  CPU核只关心 发出地址、读写数据,至于是否是虚拟地址还是物理地址,CPU不关心,至于是什么地址,是后面的设备关心的

  写程序的时候的链接地址,也是没有物理地址和虚拟地址之分,只是单纯的地址,链接地址是CPU看到的

  • MMU 操作:

    • 建立地址映射表格,即建立虚拟地址到物理地址的映射

    • 把表格地址告诉 MMU,即把内存地址告诉 MMU

    • 启动MMU

  mmu.lds

1 SECTIONS { 

2   firtst    0x00000000 : { head.o init.o }

3   second    0xB0004000 : AT(2048) { leds.o }

4 } 

  head.S


 1 @*************************************************************************

 2 @ File:head.S

 3 @ 功能:设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU,

 4 @       然后跳到SDRAM继续执行

 5 @*************************************************************************       

 6 

 7 .text

 8 .global _start

 9 _start:

10     ldr sp, =4096                       @ 设置栈指针,以下都是C函数,调用前需要设好栈,指向 SRAM 的顶端

11     bl  disable_watch_dog               @ 关闭WATCHDOG,否则CPU会不断重启

12     bl  memsetup                        @ 设置存储控制器以使用SDRAM

13     bl  copy_2th_to_sdram               @ 将第二部分代码复制到SDRAM

14     bl  create_page_table               @ 设置页表

15     bl  mmu_init                        @ 启动MMU

16     ldr sp, =0xB4000000                 @ 重设栈指针,指向SDRAM顶端(使用虚拟地址)

17     ldr pc, =0xB0004000                 @ 跳到SDRAM中继续执行第二部分代码

18 halt_loop:

19     b   halt_loop


  init.c


  1 /*

  2  * init.c: 进行一些初始化,在Steppingstone中运行

  3  * 它和head.S同属第一部分程序,此时MMU未开启,使用物理地址

  4  */ 

  5 

  6 /* WATCHDOG寄存器 */

  7 #define WTCON           (*(volatile unsigned long *)0x53000000)

  8 /* 存储控制器的寄存器起始地址 */

  9 #define MEM_CTL_BASE    0x48000000

 10 

 11 

 12 /*

 13  * 关闭WATCHDOG,否则CPU会不断重启

 14  */

 15 void disable_watch_dog(void)

 16 {

 17     WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可

 18 }

 19 

 20 /*

 21  * 设置存储控制器以使用SDRAM

 22  */

 23 void memsetup(void)

 24 {

 25     /* SDRAM 13个寄存器的值 */

 26     unsigned long  const    mem_cfg_val[]={ 0x22011110,     //BWSCON

 27                                             0x00000700,     //BANKCON0

 28                                             0x00000700,     //BANKCON1

 29                                             0x00000700,     //BANKCON2

 30                                             0x00000700,     //BANKCON3  

 31                                             0x00000700,     //BANKCON4

 32                                             0x00000700,     //BANKCON5

 33                                             0x00018005,     //BANKCON6

 34                                             0x00018005,     //BANKCON7

 35                                             0x008C07A3,     //REFRESH

 36                                             0x000000B1,     //BANKSIZE

 37                                             0x00000030,     //MRSRB6

 38                                             0x00000030,     //MRSRB7

 39                                     };

 40     int     i = 0;

 41     volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

 42     for(; i < 13; i++)

 43         p[i] = mem_cfg_val[i];    //32位CPU中,指针移动一次是4个字节

 44 }

 45 

 46 /*

 47  * 将第二部分代码复制到SDRAM

 48  */

 49 void copy_2th_to_sdram(void)

 50 {

 51     unsigned int *pdwSrc  = (unsigned int *)2048;      //链接脚本中指定了 led.o 的存放的地址为 2048

 52     unsigned int *pdwDest = (unsigned int *)0x30004000;  // led.o 存放在 SDRAM 中的地址 

 53     

 54     while (pdwSrc < (unsigned int *)4096)

 55     {

 56         *pdwDest = *pdwSrc;

 57         pdwDest++;

 58         pdwSrc++;

 59     }

 60 }

 61 

 62 /*

 63  * 设置页表

 64  */

 65 void create_page_table(void)

 66 {

 67 

 68 /* 

 69  * 用于段描述符的一些宏定义

 70  */ 

 71 #define MMU_FULL_ACCESS     (3 << 10)   /* 访问权限 */

 72 #define MMU_DOMAIN          (0 << 5)    /* 属于哪个域 */

 73 #define MMU_SPECIAL         (1 << 4)    /* 必须是1 */

 74 #define MMU_CACHEABLE       (1 << 3)    /* cacheable */

 75 #define MMU_BUFFERABLE      (1 << 2)    /* bufferable */

 76 #define MMU_SECTION         (2)         /* 表示这是段描述符 */

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>