004——内存映射(基于鸿蒙和I.MAX6ULL)

 

目录

一、 ARM架构内存映射模型

1.1 页表项

1.2 一级页表映射过程

1.3 二级页表映射过程

1.4 cache 和 buffer

二、 鸿蒙内存映射代码学习

三、 为板子编写内存映射代码

3.1 内存地址范围

3.2 设备地址范围


 

一、 ARM架构内存映射模型

(以前我以为页表机制是linux这种操作系统规定的,今天看了韦东山老师的视频才知道原来这个机制是由架构来规定的。)

        有一个这样的文档来指导开发A架构的程序。

1.1 页表项

        ARM架构支持一级页表映射,也就是说MMU根据CPU发来的虚拟地址可以找到第1个页表,从第1个页表里就可以知道这个虚拟地址对应的物理地址。一级页表里地址映射的最小单位是1M。

        ARM架构还支持二级页表映射,也就是说MMU根据CPU发来的虚拟地址先找到第1个页表,从第1个页表里就可以知道第2级页表在哪里;再取出第2级页表,从第2个页表里才能确定这个虚拟地址对应的物理地址。二级页表地址映射的最小单位有4K、1K,Linux使用4K。

        一级页表项里的内容,决定了它是指向一块物理内存,还是指问二级页表,如下图:

        页表项就是一个32位的数据,里面保存有物理地址,还有一些控制信息。
页表项的bit1、bit0表示它是一级页表项,还是二级页表项。
        对于一级页表项,里面含有1M空间的物理基地址,这也成为段映射,该物理地址也被称为**段基址**。

        上图中的TEX、C、B可以用来控制这块空间的访问方法:是否使用Cache、Buffer等待。
下图过于复杂,我们只需要知道:

* 访问外设时不能使用Cache、Buffer
* 访问内存时使用Cache、Buffer可以提高速度
* 如果内存用作DMA传输,不要使用Cache、Buffer

如下图所示:

1.2 一级页表映射过程

使用一级页表时,先在内存里设置好各个页表项,然后把页表基地址告诉MMU,就可以启动MMU了。

以下图为例介绍地址映射过程:

* ① CPU发出虚拟地址vaddr,假设为0x12345678
* ② MMU根据vaddr[31:20]找到一级页表项
  * 虚拟地址0x12345678是虚拟地址空间里第0x123个1M
  * 所以找到页表里第0x123项,根据此项内容知道它是一个段页表项
  * 段内偏移是0x45678。

* ③ 从这个表项里取出物理基地址:Section Base Address,假设是0x81000000
* ④ 物理基地址加上段内偏移得到:0x81045678

所以CPU要访问虚拟地址0x12345678时,实际上访问的是0x81045678的物理地址。

1.3 二级页表映射过程

先设置好一级页表、二级页表,并且把一级页表的首地址告诉MMU。

以下图为例介绍地址映射过程:

  • ① CPU发出虚拟地址vaddr,假设为0x12345678

  • ② MMU根据vaddr[31:20]找到一级页表项

    • 虚拟地址0x12345678是虚拟地址空间里第0x123个1M,所以找到页表里第0x123项。

    • 根据此项内容知道它是一个二级页表项。

  • ③ 从这个表项里取出地址,假设是address,这表示的是二级页表项的物理地址;

  • ④ vaddr[19:12]表示的是二级页表项中的索引index即0x45,在二级页表项中找到第0x45项;

  • ⑤ 二级页表项格式如下

* 里面含有这4K或1K物理空间的基地址page base addr,假设是0x81889000
  * 它跟vaddr[11:0]组合得到物理地址:0x81889000 + 0x678 = 0x81889678
* 所以CPU要访问虚拟地址0x12345678时,实际上访问的是0x81889678的物理地址

(linux二级页表使用的是4K大小)

(其实还有一个机制,就是为什么我们的内存只有16个G时linux能为每个进程分配4个G或者更多的虚拟空间)

  1. 虚拟内存:Linux使用虚拟内存技术,它为每个进程提供了一个独立的、连续的虚拟地址空间。这个虚拟地址空间与实际的物理内存是分开的。进程在运行时,会在这个虚拟地址空间中请求内存。Linux内核会负责将这些虚拟地址映射到实际的物理内存地址,或者当物理内存不足时,使用交换空间(swap space)来存储部分数据。
  2. 内存管理单元(MMU):现代计算机硬件中的内存管理单元(MMU)支持虚拟内存技术。当进程访问内存时,MMU负责将虚拟地址转换为物理地址。这意味着,尽管物理内存有限,但每个进程都可以有自己的虚拟地址空间。
  3. 页表:Linux内核为每个进程维护一个页表,该页表记录了虚拟地址到物理地址的映射关系。当进程访问某个虚拟地址时,内核会查找相应的页表项,将虚拟地址转换为物理地址。如果所请求的数据不在物理内存中(即发生了页面错误),内核会负责从交换空间或其他地方加载数据。
  4. 进程隔离:虚拟内存还提供了进程隔离的功能。每个进程都有自己的虚拟地址空间,因此一个进程无法直接访问另一个进程的内存。这增强了系统的安全性和稳定性。

        这个交换空间其实是我们的外存空间,比如硬盘,将进程一部分不需要立刻执行的资源放到外存里,不断的交换到内存去执行,这样效率会大大降低,但是却可以拥有更多的内存空间。

