STM32H7 内部SRAM空间的配置使用

STM32H7 内部SRAM空间的配置使用


STM32H750xB器件集成了高速嵌入式存储器,配有128 KB的Flash内存,高达1 MB的RAM(包括192 KB的TCM RAM、高达864 KB的用户SRAM和4 KB的备份SRAM),以及大量连接到APB总线、AHB总线、2个32位多AHB总线矩阵的增强型I/O和外设,支持内部及外部存储器访问的多层AXI互连。

📘内部 SRAM

STM32H7x3 器件具有:

  • 多达 864 KB 的系统 SRAM
  • 128 KB 的数据 TCM RAM
  • 64 KB 的指令 TCM RAM
  • 4 K 字节的备份 SRAM
    嵌入式系统 SRAM 最多可分为五个块:
    • AXI SRAM(D1 域):
      – 映射到地址 0x2400 0000 的 AXI SRAM,可供除 BDMA 外的所有系统主设备通过 D1 域 AXI 总线矩阵访问.
  • 6 个从接口端 ASIB1 到 ASIB6外接的主控是 LTDC,DMA2D,MDMA,SDMMC1,AXIM 和 D2-to-D1 AHB 总线。
  • 7 个主接口端 AMIB1 到 AMIB7外接的从设备是 AHB3 总线,Flash A,Flash B,FMC 总线,QSPI 和 AXI SRAM。另外 AHB3,也是由 AXI 总线分支出来的,然后再由 AHB3 分支出 APB3 总线。
    • AHB SRAM(D2 域):
      – 映射到地址 0x3000 0000 的 AHB SRAM1,可供除 BDMA 外的所有系统主设备通过 D2 域 AHB 矩阵访问
      – 映射到地址 0x3002 0000 的 AHB SRAM2,可供除 BDMA 外的所有系统主设备通 过 D2 域 AHB 矩阵访问
      – 映射到地址 0x3004 0000 的 AHB SRAM3,可供除 BDMA 外的所有系统主设备通 过 D2 域 AHB 矩阵访问
  • 10 个从接口:外接的主控是 D1-to-D2 AHB 总线,AHBP 总线,DMA1,DMA2,Ethernet MAC,SDMMC2,
    USB HS1 和 USB HS2。
  • 9 个主接口:外接的从设备是 SRAM1,SRMA2,SRAM3,AHB1,AHB2,APB1,APB2,D2-to-D1 AHB
    总线和 D2-to-D3 AHB 总线
    • AHB SRAM(D3 域):
      – 映射到地址 0x3800 0000 的 AHB SRAM4,可供大多数系统主设备通过 D3 域 AHB 矩阵访问系统 AHB SRAM 可按字节、半字(16 位单元)或全字(32 位单元)访问,而系统 AXI SRAM 可按字节、半字、全字或双字(64 位单位)访问。这些存储器可在最高系统时钟频率下以 0 等待周期寻址。
      当 AHB 主设备对 SRAM 中的一部分进行读/写访问的同时,以太网 MAC 或 USB OTG HS 外设可以访问 SRAM 的另一部分。例如,以太网 MAC 访问 SRAM2,同时 CPU 访SRAM1。
      TCM SRAM 专用于 Cortex®-M7:
    • TCM 接口上的 DTCM-RAM 映射到地址 0x2000 0000,可供 Cortex®-M7 访问,并且可供 MDMA 通过 Cortex®-M7 CPU 的 AHBS 从总线访问。
    • TCM 接口上的 ITCM-RAM 映射到地址 0x0000 0000,可供 Cortex®-M7 访问,并且可供 MDMA 通过 Cortex®-M7 CPU 的 AHBS 从总线访问。
      备份 RAM 映射到地址 0x3880 0000,可供大多数系统主设备通过 D3 域的 AHB 矩阵访问。
  • 3 个从接口:外接的主控 D1-to-D3 AHB 总线,D2-to-D3 AHB 总线和 BDMA。
  • 2 个主接口:外接的从设备是 AHB4,SRAM4 和 Bckp SRAM。另外 AHB4 也是这个总线矩阵分支出来的,然后再由 AHB4 分支出 APB4 总线.
📗各块 RAM 特性

