为什么32位宽度是从位2右移2位呢?
为什么32位宽度是从位2右移2位呢?
为什么不是从位3开始呢?
引自免费微信小程序:皆我百晓生
在STM32F7系列微控制器中,FSMC (Flexible Static Memory Controller) 用于控制不同的外部存储器,包括 NOR Flash、PSRAM 和 NAND Flash 等。这些存储器通常按照固定的宽度进行读写操作,例如8位、16位或32位。
当使用FSMC与外部存储器通信时,它会通过内部的HADDR信号线来提供地址信息。然而,HADDR线是按字节编址的,这意味着它包含了完整的内存地址,即使对于那些按字(16位或32位)寻址的存储器也是如此。为了适应不同宽度的存储器,FSMC会对HADDR中的地址进行适当的调整。
对于16位宽的存储器,FSMC实际上只使用HADDR[25:1]这25位地址,并且为了匹配16位地址格式,它会将这些地址右移一位(除以2)。这样做是因为每个字节有8位,而一个16位的字由两个连续的字节组成。因此,每次移动一位就相当于跳过一个字节,确保了正确的字对齐。
对于32位宽的存储器,情况类似。FSMC使用HADDR[25:2]这24位地址,并且为了匹配32位地址格式,它会将这些地址右移两位(除以4)。这是因为每个字节有8位,一个32位的字由四个连续的字节组成。右移两位意味着每移动一位,就会跳过两个字节,从而确保了正确地访问32位数据。
简而言之,FSMC在构建对外部存储器的实际地址时,通过右移地址来适应存储器的不同宽度,以确保数据按正确的字宽读取或写入。这样做可以简化硬件设计并保持通用性,因为同一套逻辑可以处理不同宽度的存储器。
如果你正在编写相关的驱动程序,你可能需要在计算最终的存储器地址时执行类似的右移操作。下面是一个简单的C语言示例,展示了如何根据存储器宽度调整地址:
#include <stdint.h>
// 假设你有一个函数来设置FSMC的地址
void set_fsmc_address(uint32_t haddr, uint8_t memory_width)
{
switch(memory_width)
{
case 8:
// 对于8位宽的存储器,不需要特殊处理,直接使用HADDR
break;
case 16:
// 对于16位宽的存储器,右移1位
haddr >>= 1;
break;
case 32:
// 对于32位宽的存储器,右移2位
haddr >>= 2;
break;
default:
// 错误处理:不支持的存储器宽度
assert(false);
break;
}
// 设置FSMC地址
fsmc_address_register = haddr;
}
这段代码定义了一个set_fsmc_address
函数,它接受HADDR值和存储器宽度作为参数,并根据宽度进行相应的调整。然后,这个调整后的地址会被设置到FSMC的相关寄存器中。注意,这只是一个概念性的例子,实际的代码可能需要考虑更多的细节,比如错误检查、寄存器的具体名称等。