ARM: STM32F7: hardfault caused by unaligned memory access

ARM: STM32F7: 由未对齐的内存访问引起的hardfault异常

Information in this knowledgebase article applies to:

这个知识库文章中的信息适用于:

MDK-ARM Version 5

SYMPTOM

症状

If a STM32F7xx microcontroller is used with an external SDRAM, the Cortex-M7 core may unexpectedly run into the hard fault handler because of an unaligned access. This may happen for example when the frame buffer of a LCD, a RAM filesystem or any other data is located into the SDRAM address range 0xC0000000 - 0xC03FFFFF (max. 4MB). The hardfault is executed although the bit UNALIGN_TRP (bit 3) in the CCR register is not enabled.

如果STM32F7xx微控制器使用了外部SDRAM,Cortex-M7内核可能会由于未对齐的内存访问而意外的进入hardfault异常。当LCD帧缓冲,RAM文件系统或任何其他数据位于SDRAM地址范围0xC0000000 - 0xC03FFFFF (最大. 4MB)时可能出现这种情况。尽管CCR寄存器的UNALIGN_TRP位(位3)没有使能,hardfault异常仍然会被执行。

CAUSE

原因

In general, RAM accesses on Cortex-M7 based devices do not have to be aligned in any way. The Cortex-M7 core can handle unaligned accesses by hardware. Usually variables should be naturally aligned because these accesses are slightly faster than unaligned accesses.

在一般情况下,基于Cortex-M7的设备以任何方式访问RAM都不必对齐。Cortex-M7内核可以硬件处理未对齐的访问。通常变量应该自然对齐的,因为这样的访问比未对齐的访问稍快。

STM32F7xx devices have the external SDRAM mapped to the address range 0xC0000000 - 0xC03FFFFF (max. 4MB). According to the ARMv7-M Architecture Reference Manual chapter B3.1 (table B3-1), the area 0xC0000000-0xDFFFFFFF (32MB) is specified as Device Memory Type. According to chapter A3.2.1, all accesses to Device Memory Types must be naturally aligned. If they are not, a hard fault will be executed no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is enabled or not.

STM32F7xx将外部SDRAM映射到地址范围0xC0000000 - 0xC03FFFFF (最大. 4MB)。根据ARMV7-M架构参考手册第B3.1章(表格 B3-1),范围0xC0000000-0xDFFFFFFF(32MB)作为设备内存类型。根据第A3.2.1章,对设备内存类型的访问必须自然对齐。如果不对齐,hard fault异常将被执行而不管CCR寄存器的UNALIGN_TRP位(位3)是否被使能。

RESOLUTION

解决方案

There are several possible solutions for the STM32F7xx:

针对STM32F7xx的几种解决方案:

1. Enable the MPU for this region

1. 使能该范围的MPU(内存保护单元)

This is the solution we recommend and which we are using in our emWin GUI Demo for this microcontroller. This can be achieved by the following code that needs to be called before the SDRAM is accessed.

这是我们推荐的解决方案并且是我们在该微控制器的emWin GUI Demo中使用的。这可以通过在需要被访问的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);

}

This code initializes the MPU so that the SDRAM memory area is considered as Normal Memory type instead of Device Memory type. This disables the access alignment restrictions.

此代码通过初始化MPU从而使SDRAM内存区域被认为是普通内存类型,而不是设备内存类型。这将禁用访问对齐的限制。

2. Remap the SDRAM to a different address

2.重新映射SDRAM到不同的地址

The SDRAM could also be remapped to address 0x60000000 with the following code:

可以通过以下代码重新映射SDRAM到地址0x60000000:

RCC->APB2ENR   |= RCC_APB2ENR_SYSCFGEN;

SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_1;

The data of the application needs to be linked into this area as well. The disadvantage is that this address area is usually used by external NOR Flash or PSRAM or SRAM. These external memory devices could not be used in this case.

应用的数据必须被链接到这个区域为好。该方案的缺点是,该地址区域通常由外部NOR闪存或PSRAM或SRAM使用。这些外部存储设备在这种情况下将不能使用。

3. Generate code with the natural alignment

3. 生成自然对齐的代码

If only your own code accesses the SDRAM area, you can compile your modules with the compiler option --no_unaligned_access to enforce code which uses natural alignment. This code will then be less efficient. We intentionally do not use this compiler directive for our middleware libraries (graphics, files system and TCP/IP stack) to provide best performance and code density.

如果只有你自己的代码访问SDRAM区域,你可以编译你的模块使用编译器选项--no_unaligned_access执行其采用自然对齐的代码。那么这段代码效率会降低。我们故意不使用该编译器指令对我们的中间件库(图形,文件系统和TCP / IP协议栈),以提供最佳的性能和代码密度。