各块 RAM 的特性对比如下,特别注意他们支持的最大速度和容量大小。
◆ TCM 区
TCM : Tightly-Coupled Memory 紧密耦合内存 。ITCM 用于运行指令,也就是程序代码,DTCM
用于数据存取,特点是跟内核速度一样,而片上 RAM 的速度基本都达不到这个速度,所以有降频处
理。
速度:400MHz。
DTCM 地址:0x2000 0000,大小 128KB。
ITCM 地址:0x0000 0000,大小 64KB。
◆ AXI SRAM 区
位于 D1 域,数据带宽是 64bit,挂在 AXI 总线上。除了 D3 域中的 BDMB 主控不能访问,其它都可
以访问此 RAM 区。
速度:200MHz。
地址:0x2400 0000,大小 512KB。
用途:用途不限,可以用于用户应用数据存储或者 LCD 显存。
◆ SRAM1,SRAM2 和 SRAM3 区
位于 D2 域,数据带宽是 32bit,挂在AHB 总线上。除了 D3域中的 BDMB主控不能访问这三块SRAM,
其它都可以访问这几个 RAM 区。
速度:200MHz。
SRAM1:地址 0x3000 0000,大小 128KB,用途不限,可用于 D2 域中的 DMA 缓冲,也可以当
D1 域断电后用于运行程序代码。
SRAM2:地址 0x3002 0000,大小 128KB,用途不限,可用于 D2 域中的 DMA 缓冲,也可以用于
用户数据存取。
SRAM3:地址 0x3004 0000,大小 32KB,用途不限,主要用于以太网和 USB 的缓冲。
◆ SRAM4 区
位于 D3 域,数据带宽是 32bit,挂在 AHB 总线上,大部分主控都能访这块 SRAM 区。
速度:200MHz。
地址:0x3800 0000,大小 64KB。
用途:用途不限,可以用于 D3 域中的 DMA 缓冲,也可以当 D1 和 D2 域进入 DStandby 待机方式后,继续保存用户数据。
◆ Backup SRAM 区
备份 RAM 区,位于 D3 域,数据带宽是 32bit,挂在 AHB 总线上,大部分主控都能访问这块 SRAM区。
速度:200MHz。
地址:0x3880 0000,大小 4KB。
用途:用途不限,主要用于系统进入低功耗模式后,继续保存数据(Vbat 引脚外接电池)。

  • 📄外设内存映射地址,在stm32h750xx.h文件中定义:
/** @addtogroup Peripheral_memory_map
  * @{
  */
#define D1_ITCMRAM_BASE           (0x00000000UL) /*!< Base address of : 64KB RAM reserved for CPU execution/instruction accessible over ITCM  */
#define D1_ITCMICP_BASE           (0x00100000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over ITCM         */
#define D1_DTCMRAM_BASE           (0x20000000UL) /*!< Base address of : 128KB system data RAM accessible over DTCM                            */
#define D1_AXIFLASH_BASE          (0x08000000UL) /*!< Base address of : (up to 128 KB) embedded FLASH memory accessible over AXI      */
#define D1_AXIICP_BASE            (0x1FF00000UL) /*!< Base address of : (up to 128KB) embedded Test FLASH memory accessible over AXI          */
#define D1_AXISRAM_BASE           (0x24000000UL) /*!< Base address of : (up to 512KB) system data RAM accessible over over AXI                */

#define D2_AXISRAM_BASE           (0x10000000UL) /*!< Base address of : (up to 288KB) system data RAM accessible over over AXI                */
#define D2_AHBSRAM_BASE           (0x30000000UL) /*!< Base address of : (up to 288KB) system data RAM accessible over over AXI->AHB Bridge    */

#define D3_BKPSRAM_BASE           (0x38800000UL) /*!< Base address of : Backup SRAM(4 KB) over AXI->AHB Bridge                                */
#define D3_SRAM_BASE              (0x38000000UL) /*!< Base address of : Backup SRAM(64 KB) over AXI->AHB Bridge                               */

#define PERIPH_BASE               (0x40000000UL) /*!< Base address of : AHB/APB Peripherals                                                   */
#define QSPI_BASE                 (0x90000000UL) /*!< Base address of : QSPI memories  accessible over AXI                                    */

