MMU 裸机程序

从零实现RK3588的aarch64裸机程序操作指南 手把手带你完成RK3588平台的aarch64裸机程序开发,涵盖工具链配置、启动代码编写、内存映射设置与串口调试等核心环节。全程基于aarch64指令集架构,不依赖任何操作系统,适合嵌入式底层开发者快速上手实战。 阅读详情

来自:http://blog.sina.com.cn/s/blog_49d9a0820100e37l.html

一级页表

////////////////////////////////////head.S//////////////////////////////////////////////////////////////////////

@*************************************************************************
@ File:head.S
@ 功能:设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU,
@ 

     然后跳到SDRAM继续执行
@************************************************************************* 
     

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

//////////////////////////////////init.c//////////////////////////////////////////////



#defineWTCON 
         (*(volatile unsigned long *)0x53000000)

#defineMEM_CTL_BASE 
  0x48000000



void disable_watch_dog(void)
{
 
   WTCON = 0;// 关闭WATCHDOG很简单,往这个寄存器写0即可
}


void memsetup(void)
{
 
  
 
   unsignedlong const   mem_cfg_val[]={0x22011110,    //BWSCON
 
                                          0x00000700,    //BANKCON0
 
                                          0x00000700,    //BANKCON1
 
                                          0x00000700,    //BANKCON2
 
                                          0x00000700,    //BANKCON3
 
                                          0x00000700,    //BANKCON4
 
                                          0x00000700,    //BANKCON5
 
                                          0x00018005,    //BANKCON6
 
                                          0x00018005,    //BANKCON7
 
                                          0x008C07A3,    //REFRESH
 
                                          0x000000B1,    //BANKSIZE
 
                                          0x00000030,    //MRSRB6
 
                                          0x00000030,    //MRSRB7
 
                                  };
 
  int    i = 0;
 
   volatileunsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
 
   for(; i< 13; i++)
 
      p[i] = mem_cfg_val[i];
}


void copy_2th_to_sdram(void)
{
 
   unsigned int*pdwSrc = (unsigned int *)2048;
 
   unsigned int*pdwDest = (unsigned int *)0x30004000;
 
  
 
   while(pdwSrc < (unsigned int *)4096)
 
   {
 
      *pdwDest = *pdwSrc;
 
      pdwDest++;
 
      pdwSrc++;
 
   }
}


void create_page_table(void)
{


#defineMMU_FULL_ACCESS 
   (3 <<10)  
#defineMMU_DOMAIN 
        (0 <<5)   
#defineMMU_SPECIAL 
       (1 <<4)   
#defineMMU_CACHEABLE 
     (1 <<3)   
#defineMMU_BUFFERABLE 
    (1 <<2)   
#defineMMU_SECTION 
       (2)        
#defineMMU_SECDESC 
       (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | \
 
                           MMU_SECTION)
#defineMMU_SECDESC_WB 
    (MMU_FULL_ACCESS | MMU_DOMAIN | MMU_SPECIAL | \
 
                           MMU_CACHEABLE | MMU_BUFFERABLE | MMU_SECTION)
#defineMMU_SECTION_SIZE 
  0x00100000

 
   unsignedlong virtuladdr, physicaladdr;
 
   unsignedlong *mmu_tlb_base = (unsigned long *)0x30000000;
 
  
 
  
 
   virtuladdr =0;
 
   physicaladdr= 0;
 
  *(mmu_tlb_base + (virtuladdr >> 20))= (physicaladdr & 0xFFF00000) | \
 
                                          MMU_SECDESC_WB;

//从SDRAM的开始存放页表,将虚拟地址0对应的物理地址0的页表创建好,当我们以后对这个虚拟地址操作的时候,MMU可以为我们在这个页表也找到相应的物理地址。
 
  
 
   virtuladdr =0xA0000000;
 
   physicaladdr= 0x56000000;
 
  *(mmu_tlb_base + (virtuladdr >> 20))= (physicaladdr & 0xFFF00000) | \
 
                                          MMU_SECDESC;

 
  
 
   virtuladdr =0xB0000000;
 
   physicaladdr= 0x30000000;
 
   while(virtuladdr < 0xB4000000)
 
  {创建好了页表以后
 
      *(mmu_tlb_base + (virtuladdr >> 20))= (physicaladdr & 0xFFF00000) | \
 
                                              MMU_SECDESC_WB;
 
      virtuladdr += 0x100000;
 
      physicaladdr += 0x100000;
 
   }
}


