BootLoader—vivi注释

合集下载

bootloader代码解析

bootloader代码解析

GET ..\inc\option.s //相当于c语言中的#include "option.s"GET ..\inc\memcfg.s;Interrupt Control //中断控制器的特殊功能寄存器对应的地址INTPND EQU 0x01e00004INTMOD EQU 0x01e00008INTMSK EQU 0x01e0000cI_ISPR EQU 0x01e00020I_CMST EQU 0x01e0001c;Watchdog timer //看门狗定时器WTCON EQU 0x01d30000;Clock Controller //时钟控制器PLLCON EQU 0x01d80000CLKCON EQU 0x01d80004LOCKTIME EQU 0x01d8000c;Memory Controller //内存控制器REFRESH EQU 0x01c80024 ;Dram/sdram刷新控制寄存器;Pre-defined constants //预定义的常量;下面是对arm处理器模式寄存器对应值的常数定义,arm处理器中有一个CPSR程序状态寄存器它的后五位决定目前的处理器模式;0b10000用户模式;0b10001FIQ模式等USERMODE EQU 0x10FIQMODE EQU 0x11IRQMODE EQU 0x12SVCMODE EQU 0x13ABORTMODE EQU 0x17UNDEFMODE EQU 0x1bMODEMASK EQU 0x1fNOINT EQU 0xc0;arm处理器有两种工作状态 1.arm:32位这种工作状态下执行字对准的arm指令 2.Thumb:16位这种工作状态执行半字对准的Thumb指令;因为处理器分为16位 32位两种工作状态程序的编译器也是分16位和32两种编译方式所以下面的程序用于根据处理器工作状态确定编译器编译方式;code16伪指令指示汇编编译器后面的指令为16位的thumb指令;code32伪指令指示汇编编译器后面的指令为32位的arm指令;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译);check if tasm.exe is used.GBLL THUMBCODE ;设置一个全局逻辑变量[ {CONFIG} = 16THUMBCODE SETL {TRUE}CODE32|THUMBCODE SETL {FALSE}];if config==16 这里表示你的目前处于领先地16位编译方式,设置THUMBCODE 为 true,否则就转入32位编译模式,设置THUMBCODE 为 false[ THUMBCODECODE32 ;for start-up code for Thumb mode]注意下面这段程序是个宏定义;这段程序用于把中断服务程序的首地址装载到pc中,有人称之为“加载程序”。

Bootloader的学习

Bootloader的学习

Bootloader 的学习/user1/5809/archives/2009/60942.htmlBootload: 在操作系统内核运行前运行的一段程序,相当于PC机上的BIOS, 用于初始化硬件设备,和建立内存空间的映射,从而将系统的软硬件环境带到一个合适的状态。

复位后,从地址0x 0000 0000 处取它第一条指令。

典型的嵌入式系统Bootload 有 Blob (boot load object) 和 U-boot (universal boot loader)其中U-boot 支持ARM, MIPS, X86, Nios,可启动VxWorks,QNX,Linux在flash里,首先存放bootload, 其次启动参数,是内核和根文件系统bootloader分两个部分,stage1和stage2:stage1: 汇编部分执行简单的硬件初始化.1. 硬件设备初始化2. 为加载bootloader的stage2准备RAM空间3. 设置好堆栈4. 跳转到stage2的C入口stage2: C语言部分负责复制数据,设置启动参数和串口通信等1. 初始化本阶段使用到的硬件设备2. 检测系统内存映像3. 将kernel映像和根文件映像从flash读到RAM中4. 为内核设置启动参数5. 调用内核------------------------------------Mini2440 的Bootloader 结构分析1.Import some head files.GET option.inc ;GET = includeGET memcfg.incGET 2440addr.incoption.inc 顾名思义是可以改变的配置选项,其中包括一些起始地址,初始状态,总线宽度,时钟频率。