#define FLASH_BANK1_BASE          (0x08000000UL) /*!< Base address of : (up to 128 KB) Flash Bank1 accessible over AXI                        */
#define FLASH_BANK2_BASE          (0x08100000UL) /*!< For legacy only , Flash bank 2 not available on STM32H750xx value line          */
#define FLASH_END                 (0x0801FFFFUL) /*!< FLASH end address                                                                       */

/* Legacy define */
#define FLASH_BASE                FLASH_BANK1_BASE

/*!< Device electronic signature memory map */
#define UID_BASE                  (0x1FF1E800UL)            /*!< Unique device ID register base address */
#define FLASHSIZE_BASE            (0x1FF1E880UL)            /*!< FLASH Size register base address */

🌟各块 RAM 的 DMA 问题
  • Bus Master 总线主控端和 Bus Slave 设备端的控制互联::
    在这里插入图片描述
  • 加粗字体是 64 位总线(ITCM,DTCM,Flash A,Flash,AXI SRAM,FMC 等),普通字体是 32位总线。
  • 访问通路(每个小方块里面的字符);
  • 任何有数字的表示有访问通路。
  • 短横杠“-”表示不可访问。
  • 有灰色阴影的表示有实用价值的访问通路
  • 总线访问类型:

普通字体表示 32 位总线。
斜体表示 32 位总线主机端/ 64 位总线从机端。
粗体表示 64 位总线.

  • 以上相关内容参考来源安富莱_STM32-V7开发板_用户手册
📒通过这个总线互联图,要了解到下面三个重要知识点:

◆ DTCM 和 ITCM 不支持 DMA1,DMA2 和 BDMA,仅支持 MDMA。
◆ AXI SRAM,SRAM1,SRAM2,SRAM3 不支持 BDMA,支持 MDMA,DMA1 和 DMA2。
◆ SRAM4 支持所有 DMA,即 MDMA,DMA1,DMA2 和 BDMA

🛠配置使用

  • 用户变量定义到指定的CCM 或者SRAM中:
//AC5 Compliler
__align(4) uint8_t SendBuff[SEND_BUF_SIZE]__attribute((at(0X24040000)));
//__ARMCC_VERSION >= 6010050
 __attribute__((section (".RAM_D3"))) uint8_t g_spiTxBuf[SPI_BUFFER_SIZE];
  • 采用4字节对齐方式
#if defined ( __ICCARM__ ) /* IAR Compiler */
  #pragma data_alignment=4
#endif /* defined ( __ICCARM__ ) */
/* Internal string descriptor. */
__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END;

#if defined ( __ICCARM__ ) /*!< IAR Compiler */
  #pragma data_alignment=4
#endif
__ALIGN_BEGIN uint8_t USBD_StringSerial[USB_SIZ_STRING_SERIAL] __ALIGN_END = {
  USB_SIZ_STRING_SERIAL,
  USB_DESC_TYPE_STRING,
};

......

uint8_t USART_RX_BUF[64*2] __attribute__((section(".ARM.__at_0x24000000")));

📘自定义分散加载(.SCT)文件

在这里插入图片描述

  • 🌿片内启动,片上RAM配置(Start addr:0x08000000)
