"叮铃铃… 叮铃铃…"

"谁呀?"黛丝博士打开了家门,"哇,高飞,你怎么来了?"

高飞狗:"好久不见,想来看看你,还买了你最喜欢吃的纯黑巧克力。"

黛丝:"以往都是布鲁托领着你来的,今天你独自上门,必定不怀好意。买了这么多巧克力,必是别有他图吧?"

高飞狗:"你这说的什么话,咱俩一块长大的,怎么会不怀好意? 别有他图倒是真的。"

黛丝:"我就知道你无事不登八宝殿! 说吧,又遇到什么伤脑筋的难题了。"

高飞狗:"是这样的,这两年以Cortex-M7(以下简称CM7)为核心的MCU越来越多,CPU周围新增了几种部件,例如ITCM和ICache,最新的STM32H743,ITCM容量高达64KB,ICache容量高达16KB,我对其功能一知半解,对其用法一头雾水,你能不能给详细讲解一番?"

黛丝:"高飞,你什么时候变得勤奋好学了,居然研究起高大上的科技来了。"

高飞狗心想:"只要能把你这白富美搞到手,再高大上的困难也要不惜一切代价克服。"

黛丝:"ITCM和ICache还真是很时尚的东西,毕竟是新事物,我研究的时间也不长,谈不上讲解,说错的地方还请及时指正。"

高飞狗:"你太谦虚了!"

黛丝:"咱们还是从实际问题出发吧。"

黛丝:"以堆栈空间为例。堆栈空间及其存储的各种数据(含应用程序中的所有局部变量),只有CPU才会访问,而且是频繁访问。但是,在CM7出现以前,堆栈空间只能放在SRAM中,而SRAM是共享资源,DMA可以访问,其它总线Master也都可以访问。导致了以下问题:"

黛丝:"Q1:CPU要和其它总线Master争夺SRAM访问控制权,最惨的时候,CPU只有50%的时间可以访问SRAM,极大地降低了程序性能。"

黛丝:"Q2:其它总线Master有可能篡改堆栈空间上的数据,严重威胁应用程序的安全。"

高飞狗:"对对对,我就有过这样的经历。"

黛丝:"ITCM的出现,彻底解决了以上两个问题。ITCM就是CPU的后宫,归CPU专享、专用、私有、独占。我们把堆栈空间安排在ITCM内,CPU就可以零等待、单周期、全速访问堆栈空间和频繁用到的数据对象,大大提升应用程序性能,且其中的数据不会被其它总线Master篡改,大大提升了应用程序的安全性。"

高飞狗:"茅塞顿开!"

高飞狗:"除此之外,ITCM还有什么用?"

黛丝:"在复杂应用程序中,常常高频地、随机地发生各种中断。发生中断时,就要读取中断向量表(IVT),然后跳转到中断服务程序(ISR)。在CM7出现之前,CPU应对中断存在以下几个头疼的问题:"

黛丝:"Q1:IVT与被中断代码的物理地址相距(简称空距)通常较远,需要耗费多个机器周期才能读取中断向量。"

黛丝:"Q2:而ISR与IVT的空距通常也较远,又需要耗费多个机器周期才能跳转到ISR。"

黛丝:"于是,产生一次中断,要耗费许多机器周期才能跳转执行到ISR。"

黛丝:"Q3:ISR返回到被中断代码又要耗费许多个机器周期。"

黛丝:"执行一次ISR,花费在代码跳转上的时间看似不多。但是,高度频繁、随机发生的各种中断,将使CPU在程序跳转上耗费极其巨大的时间。在复杂、实时性要求较高的应用中,其代价还是很可观的。"

黛丝:"ITCM的出现,完美解决了以上3个问题。程序设计者可以人为地把IVT和ISR安排在一块连续地址空间内,在系统启动时将其全部装入ITCM中,由于CPU访问ITCM总是单周期的,以上3个问题中的程序跳转均可以单周期完成,大幅提升了ISR的实时性能。"

高飞狗:"我记得MCU内部通常都配有自适应实时加速器 (ART-Accelerator™),为什么还需要ITCM来做这项工作呢?"