如果以后对系统的设置有变化,直接修改”option.inc”中的配置即可,无需大量改动boot loader.对mini2440中option.inc分析如下:_STACK_BASEADDRESS EQU 0x33ff8000; STACK 的起始地址_MMUTT_STARTADDRESS EQU 0x33ff8000; 定义MMU表基地址_ISR_STARTADDRESS EQU 0x33ffff00;补充MMU知识:a.什么是MMUMMU –Memory Management Unit 缩写,用来管理virtual memory和physical memory的控制线路。

嵌入式课后习题答案

嵌入式课后习题答案
Vivi是Mizi公司针对SAMSUNG的ARM架构CPU专门设计的,基本上可以直接使用,命令简单方便。不过其初始版本只支持串口下载,速度较慢。在网上出现了各种改进版本:支持网络功能、USB功能、烧写YAFFS文件系统映象等。
第八章
一、填空题。
1、Makefile、配置文件、配置工具。
2、配置命令解释器、配置用户界面。
arch:arch目录包括了所有和体系结构相关的核心代码。include:include目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下;init:init目录包含核心的初始化代码(不是系统的引导代码),有main.c和Version.c两个文件;mm:mm目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下;drivers:drivers目录中是系统中所有的设备驱动程序。它又进一步划分成几类设备驱动,每一种有对应的子目录,如声卡的驱动对应于drivers/sound;ipc:ipc目录包含了核心进程间的通信代码;modules:modules目录存放了已建好的、可动态加载的模块;fs:fs目录存放Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext3文件系统对应的就是ext3子目录;Kernel:Kernel内核管理的核心代码放在这里。同时与处理器结构相关代码都放在arch/*/kernel目录下;net:net目录里是核心的网络部分代码,其每个子目录对应于网络的一个方面;lib:lib目录包含了核心的库代码,不过与处理器结构相关的库代码被放在arch/*/lib/目录下;scripts:scripts目录包含用于配置核心的脚本文件;documentation:documentation目录下是一些文档,是对每个目录作用的具体说明。

天津科技大学嵌入式操作系统---第3章 基于linux的嵌入式软件开发

天津科技大学嵌入式操作系统---第3章 基于linux的嵌入式软件开发
3.1.1 嵌入式软件体系结构 3.1.2 基于Linux的嵌入式软件
18:19
4
3.1.1 嵌入式软件体系结构
18:19
5
1. 设备驱动层
设备驱动层是嵌入式系统中必不可少的重 要部分,使用任何外部设备都需要有相应 驱动程序的支持,它为上层软件提供了设 备的操作接口。 上层软件不用理会设备的具体内部操作, 只需调用驱动层程序提供的接口即可。 驱动层一般包括硬件抽象层HAL、板级支 持包BSP和设备驱动程序。
18
3.2.2 基于开发板的二次开发
所谓二次开发是利用现成的开发板进行开发,不同于通用 计算机和工作站上的软件开发工程,一个嵌入式软件的开 发过程具有很多特点和不确定性。其中最重要的一点是软 件跟硬件的紧密耦合特性。 由于嵌入式系统的灵活性和多样性,这样就给软件设计人 员带来了极大地困难。第一,在软件设计过程中过多地考 虑硬件,给开发和调试都带来了很多不便;第二,如果所 有的软件工作都需要在硬件平台就绪之后进行,自然就延 长了整个的系统开发周期。这些都是应该从方法上加以改 进和避免的问题。 为了解决这个问题,通常的做法是基于某种开发板做二次 开发,从这个角度看,硬件开发所占的比重不到20%,而 软件开发的比重占到了80%。
3.1 嵌入式软件结构 3.2 嵌入式软件开发流程 3.3 嵌入式linux开发环境 3.4 嵌入式系统引导代码 3.5 linux内核结构及移植 3.6 嵌入式文件系统及移植 3.7 linux设备驱动概述 3.8 设备驱动程序接口 3.9 linux设备驱动开发流程
18:19 3
3.1 嵌入式软件结构
?在嵌入式开发中经常要面对设备驱动程序的开发嵌入式系统通常有许多设备用于与用户交互象触摸屏小键盘滚动轮传感器在嵌入式开发中经常要面对设备驱动程序的开发嵌入式系统通常有许多设备用于与用户交互象触摸屏小键盘滚动轮传感器rs232接口lcd等等

S3C2410完全开发流程