void mmu_init(void)
{
 
   unsignedlong ttb = 0x30000000;

__asm__(
 
  "mov    r0,#0\n"
 
  "mcr    p15, 0,r0, c7, c7,0\n"   
 
  
 
  "mcr    p15, 0,r0, c7, c10, 4\n"  
 
  "mcr    p15, 0,r0, c8, c7,0\n"   
 
  
 
  "mov    r4,%0\n"                  
 
  "mcr    p15, 0,r4, c2, c0,0\n"   
 
  
 
  "mvn    r0,#0\n"                  
 
  "mcr    p15, 0,r0, c3, c0,0\n"      
 
  
 
  "mrc    p15, 0,r0, c1, c0,0\n"   
 
  
 
  
 
  
 
  
 
                                      
 
  "bic    r0, r0,#0x3000\n"         
 
  "bic    r0, r0,#0x0300\n"         
 
  "bic    r0, r0,#0x0087\n"         

 
  
 
  "orr    r0, r0,#0x0002\n"         
 
  "orr    r0, r0,#0x0004\n"         
 
  "orr    r0, r0,#0x1000\n"         
 
  "orr    r0, r0,#0x0001\n"         
 
  
 
  "mcr    p15, 0,r0, c1, c0,0\n"   
 
   :
 
   : "r" (ttb));
}

/////////////////////////////mmu.lds/////////////////////////////////
SECTIONS
{
 
      first0x00000000 : {head.o init.o} #first
 
      second0xB0004000 : AT(2048) {leds.o}#指定这个段在编译出来的映像文件中的地址-加载地址。如果不使用这个选项,并且不指定0xB0004000,则加载地址等于运行地址,否则指定了 0xB0004000是不相同的。通过这个选项。可以控制各段分别保存输出文件中不同的位置。这里指定leds.o保存在映像文件的2048这个起始地址,而0xB0000000这个是段重定位地址,也称为运行地址,它是个虚拟地址。
}

///////////////////////////////////Makefile/////////////////////////////
objs := head.o init.o leds.o

mmu.bin : $(objs)
 
  arm-softfloat-linux-gnu-ld -Tmmu.lds -o mmu_elf $^
 
  arm-softfloat-linux-gnu-objcopy -O binary -S mmu_elf $@
 
  arm-softfloat-linux-gnu-objdump -D -m arm mmu_elf >mmu.dis
 
  
%.o:%.c
 
  arm-softfloat-linux-gnu-gcc -Wall -O2 -c -o $@$<

%.o:%.S
 
  arm-softfloat-linux-gnu-gcc -Wall -O2 -c -o $@$<

clean:
 
   rm -fmmu.bin mmu_elf mmu.dis*.o      

////////////////////////////leds.c///////////////////////////////////


#defineGPFCON 
    (*(volatile unsigned long*)0xA0000050)    // 物理地址0x56000050
#defineGPFDAT 
    (*(volatile unsigned long*)0xA0000054)    // 物理地址0x56000054

#defineGPF4_out 
  (1<<(4*2))
#defineGPF5_out 
  (1<<(5*2))
#defineGPF6_out 
  (1<<(6*2))
#defineGPF7_out 
  (1<<(7*2))


static inline void wait(unsigned long dly)
{
 
   for(; dly> 0; dly--);
}

int main(void)
{
 
   unsignedlong i = 0;
 
  
 
   //将LED1-4对应的GPF4/5/6/7四个引脚设为输出
 
   GPBCON =GPF4_out|GPF5_out|GPF6_out|GPF7_out;      

 
  while(1){
 
      wait(300000);
 
      GPBDAT =(~(i<<4));    // 根据i的值,点亮LED1-4
 
      if(++i == 16)
 
          i = 0;
 
   }

 
   return0;
}