黛丝:"在顺序读取连续存放的指令时,ART- Accelerator有明显的提速效果。而以上3个问题的情形,基本上是随机读取指令,也就是代码间的空距较远,ART- Accelerator的效果就大打折扣,基本没什么提速作用,这正是ART- Accelerator的短板,而ITCM的出现则大大提升了随机读取指令和数据的性能,补上了ART- Accelerator的短板。"

高飞狗:"我明白了。"

高飞狗:"亲爱的,我发现,STM32H743的ITCM容量高达64KB,除了缓存IVT、ISR、堆栈空间之外,把整个RTOS缓存进去也没问题。如此,CPU就可以独占地、单周期访问高频度用到的代码和数据,应用程序的性能提高幅度将是不可想象的。"

黛丝:"你还是很开窍的! 比以前聪明多了!"

高飞狗:"我明白为什么要把ITCM的容量设计得这么大了。"

高飞狗:"CM7是32位核心,为何ITCM被设计为64位宽度?"

黛丝:"虽然CM7的整数运算能力多为32位,但也有少量64位整数运算指令和大量64位双精度浮点数运算指令,传送64位数据的需求还是很多的,而且很多指令需要一次传送多个32位数据,如下表所示,与32位总线宽度相比,64位的总线宽度可以节省50%的数据传送时间,性能提升是非常可观的。"

例子:一次传送64位宽度数据的指令

说明

LDRD R8, R9, [R3];

以R3为地址指针,将一个64位双字载入R8和R9

LDM R8, {R0-R3}

以R8为地址指针,读取4个32位数据到寄存器中

相当于传送2个64位双字

STM R1, {R3-R6,R11,R12}

以R1为地址指针,存储6个32位寄存器数据

相当于传送3个64位双字

PUSH {R4-R7};

将4个32位寄存器推入堆栈,相当于2个64位双字

64位双精度浮点数的读取和存储指令

不再列出具体指令

高飞狗:"听你讲了这么多,胜读多年书。有点累了吧? 我给你泡杯咖啡,吃块巧克力如何?"

黛丝:"你倒反客为主了!还有啥问题,一气问了,我还要出去办事呢。"

高飞狗心想:"还这么厉害,一丝咸聊的机会都不给。"

高飞狗:"既然ITCM这么好,为什么还出了个ICache,又有什么用呢? 总有种既生高飞,何生黛丝的感觉!"

黛丝:"巧言令色,看我不踩死你!"

黛丝:"这还得看一个小例子,才能说得明白。如下表所示。"

// 循环1亿次

while (…) {

function1(); // 函数地址在0x10000

function2(); // 函数地址在0x20000

function3(); // 函数地址在0x30000

}

黛丝:"这段小程序有2个特点:

F1:3个函数顺序得到执行,在执行时间上是相邻的,简称时距相邻。

F2:3个函数的物理地址相距很远,简称空距很远。

因为空距很远,前一个函数执行完毕后,跳转执行到下一个函数,至少需要花费3个机器周期,循环的1次执行花费在跳转上的时间至少9个机器周期,循环的1亿次执行相应的开销至少9亿个机器周期!

有了ICache之后,情况大不相同。

ICache的特点是自动地把时距相邻的代码尽可能集中存放在自己体内,而不管这些代码的空距有多远,且CPU以单周期访问ICache。"

黛丝:"以上述小循环为例,在执行function1()期间,ICache会把function1()尽可能缓存在自己体内,在执行完一次循环后,如果3个函数的总容量不超过ICache的容量,那么3个函数的全部代码均已缓存在ICache体内。从循环的第2次执行开始,CPU只需访问ICache就可以执行整个循环,不必再访问FLASH,所有指令的获取都是单周期的。前一个函数执行完毕后,跳转执行到下一个函数,只需1个机器周期,循环的1亿次执行花费在函数跳转上的时间只需3亿个机器周期!"

