6969#define SDRAM_SIZE (16 * 1024 * 1024)
7070#define SDRAM_START ((void *)FSMC_Bank5_MAP_BASE)
7171
72+ void SetupDeviceMemoryToEliminateUnalignedAccess ();
73+
7274// SDRAM driver configuration structure.
7375static const SDRAMConfig sdram_cfg = {
7476 .sdcr = (uint32_t )FMC_ColumnBits_Number_8b | FMC_RowBits_Number_12b | FMC_SDMemory_Width_32b |
@@ -92,11 +94,67 @@ static const SDRAMConfig sdram_cfg = {
9294
9395void Target_ExternalMemoryInit ()
9496{
97+ SetupDeviceMemoryToEliminateUnalignedAccess ();
9598 fsmcSdramInit ();
96-
97- // FIXME
98- // this swaps SDRAM address to 0x60000000 and makes it L1 cacheable
99- // SYSCFG->MEMRMP |= SYSCFG_MEMRMP_SWP_FMC_0;
100-
10199 fsmcSdramStart (& SDRAMD , & sdram_cfg );
102100}
101+
102+ void SetupDeviceMemoryToEliminateUnalignedAccess ()
103+ {
104+ // ARM: STM32F7: hard fault caused by unaligned Memory Access
105+ // reference https://www.keil.com/support/docs/3777%20%20.htm
106+ // SYMPTOM
107+ // If you use an STM32F7xx microcontroller with an external SDRAM,
108+ // the Cortex-M7 core may unexpectedly run into the hard fault handler because of unaligned access.
109+ // This may happen for example, when the frame buffer of an LCD, a RAM filesystem or any other data is
110+ // located into the SDRAM address range 0xC0000000 - 0xC03FFFFF (max. 4MB).
111+ // The hard fault is executed although the bit UNALIGN_TRP (bit 3) in the CCR register is not enabled.
112+
113+ // CAUSE
114+ // In general, RAM accesses on Cortex-M7 based devices do not have to be aligned in any way.
115+ // The Cortex-M7 core can handle unaligned accesses by hardware.
116+ // Usually, variables should be naturally aligned because these accesses are slightly faster than unaligned
117+ // accesses.
118+
119+ // STM32F7xx devices have the external SDRAM mapped to the
120+ // address range 0xC0000000 - 0xC03FFFFF (max. 4MB).
121+ // According to the ARMv7-M Architecture Reference Manual chapter B3.1 (table B3-1),
122+ // the area 0xC0000000-0xDFFFFFFF (32MB) is specified as Device Memory Type.
123+ // According to chapter A3.2.1, all accesses to Device Memory Types must be naturally aligned.
124+ // If they are not, a hard fault will execute no matter if the bit UNALIGN_TRP (bit 3) in the CCR register is
125+ // enabled or not.
126+
127+ // Solution recommended by KEIL
128+
129+ #define MPU_REGION_ENABLE ((uint8_t)0x01U)
130+ #define MPU_REGION_SIZE_4MB ((uint8_t)0x15)
131+ #define MPU_REGION_FULL_ACCESS ((uint8_t)0x03U)
132+ #define MPU_ACCESS_NOT_BUFFERABLE ((uint8_t)0x00U)
133+ #define MPU_ACCESS_NOT_CACHEABLE ((uint8_t)0x00U)
134+ #define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U)
135+ #define MPU_ACCESS_NOT_SHAREABLE ((uint8_t)0x00U)
136+ #define MPU_REGION_NUMBER0 ((uint8_t)0x00U)
137+ #define MPU_TEX_LEVEL1 ((uint8_t)0x01U)
138+ #define MPU_INSTRUCTION_ACCESS_DISABLE ((uint8_t)0x01U)
139+ #define MPU_PRIVILEGED_DEFAULT ((uint32_t)0x00000004U)
140+
141+ // Disable the MPU
142+ __DMB ();
143+ SCB -> SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk ;
144+ MPU -> CTRL = 0 ;
145+
146+ // Configure the region
147+ MPU -> RNR = MPU_REGION_NUMBER0 ;
148+ MPU -> RBAR = 0xC0000000 ;
149+ MPU -> RASR = (MPU_INSTRUCTION_ACCESS_DISABLE << MPU_RASR_XN_Pos ) | (MPU_REGION_FULL_ACCESS << MPU_RASR_AP_Pos ) |
150+ (MPU_TEX_LEVEL1 << MPU_RASR_TEX_Pos ) | (MPU_ACCESS_NOT_SHAREABLE << MPU_RASR_S_Pos ) |
151+ (MPU_ACCESS_NOT_CACHEABLE << MPU_RASR_C_Pos ) | (MPU_ACCESS_NOT_BUFFERABLE << MPU_RASR_B_Pos ) |
152+ (0x00 << MPU_RASR_SRD_Pos ) | (MPU_REGION_SIZE_4MB << MPU_RASR_SIZE_Pos ) |
153+ (MPU_REGION_ENABLE << MPU_RASR_ENABLE_Pos );
154+
155+ // Enable the MPU
156+ MPU -> CTRL = MPU_PRIVILEGED_DEFAULT | MPU_CTRL_ENABLE_Msk ;
157+ SCB -> SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk ;
158+ __DSB ();
159+ __ISB ();
160+ }
0 commit comments