什么情况下需要禁用MMU/i-cache/d-cache?——嵌入式 在嵌入式系统开发中,MMU(内存管理单元)、I-cache(指令缓存)和D-cache(数据缓存)是核心的硬件组件,它们对系统的性能和功能起着至关重要的作用。然而,在某些特定的情况下,禁用这些组件可能是必要的。本文将详细探讨在嵌入式系统中禁用MMU、I-cache和D-cache的场景,并提供相应的源代码实例。禁用MMU、I-cache和D-cache在嵌入式系统开发中是一种特殊场景下的需求,并非常规操作。什么情况下需要禁用MMU/i-cache/d-cache?三、禁用D-cache的情况。 阅读详情

相关推荐

I2C通信协议SCL与SDA引脚特性:核心要点总结

深入讲解I2C通信协议中SCL和SDA引脚的工作机制与电气特性,帮助理解i2c通信协议的稳定传输原理,掌握上拉电阻配置与信号时序控制要点。

weixin_42103128的博客 2736

MMU,cache,裸机嵌入式C编程还有带操作系统的编程

通过CMSIS-utrealos项目中的CTBUG调试,使我对裸机C编程加深了认识。那个BUG调试,现象是出现hard fault,但是fault出现地的汇编指令看着貌似没啥问题,解决一处的fault后,其他处又出现fault了。最后我看到原来是fault出现地的指令中源地址错误了,源地址应该在数据段中,却意外地落到了代码段中。这个现象我忙活了半天才找到。 然后通过看那奇怪的源地址,对照它四周的

buhui912的专栏 1405

如何使用3D高斯分布进行环境建模

使用3D高斯分布来进行建模,关键在于通过引入不确定性描述来提高建图的鲁棒性和精度。与传统点云表示相比,3D高斯分布提供了一种更为灵活和有效的方式来处理空间数据,能够通过协方差矩阵表示点的空间不确定性,帮助优化SLAM过程中的定位和地图更新。

JaydenQ的博客 2355

FS4412裸机程序------uboot下的MMU验证

1、使用vim查看编译后的uboot目录中的u-boot.map文件,可以看出uboot的运行地址(加载地址)的起始地址为0xc3e0_0000,结束地址为0xc3f7_6578 2、从FS4412的原理图(FS4412_CoreBoard_V2)与Exynos4412的手册(Exynos(通用版)客户手册)可以看到1GB的DDR3在物理空间上的分布为0x4000_00000xA000_0000(共1.5GB),而uboot的起始地址为0xc3e0_0000,所以可以断定:uboot开启了MMU,将ub

weixin_51082062的博客 818

使用 Java + PaddleOCR 实现表格识别,支持导出 HTML 和 Excel(附源码)

使用Java+PaddleOCR快速搭建表格识别系统,无需处理底层模型细节。系统支持表格结构识别和内容识别,可将图片转换为可编辑表格格式。文章提供了完整的实现流程,包括Maven依赖引入、模型下载(包含检测、识别、分类和表格结构模型)及参数配置说明。SmartJavaAI支持多种高性能模型选择,适用于不同应用场景,帮助开发者快速实现表格识别功能。

deng775747758的博客 1474

STM32标准库下载保姆级教程:2024最新官网免注册直接下载方法

本文提供2024年最新STM32标准库免注册下载方法,包括直接下载链接、GitHub镜像仓库和开发工具内置库三种途径。详细介绍了标准外设库的优势、配置步骤及常见问题解决方案,帮助开发者快速获取并应用这一重要开发资源。

weixin_29163581的博客 367

4412裸机程序之mmu

内存管理单元MMU,负责虚拟地址到物理地址的转换,并提供硬件进制的内存访问权限检查,操作系统通过MMU可以实现各个用户进程自己独立的地址空间, 通过内存权限的检查可以保证每个进程使用的内存不被其他进程破坏。具体操作系统怎么运用MMU的就比较复杂了,我们只看看最原始的裸机程序怎么配置寄存器 操作MMU建立虚拟地址到物理地址映射,了解其原理。 ARM提供4种映射长度:段(1M),大页(64K),

cyj88jyc的专栏 1687

大模型工作流Dify面试题及参考答案