黛丝:"通常,函数function1/2/3()还会调用其它许多函数,函数之间的跳转切换数量要远远多于如上所说。只要容量足够大,ICache还会把被function1/2/3()调用的其它函数通通缓存到体内,由此而节约的执行时间远远大于如上所述。"

黛丝:"所以,ICache的优势是智能地、自动地将时距相邻而空距很远的代码段放置在体内,CPU以单周期访问这些代码,大大提升了程序性能。"

黛丝:"而ITCM的优势是大大提升了时距不相邻而空距相邻的代码段的执行性能,且需要人为地把代码组织成空距相邻。"

高飞狗:"ICache会不会缓存ITCM中的代码?"

黛丝:"由于CPU能够以单周期访问ITCM中的全部内容,所以ITCM中的内容不必缓存到ICache。在CPU硬件设计上就确保做到这一点。所以,ICache中缓存的代码一定是ITCM之外的内容。"

高飞狗:"ITCM和ICache还真的各有所长。"

高飞狗:"你讲了这么多,我来总结一下,你看对不对。"

高飞狗:"结论1:ITCM既能缓存代码也能缓存数据,但需要人为地把频繁执行的代码、IVT、ISR和堆栈空间连成一片(空距相邻),人为地装入其中。从而使CPU以单周期、独占方式访问这些代码和数据,大幅提升应用程序的性能和安全性。"

高飞狗:"结论2:ICache只能缓存代码,但智能地、自动地将时距相邻而空距很远的代码段放置在体内,CPU以单周期访问这些代码,大幅提升程序性能。"

高飞狗:"简而言之,ITCM和ICache是CPU的贴身侍卫。"

黛丝:"概括得非常好。"

黛丝:"对于STM32H743,ITCM和ICache的总容量已达到80KB,如果程序设计者精心安排,使得80%的时间CPU是在这两者内部执行程序,应用程序的性能提升将会极其巨大。"

高飞狗:"ITCM是Instruction Tightly Coupled Memory的缩写,似乎其中只能存放代码?"

黛丝:"你还挺细心的!ITCM也可以存放数据,例如堆栈空间。所以,这个名词的确有些词不达意。"

高飞狗:"对了,CM7核心还新增了DCache部件。最近做了一些实验,涉及DMA传送,好像一启用DCache,数据读写和传送就出问题;只要禁用DCache,一切都正常。你能不能给我详细讲解一番?"

黛丝:"今天时间不早了,我还得出去办事,下次再说吧。"

高飞狗:"那我请吃晚饭,聊表谢意!"

黛丝:"饭和谢就免了,你再不走我就打跑了你!"

高飞狗:"这么厉害呀!那我就不客气了,先走一步了。"

"高飞的白鹭,黛丝的鹅,唐诗里有画,唐诗里有歌,唐诗是我对你的表白…"

童话故事 --- CPU的贴身侍卫ITCM和ICache的更多相关文章

  1. 责任链模式-Chain of Responsibility(Java实现), 例2

    责任链模式-Chain of Responsibility 在这种模式中,通常每个接收者都包含对另一个接收者的引用.如果一个对象不能处理该请求,那么它会把相同的请求传给下一个接收者,依此类推. 咱们在 ...

  2. JZ2440 裸机驱动 第7章 内存管理单元MMU

    本章目标:     了解虚拟地址和物理地址的关系:     掌握如何通过设置MMU来控制虚拟地址到物理地址的转化:     了解MMU的内存访问权限机制:     了解TLB.Cache.Write ...

  3. Uboot流程分析

    1. uboot的配置分析 1).配置入口分析 首先分析配置: 从make mx6dl_sabresd_android_config可知配置项,搜索Makefile: mx6solo_sabresd_ ...

  4. python_根据"词库"进行“词联想”

    输入法中,当你输入一个字的时候,输入法就能猜出你要输入什么词.这就是词联想.现在,再python中简单实现类似这样的功能:根据制定好的词库,输入一个新的词,帮助实现词联想.其中分词用了jieba包. ...

  5. 移植最新u-boot(裁剪和修改默认参数)

    [参考]韦东山 教学笔记 ================================================== 最简单的bootloader的编写步骤: 1. 初始化硬件:关看门狗.设 ...

  6. (嵌入式开发)自己写bootloader之编写第一阶段

    最简单的bootloader的编写步骤: 1. 初始化硬件:关看门狗.设置时钟.设置SDRAM.初始化NAND FLASH 2. 如果bootloader比较大,要把它重定位到SDRAM 3. 把内核 ...

  7. 2、在uboot上实现电源管理

    tar xjf u-boot-1.1.6.tar.bz2 cd u-boot-1.1.6 patch -p1 < ../u-boot-1.1.6_jz2440.patch make 100ask ...

  8. 使用PSCI机制的SMP启动分析

    其他core的入口 文件:arch/arm64/kernel/head.S secondary_entry: 在从bl31切到EL1上的Linux Kernel后: 第595行,在el2_setup中 ...

  9. u-boot v2018.01 启动流程分析 简单版(转)

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/weixin_39655765/artic ...