S3C2410完全开发流程

S3C2410完全开发流程作者:thisway.diy@ 一.简介 (2)二.建立开发环境 (3)(1)编译器arm-linux-gcc-3.4.1 (3)(2)Jflash-s3c2410:S3C2410芯片的JTAG工具 (3)(3)安装gdb调试工具 (3)三.S3C2410基础实验 (4)(1)实验一:LED_ON (4)(2)实验二:LED_ON_C (5)(3)实验三:I/O PORTS (7)(4)实验四:arm-linux-ld (9)(5)实验五:MEMORY CONTROLLER (10)(6)实验六:NAND FLASH CONTROLLER (13)(7)实验七:UART (15)(8)实验八:printf、scanf (18)(9)实验九:INTERRUPT CONTROLLER (19)(10)实验十:TIMER (23)(11)实验十一:MMU (25)(12)实验十二:CLOCK (33)四.Bootloader vivi (36)(1)阶段1:arch/s3c2410/head.S (36)(2)阶段2:init/main.c (37)1、Step 1:reset_handler() (38)2、Step 2:board_init() (39)3、Step 3:建立页表和启动MMU (39)4、Step 4:heap_init() (42)5、Step 5:mtd_dev_init() (44)6、Step 6:init_priv_data() (49)7、Step 7:misc()和init_builtin_cmds() (50)8、Step 8:boot_or_vivi() (51)一.简介本书面向由传统51单片机转向ARM嵌入式开发的硬件工程师、由硬件转嵌入式软件开发的工程师、没有嵌入式开发经验的软件工程师。

分9个部分:1、开发环境建立2、S3C2410功能部件介绍与实验(含实验代码)3、bootloader vivi详细注释4、linux移植5、linux驱动6、yaffs文件系统详解7、调试工具8、GUI开发简介9、UC/OS移植通过学习第二部分,即可了解基于ARM CPU的嵌入式开发所需要的外围器件及其接口。

2440超详细U-BOOT(UBoot介绍+H-jtag使用+Uboot使用)

2440超详细U-BOOT(UBoot介绍+H-jtag使用+Uboot使用)

凌FL2440超详细U-BOOT作业(UBoot介绍+H-jtag使用+Uboot使用)Bootloader是高端嵌入式系统开发不可或缺的部分。

它是在操作系统内核启动之前运行的一段小程序。

通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。

现在主流的bootloader有U-BOOT、vivi、Eboot等。

本次作业先做Uboot的烧写吧。

希望通过这个帖子,能让更多的初学者朋友了解一些UBoot的知识,也希望高手朋友对我的不足予以斧正。

首先说一下什么是Uboot:U-Boot,全称Universal Boot Loader,是遵循GPL条款的开放源码项目。

从FAD SROM、8xxROM、PPCBOOT逐步发展演化而来。

其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是相应的Linux内核源程序的简化,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。

但是U-Boot不仅仅支持嵌入式Linu x系统的引导,当前,它还支持NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式操作系统。

其目前要支持的目标操作系统是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS。

这是U-Boot中Universal的一层含义,另外一层含义则是U-Boot除了支持PowerPC系列的处理器外,还能支持MIPS、x86、ARM、NIOS、XScale等诸多常用系列的处理器。

这两个特点正是U-Boot项目的开发目标,即支持尽可能多的嵌入式处理器和嵌入式操作系统。

vivi中调用mtd_dev_init函数初始化Flash为MTD设备函数调用结构