设计一个基于 Dify 的智能摘要与重点提取 Agent,需结合Prompt 工程、模型能力配置和工作流优化,确保对长文本的高效解析和关键信息提炼。1. 明确任务需求与输入输出输入:长文本内容(如文章、报告、会议记录)或文本 URL输出摘要:简洁概括原文核心内容,控制在原文长度的 10%-20%重点列表:分点列出关键数据、结论、行动项等可选:关键词提取、情感倾向分析示例场景输入:一篇 5000 字的行业报告。

大模型大数据攻城狮的专栏 2511

Eclipse开发调试ARM裸机程序(五)MMU调试

Eclipse开发调试ARM裸机程序(五)MMU调试            代码如下: @************************************************************************* @ File:head.S @ 功能:设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU, @ 然后跳到SDRAM继续

Android/Linux的专栏 2485

DB文件在编程中的作用及示例代码

通过使用DB文件,我们可以实现数据的持久化存储,并能够高效地进行数据的增删改查操作。在本文中,我们以SQLite数据库为例,演示了如何使用Python语言创建和操作DB文件的示例代码。在实际的编程中,我们可以根据具体的需求和使用的数据库系统来进行更复杂的操作和优化。通过使用DB文件,我们可以实现数据的持久化存储,确保数据在程序关闭后也能被保留,并且能够高效地进行数据检索和更新。在本文中,我们将探讨DB文件的作用,并提供一些示例代码展示如何在编程中使用DB文件。上述代码中,我们使用SQLite提供的。

CodeSpark的博客 1821

点云语义分割:PointNet训练S3DIS数据集

文章目录一、数据准备1.1、数据下载二、训练三、测试 项目地址:pointnet 此次我们是用pointnet网络来做语义分割。代码在pointnet项目中的sem_seg文件夹下,里面也有README.md介绍了训练的过程。 一、数据准备 1.1、数据下载 原始数据下载 处理好的h5格式数据下载 二、训练 三、测试 ...

zhaoguanhua的博客 4176

裸机程序也可以写关于mmu程序,相当于实现操作系统的部分功能

TQ2440裸机开发试验之MMU.ra  http://download.youkuaiyun.com/download/opwwwp123/3311755   裸机程序里,程序从flash调入到内存的地址,这个是由谁控制的,还是裸机只能执行单任务,跳入程序的地址就只是0或其它固定地址???

fengyunjh的专栏 1278

电能质量仿真:电能质量改善措施仿真_(12).电能质量改善措施综合仿真案例

假设我们有一个微电网系统,该系统包含分布式电源(如光伏板、风力发电机)、储能设备、负荷和电网连接。电压波动:由于负荷的波动和分布式电源的间歇性输出,系统电压出现了不稳定的情况。谐波污染:非线性负荷和逆变器的运行导致系统中出现了显著的谐波污染。频率偏差:分布式电源的波动和负荷的突变导致系统频率出现了偏差。我们需要通过仿真来评估这些问题的影响,并提出相应的改善措施。

2401_87715305的博客 1360

s3c2440的MMU裸机程序

1.权限管理 内核以及各个应用程序都有自己的空间,各自都只能访问属于自己的内存空间段,这样做的好处是A程序的崩溃不会导致B程序出问题,同时也可以防止恶意程序修改别的程序的空间的数据。 2.在windows中打开两个C程序(都是打印A变量的地址和值),打印出来A的地址值一样,但是A的值却不一样。 解释:这是因为windows的虚拟地址导致的,打印出来的A的地址是一个虚拟的地址,并不是A变量存放

laoniu_c的专栏 1328

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

四、mini2440裸机程序之MMU(下)

1.本实验相关管脚介绍        1)原理图           2)由上图可以看出,4个LED灯所对应的管脚: 名称 对应管脚 管脚功能 对应逻辑 LED1 GPB5 内部上拉输出 0:灯亮 1:灯灭 LED2 GPB6 内部上拉输出 0

shengnan_wu的专栏 2464

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

s3c2440 mmu 裸机程序