1.4 cache 和 buffer

ARM的cache和写缓冲器(write buffer)_arm coretex a7 write buffer-CSDN博客

使用MMU时,需要有cache、buffer的知识。
下图是CPU和内存之间的关系,有cache、buffer(写缓冲器)。
Cache是一块高速内存;写缓冲器相当于一个FIFO,可以把多个写操作集合起来一次写入内存。

程序运行时有“局部性原理”,这又分为时间局部性、空间局部性。

* 时间局部性:
  在某个时间点访问了存储器的特定位置,很可能在一小段时间里,会反复地访问这个位置。

* 空间局部性
  访问了存储器的特定位置,很可能在不久的将来访问它附近的位置。

而CPU的速度非常快,内存的速度相对来说很慢。
CPU要读写比较慢的内存时,怎样可以加快速度?
根据“局部性原理”,可以引入cache:

* 读取内存addr处的数据时
  * 先看看cache中有没有addr的数据,如果有就直接从cache里返回数据:这被称为cache命中。
  * 如果cache中没有addr的数据,则从内存里把数据读入
    注意:它不是仅仅读入一个数据,而是读入一行数据(cache line)。
  * 而CPU很可能会再次用到这个addr的数据,或是会用到它附近的数据,这时就可以快速地从cache中获得数据。

* 写数据
  * CPU要写数据时,可以直接写内存,这很慢;也可以先把数据写入cache,这很快。
  * 但是cache中的数据终究是要写入内存的啊,这有2种写策略:
    * a. 写通(write through):
      数据要同时写入cache和内存,所以cache和内存中的数据保持一致,但是它的效率很低。
      能改进吗?可以!
      使用“写缓冲器”:cache大哥,你把数据给我就可以了,我来慢慢写,保证帮你写完。
      有些写缓冲器有“写合并”的功能,比如CPU执行了4条写指令:写第0、1、2、3个字节,每次写1字节;写缓冲器会把这4个写操作合并成一个写操作:写word。
      对于内存来说,这没什么差别,但是对于硬件寄存器,这就有可能导致问题。
      所以对于寄存器操作,不会启动buffer功能;对于内存操作,比如LCD的显存,可以启用buffer功能。
    * b. 写回(write back):
      新数据只是写入cache,不会立刻写入内存,cache和内存中的数据并不一致。
      新数据写入cache时,这一行cache被标为“脏”(dirty);当cache不够用时,才需要把脏的数据写入内存。
      使用写回功能,可以大幅提高效率。但是要注意cache和内存中的数据很可能不一致。这在很多时间要小心处理:比如CPU产生了新数据,DMA把数据从内存搬到网卡,这时候就要CPU执行命令先把新数据从cache刷到内存。反过来也是一样的,DMA从网卡得过了新数据存在内存里,CPU读数据之前先把cache中的数据丢弃。

 是否使用cache、是否使用buffer,就有4种组合(Linux内核文件arch\arm\include\asm\pgtable-2level.h):

(已经不止4种了哦,这是3.14版本的)

韦东山老师这个是哪个版本不太清楚,这四种对应下面的表。

第1种是不使用cache也不使用buffer,读写时都直达硬件,这适合寄存器的读写。

第2种是不使用cache但是使用buffer,写数据时会用buffer进行优化,可能会有“写合并”,这适合显存的操作。因为对显存很少有读操作,基本都是写操作,而写操作即使被“合并”也没有关系。

第3种是使用cache不使用buffer,就是“write through”,适用于只读设备:在读数据时用cache加速,基本不需要写。

第4种是既使用cache又使用buffer,适合一般的内存读写。

二、 鸿蒙内存映射代码学习

分析启动文件`kernel\liteos_a\arch\arm\arm\src\startup\reset_vector_up.S`,(up和mp的区别和我昨天猜测的一样,up是单核mp是多核(multi-processor)(uni-processor)环境)
可以得到下图所示的地址映射关系:

* 内存地址
  * KERNEL_VMM_BASE开始的这块虚拟地址,使用Cache,速度快
  * UNCACHED_VMM_BASE开始的这块虚拟地址,不使用Cache,适合DAM传输、LCD Framebuffer等