LR_IROM1 0x08000000 0x00200000 { ; load region size_region
 ER_IROM1 0x08000000 0x00200000 { ; load address = execution address
 *.o (RESET, +First)
 *(InRoot$$Sections)
 .ANY (+RO)
 }
 
 ; RW data - 128KB DTCM
 RW_IRAM1 0x20000000 0x00020000 { 
 .ANY (+RW +ZI)
 }
 
 ; RW data - 512KB AXI SRAM
 RW_IRAM2 0x24000000 0x00080000 { 
 *(.RAM_D1) 
 }
 
 ; RW data - 128KB SRAM1(0x30000000) + 128KB SRAM2(0x3002 0000) + 32KB SRAM3(0x30040000)
 RW_IRAM3 0x30000000 0x00048000 { 
 *(.RAM_D2)
 }
 
 ; RW data - 64KB SRAM4(0x38000000)
 RW_IRAM4 0x38000000 0x00010000 { 
 *(.RAM_D3)
 }
  • 🌿片外启动,片上RAM配置(Start addr:0x90000000)
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x90000000 0x20000000  {    ; load region size_region
  ER_IROM1 0x90000000 0x20000000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data - 128KB DTCM
   .ANY (+RW +ZI)
  }
  RW_IRAM2 0x24000000 0x00080000  {   ; RW data - 512KB AXI SRAM
   .ANY (+RW +ZI)
  }
  ; RW data - 128KB SRAM1(0x30000000) + 128KB SRAM2(0x3002 0000) + 32KB SRAM3(0x30040000)
 RW_IRAM3 0x30000000 0x00048000 { 
 *(.RAM_D2)
 }
 
 ; RW data - 64KB SRAM4(0x38000000)
 RW_IRAM4 0x38000000 0x00010000 { 
 *(.RAM_D3)
 }
}
  • 🔖以下内容参考来自:安富莱stm32-V7用户手册
  • LR_IROM1 是 Load Region 加载域,ER_IROM1 是 Execution Region 执行域。首地址都是 0x0800 0000,大小都是 0x0020 0000,即 STM32H7 的 Flash 地址和对应大小。
  • 加载域就是程序在 Flash 中的实际存储,而运行域是芯片上电后的运行状态,通过下面的框图可以有一个感性的认识:
    在这里插入图片描述
    通过上面的框图可以看出,RW 区也是要存储到 ROM/Flash 里面的,在执行映像之前,必须将已初始化的 RW 数据从 ROM 中复制到 RAM 中的执行地址并创建 ZI Section(初始化为 0 的变量区)。
  • 的*.o (RESET, +First):在启动文件 startup_stm32h750xx.s 有个段名为 RESET 的代码段,主要存储了中断向量表。这里是将其存放在 Flash 的首地址。
  • *(InRoot$$Sections):将 MDK 的一些库文件全部放在根域,比如__main.o, _scatter*.o, _dc*.o
  • .ANY (+RO):将目标文件中所有具有 RO 只读属性的数据放在这里,即 ER_IROM1。
  • RW_IRAM1 是执行域,配置的是 DTCM,首地址 0x2000 0000,大小 128KB。将目标文件中所有具有 RW 和 ZI 数据放在这里。
  • RW_IRAM2 是执行域,配置的是 AXI SRAM,首地址 0x24000000,大小 512KB。给这个域专门配了一个名字 .RAM_D1。这样就可以通过__attribute__((section(“name”)))将其分配到这个 RAM 域。
  • RW_IRAM3 是执行域,配置的是 D2 域的 SRAM1,SRAM2 和 SRAM3,首地址0x30000000,共计大小 288KB。给这个域专门配了一个名字 .RAM_D2。这样就可以通过__attribute__((section(“name”)))将其分配到这个 RAM 域。
  • RW_IRAM3 是执行域,配置的是 D3 域的 SRAM4,首地址 0x38000000,共计大小
    64KB。给这个域专门配了一个名字 .RAM_D3。这样就可以通过__attribute__((section(“name”))),将其分配到这个 RAM 域。
  • 在外设开启DMA传输模式下同时启用了I缓存和D缓存下,有必要开启这样的设置,不然读取的数据容易出错。
  • I缓存和D缓存启用下,串口DMA传输:
					SCB_CleanDCache_by_Addr((uint8_t *)USART_RX_BUF, len);
//					SCB_CleanInvalidateDCache_by_Addr ((uint8_t *)USART_RX_BUF, len);//或者
					HAL_UART_Transmit_DMA(&huart1,(uint8_t *)USART_RX_BUF, len);//配合上面的函数一起使用
  • 读取数据操作:
    在这里插入图片描述
  • I缓存和D缓存启用,接收数组变量指定SRAM情况下,读取数据可以不用在读前读后,分别作启用和禁用的操作。不包括上面表中:短横杠“-”表示不可访问的外设。

