关于内存以及如何计算结束地址



我读到控制器的基址和内存映射,我怀疑是否所有的内存位置都只有1字节,并且假设内存映射说ROM的基址是0x0000,它的大小是8K(我相信它是8千字节=8*1024字节,简言之,是8K)我如何计算ROM的结束地址,即0x1FFF我能得出这样的结论吗?在看到ROM的基址为0x0000后,它是由32位处理器访问的,ROM可以存储4GB?

我的理解正确吗?0x0000=0000_0000_0000_0000表示从微处理器指向该位置的16条地址线0000_0000_0000_0000在ROM中,在ROM中的该地址中,ROM可以保存8位数据。

在ARM Cortex M3中,处理器中有32位地址线和32位数据线,以及32位寄存器。因此,由于有32位地址线,我们可以说,我们有4294967296个1’和0’的组合,代表429496729个内存位置,每个位置都能容纳1字节的数据。我的疑问是,由于寄存器是32位的,这就像一个寄存器有4个连续的内存位置(有4个不同的地址),因为内存是1字节。

我认为在这个伟大的平台上,这些问题似乎微不足道,但会有点帮助它以简单的术语或进行解释,并建议链接。:)

除了极少数例外,当前产品以字节为单位寻址内存。因此;地址";是";字节地址";。现在,当您深入研究逻辑时,有很多情况下总线将具有非字节寻址。例如,如果sram是32位宽的,那么在sram之前,您有一个正常的基于字节的地址,通常没有理由保留较低的两个地址位并浪费它们上的信号——当一次寻址基本上是四个字节时,它们不会被使用。当你访问一个16或32位的控制寄存器(比如说uart外设中的uart波特率寄存器)时,情况也是如此,最终地址的低位被剥离为逻辑中未使用的DEEP。

正确的想法是,当16位传输发生时,无论是到实际的ram、rom/flash还是控制寄存器,都是两个字节。从字节地址的角度来看,这两个字节可能是0x40001000和0x40001001,但是,作为程序员,也从系统级的角度看,16位传输不是在这两个地址的两个字节传输,而是在一个地址0x40001000的16位传输(大或小endian,您提到了cortex-m,所以在您的情况下基本上是小endian)。

虽然也有例外,但你可能使用的处理器的总线比一个字节宽,皮层ms可能是32位的,可能更大的是64位的,但肯定不是8位的。因此,每次传输,无论是一个字节、半字、字还是双字(64位),都会在总线上完成,当你这样做时,你不会神奇地移除芯片中的导线/信号,它们总是在那里。读取通常(毫无疑问是例外)是以整个总线宽度为单位进行的,因此,如果您要从内存中读取单个字节,您通常会发现系统的设计是读取包含该字节的整个32位或64位,并且处理器会隔离从总线返回的一个字节,并丢弃其他字节。对于写入,根据总线规则(因处理器而异)将一个字节放在总线上,总线上的其他数据线通常由来自总线控制器的垃圾或陈旧数据驱动,或者有时让其浮动。根据总线规则/设计,对另一侧的指示以及说明这是一次写入将通过字节掩码(总线上每个字节通道一位,一个状态(一或零)指示字节有效/使用,另一个状态指示字节无效)或基于字节的长度与地址等相结合来指示大小。ARM倾向于基于字节掩码,你可以读一下。

要知道,ARM制造处理器IP,而不是制造芯片,ARM几乎与芯片供应商在哪里挂钩无关,没有任何规则规定地址0x00000000是rom/flash。从历史上看,整个地址空间(多大由购买的核心决定,理想情况下是32位,但对arm来说并不总是这样——在arms网站上阅读核心的文档)对芯片设计者来说是公平的。对核心控制寄存器的访问是通过特殊的协处理器指令完成的。Cortex-m的ARM确实规定了宽的地址范围,如果你想要一个rom,你应该把它放在这个范围内,这个范围应该是sram,超过这个地址是内部的,对这个范围的访问不会在总线上出去,它会在内核内消耗。作为一名芯片设计师,尽管你仍然可以自由地做你想做的事情,了解核心中的逻辑是如何使用这些地址空间的(如果有缓存,那么可能没有完整的mcu,所以你想把外围设备的控制寄存器放在arm建议的范围内,以避免缓存该地址空间)。

