关于内存以及如何计算结束地址
About memory and how to calculate the ending address
我读到了控制器的基地址和内存映射,我怀疑是否所有的内存位置都只有 1 个字节,并且假设如果内存映射说 ROM 的基地址是 0x0000 及其大小是8K(我相信是8 Kilo-bytes = 8 * 1024 bytes,简而言之就是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 位地址线,我们可以说我们有 4,294,967,296 种 1' 和 0 的组合,代表 4,294,967,296 个内存位置,每个位置可容纳 1 字节的数据容量。我的疑问是,因为寄存器是 32 位的,所以它就像一个寄存器有 4 个连续的内存位置(有 4 个不同的地址),因为内存是 1 字节。
我认为这些问题在这个伟大的平台上似乎微不足道,但它会有点帮助
它用简单的术语解释或建议链接。:)
目前的产品以字节为单位寻址内存,可能很少有例外。所以“地址”是一个“字节地址”。现在说当您深入研究逻辑时,在许多情况下总线将具有非字节寻址。例如,如果一个 sram 是 32 位宽,在该 sram 之前你有一个正常的基于字节的地址,通常没有理由保留较低的两个地址位和浪费信号它们在寻址基本上是四个时不被使用字节一次。当您访问 16 位或 32 位控制寄存器(假设是 uart 外围设备中的 uart 波特率寄存器)时,情况也是如此,最终地址的低位被剥离为未使用的 DEEP IN THE LOGIC。
认为当 16 位传输发生到实际 ram 或 rom/flash 或控制寄存器时,这是两个字节的想法是正确的。从字节地址的角度来看,这两个字节可能是 0x40001000 和 0x40001001,但是,作为程序员以及从系统级的角度来看,16 位传输不是在这两个地址上的两字节传输,而是在一个地址上的 16 位传输0x40001000(大端或小端,你提到了 cortex-m 所以在你的情况下基本上是小端)。
虽然有例外,但您可能使用的处理器的总线宽度超过一个字节,cortex-ms 可能是 32 位的,更大的可能是 64 位的,但绝对不是 8 位的。因此,您所做的每一次传输,无论是一个字节、半字、字或双字(64 位),都是通过该总线完成的,并且当您这样做时,您不会神奇地删除芯片中的 wires/signals 它们总是在那里.读取通常(毫无疑问有例外)以完整总线宽度为单位完成,因此如果您要从内存中读取单个字节,您通常会发现系统设计为整个 32 位或 64 位包含该字节被读取,处理器将一个字节 return 从总线中分离出来并丢弃其他字节。对于写入,根据总线规则(因处理器而异)将一个字节放置在总线上,总线上的其他数据线通常由来自总线控制器的垃圾或陈旧数据驱动,或者有时会悬空。根据总线 rules/design 向另一侧的指示以及声明这是一个写入将通过字节掩码指示大小(总线上每个字节通道的一位状态(一或零)指示byte 是 valid/used 而另一个状态表明它不是)或基于字节的长度结合地址等。ARM 倾向于基于字节掩码,您可以阅读它。
了解 ARM 制造处理器 IP 但它不制造芯片,ARM 几乎与芯片供应商连接的内容无关,没有任何规则说地址 0x00000000 是 rom/flash。从历史上看,整个地址 space(大小由购买的内核决定,理想情况下是 32 位,但 arm 并不总是这样,请阅读 arm 网站上的内核文档)对芯片设计者来说是公平的游戏。对核心控制寄存器的访问是通过特殊的协处理器指令完成的。 Cortex-m 的 ARM 确实规定了宽地址范围,如果你想要一个 ROM,你应该把它放在这个范围内,这个范围应该是 sram 并且在这个地址之上是内部地址,对该范围的访问不会在总线上出去它会在核心内部消耗。作为一名芯片设计师,尽管你仍然可以自由地做你想做的事情,但了解核心中的逻辑如何使用这些地址 spaces(如果有缓存,那么可能不会有一个完整的 mcu 所以你想将外围设备的控制寄存器放在范围内 arm 建议避免缓存该地址 space)。
因为处理器(不是芯片)通过检查从地址 0x00000000 开始的前几个字位置处的字来启动,芯片设计者需要为软件开发人员提供一种方法来将他们的向量 table 放在前面这样他们的程序就可以运行了。一些芯片设计者只是简单地将用户闪存的地址设计在相对于 ARM 的那个地址。其他像 stm32,例如 some/many 基于 TI cortex-m 的芯片,使用不同的地址,例如 stm32s all/most 使用 0x08000000,所以在该地址可以完全访问闪存,但在引导期间具有特定设置的芯片组,芯片逻辑将访问基于 0x00000000 的地址的一小部分并访问用户闪存。因此,对于 stm32 系列的开发,您将为 0x08000000 而不是 0x00000000 构建程序以利用整个闪存。 (stm32 可以从 ram 0x20000000 和单独闪存上的内部引导加载程序引导,并且 0x00000000 地址 space 根据引导模式路由到这些资源)。
因此,尽管如此,32 位寄存器通常并不相关,但在这种情况下,它是 32 位寄存器,至少从指令集的角度来看,有一个 32 位地址 space 这意味着 0x100000000 个可能的唯一地址,基于字节。这并不意味着您可以访问这些字节中的每一个而不会在特定芯片实现中崩溃,但从指令集的角度来看,是的,32 位地址,因此 0x10000000 个可能的地址。
通用寄存器,r0,r1,r2,r3。大小为 32 位,它们不是内存映射的,您无法寻址它们。指令集中有指令允许对地址 space 进行 8、16、32、64 次(及更大)访问(ldrb、ldrh、ldr、ldrd、strb、strh、str、strd、ldm/stm).如上所述,总线上发生 8 位或 16 位或 32 或 64 位访问是核心系统设计的一部分,对地址 0x1004 的 64 位写入很可能会成为两个独立的总线传输,一个 32 位,一个在 0x1004 和在 0x1008 进行一次 32 位传输。但是对地址 0x1000 的 64 位写入很可能是一个总线传输,具有一个时钟或两个价值的数据(加上传输开销的少量时钟),具体取决于总线宽度 32 或 64 位。从全部隐藏的指令集角度来看,它只是一条 strd 指令。如果性能是一个目标,那么你想知道你正在使用的 core/chip 的副作用,如果不是,那么按照指令规则使用 strd。
如果一个芯片在其文档中说有 8KBytes 的闪存,那么是的,这意味着 0x8 * 0x400 = 0x2000 所以有 0x2000 个单独的字节可以在该闪存中的地址 space 的 BASE 中访问+0x0000 到 BASE+0x2000-1 或 BASE+0x0000 到 BASE+0x1FFF。如果 BASE 是 0x00000000 那么 0x0000 到 0x1FFF,那是正确的。根据芯片设计等,有些会翻转有些不会所以如果你有一个错误并访问 0x2000 它可能会崩溃它可能 return 垃圾或固定模式或者它可能被屏蔽 0x2000 & 0x1FFF = 0x0000地址 0x0000 处的项目将被 returned。我不会尝试也不会依赖它来工作,除非你在芯片公司工作并且与芯片工程师定期沟通并且有充分的理由这样做(例如检测闪存的大小)。
这并不意味着你 could/should 在地址 0x1FFF 处进行 16 位或 32 位传输,如果你正在进行一个字节(在 arm cortex-m 的情况下为 8 位)传输,那么 0x1FFF 是一个8KByte 闪存的有效地址(通常)。但是 0x1FFE 是 16 位传输的最后地址,0x1FFC 是 32 位传输的最后地址。
旁注:当您作为芯片工程师或电路板设计师工作时,内存通常以位为单位。因此,当芯片设计人员购买或构建 8KByte 闪存时,他们正在寻找 64K 闪存,因为当您购买它们时,存储器是由位定义的(不是您在亚马逊为 PC 购买的记忆棒,而是芯片或 IP)。如果您的计算机中有一个 16 GB 的内存模块,并且该模块有 64 个数据信号和 4 个芯片,这意味着每个芯片 4 GB。但是当您查找该芯片的部件号时,它是一个 32G 芯片,没有 bit/byte 命名法,只是 32G 芯片。根据您的职业发展方向,这些事情会变得多么混乱,这只是火上浇油。即使有几十年的经验,这个事实仍然经常让人们感到困惑,纯硬件人员在订购部件或 IP 时使用位大小,软件人员使用字节大小,而介于两者之间的人员则在努力在团队之间进行转换。如果两个团队互动,通常会出现混淆。 (Hardware/chip 人们自然知道发生了什么,但软件人员往往只关注基于字节的寻址,而不经常自然地在基于位、字节、半字、字等的寻址之间流动)。
简单的解释。 STM32设计者决定划分可用地址space,将内存和内存映射外设放在特定地址
总线架构要复杂得多。它解码地址并访问适当的内存或外围设备。
因此,32 位可以寻址多少字节并不重要,重要的是芯片设计者实现了什么。
因此,如果您的芯片有 64kB 闪存,则意味着您在芯片文档中的地址处有 64k 闪存。
我读到了控制器的基地址和内存映射,我怀疑是否所有的内存位置都只有 1 个字节,并且假设如果内存映射说 ROM 的基地址是 0x0000 及其大小是8K(我相信是8 Kilo-bytes = 8 * 1024 bytes,简而言之就是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 位地址线,我们可以说我们有 4,294,967,296 种 1' 和 0 的组合,代表 4,294,967,296 个内存位置,每个位置可容纳 1 字节的数据容量。我的疑问是,因为寄存器是 32 位的,所以它就像一个寄存器有 4 个连续的内存位置(有 4 个不同的地址),因为内存是 1 字节。
我认为这些问题在这个伟大的平台上似乎微不足道,但它会有点帮助 它用简单的术语解释或建议链接。:)
目前的产品以字节为单位寻址内存,可能很少有例外。所以“地址”是一个“字节地址”。现在说当您深入研究逻辑时,在许多情况下总线将具有非字节寻址。例如,如果一个 sram 是 32 位宽,在该 sram 之前你有一个正常的基于字节的地址,通常没有理由保留较低的两个地址位和浪费信号它们在寻址基本上是四个时不被使用字节一次。当您访问 16 位或 32 位控制寄存器(假设是 uart 外围设备中的 uart 波特率寄存器)时,情况也是如此,最终地址的低位被剥离为未使用的 DEEP IN THE LOGIC。
认为当 16 位传输发生到实际 ram 或 rom/flash 或控制寄存器时,这是两个字节的想法是正确的。从字节地址的角度来看,这两个字节可能是 0x40001000 和 0x40001001,但是,作为程序员以及从系统级的角度来看,16 位传输不是在这两个地址上的两字节传输,而是在一个地址上的 16 位传输0x40001000(大端或小端,你提到了 cortex-m 所以在你的情况下基本上是小端)。
虽然有例外,但您可能使用的处理器的总线宽度超过一个字节,cortex-ms 可能是 32 位的,更大的可能是 64 位的,但绝对不是 8 位的。因此,您所做的每一次传输,无论是一个字节、半字、字或双字(64 位),都是通过该总线完成的,并且当您这样做时,您不会神奇地删除芯片中的 wires/signals 它们总是在那里.读取通常(毫无疑问有例外)以完整总线宽度为单位完成,因此如果您要从内存中读取单个字节,您通常会发现系统设计为整个 32 位或 64 位包含该字节被读取,处理器将一个字节 return 从总线中分离出来并丢弃其他字节。对于写入,根据总线规则(因处理器而异)将一个字节放置在总线上,总线上的其他数据线通常由来自总线控制器的垃圾或陈旧数据驱动,或者有时会悬空。根据总线 rules/design 向另一侧的指示以及声明这是一个写入将通过字节掩码指示大小(总线上每个字节通道的一位状态(一或零)指示byte 是 valid/used 而另一个状态表明它不是)或基于字节的长度结合地址等。ARM 倾向于基于字节掩码,您可以阅读它。
了解 ARM 制造处理器 IP 但它不制造芯片,ARM 几乎与芯片供应商连接的内容无关,没有任何规则说地址 0x00000000 是 rom/flash。从历史上看,整个地址 space(大小由购买的内核决定,理想情况下是 32 位,但 arm 并不总是这样,请阅读 arm 网站上的内核文档)对芯片设计者来说是公平的游戏。对核心控制寄存器的访问是通过特殊的协处理器指令完成的。 Cortex-m 的 ARM 确实规定了宽地址范围,如果你想要一个 ROM,你应该把它放在这个范围内,这个范围应该是 sram 并且在这个地址之上是内部地址,对该范围的访问不会在总线上出去它会在核心内部消耗。作为一名芯片设计师,尽管你仍然可以自由地做你想做的事情,但了解核心中的逻辑如何使用这些地址 spaces(如果有缓存,那么可能不会有一个完整的 mcu 所以你想将外围设备的控制寄存器放在范围内 arm 建议避免缓存该地址 space)。
因为处理器(不是芯片)通过检查从地址 0x00000000 开始的前几个字位置处的字来启动,芯片设计者需要为软件开发人员提供一种方法来将他们的向量 table 放在前面这样他们的程序就可以运行了。一些芯片设计者只是简单地将用户闪存的地址设计在相对于 ARM 的那个地址。其他像 stm32,例如 some/many 基于 TI cortex-m 的芯片,使用不同的地址,例如 stm32s all/most 使用 0x08000000,所以在该地址可以完全访问闪存,但在引导期间具有特定设置的芯片组,芯片逻辑将访问基于 0x00000000 的地址的一小部分并访问用户闪存。因此,对于 stm32 系列的开发,您将为 0x08000000 而不是 0x00000000 构建程序以利用整个闪存。 (stm32 可以从 ram 0x20000000 和单独闪存上的内部引导加载程序引导,并且 0x00000000 地址 space 根据引导模式路由到这些资源)。
因此,尽管如此,32 位寄存器通常并不相关,但在这种情况下,它是 32 位寄存器,至少从指令集的角度来看,有一个 32 位地址 space 这意味着 0x100000000 个可能的唯一地址,基于字节。这并不意味着您可以访问这些字节中的每一个而不会在特定芯片实现中崩溃,但从指令集的角度来看,是的,32 位地址,因此 0x10000000 个可能的地址。
通用寄存器,r0,r1,r2,r3。大小为 32 位,它们不是内存映射的,您无法寻址它们。指令集中有指令允许对地址 space 进行 8、16、32、64 次(及更大)访问(ldrb、ldrh、ldr、ldrd、strb、strh、str、strd、ldm/stm).如上所述,总线上发生 8 位或 16 位或 32 或 64 位访问是核心系统设计的一部分,对地址 0x1004 的 64 位写入很可能会成为两个独立的总线传输,一个 32 位,一个在 0x1004 和在 0x1008 进行一次 32 位传输。但是对地址 0x1000 的 64 位写入很可能是一个总线传输,具有一个时钟或两个价值的数据(加上传输开销的少量时钟),具体取决于总线宽度 32 或 64 位。从全部隐藏的指令集角度来看,它只是一条 strd 指令。如果性能是一个目标,那么你想知道你正在使用的 core/chip 的副作用,如果不是,那么按照指令规则使用 strd。
如果一个芯片在其文档中说有 8KBytes 的闪存,那么是的,这意味着 0x8 * 0x400 = 0x2000 所以有 0x2000 个单独的字节可以在该闪存中的地址 space 的 BASE 中访问+0x0000 到 BASE+0x2000-1 或 BASE+0x0000 到 BASE+0x1FFF。如果 BASE 是 0x00000000 那么 0x0000 到 0x1FFF,那是正确的。根据芯片设计等,有些会翻转有些不会所以如果你有一个错误并访问 0x2000 它可能会崩溃它可能 return 垃圾或固定模式或者它可能被屏蔽 0x2000 & 0x1FFF = 0x0000地址 0x0000 处的项目将被 returned。我不会尝试也不会依赖它来工作,除非你在芯片公司工作并且与芯片工程师定期沟通并且有充分的理由这样做(例如检测闪存的大小)。
这并不意味着你 could/should 在地址 0x1FFF 处进行 16 位或 32 位传输,如果你正在进行一个字节(在 arm cortex-m 的情况下为 8 位)传输,那么 0x1FFF 是一个8KByte 闪存的有效地址(通常)。但是 0x1FFE 是 16 位传输的最后地址,0x1FFC 是 32 位传输的最后地址。
旁注:当您作为芯片工程师或电路板设计师工作时,内存通常以位为单位。因此,当芯片设计人员购买或构建 8KByte 闪存时,他们正在寻找 64K 闪存,因为当您购买它们时,存储器是由位定义的(不是您在亚马逊为 PC 购买的记忆棒,而是芯片或 IP)。如果您的计算机中有一个 16 GB 的内存模块,并且该模块有 64 个数据信号和 4 个芯片,这意味着每个芯片 4 GB。但是当您查找该芯片的部件号时,它是一个 32G 芯片,没有 bit/byte 命名法,只是 32G 芯片。根据您的职业发展方向,这些事情会变得多么混乱,这只是火上浇油。即使有几十年的经验,这个事实仍然经常让人们感到困惑,纯硬件人员在订购部件或 IP 时使用位大小,软件人员使用字节大小,而介于两者之间的人员则在努力在团队之间进行转换。如果两个团队互动,通常会出现混淆。 (Hardware/chip 人们自然知道发生了什么,但软件人员往往只关注基于字节的寻址,而不经常自然地在基于位、字节、半字、字等的寻址之间流动)。
简单的解释。 STM32设计者决定划分可用地址space,将内存和内存映射外设放在特定地址
总线架构要复杂得多。它解码地址并访问适当的内存或外围设备。
因此,32 位可以寻址多少字节并不重要,重要的是芯片设计者实现了什么。
因此,如果您的芯片有 64kB 闪存,则意味着您在芯片文档中的地址处有 64k 闪存。