现象 如果STM32F7xx微控制器与外部SDRAM一起使用时,由于未对齐访问,Cortex-M7内核可能会意外地进入硬件异常处理程序。 例如,这可能发生在LCD的帧缓冲器、RAM文件系统或任何其它数据位于SDRAM地址范围0xC0000000-0xC03FFFFF(最大4MB)中时。 即使CCR寄存器中的位UNALIGN_TRP(位3)未使能,但仍会产生硬件异常。
原因 一般来说,基于Cortex-M7的器件上的RAM访问不必以任何方式对齐。 Cortex-M7内核可以处理硬件的非对齐访问。 通常变量应该自然对齐,因为这些访问略快于未对齐访问。 STM32F7xx器件的外部SDRAM映射到地址范围0xC0000000 - 0xC03FFFFF(最大4MB)。 根据ARMv7-M体系结构参考手册B3.1章(表B3-1),区域0xC0000000-0xDFFFFFFF(32MB)被指定为Device Memory Type。 根据A3.2.1章节,对Device Memory Type的所有访问必须自然对齐。 如果不是,则将执行硬件异常,无论CCR寄存器中的位UNALIGN_TRP(位3)是否使能。
解决方法 STM32F7xx有几种可能的解决方法: 1. 启用此区域的MPU 这是我们推荐的解决方法,该微控制器的emWin GUI演示中我们使用了该方法。 可以通过在访问SDRAM之前调用的以下代码来实现。 - static void MPU_Config (void) {
- MPU_Region_InitTypeDef MPU_InitStruct;
- /* Disable the MPU */
- HAL_MPU_Disable();
- /* Configure the MPU attributes for SDRAM */
- MPU_InitStruct.Enable = MPU_REGION_ENABLE;
- MPU_InitStruct.BaseAddress = 0xC0000000;
- MPU_InitStruct.Size = MPU_REGION_SIZE_4MB;
- MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
- MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
- MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
- 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_DISABLE;
- HAL_MPU_ConfigRegion(&MPU_InitStruct);
- /* Enable the MPU */
- HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
- }
复制代码该代码初始化MPU,使得SDRAM存储器区域被认为是Normal Memory type,而不是Device Memory type。 这将禁用访问对齐限制。 2. 将SDRAM区域重新映射到不同的地址 SDRAM还可以使用以下代码重映射到地址0x60000000: - RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
- SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_1;
复制代码应用程序的数据也需要链接到此区域。 缺点是该地址区域通常由外部NOR Flash、PSRAM或SRAM使用。 在这种情况下,不能使用这些外部存储器设备。 3. 使用自然对齐生成代码 如果只有自己的代码访问SDRAM区域,则可以使用编译器选项--no_unaligned_access编译模块,以强制使用自然对齐的代码。 这个代码的效率会降低。 我们有意为我们的中间件库(图形,文件系统和TCP / IP堆栈)不使用这个编译器指令,以便提供最佳的性能和代码密度。
参考连接:Application Note 209, Using Cortex-M3 and Cortex-M4 Fault Exceptions |