Hi there!
I have a strange problem after relocating a portion of software to another part of the flash memory.
First of all a little description of my configuration. I have got two separate programs installed in the same controller (STM32F427ZGT6, i am using using Keil v5.20, Pro version).
First part is a kind of a bootloader which is positioned at 0x80000000, and the second part starts at 0x80010000. Of course bootloader after proper start relocates vector table to 0x80010000 and moves the PC to 0x80010000. And that's really fine. Everything works perfect in such a configuration.
But the problem appears when the address is not 0x80010000, but 0x80020000 and above. When i relocate the main portion of software to 0x80020000 program hangs and stops on HardFault.
As far as i see the program stops on rt_memcpy_w function. But sometimes the "caller" of HardFault points to 0x0 adress, not to rt_memcpy_w. I've tried other adresses - 0x80030000 and so on. But the situation is the same.
I have to move the second portion of the software because of additional functions in the bootloader part, so now it's code is more than 0x10000 bytes.
I've checked the reference manual about the memory map, but i haven't found any clue for such a behavior.
Thanks in advance for any help!
Hello Michal,
I am glad you got the code working.
There is also a "VTOR relocate" code snippet here:
www.keil.com/.../using_VTOR_pg.html
Maybe not for this device (but others) you might need a barrier instruction like __DSB(); in order to safely relocate the code.
Next time you get a hard fault, use "Application Note 209: Using Cortex-M3/M4/M7 Fault Exceptions" to better understand the cause of it.
http://www.keil.com/appnotes/docs/apnt_209.asp
Good luck with your project.
DSB really shouldn't be required here, that it uses a new/old vector table at the immediate instant the value is updated would mean a whole lot of other stupidity is involved. Having the runtime/statics properly initialized along with the NVIC, should be much more of a concern.
You're basically describing an "ARC FLASH HAZARD" and DSB isn't really going to mitigate that on a CM4 where the write buffer is going to clear in-order, and can be fenced with a read.
And honestly, DSB is useless on CM7 parts because it doesn't flush/clean the cache either, so is a really poor fencing/barrier implementation.
If you Invalidate the cache on a CM7 you'll usually Hard Fault because it nukes pending stack writes.
/** \brief Invalidate D-Cache \details Invalidates D-Cache */ __STATIC_INLINE void SCB_InvalidateDCache (void) { #if (__DCACHE_PRESENT == 1U) uint32_t ccsidr; uint32_t sets; uint32_t ways; SCB->CSSELR = (0U << 1U) | 0U; /* Level 1 data cache */ __DSB(); ccsidr = SCB->CCSIDR; /* invalidate D-Cache */ sets = (uint32_t)(CCSIDR_SETS(ccsidr)); do { ways = (uint32_t)(CCSIDR_WAYS(ccsidr)); do { SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) | ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk) ); #if defined ( __CC_ARM ) __schedule_barrier(); #endif } while (ways--); } while(sets--); __DSB(); __ISB(); #endif }