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的倍数。

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

力扣● 84.柱状图中最大的矩形

84.柱状图中最大的矩形 需要找到元素i的上一个更小的元素leftmin和下一个更小的元素rightmin,这样leftmin和rightmin之间的元素都比当前元素i更大,那么矩形的宽就是中间的这些元素:可以从leftmin1延伸到rightmin-1,长即为height[i…

阿里云轻量应用服务器和云服务器ECS有什么区别?

阿里云服务器ECS和轻量应用服务器有什么区别?轻量和ECS优缺点对比,云服务器ECS是明星级云产品,适合企业专业级的使用场景,轻量应用服务器是在ECS的基础上推出的轻量级云服务器,适合个人开发者单机应用访问量不高的网站…

dash 初体验(拔草)

Dash简介 Dash 是一个高效简洁的 Python 框架,建立在 Flask、Poltly.js 以及 React.js 的基础上,设计之初是为了帮助前端知识匮乏的数据分析人员,以纯 Python 编程的方式快速开发出交互式的数据可视化 web 应用。 搭建环境 在学习 Dash 的…

算法之美:数据结构之二叉树

平时写业务代码的时候很少写对应的算法,因为很少会在内存中存储大量数据,在需要比较大量数据的查找时,多会依赖的中间件,而中间件底层就应用了很多不同算法,尤其是树结构的查找存储算法,二分查找算法在树里…

把 Taro 项目作为一个完整分包,Taro项目里分包的样式丢失

现象: 当我们把 Taro 项目作为原生微信小程序一个完整分包时,Taro项目里分包的样式丢失,示意图如下: 原因: 在node_modules/tarojs/plugin-indie/dist/index.js文件里,限制了只有pages目录下会被引入app.w…

C# WPF编程-事件

C# WPF编程-路由事件 路由事件概要路由事件的三种方式 WPF事件WPF最重要的5类事件:生命周期事件 鼠标事件键盘事件多点触控输入原始触控 路由事件概要 路由事件是具有更强传播能力的事件,它们可在元素树中向上冒泡和向下隧道传播,并沿着传播…

稀碎从零算法笔记Day21-LeetCode:单词规律

题型:哈希表、字符串 链接:290. 单词规律 - 力扣(LeetCode) 来源:LeetCode 题目描述 给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。 这里的 遵循 指完全匹配,例如&am…

uni-app从零开始快速入门

教程介绍 跨端框架uni-app作为新起之秀,在不到两年的时间内,迅速被广大开发者青睐和推崇,得益于它颠覆性的优势“快”,快到可以节省7套代码。本课程由uni-app开发者团队成员亲授,带领大家无障碍快速掌握完整的uni-app…

QT文件读写操作和内容提取

访问IO设备,需要先调用open()来设置正确的OpenMode(例如ReadOnly或ReadWrite) 打开设备后后,使用write() 或putChar() 写入数据到文件和设备,并通过调用read(),readLine() 或readAll() 进行读取;使用完设备后&#xf…

机器学习——决策树剪枝算法

机器学习——决策树剪枝算法 决策树是一种常用的机器学习模型,它能够根据数据特征的不同进行分类或回归。在决策树的构建过程中,剪枝算法是为了防止过拟合,提高模型的泛化能力而提出的重要技术。本篇博客将介绍剪枝处理的概念、预剪枝和后剪…

代码随想录算法训练营第二十四天| 回溯算法理论基础、LeetCode77. 组合

# 回溯算法理论基础 # Backtracking 理论基础视频讲解:带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili #LeetCode 77. Combinations #LeetCode 77. 视频讲解:带你学透回溯算法-组合问题(对应力…

力扣爆刷第103天之CodeTop100五连刷1-5

力扣爆刷第103天之CodeTop100五连刷1-5 文章目录 力扣爆刷第103天之CodeTop100五连刷1-5一、3. 无重复字符的最长子串二、206. 反转链表三、146. LRU 缓存四、215. 数组中的第K个最大元素五、25. K 个一组翻转链表 一、3. 无重复字符的最长子串 题目链接:https://l…

Oracle数据库如果出现乱码,需要查看是否时字符集不一致导致乱码,这样解决

1、如果出现乱码,需要查看是否时字符集不一致导致乱码 以修改为ZHS16GBK字符集为例,具体字符集需要sql查询。 Oracle查看字符集 SELECT * FROM NLS_DATABASE_PARAMETERS p where p.PARAMETERNLS_CHARACTERSET; SELECT USERENV(language) FROM DUAL; 1.…

谷歌seo营销服务有哪些服务?

以我们举例,如果你在做B2B外贸建站,这里有全套保姆式托管服务,让你既省心又省力,七天就能搞定网站建设,快速上线,再来就是谷歌白帽SEO,我们这边强调的是纯白帽操作,专注于高质量的原…

Cmake和opencv环境安装

1 Cmake下载及安装 Download CMake 根据需要下载,历史版本下载方法如下 CMake 的版本号中的后缀 "rc1" 和 "rc2" 表示 Release Candidate 1 和 Release Candidate 2,它们都是候选版本,用于测试新功能和修复 bug。通常情…

uni-app里面如何使用图标

目录 一、导入 1.在官方(iconfont-阿里巴巴矢量图标库)选择自己想要的图标,加入购物车 2. 在点击购物车下载代码 3.解压文件夹 并更改名字 4.将文件夹(iconfont)整个放到项目中的static中 5.修改iconfont.css文件…

ctfshow-web入门-反序列化

web254 先看题 <?php/* # -*- coding: utf-8 -*- # Author: h1xa # Date: 2020-12-02 17:44:47 # Last Modified by: h1xa # Last Modified time: 2020-12-02 19:29:02 # email: h1xactfer.com # link: https://ctfer.com*/error_reporting(0); highlight_file(__FIL…

系统架构设计-构建系统应用

1. 系统架构目标与设计原则 在设计系统架构时&#xff0c;我们的目标是确保系统具有以下特点&#xff1a; 可靠性&#xff1a;系统能够持续稳定运行&#xff0c;保证业务可用性。可伸缩性&#xff1a;系统能够根据负载变化自动扩展或收缩&#xff0c;以应对不同的流量需求。容…

string类的详细模拟实现

string类的模拟实现 文章目录 string类的模拟实现前言1. 类的框架设计2. 构造函数与析构函数3. 拷贝构造与重载赋值运算符函数4. 运算符重载5. 成员函数6. 迭代器的实现7. 非成员函数8. 单元测试总结 前言 ​ 在现代编程中&#xff0c;字符串处理是每个程序员都会遇到的基本任…

Web核心简介

简介 web&#xff1a;全球广域网&#xff0c;也称万维网(www)&#xff0c;能够通过浏览器访问的网站 JavaWeb&#xff1a;是用Java技术来解决相关web互联网领域的技术栈 JavaWeb技术栈 B/S架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式&#xff0c;它的…