optimization - 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 并进行位移以访问更高的字节,但从速度优化的角度来看,这似乎代价高昂。这里推荐的做法是什么?
解决方案
在这种情况下,总线大小无关紧要。内存使用情况相同。
一些 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 消耗完全相同
推荐阅读
- flutter - 带有 IndexedStack 的 AnimatedSwitcher
- javascript - react-native-navigation V3 使应用程序崩溃
- android - 如何在 Android Camera API 2 中使用零快门延迟?
- linux - 对 `ldap_msgtype@OPENLDAP_2.4_2' 和许多其他的未定义引用
- spring-security - 如何在本地网络企业中配置 Ldap 认证?
- vue.js - 动态创建 vue 组件
- react-native - 打印反应原生文本和 QR 生成
- java - 在 Android 导航架构中,如何从主机(活动)调用目标片段的方法之一
- javascript - 获取两个元素之间的内容
- java - 授予权限后权限被拒绝