vivi中调用mtd_dev_init函数初始化Flash为MTD设备函数调用结构
鲁东大学 LUDONG UNIVERSITY
第一阶段
基本硬件设备初始化 为第二阶段准备RAM空间 复制BootLoader第二阶段代码到RAM 堆栈设置 跳转至第二阶段的C程序入口
BootLoader vivi第二阶段
鲁东大学 LUDONG UNIVERSITY
vivi第二阶段
—C语言编写的一个main()函数 共包括8个步骤
Next
vivi第二阶段代码(2)
鲁东大学 LUDONG UNIVERSITY
/*Step 4*/ Step4 堆初始化 ret = heap_init(); if (ret) { putstr("Failed initailizing heap region\r\n"); error(); } Step5 mtd设备初始化 /*Step 5*/ ret = mtd_dev_init(); /*Step 6*/ Step6 私有数据初始化 init_priv_data(); /*Step 7*/ Step7 vivi命令初始化 misc(); init_builtin_vivi_cmds(); / /*Step 8*/ Step8 启动os 或者 vivi-shell boot_or_vivi(); return 0; }
main() mem_map_init() mem_map_nand_boot() mem_mapping_linear() mem_map_nor()
cache_clean_invalidate tlb_invalidate
源码 mmu.c
vivi第二阶段 步骤3
鲁东大学 LUDONG UNIVERSITY
vivi第一阶段 head.s
… bl main

广州友善之臂 SBC-2410X 说明书 Version0.9

广州友善之臂 SBC-2410X 说明书 Version0.9