因为处理器(NOT CHIP)通过检查从地址0x00000000开始的前几个字位置的字来启动,所以芯片设计者需要为软件开发人员提供一种方法,将他们的矢量表放在前面,以便他们的程序运行。一些芯片设计者简单地在地址中为用户设计相对于ARM在该地址处的闪存。其他的,比如stm32的一些/许多基于TI cortex-m的芯片,使用不同的地址,stm32的所有/大多数使用0x08000000,所以对闪存的完全访问是在该地址,但在使用特定设置的芯片进行引导期间,芯片逻辑将访问一小部分基于0x00000000的地址并访问用户闪存。因此,为了在stm32系列上进行开发,您应该为0x08000000而不是0x00000000构建程序,以利用整个闪存。(stm32可以从ram 0x20000000和单独闪存上的内部引导加载程序引导,0x00000000地址空间根据引导模式路由到这些资源)。

因此,32位寄存器通常不相关,但在这种情况下,它是排成一行的,是的,是32位寄存器,至少从指令集的角度来看,有一个32位地址空间,这意味着0x100000000个可能的唯一地址,基于字节。这并不意味着你可以在特定的芯片实现中访问这些字节中的每一个而不会崩溃,但从指令集的角度来看,是的,32位地址,所以0x10000000个可能的地址。

通用寄存器r0、r1、r2、r3。大小是32位,它们没有内存映射,您无法对它们进行寻址。指令集中有允许对地址空间(ldrb、ldrh、ldr、ldrd、strb、strh、str、strd、ldm/stm)进行8,16,32,64(及更大)访问的指令。如上所述,8位、16位、32位或64位访问是如何在总线上发生的,这是核心系统设计的一部分。64位写入地址0x1004很可能会变成两个独立的总线传输——一个32位,一个0x1004,一个32比特,一个在0x1008。但是,根据总线宽度32或64位,对地址0x1000的64位写入很可能是一个总线传输,其中有一个时钟或两个数据(加上传输的少数时钟开销)。从完全隐藏的指令集角度来看,它只是一条strd指令。如果性能是一个目标,那么你需要意识到你正在使用的核心/芯片的副作用,如果不是,那么就按照指令规则使用strd。

如果一个芯片在其文档中有8KB的闪存,那么是的,这意味着0x8*0x400=0x2000,因此在BASE+0x000到BASE+0x20000-1或BASE+0x0000到BASE+0x1FFF的地址空间中,该闪存中可以访问0x2000个单独的字节。如果BASE是0x00000000,则0x0000到0x1FFF,这是正确的。根据芯片设计等,有些会翻车,有些不会,所以如果你有一个错误并访问了0x2000,它可能会崩溃,它可能返回垃圾或固定模式,或者它可能会被屏蔽0x2000&0x1FFF=0x000,并且地址0x0000处的项将被返回。我不会尝试也不会依赖它来工作,除非你在芯片公司工作,与芯片工程师有定期沟通,并且有充分的理由这样做(例如检测闪光灯的大小)。

这并不意味着您可以/应该在地址0x1FFF进行16或32位传输,如果您正在进行字节(在arm cortex-m的情况下为8位)传输,则0x1FFF是8KB闪存的有效地址(通常)。但是0x1FFE是16位传输的最后一个地址,0x1FFC是32位传输的最终地址。

旁注:当你作为芯片工程师或电路板设计师工作时,内存通常以位为单位。因此,当芯片设计师购买或制造8K字节的闪存时,他们正在寻找64K闪存,因为当你购买时,内存是由位定义的(不是你在亚马逊为电脑购买的记忆棒,而是芯片或IP)。如果你的计算机中有一个16GB的内存模块,该模块有64个数据信号和4个芯片,即每个芯片4字节。但当你查找该芯片的零件号时,它是一个32G芯片,没有位/字节命名法,只是32G芯片。根据你的职业发展方向,这些事情会变得多么混乱,这只是火上浇油。即使有几十年的经验,这一事实也会让人们经常感到困惑,纯硬件的人在订购零件或IP时使用的是比特大小,软件的人使用的是字节大小,而介于两者之间的人则在团队之间努力翻译。如果两个团队互动,往往会出现混乱。(硬件/芯片人员自然知道发生了什么,但软件人员往往只关注基于字节的寻址,而不经常在基于位、字节、半字、字等的寻址之间自然流动)。

简单的解释。STM32的设计者决定划分可用的地址空间,并将内存和内存映射的外围设备放置在特定的地址。

总线体系结构要复杂得多。它对地址进行解码并访问适当的存储器或外围设备。

因此,32位可以寻址多少字节并不重要,重要的是芯片设计者实现了什么。

因此,如果你的芯片有64kB的闪存,这意味着你的芯片文档中的地址有64k的闪存。

最新更新