首页 > 解决方案 > ARM 设备中的 SRAM 使用优化

问题描述

变量大小和数据总线大小之间的关系让我感到困惑,所以我决定通过检查汇编代码来深入了解它。我在STM32CubeIDE Version 1.2.0中编译了下面的源代码。

#define BUFFER_SIZE         ((uint8_t)0x20)

uint8_t aTxBuffer[BUFFER_SIZE];
int i;  

for(i=0; i<BUFFER_SIZE; i++){
        aTxBuffer[i]=0xFF;   /* TxBuffer init */
}

查看汇编代码证实了我的怀疑。除非我严重误解它,否则这段代码将分配一个总大小为 BUFFER_SIZE * DATA_BUS_SIZE 的数组(在 Cortex-M 上为 32 位),但我们将只使用每个内存地址的最低有效字节。

for(i=0; i<BUFFER_SIZE; i++)
//reset i to 0
 800051c:   4b09        ldr r3, [pc, #36]   ; (8000544 <main+0x3c>)         
 800051e:   2200        movs    r2, #0                          
 8000520:   601a        str r2, [r3, #0]                        
 8000522:   e009        b.n 8000538 <main+0x30>                 
    {
//store 0xFF in each member of TxBuffer
        aTxBuffer[i]=0xFF;   /* TxBuffer init */
 8000524:   4b07        ldr r3, [pc, #28]   ; (8000544 <main+0x3c>)
 8000526:   681b        ldr r3, [r3, #0]
 8000528:   4a07        ldr r2, [pc, #28]   ; (8000548 <main+0x40>)
 800052a:   21ff        movs    r1, #255    ; 0xff
 800052c:   54d1        strb    r1, [r2, r3]
    for(i=0; i<BUFFER_SIZE; i++)
//increment i
 800052e:   4b05        ldr r3, [pc, #20]   ; (8000544 <main+0x3c>)
 8000530:   681b        ldr r3, [r3, #0]
 8000532:   3301        adds    r3, #1
 8000534:   4a03        ldr r2, [pc, #12]   ; (8000544 <main+0x3c>)
 8000536:   6013        str r3, [r2, #0]
//compare if i is less than 31. then jump to 8000524
 8000538:   4b02        ldr r3, [pc, #8]    ; (8000544 <main+0x3c>)
 800053a:   681b        ldr r3, [r3, #0]
 800053c:   2b1f        cmp r3, #31
 800053e:   d9f1        bls.n   8000524 <main+0x1c>
//pointer to i in SRAM
 8000544:   2000002c    .word   0x2000002c
//pointer to TxBuffer in SRAM 
 8000548:   20000064    .word   0x20000064

由于 SRAM 在嵌入式设备中非常重要,我相信必须有一些巧妙的方法来优化使用。我能想到的一种天真的解决方案是将缓冲区分配为 uint32_t 并进行位移以访问更高的字节,但从速度优化的角度来看,这似乎代价高昂。这里推荐的做法是什么?

标签: optimizationmemoryarmstm32

解决方案


在这种情况下,总线大小无关紧要。内存使用情况相同。

一些 Cortex 内核不允许非对齐访问。什么是非对齐访问?当您尝试访问(作为单个操作)从不能被 N 整除的地址(即 addr % N != 0)开始的 N 字节数据时,会发生未对齐的内存访问。在我们的例子中,N 可以是 1、2 和 4。

您的示例应该在打开优化的情况下进行分析。

#define BUFFER_SIZE         ((uint8_t)0x20)

uint8_t aTxBuffer[BUFFER_SIZE];

void init(uint8_t x)
{
    for(int i=0; i<BUFFER_SIZE; i++)
    {
            aTxBuffer[i]=x;   
    }
}

不允许未对齐访问的 STM32F0 将不得不逐字节存储数据

init:
  ldr r3, .L5
  movs r2, r3
  adds r2, r2, #32
.L2:
  strb r0, [r3]
  adds r3, r3, #1
  cmp r3, r2
  bne .L2
  bx lr
.L5:
  .word aTxBuffer

但是 stm32F4 会更快(在更少的操作中)存储完整的单词 32birs - 4 个字节。

init:
        movs    r3, #0
        bfi     r3, r0, #0, #8
        bfi     r3, r0, #8, #8
        ldr     r2, .L3
        bfi     r3, r0, #16, #8
        bfi     r3, r0, #24, #8
        str     r3, [r2]  @ unaligned
        str     r3, [r2, #4]      @ unaligned
        str     r3, [r2, #8]      @ unaligned
        str     r3, [r2, #12]     @ unaligned
        str     r3, [r2, #16]     @ unaligned
        str     r3, [r2, #20]     @ unaligned
        str     r3, [r2, #24]     @ unaligned
        str     r3, [r2, #28]     @ unaligned
        bx      lr
.L3:
        .word   aTxBuffer

两种情况下的 SRAM 消耗完全相同


推荐阅读