STM32 Flash对齐技巧详解

这行代码 uint32_t aligned_address = (address + 3) & ~0x03; 是一个经典的位运算技巧,用于将任意地址值向上取整为 4 的倍数。下面从原理到示例详细解释:

一、核心目标:向上对齐到 4 的倍数

  • 对齐需求:STM32 的 32 位 Flash 写入要求地址必须是 4 的倍数(如 0x08010000、0x08010004)
  • 向上取整:无论输入地址是否已经对齐,都返回大于等于该地址的最小 4 的倍数
  • 例如:
  • 输入 0x08010001 → 输出 0x08010004
  • 输入 0x08010004 → 输出 0x08010004(已对齐,保持不变)
  • 二、位运算拆解:(address + 3) & ~0x03

    1. ~0x03 的含义
  • 0x03 的二进制是 0000 0011
  • 按位取反后 ~0x03 变为 1111 1100(即 0xFFFC
  • 作用:这是一个掩码,用于清除二进制数的最后两位(最低 2 位)
  • 2. address + 3 的作用
  • 加 3 的目的:将地址值向上偏移,确保后续取整的正确性
  • 对于未对齐的地址(如 0x08010001),加 3 后会进入下一个 4 的倍数区间
  • 对于已对齐的地址(如 0x08010004),加 3 后仍在下一个 4 的倍数区间的边界内
  • 3. & ~0x03 的作用
  • 通过与 1111 1100 按位与,清除地址的最低 2 位(即模 4 的余数部分)
  • 清除后,地址必然是 4 的倍数
  • 三、示例验证

    示例 1:输入 0x08010001(未对齐)
    1. 加 30x08010001 + 3 = 0x08010004
    2. 按位与0x08010004 & 0xFFFC = 0x08010004
    3. 二进制过程:
      0x08010004 → 0000 1000 0000 0001 0000 0000 0000 0100
      0xFFFC     → 1111 1111 1111 1100
      -----------------------------------
      结果      → 0000 1000 0000 0001 0000 0000 0000 0100 → 0x08010004
      
    示例 2:输入 0x08010004(已对齐)
    1. 加 30x08010004 + 3 = 0x08010007
    2. 按位与0x08010007 & 0xFFFC = 0x08010004
    3. 二进制过程:
      0x08010007 → 0000 1000 0000 0001 0000 0000 0000 0111
      0xFFFC     → 1111 1111 1111 1100
      -----------------------------------
      结果      → 0000 1000 0000 0001 0000 0000 0000 0100 → 0x08010004
      
    示例 3:输入 0x08010003(边界值)
    1. 加 30x08010003 + 3 = 0x08010006
    2. 按位与0x08010006 & 0xFFFC = 0x08010004
    3. 二进制过程:
      0x08010006 → 0000 1000 0000 0001 0000 0000 0000 0110
      0xFFFC     → 1111 1111 1111 1100
      -----------------------------------
      结果      → 0000 1000 0000 0001 0000 0000 0000 0100 → 0x08010004
      

    四、数学原理

    对于任意整数 x,向上取整到 n 的倍数可以表示为:

    ceil(x / n) * n
    

    位运算技巧:当 n 是 2 的幂(如 4、8、16)时,可以简化为:

    (x + (n-1)) & ~(n-1)
    

    推导过程

    1. n-1 的二进制形式是低位全 1(如 0x03 → 0000 0011
    2. ~(n-1) 的二进制形式是低位全 0,高位全 1(如 0xFFFC → 1111 1100
    3. (x + (n-1)) 将值偏移到下一个区间
    4. & ~(n-1) 清除低位,得到对齐结果

    五、通用公式

    对齐目标 代码实现 示例(输入→输出)
    4 字节对齐 (x + 3) & ~0x03 5 → 88 → 8
    8 字节对齐 (x + 7) & ~0x07 10 → 1616 → 16
    16 字节对齐 (x + 15) & ~0x0F 20 → 3232 → 32

    六、在 STM32 Flash 编程中的应用

    当你需要在任意地址写入 32 位数据时,可先对齐地址:

    uint32_t address = 0x08010001;  // 未对齐的地址
    uint32_t aligned_addr = (address + 3) & ~0x03;  // 对齐到0x08010004
    
    // 安全写入
    FLASH_ProgramWord(aligned_addr, 0x12345678);
    

    七、注意事项

    1. 仅适用于 2 的幂对齐:该技巧只对 n=2^k 有效(如 4、8、16)
    2. 数据类型匹配:32 位对齐适用于 FLASH_ProgramWord(),16 位对齐适用于 FLASH_ProgramHalfWord()
    3. 溢出风险:如果 address 接近 UINT32_MAX,加 3 可能导致溢出(实际应用中 Flash 地址远小于此值,通常安全)

    掌握这种位运算对齐技巧,能帮助你高效处理 STM32 Flash 编程中的地址约束问题。

    作者:weixin_58038206

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32 Flash对齐技巧详解

    发表回复