MORE INFORMATION

Refer to Application Note 209, Using Cortex-M3 and Cortex-M4 Fault Exceptions

ARM: STM32F7: hardfault caused by unaligned memory access的更多相关文章

  1. (转)DMA(Direct Memory Access)

    DMA(Direct Memory Access) DMA(Direct Memory Access)即直接存储器存取,是一种快速传送数据的机制. 工作原理 DMA是指外部设备不通过CPU而直接与系统 ...

  2. NONUNIFORM MEMORY ACCESS

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION In terms of commercia ...

  3. Catch a Memory Access Violation in C++

    From:  https://stackoverflow.com/questions/16612444/catch-a-memory-access-violation-in-c In C++, is ...

  4. numactl 修改 非统一内存访问架构 NUMA(Non Uniform Memory Access Architecture)模式

    当今数据计算领域的主要应用程序和模型可大致分为三大类: (1)联机事务处理(OLTP). (2)决策支持系统(DSS) (3)企业信息通讯(BusinessCommunications) 上述三类系统 ...

  5. CUDA ---- Memory Access

    Memory Access Patterns 大部分device一开始从global Memory获取数据,而且,大部分GPU应用表现会被带宽限制.因此最大化应用对global Memory带宽的使用 ...

  6. [中英对照]Introduction to Remote Direct Memory Access (RDMA) | RDMA概述

    前言: 什么是RDMA? 简单来说,RDMA就是指不通过操作系统(OS)内核以及TCP/IP协议栈在网络上传输数据,因此延迟(latency)非常低,CPU消耗非常少. 下面给出一篇简单介绍RDMA的 ...

  7. DMA(Direct Memory Access)简介

    什么是DMA(Direct Memory Access) DMA绕过CPU,在内存和外设之间开辟了一条 "隧道" ,直接控制内存与外设之间的操作,并完全由硬件控制. 这样数据传送不 ...

  8. Atitit. 。Jna技术与 解决 java.lang.Error: Invalid memory access

    Atitit. .Jna技术与 解决 java.lang.Error: Invalid memory access 1. 原因与解决1 2. jNA (这个ms sun 的)1 3. Code1 4. ...

  9. DMA(direct memory access)直接内存访问

    DMA(Direct Memory Access),这里的 memory,指的是计算机的内存,自然与外存(storage)相对.这里的关键词在 Direct (直接),与传统的相对低效的,需要通过 C ...

随机推荐

  1. js如何判断获取到的值是否在数组中

    很简单,定义一个数组,判断下就得了. var arrayList = [1,2,3,4]; arrayList .indexOf(2); 返回0 arrayList .indexOf(6); 返回1 ...

  2. jmx配置

    # ----- Execute The Requested Command ----------------------------------------- # ----- JMX Config S ...

  3. 关闭编辑easyui datagrid table

    var rows = dg.datagrid('getRows');    for (var i = 0; i < rows.length; i++) {        dg.datagrid( ...

  4. Mybatis框架基于注解的方式,实对数据现增删改查

    编写Mybatis代码,与spring不一样,不需要导入插件,只需导入架包即可: 在lib下 导入mybatis架包:mybatis-3.1.1.jarmysql驱动架包:mysql-connecto ...

  5. laravel框架总结(十一) -- 集合

      创建集合: collect 辅助函数会利用传入的数组生成一个新的 Illuminate\Support\Collection 实例. $collection = collect([1, 2, 3] ...

  6. DirectDraw创建Windows窗口

    KWindow.h  KWindow.cpp KDDrawWindow.cpp #define STRICT #define WIN32_LEAN_AND_MEAN #include <wind ...

  7. 【前端】js中new和Object.create()的区别

    js中new和Object.create()的区别 var Parent = function (id) { this.id = id this.classname = 'Parent' } Pare ...

  8. JQuery获取浏览器窗口的可视区域高度和宽度,滚动条高度

    alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(document).height()); //浏览器时下窗口文档的高度 alert($(docum ...

  9. EF CodeFirst 关系配置

    自从开始学习asp.net mvc采用code first以来,关系配置就没有搞清楚过!(⊙﹏⊙)b 笔记之前先感谢以下文章和博主,对他们表示崇拜,由浅入深.举例恰当.拨云见日.茅塞顿开,还有什么词, ...

  10. VBA中方法传参

    将变量做为参数传递给方法 Sub Test() Dim a As Integer a = Add a Debug.Print a '引用传递,a的值发生了变化,输出101 End Sub Functi ...