随机推荐

  1. 最强离线安装MySQL_8.0.2方法

    最强离线安装MySQL_8.0.2方法,一次就能安装成功. 按照此方式,离线安装MySQL五分钟都花不到,节省了大量的宝贵时间. 前戏,假设你已经从MySQL官网中获取了下面这个压缩包: 解压之后变成 ...

  2. 用vue2.x注册一个全局的弹窗alert组件

    一.在实际的开发当中,弹窗是少不了的,默认系统的弹窗样式太丑,难以满足项目的实际需求,所以需要自己定义弹窗组件,把弹窗组价定义为全局的,这样减少每次使用的时候引入麻烦,节省开发时间.本文将分享如何定义 ...

  3. Linux 链接详解----动态链接库

    静态库的缺点: 库函数被包含在每一个运行的进程中,会造成主存的浪费. 目标文件的size过大 每次更新一个模块都需要重新编译,更新困难,使用不方便. 动态库: 是一个目标文件,包含代码和数据,它可以在 ...

  4. 【17-06-16】Java入门测试题,测测你基础知识掌握程度(附答案及个人解析)

    描述 前几天在知乎里看到一份这样的题,当时只是随便做了一下,对了一下答案.昨天又有了一份进阶的题,里面有些还是需要记录一下,于是就从这个入门的题开始. 题目和答案来自阿里云大学 - 知乎专栏 题目 现 ...

  5. Elasticsearch的基友Logstash

    Logstash 是一款强大的数据处理工具,它可以实现数据传输,格式处理,格式化输出,还有强大的插件功能,常用于日志处理. 一.原理 Input 可以从文件中.存储中.数据库中抽取数据,Input有两 ...

  6. PostgreSQL索引描述

    索引方式:唯一索引,主键索引,多属性索引,部分索引,表达式索引. 索引类型:B-Tree,Hash,GiST,GIN以及表达式索引 PostgreSQL所有索引都是“从属索引”,也就是说,索引在物理上 ...

  7. Solr6.5.0配置中文分词器配置

    准备工作: solr6.5.0安装成功 1.去官网https://github.com/wks/ik-analyzer下载IK分词器 2.Solr集成IK a)将ik-analyzer-solr6.x ...

  8. Navicat for Mysql 暴力破解教程

    关于破解Navicat for MySQL的教程有很多 ,但是比较繁琐, 这里推荐一种比较简单的办法~ 网盘地址:链接: https://pan.baidu.com/s/1kVHyShL 密码: ws ...

  9. 解决EJB本地调用“java.lang.ClassCastException: $Proxy96 cannot be cast to com.tgb.ejb.UserManager”异常

    EJB本地调用方式:把Webclient和EJB服务端部署到同一个JBoss,client和server通过一个JVM进行通信. Web客户端本地调用时.需引用EJB服务端打包的jar,不需引用JBo ...

  10. 彻底弄懂 JavaScript 执行机制

    本文的目的就是要保证你彻底弄懂javascript的执行机制,如果读完本文还不懂,可以揍我. 不论你是javascript新手还是老鸟,不论是面试求职,还是日常开发工作,我们经常会遇到这样的情况:给定 ...