SBC-2410X使用手册Version0.9广州友善之臂科技有限公司二零零四年十月(请拿到板子后请务必先阅读说明书,谨防随意破坏系统启动程序bootloader(vivi)修正2. 第145页:添加ld.so.conf内容(2004-11-1)1. 页眉的“祝您一臂之力”改为“助您一臂之力”(2004-11-1)前言SBC-2410X是由广州友善之臂科技有限公司设计生产的一款基于ARM9的嵌入式电脑平台,它基于三星公司的ARM处理器S3C2410X,采用6层板设计。

S3C2410X使用ARM920T核,内部带有全性能的MMU(内存处理单元),它适用于设计移动手持设备类产品,具有高性能、低功耗、接口丰富和体积小等优良特性。

SBC-2410X正是基于此芯片本身的各种特点而设计的。

SBC-2410X的设计遵循了S3C2410X嵌入式芯片的特点,其设计理念参考了当前市场上众多的开发板及嵌入式单板机的优点,并融入最新掌上电脑/手持设备的特点,因此是一款单板机和开发板两用的嵌入式电脑平台。

侧面复位按键的设计位置恰到好处,不会阻挡用户罩在板上的面板;板载采用高质量进口按键,手感特别舒适,经久耐用,而且用户可以随心所欲设计自己的键盘外观,而不需要修改驱动程序;精致的1220型板载备份电池更可以保持时间随时随地准确无误;20针的标准JTAG接口让您可以方便的连接各种仿真器;SD卡、各种优盘移动硬盘、音频输入输出、串口、RJ-45网线等即插即用;定位孔的设计参考了市面上大量的液晶屏模块尺寸,用户可以使用现成的或者设计自己的液晶模块,扣在板上,完全就是一个标准的PDA。

你可以使用套件提供的各种开发工具按照自己的意图或需要设计各种各样的应用程序,而我们的网站也提供了很多精彩的应用制作实例供您参考,这些实例均有映象文件可以下载演示;整个板子的尺寸只有120mmx90mm,这仅相当于一个普通PDA的大小。

基于以往我们的产品反馈意见,SBC-2410X进行了严格的电磁,温度,高压脉冲,老化,灰尘等测试,性能稳定,可代替部分工控单板机。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

s3c2410 bootloader vivi完全注释四.Bootloader vivi 为了将linux移植到ARM上,碰到的第一个程序就是bootloader,我选用韩国mizi公司的vivi。

您可以在以下地址下载:/developer/s3c2410x/download/vivi.html如果您对bootloader没有什么概念,在学习VIVI的代码之前,建议您阅读一篇文章《嵌入式系统 Boot Loader 技术内幕》(詹荣开著)。

链接地址如下:/developerworks/cn/linux/l-btloader/当您阅读了上述文章后,我再企图在理论上罗嗦什么就不合适了(这篇文章实在太好了)。

vivi也可以分为2个阶段,阶段1的代码在 arch/s3c2410/head.S 中,阶段2的代码从init/main.c的main函数开始。

您可以跳到实验部分先感受一下vivi。

(1)阶段1:arch/s3c2410/head.S 沿着代码执行的顺序,head.S完成如下几件事情:1、关WATCH DOG:上电后,WATCH DOG默认是开着的2、禁止所有中断:vivi中没用到中断(不过这段代码实在多余,上电后中断默认是关闭的)3、初始化系统时钟:启动MPLL,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz,“CPU bus mode”改为“Asynchronous bus mode”。

请参考实验十一:CLOCK4、初始化内存控制寄存器:还记得那13个寄存器吗?请复习实验五:MEMORY CONTROLLER5、检查是否从掉电模式唤醒,若是,则调用WakeupStart函数进行处理——这是一段没用上的代码,vivi不可能进入掉电模式6、点亮所有LED7、初始化UART0:a.设置GPIO,选择UART0使用的引脚b.初始化UART0,设置工作方式(不使用FIFO)、波特率115200 8N1、无流控等,请参考实验七:UART8、将vivi所有代码(包括阶段1和阶段2)从nand flash复制到SDRAM中:a.设置nand flash控制寄存器b.设置堆栈指针——调用C函数时必须先设置堆栈c.设置即将调用的函数nand_read_ll的参数:r0=目的地址(SDRAM的地址),r1=源地址(nand flash的地址),r2=复制的长度(以字节为单位)d.调用nand_read_ll进行复制e.进行一些检查工作:上电后nand flash最开始的4K代码被自动复制到一个称为“Steppingstone”的内部RAM中(地址为0x00000000-0x00001000);在执行nand_read_ll之后,这4K代码同样被复制到SDRAM中(地址为0x33f00000-0x33f01000)。

比较这两处的4K代码,如果不同则表示出错9、跳到bootloader的阶段2运行——就是调用init/main.c中的main函数:a.重新设置堆栈b.设置main函数的参数c.调用main函数如果您做了第二章的各个实验,理解head.S就不会有任何困难——上面说到的几个步骤,都有相应的实验。

head.S有900多行,把它搬到这篇文章上来就太不厚道了——白白浪费页数而已。

在vivi/arch/s3c2410/head.S上,我做了比较详细的注释(其中的乱码可能是韩文,不去管它)。

(2)阶段2:init/main.c 本阶段从init/main.c中的main函数开始执行,它可以分为8个步骤。

我先把main函数的 肼蘖腥缦?去掉了乱码——可能是韩文,现在没留下多少有用的注释了),然后逐个分析:1 int main(int argc, char *argv[])2 {3 int ret;4 /*Step 1*/5 putstr("\r\n");6 putstr(vivi_banner);7 reset_handler();8 /*Step 2*/9 ret = board_init();10 if (ret) {11 putstr("Failed a board_init() procedure\r\n");12 error();13 }14 /*Step 3*/15 mem_map_init();16 mmu_init();17 putstr("Succeed memory mapping.\r\n");18 /* Now, vivi is running on the ram. MMU is enabled.*/19 /*Step 4*/20 /* initialize the heap area */21 ret = heap_init();22 if (ret) {23 putstr("Failed initailizing heap region\r\n");24 error();25 }26 /*Step 5*/27 ret = mtd_dev_init();28 /*Step 6*/29 init_priv_data();30 /*Step 7*/31 misc();32 init_builtin_cmds();33 /*Step 8*/34 boot_or_vivi();35 return 0;36 }1、Step 1:reset_handler() reset_handler用于将内存清零,代码在lib/reset_handle.c中。