* 设备空间:就是各种外设,比如UART、LCD控制器、I2C控制器、中断控制器
  * PERIPH_DEVICE_BASE开始的这块虚拟地址,不使用Cache不使用Buffer
  * PERIPH_CACHED_BASE开始的这块虚拟地址,使用Cache使用Buffer
  * PERIPH_UNCACHE_BASE开始的这块虚拟地址,不使用Cache但是使用Buffer

Liteos-a的地址空间是怎么分配的?
`KERNEL_VMM_BASE`等于0x40000000,并且在`kernel\liteos_a\kernel\base\include\los_vm_zone.h`看到如下语句:

#if (PERIPH_UNCACHED_BASE >= (0xFFFFFFFFU - PERIPH_UNCACHED_SIZE))
#error "Kernel virtual memory space has overflowed!"
#endif


 

所以可以粗略地认为:

* 内核空间:0x40000000 ~ 0xFFFFFFFF
* 用户空间:0 ~ 0x3FFFFFFF

三、 为板子编写内存映射代码

3.1 内存地址范围

这里我还是以exynos4412为例

找到了一张这个图,挺有意思的

下面这个是6ull的内存映射图

下面这个是exynos4412的内存映射图

这里我们要按手册修改,这点两个芯片有所不同,6uLL是固定的2个G

但是4412是可选的从0x40000000开始可以安3个G的内存条,这里我们安了一个G所以就是

从0x40000000~0x80000000

3.2 设备地址范围

IMX6ULL芯片上设备地址分部太零散,从0到0x6FFFFFFF都有涉及,中间有很多保留的地址不用,入下图:

如果把0到0x6FFFFFFF全部映射完,地址空间不够; 正确的做法应该是忽略那些保留的地址空间,为各个模块单独映射地址。 但是Liteos-a尚未实现这样的代码(要自己实现也是可以的,但是我们先把最小系统移植成功)。 我们至少要映射2个设备的地址:UART1(100ASK_IMX6ULL开发板使用UART1)、GIC,如下图:

所以:

// source\vendor\democom\demochip\board\include\board.h
#define PERIPH_PMM_BASE         0x00a00000   // GIC的基地址
#define PERIPH_PMM_SIZE         0x02300000   // 尽可能大一点,以后使用其他外设时就不用映射了

PERIPH_PMM_SIZE也不能太大,限制条件是:

#if (PERIPH_UNCACHED_BASE >= (0xFFFFFFFFU - PERIPH_UNCACHED_SIZE))
#error "Kernel virtual memory space has overflowed!"
#endif

但是我们不用考虑这个问题我们有一个G的内存可以把整个SFR寄存器都进行映射

                                                                ...

注意:MMU以1MB为单位映射,大小要是1MB的倍数。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/766794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用插件将swagger文档转html或pdf

github上有maven开源插件swagger2markup将swagger文档转为.adoc格式的文档,另外一个maven开源插件asciidoctorj-pdf则可以将.adoc格式的文档转为html和pdf。由于GitHub访问不稳定,在gitee上有镜像项目。所以我就贴gitee上的项目地址了。 实现从swagger文…

局域网内的手机、平板、电脑的文件共享

在日常工作生活中,经常需要将文件在手机、平板、电脑间传输,以下介绍三种较为便捷的方法: 1.LocalSend 该软件是免费开源的,可以在局域网内的任意手机、平板、电脑间传递文件,并且任意一方都可以作为“发送方”和“接…

MapReduce学习问题记录

1、如何跳过对某行数据的处理 第一行数据是字段名不需要处理,我们知道第一行偏移量是0(行记录的时候是从数组首地址开始,到了行标识符进行一次计数,这个计数就是行偏移量,从0开始),我们根据偏移…

线程池的7大参数

线程池的7大参数 一、 corePoolSize 线程池核心线程大小 核心线程永远不会销毁,即使他们处于空闲状态,除非设置了allowCoreThreadTimeOut。任务提交到线程池后,首先会检查当前线程数是否达到了corePoolSize,如果没有达到的话&…

【绘图案例-奇偶填充规则 Objective-C语言】

一、接下来,我们来学习奇偶填充规则 1.就是说,你在填充的时候,实际上,是有一些规则的, 奇偶填充规则:even-odd rule, even:偶数,odd:奇数 2.把之前的copy代码,复制粘题一份,名字改成“07-奇偶填充规则”, 把ppt里的代码复制粘贴过来, 我们来看一下这段儿代码,…

CSS(一)

一、CSS 简介 1.1 HTML 的局限性 说起 HTML&#xff0c;这其实是个非常单纯的家伙&#xff0c;他只关注内容的语义。比如 <h1> 表明这是一个大标题&#xff0c;<p> 表明这是一个段落&#xff0c;<img> 表明这儿有一个图片&#xff0c;<a> 表示此处有链…