程序用的韦东山的第七章的示例代码。这里总结下问题: 韦东山的代码写的挺好的。注释比较多,结合芯片手册以及920T内核手册页很容易看懂。我用的JLINK直接在内存里调试裸机程序。因此不需要使用H-JTAG烧写nandflash,程序直接下载到内部ram里面运行。编译好的mmu.bin大小为3KB,内部ram为4KB。FL2440的几个led灯对应于GPB5,6,8,10.因此改了下leds.c

画卷 780

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

四、mini2440裸机程序之MMU(上)

来自ARM920T参考手册 可在以下官方网站下载: http://infocenter.arm.com/help/index.jsp   一、前期介绍   访问CP15寄存器组的语法:          在特权模式下,访问CP15寄存器组通过MCR/MRC指令: MCR/MRC{cond}  P15 , opcode_1 , Rd , CRn  , CRm , opcode_2

shengnan_wu的专栏 2254

WDS1期第4课 裸机3 - MMU

通常CPU不是和内存直接打交道,CPU执行程序时要存放A变量到内存的某个地址,由MMU做地址转换,然后交给存储管理器去存放。 CPU -----(虚拟地址)----- MMU -----(物理地址)------ 存储管理器 但是在裸机程序中,CPU也可以绕过MMU(不开启MMU)直接给存储管理器发地址而不转换地址。 CPU -----(物理地址)------ 存储管理器 在CPU的眼里,没有虚拟地...

巴德鸟 243

MMU工作原理

MMU的工作原理就是把虚拟地址转换成物理地址。 虚拟地址:由编译器和连接器在定位程序时分配。 物理地址:用来访问实际的主存硬件模块。 使用虚拟存储器的系统都使用一种称为分页(paging)。虚拟地址空间划分成称为页(page)的单位,而相应的物理地址空间也被进行划分,单位是页框(frame).页和页框的大小必须相同。 自己写的裸机程序: void mem_init(unsigned ...

weixin_30244889的博客 193

MMU的通俗理解

转自http://blog.youkuaiyun.com/kangear/article/details/8797533 MMU的通俗理解        看了两天了MMU,有点眉目,记下来。只说原理,不说具体的寄存器设置。        没有MMU时候,CPU核和外部存储器直接对话。情况是这样的:                 有了MMU,CPU核外部存

qingkongyeyue的博客 1271

Zynq 7020 烧录裸机程序报错Error while launching program memory

具体报错内容:write error at 0x105000 MMU section translation fault。解决方法:切回启动模式到JTAG再往里面烧裸机程序。

pengfirefire的博客 257

ARM裸机MMU调试

代码如下: @************************************************************************* @ File:head.S @ 功能:设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU, @ 然后跳到SDRAM继续执行 @****************************************

Hello Mr.Z的博客 1540

关于调试裸机中断程序的一点见解

来自:http://blog.chinaunix.net/uid-26435987-id-3130810.html 最近调试触摸屏裸机程序,下到SDRAM中就是进不了中断,在ADS下调试,触摸屏一发出中断就提示Dummy error...... 后来想了一下,其实在ADS中调试中断这个方法论都是错误的,利用supervivi的download&run功能调试也是错误的。 因为两种情况下内部S

sig1298363738的专栏 787

s3c2440时钟+nandflash拷贝至SDRAM+开启mmu

涉及6个文件 head.S,init.c,main.c,makefile,nand.c,out.lds head.S .text .global _start _start: b Reset HandleUndef: b HandleUndef HandleSWI: b HandleSWI HandlePrefetchAbort:

Calcular的博客 1198

ARM嵌入式linux系统学习之裸机(一)

1.裸机学习什么?裸机主要是学习对通过arm处理器的寄存器的操作来实现其内部资源和外部设备的控制及通信。学习裸机主要有两个目的,第一是熟悉其硬件的资源配置,学会编写bootloader;第二就是学习硬件驱动程序的工作原理,为内核驱动打下基础。2.裸机学习需要具备哪些基础?由于裸机程序主要是通过对核心处理器寄存器的操作来实现开发板外部设备、接口的功能,即主要和硬件打交道,因此首先你应该能看懂开发板的原

开坦克的飞行员 2243
上一篇: UCOS-II常用变量说明
下一篇: MMU(深入浅出)
shareCode
博客等级 码龄15年 125粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值