[main(int argc, char *argv[]) > reset_handler()]1 void2 reset_handler(void)3 {4 int pressed;5 pressed = is_pressed_pw_btn(); /*判断是硬件复位还是软件复位*/6 if (pressed == PWBT_PRESS_LEVEL) {7 DPRINTK("HARD RESET\r\n");8 hard_reset_handle(); /*调用clear_mem对SDRAM清0*/9 } else {10 DPRINTK("SOFT RESET\r\n");11 soft_reset_handle(); /*此函数为空*/12 }13 }在上电后,reset_handler调用第8行的hard_reset_handle(),此函数在lib/reset_handle.c中:[main(int argc, char *argv[]) > reset_handler() > hard_reset_handle()]1 static void2 hard_reset_handle(void)3 {4 #if 05 clear_mem((unsigned long)(DRAM_BASE + VIVI_RAM_ABS_POS), \6 (unsigned long)(DRAM_SIZE - VIVI_RAM_ABS_POS));7 #endif8 /*lib/memory.c,将起始地址为USER_RAM_BASE,长度为USER_RAM_SIZE 的内存清0*/9 clear_mem((unsigned long)USER_RAM_BASE, (unsignedlong)USER_RAM_SIZE);10 }2、Step 2:board_init() board_init调用2个函数用于初始化定时器和设置各GPIO引脚功能,代码在arch/s3c2410/smdk.c中:[main(int argc, char *argv[]) > board_init()]1 int board_init(void)2 {3 init_time(); /*arch/s3c2410/proc.c*/4 set_gpios(); /*arch/s3c2410/smdk.c*/5 return 0;6 }init_time()只是简单的令寄存器TCFG0 = 0xf00,vivi未使用定时器,这个函数可以忽略。

set_gpios()用于选择GPA-GPH端口各引脚的功能及是否使用各引脚的内部上拉电阻,并设置外部中断源寄存器EXTINT0-2(vivi中未使用外部中断)。

3、Step 3:建立页表和启动MMU mem_map_init函数用于建立页表,vivi使用段式页表,只需要一级页表。

它调用3个函数,代码在arch/s3c2410/mmu.c 中:[main(int argc, char *argv[]) > mem_map_init(void)]1 void mem_map_init(void)2 {3 #ifdef CONFIG_S3C2410_NAND_BOOT /* CONFIG_S3C2410_NAND_BOOT=y */4 mem_map_nand_boot(); /* 最终调用mem_mepping_linear,建立页表 */5 #else6 mem_map_nor();7 #endif8 cache_clean_invalidate(); /* 清空cache,使无效cache */9 tlb_invalidate(); /* 使无效快表TLB */10 }第9、10行的两个函数可以不用管它,他们做的事情在下面的mmu_init函数里又重复了一遍。

对于本开发板,在.config中定义了CONFIG_S3C2410_NAND_BOOT。

mem_map_nand_boot()函数调用mem_mapping_linear()函数来最终完成建立页表的工作。

页表存放在SDRAM物理地址0x33dfc000开始处,共16K:一个页表项4字节,共有4096个页表项;每个页表项对应 1M地址空间,共4G。

mem_map_init先将4G虚拟地址映射到相同的物理地址上,NCNB(不使用cache,不使用write buffer)——这样,对寄存器的操作跟未启动MMU时是一样的;再将SDRAM对应的64M空间的页表项修改为使用cache。

mem_mapping_linear函数的代码在arch/s3c2410/mmu.c中:[main(int argc, char *argv[]) > mem_map_init(void) >mem_map_nand_boot( ) > mem_mapping_linear(void)]1 static inline void mem_mapping_linear(void)2 {3 unsigned long pageoffset, sectionNumber;4 putstr_hex("MMU table base address = 0x", (unsignedlong)mmu_tlb_base);5 /* 4G 虚拟地址映射到相同的物理地址. not cacacheable, not bufferable */6 /* mmu_tlb_base = 0x33dfc000*/7 for (sectionNumber = 0; sectionNumber < 4096; sectionNumber++) {8 pageoffset = (sectionNumber << 20);9 *(mmu_tlb_base + (pageoffset >> 20)) = pageoffset |MMU_SECDESC;10 }11 /* make dram cacheable */12 /* SDRAM物理地址0x3000000-0x33ffffff,13 DRAM_BASE=0x30000000,DRAM_SIZE=64M14 */15 for (pageoffset = DRAM_BASE; pageoffset < (DRAM_BASE+DRAM_SIZE); \16 pageoffset += SZ_1M) {17 //DPRINTK(3, "Make DRAM section cacheable: 0x%08lx\n", pageoffset);18 *(mmu_tlb_base + (pageoffset >> 20)) = \pageoffset | MMU_SECDESC | MMU_CACHEABLE;19 }20 }mmu_init()函数用于启动MMU,它直接调用arm920_setup()函数。

相关文档
最新文档