每日一题 --- 设计链表[力扣][Go]

设计链表 题目&#xff1a;707. 设计链表 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则…

pytest之统一接口请求封装

pytest之统一接口请求封装 pytest的requests_util.pyrequests_util.py 接口自动化测试框架的封装yaml文件如何实现接口关联封装yaml文件如何实现动态参数的处理yaml文件如何实现文件上传有参数化时候&#xff0c;怎么实现断言yaml的数据量大怎么处理接口自动化框架的扩展&#…

FFmepg--AVFilter过滤器使用以及yuv视频裁剪

文章目录 AVFilter 流程&#xff1a;api核心代码变量yuv视频裁剪 AVFilter 流程&#xff1a; ⾸先使⽤split滤波器将input流分成两路流&#xff08;main和tmp&#xff09;&#xff0c;然后分别对两路流进⾏处理。对于tmp流&#xff0c;先经过crop滤波器进⾏裁剪处理&#xff0c…

Kotlin零基础入门到进阶实战

教程介绍 Kotlin现在是Google官方认定Android一级开发语言&#xff0c;与Java100%互通&#xff0c;并具备诸多Java尚不支持的新特性&#xff0c;每个Android程序员必备的Kotlin课程&#xff0c;每个Java程序员都需要了解的Kotlin&#xff0c;掌握kotlin可以开发Web前端、Web后…

主干网络篇 | YOLOv8更换主干网络之GhostNet

前言:Hello大家好,我是小哥谈。GhostNet是2019年由华为诺亚方舟实验室发布的轻量级网络,速度和MobileNetV3相似,但是识别的准确率比MobileNetV3高,在ImageNet ILSVRC2012分类数据集的达到了75.7%的top-1精度。该论文提除了Ghost模块,通过廉价操作生成更多的特征图。基于一…

是德科技keysight DSOX3024T示波器

181/2461/8938产品概述&#xff1a; DSOX3024T 示波器 要特性与技术指标 使用电容触摸屏进行简洁的触控操作&#xff1a; •提高调试效率 •触控设计可以简化文档记录 •使用起来就像您喜欢的智能手机或平板电脑一样简单 使用 MegaZoom IV 技术揭示偶发异常&#xff1a; •超快…

思通舆情 是一款开源免费的舆情系统 介绍

思通舆情 是一款开源免费的舆情系统。 支持本地化部署&#xff0c;支持在线体验。 支持对海量舆情数据分析和挖掘。 无论你是使用者还是共同完善的开发者&#xff0c;欢迎 pull request 或者 留言对我们提出建议。 您的支持和参与就是我们坚持开源的动力&#xff01;请 sta…

申请双软认证需要哪些材料?软件功能测试报告怎么获取?

“双软认证”是指软件产品评估和软件企业评估&#xff0c;其中需要软件测试报告。 企业申请双软认证除了获得软件企业和软件产品的认证资质&#xff0c;同时也是对企业知识产权的一种保护方式&#xff0c;更可以让企业享受国家提供给软件行业的税收优惠政策。 那么&#xff0c;…

6-191 拓扑排序

一项工程由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其他子任务后才能执行。例如,下图表示了一项工程若干子任务之间的先后关系。 编写函数输出所有子任务的拓扑序列。 函数接口定义: Status Push_SeqStack(SeqStack &s, ElemType x)//入栈,x入到…

框架结构模态分析/动力时程分析Matlab有限元编程 【Matlab源码+PPT讲义】|梁单元|地震时程动画|结果后处理|地震弹性时程分析| 隐式动力学

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

基于springboot+vue的旅游网站

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

JavaScript 权威指南第七版(GPT 重译)(六)

第十五章&#xff1a;JavaScript 在 Web 浏览器中 JavaScript 语言是在 1994 年创建的&#xff0c;旨在使 Web 浏览器显示的文档具有动态行为。自那时以来&#xff0c;该语言已经发生了显著的演变&#xff0c;与此同时&#xff0c;Web 平台的范围和功能也迅速增长。今天&#…

2024.3.24阶段性测试题解

VJ测试链接考试链接 成绩表如下&#xff0c;信息学是非常检验平时努力的&#xff0c;而且也是一分耕耘一分收获的&#xff0c;总的来说每天订正晚训跟只订正一部分题还是有区别的…希望同学们再接再厉。 A题 简单判断题&#xff0c;单独判断首字母&#xff0c;再判断其余字母…

Java 学习和实践笔记(45):数组的遍历,复制,

数组的两种遍历方式&#xff1a; package innerClass;public class Test01 {public static void main(String[] args) {String[] cities {"北京","上海","广州","深圳",};//遍历方式一&#xff0c;这是一般的方式for (int i0; i<…