STM32H743 具有多种不同类型的 RAM,如 ITCM、DTCM、AXI SRAM、SRAM1、SRAM2 等,每种 RAM 都有其特点和适用场景。下面将详细介绍如何充分利用这些 RAM。
各类 RAM 的特点
- ITCM(Instruction Tightly - Coupled Memory):
- 与 CPU 紧密耦合,专门用于存储指令,具有零等待状态,访问速度极快,可显著提高代码执行效率。
- 容量通常较小,STM32H743 中 ITCM 大小为 128KB。
- DTCM(Data Tightly - Coupled Memory):
- 同样与 CPU 紧密耦合,用于存储数据,访问速度快,零等待状态。
- 容量一般为 128KB,适合存储需要快速访问的数据,如关键变量、数组等。
- AXI SRAM:
- 通过 AXI 总线连接到系统,访问速度较快,容量较大(STM32H743 中为 512KB)。
- 可被多个总线主设备(如 CPU、DMA 等)同时访问,适用于数据共享和高速数据传输。
- SRAM1 和 SRAM2:
- 通用静态随机存取存储器,容量分别为 128KB 和 128KB。
- 访问速度相对 AXI SRAM 稍慢,但足以满足大多数应用场景,可用于存储一般性的数据和代码。
使用方法
1. 代码和数据的合理分配
- 将关键代码存放在 ITCM:
- 在 Keil 中,可以通过修改链接脚本(.sct 文件)来指定代码段存储在 ITCM 中。例如:
收起
plaintext
; ITCM 区域定义
LR_IROM1 0x00200000 0x00020000 { ; load region size_region
ER_IROM1 0x00200000 0x00020000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; RW data
.ANY (+RW +ZI)
}
}
- 在 GCC 中,可以通过修改链接脚本(.ld 文件)实现:
收起
plaintext
MEMORY
{
ITCM_RAM (xrw) : ORIGIN = 0x00200000, LENGTH = 128K
DTCM_RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
AXI_SRAM (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
SRAM1 (xrw) : ORIGIN = 0x30000000, LENGTH = 128K
SRAM2 (xrw) : ORIGIN = 0x30020000, LENGTH = 128K
}
SECTIONS
{
.text :
{
*(.text)
} > ITCM_RAM
}
- 将关键数据存放在 DTCM:
- 在 C 语言中,可以使用
__attribute__关键字指定变量存储在 DTCM 中:
- 在 C 语言中,可以使用
收起
c
#define DTCM_RAM __attribute__((section(".dtcm_data")))
DTCM_RAM uint32_t critical_data[100];
- 同时需要在链接脚本中为
.dtcm_data段分配 DTCM 空间。
2. 利用 AXI SRAM 进行数据共享
- AXI SRAM 可被多个总线主设备同时访问,适合用于 DMA 数据传输和多任务间的数据共享。例如,在使用 DMA 进行数据传输时,可以将 DMA 目标地址设置为 AXI SRAM:
收起
c
// 初始化 DMA 传输到 AXI SRAM
DMA_InitTypeDef DMA_InitStruct = {0};
DMA_InitStruct.Direction = DMA_PERIPH_TO_MEMORY;
DMA_InitStruct.PeriphInc = DMA_PINC_DISABLE;
DMA_InitStruct.MemInc = DMA_MINC_ENABLE;
DMA_InitStruct.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
DMA_InitStruct.MemDataAlignment = DMA_MDATAALIGN_BYTE;
DMA_InitStruct.Mode = DMA_NORMAL;
DMA_InitStruct.Priority = DMA_PRIORITY_LOW;
DMA_InitStruct.MemAddress = (uint32_t)0x24000000; // AXI SRAM 起始地址
3. SRAM1 和 SRAM2 的使用
- SRAM1 和 SRAM2 可用于存储一般性的数据和代码。可以在链接脚本中为它们分配相应的段,然后将不需要快速访问的数据和代码存放在这些区域。例如:
收起
plaintext
// GCC 链接脚本中为 SRAM1 分配段
SECTIONS
{
.sram1_data :
{
*(.sram1_data)
} > SRAM1
}
c
// 将变量存放在 SRAM1
#define SRAM1_DATA __attribute__((section(".sram1_data")))
SRAM1_DATA uint8_t general_data[200];
注意事项
- 地址冲突:在使用不同的 RAM 时,要确保各区域的地址不会发生冲突,避免数据混乱。
- 数据一致性:当多个总线主设备同时访问 RAM 时,要注意数据一致性问题,避免出现数据读写错误。可以使用同步机制(如互斥锁)来保证数据的正确性。
- 容量管理:合理规划各 RAM 的使用,避免某个 RAM 区域容量不足,影响系统性能。
在 IAR 中使用 STM32H743 的各类 RAM(如 ITCM、DTCM、AXI SRAM、SRAM1、SRAM2 等),可以通过以下步骤和方法来实现合理分配与使用。
1. 配置内存区域
在 IAR 中,需要在链接器配置文件(通常为 .icf 文件)里对不同的内存区域进行定义和分配。以下是一个示例 .icf 文件的部分内容,展示如何定义 STM32H743 的各类 RAM 区域:
收起
plaintext
// 定义内存区域
define region ITCM_region = mem:[from 0x00200000 size 128K];
define region DTCM_region = mem:[from 0x20000000 size 128K];
define region AXI_SRAM_region = mem:[from 0x24000000 size 512K];
define region SRAM1_region = mem:[from 0x30000000 size 128K];
define region SRAM2_region = mem:[from 0x30020000 size 128K];
// 定义段并分配到相应的内存区域
define symbol __ICFEDIT_intvec_start__ = 0x00200000;
define symbol __ICFEDIT_size_cstack__ = 0x400;
// 代码段分配到 ITCM
place at start of ITCM_region { readonly section .intvec, readonly section .text };
// 数据段分配到 DTCM
place in DTCM_region { section .data, section .bss };
// 其他区域可根据需求分配,例如将一些大数组放到 AXI SRAM
define block LARGE_ARRAY_BLOCK with alignment = 4 {
readonly variable large_array[1024];
};
place in AXI_SRAM_region { block LARGE_ARRAY_BLOCK };
2. 将代码存放在 ITCM
若要将特定的代码存放在 ITCM 中,可以使用 IAR 的 @ 语法或者 __no_init 等关键字。以下是示例代码:
收起
c
// 使用 @ 语法将函数存放在 ITCM
#pragma location = 0x00200000
void critical_function(void) {
// 关键代码
}
3. 将数据存放在 DTCM
可以使用 __no_init 和 __attribute__ 等方式将数据存放在 DTCM 中。示例如下:
收起
c
// 使用 __no_init 和 section 属性将变量存放在 DTCM
__no_init uint32_t critical_data[100] @ 0x20000000;
4. 利用 AXI SRAM 进行数据共享
对于需要多设备访问或者进行 DMA 传输的数据,可以将其存放在 AXI SRAM 中。在代码中可以通过指定地址来访问 AXI SRAM 中的数据。
收起
c
// 定义指向 AXI SRAM 的指针
volatile uint32_t *axi_sram_ptr = (volatile uint32_t *)0x24000000;
// 向 AXI SRAM 写入数据
axi_sram_ptr[0] = 0x12345678;
// 从 AXI SRAM 读取数据
uint32_t read_data = axi_sram_ptr[0];
5. 使用 SRAM1 和 SRAM2
同样可以通过指定地址的方式来使用 SRAM1 和 SRAM2。以下是访问 SRAM1 的示例:
收起
c
// 定义指向 SRAM1 的指针
volatile uint8_t *sram1_ptr = (volatile uint8_t *)0x30000000;
// 向 SRAM1 写入数据
sram1_ptr[0] = 0xAA;
// 从 SRAM1 读取数据
uint8_t read_byte = sram1_ptr[0];
注意事项
- 内存保护:在使用不同的 RAM 区域时,要注意避免越界访问,防止破坏其他区域的数据。
- 初始化问题:对于存放在特定 RAM 区域的数据,要确保其初始化操作符合要求,避免出现未定义行为。
- 链接器配置检查:修改
.icf文件后,要仔细检查链接器的输出信息,确保代码和数据被正确分配到指定的 RAM 区域。

892

被折叠的 条评论
为什么被折叠?