📑相关函数

  • 🌿void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize):D-Cache Clean by address
  • 作用: 用于清除指定地址范围内的数据缓存。它将缓存中的数据写回到主存储器中,以确保缓存中的数据与主存储器中的数据一致。
  • 使用场景: 当你需要确保某个特定内存区域的数据已经被更新到主存储器时,可以使用这个函数。例如,在将数据写入外设之前,或者在修改了关键数据之后。
  • 🌿void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize):D-Cache Clean and Invalidate by address
  • 作用: 这个函数不仅会清除指定地址范围内的数据缓存,还会使这些缓存行无效。这意味着在调用这个函数后,处理器将不会从缓存中读取这些地址的数据,而是直接从主存储器中读取。
  • 使用场景: 当你需要确保某个内存区域的数据是最新的,并且不希望处理器从缓存中读取旧的数据时,可以使用这个函数。例如,在加载新的程序代码或数据到内存中之后。
  • 🌿 SCB_CleanDCache()函数:
    作用: 这个函数用于将数据缓存中的数据写回到主存储器中,以确保缓存中的数据与主存储器中的数据一致。这通常在以下情况下使用:
    在将数据写入外设之前,确保数据已经更新到主存储器。
    在修改了关键数据之后,确保这些数据已经被正确地写回到主存储器。
    特点: 只执行写回操作,不使缓存行无效。这意味着处理器仍然可以从缓存中读取数据,即使这些数据已经被写回到主存储器。
  • 🌿 SCB_CleanInvalidateDCache() 函数:
    作用: 这个函数不仅会将数据缓存中的数据写回到主存储器,还会使这些缓存行无效。这意味着在调用这个函数后,处理器将不会从缓存中读取这些地址的数据,而是直接从主存储器中读取。这通常在以下情况下使用:
    在加载新的程序代码或数据到内存中之后,确保处理器使用的是最新的数据。
    在需要确保数据一致性的关键操作之前,例如系统启动或上下文切换。
    特点: 执行写回操作并且使缓存行无效。这确保了处理器在需要时总是从主存储器中获取最新的数据。

📙MPU内存保护单元

  • 📌ST32 MPU应用笔记AN4838文档推荐:https://www.st.com/resource/zh/application_note/an4838-managing-memory-protection-unit-in-stm32-mcus-stmicroelectronics.pdf
    MPU 可以将 memory map 内存映射区分为多个具有一定访问规则的区域,通过这些规则可以实现如下功能:
    ◆ 防止不受信任的应用程序访问受保护的内存区域。
    ◆ 防止用户应用程序破坏操作系统使用的数据。
    ◆ 通过阻止任务访问其它任务的数据区。
    ◆ 允许将内存区域定义为只读,以便保护重要数据。
    ◆ 检测意外的内存访问。

简单的说就是内存保护、外设保护和代码访问保护。

STM32H7的MPU提供多达16个可编程保护区域(region),每个区域(region)都有自己的可编程起始地址、大小及设置。MPU功能必须开启才会有效,MPU默认处于关闭的状态,使用MPU,必须先启用MPU才行.

  • 配置MPU保护块
/*
*********************************************************************************************************
* 函 数 名: MPU_Config
* 功能说明: 保护整个AXI SRAM,共512K字节,允许指令访问,禁止共用,允许cache,允许缓冲
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void MPU_Config( void )
{
MPU_Region_InitTypeDef MPU_InitStruct;
/* 禁止 MPU */
HAL_MPU_Disable();
/* 配置 AXI SRAM 的 MPU 属性为 Write back, Read allocate,Write allocate */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x24000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_512KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;//允许缓冲
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;//允许cache
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;//禁止共用
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/*使能 MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
  • 🌿片外启动MPU初始化配置:
void MPU_RegionConfig(void)
{
 /* Disable MPU */
 HAL_MPU_Disable();
    /* 设置QSPI FLASH空间的MPU保护 */
    SCB->SHCSR &= ~(1 << 16);       /* 禁止MemManage */
    MPU->CTRL &= ~(1 << 0);         /* 禁止MPU */
    MPU->RNR = 0;                   /* 设置保护区域编号为0(1~7可以给其他内存用) */
    MPU->RBAR = 0X90000000;         /* 基地址为0X9000 000, 即QSPI的起始地址 */
    MPU->RASR = 0X0303002D;         /* 设置相关保护参数(禁止共用, 允许cache, 允许缓冲), 详见MPU实验的解析 */
    MPU->CTRL = (1 << 2) | (1 << 0);/* 使能PRIVDEFENA, 使能MPU */
    SCB->SHCSR |= 1 << 16;          /* 使能MemManage */
 /* Enable MPU */
 HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值