Keil Logo

HardFault when relocating vector table and code above 0x80010000

Next Thread | Thread List | Previous Thread Start a Thread | Settings

Details Message
Author
Michal Zych
Posted
1-Feb-2019 15:59 GMT
Toolset
ARM
New! HardFault when relocating vector table and code above 0x80010000

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!

Author
Westonsupermare Pier
Posted
1-Feb-2019 20:53 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

>> PC to 0x80010000

The addresses are wrong. It should be a table, not executable code. Thumb code will be at an odd address.

Examine the word at 0x08010000

Author
Michal Zych
Posted
4-Feb-2019 09:26 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

Hello!

In fact i use such code to move the address of the vector atable and code:

//####################################################################################
__asm void boot_jump( unsigned int address )
{
        LDR SP, [R0]            ;Load new stack pointer address
        LDR PC, [R0, #4]        ;Load new program counter address
}

And everything works perfect when i'm using address such as 0x80010000 or 0x8000f000.
But when i use 0x80020000 and above it is not working. I mean the processor starts and
runs the bootloader and when it jumps to the 0x80020000 part it hangs at random points
somewhere near the begin of the second part of the code.

Best regards!

Author
Michal Zych
Posted
4-Feb-2019 09:58 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

Hello!

One more thing. I'am using such an instruction to move the vector table:

#define _APPLIC_ADDR 0x0020000
SCB->VTOR = (_APPLIC_ADDR & 0x1FFFFF80);


and then function boot_jump() to move the PC and SP.

Best regards!

Author
Westonsupermare Pier
Posted
4-Feb-2019 20:56 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

That's not where the vector table is, set SCB->VTOR = 0x08020000;

And make sure you don't have other code in SystemInit() or wherever changing it to other addresses.

The shadowing/aliasing of 0x08000000 at 0x00000000 might not span the entire FLASH

Author
Michal Zych
Posted
5-Feb-2019 09:12 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

Hi there!

I've checked it and definetely the address of the vector table is
0x8020000. I've added 0x8000000 mask to this address, but it doesn't
change anything.
I've prepared another bootloader which put the main code
at this address. And this one is working. I mean now i can
move entire code at address 0x8020000 and averything works perfect.
It seems, that i have a problem somewhere else. The main differences
between those two bootloaders is that i am using USB stack from KEIL
in the first one bootloader (this one, which is not working properly).
I am sure, that the code of the bootloader with USB stack is not bigger than
this 0x20000. But is there a possibility, that the stack or heap or something
else is messed up during the change of the vtor address? But, as far as i know,
the stack and heap are in the SRAM, so how this could be connected to code in FLASH?
I do not have any idea, why it is not working at that moment.
I've tried to localize this problem via debbuging, but i cannot
see the answer here.

Best regards!

Author
Michal Zych
Posted
5-Feb-2019 14:07 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

Hi there!

Ok, i've found the problem.
The problem was with the HAL and it's "stack".
I've used HAL library for USB stack.
So in my code there is HAL_Init() instruction.
But, when i've changed vtor and PC and SP
i haven't stopped HAL (by using HAL_DeInit()).
And that was the problem.
I assume, that for example SysTick has been
working still, but i've changed the vector table
and everything collapsed.
So, thanks for the discussion. It has helped me
to track the bug.

Best regards!

Author
Kevin From Support
Posted
6-Feb-2019 19:31 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

Hello Michal,

I am glad you got the code working.

There is also a "VTOR relocate" code snippet here:

http://www.keil.com/pack/doc/CMSIS/Core/html/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.

Author
Westonsupermare Pier
Posted
7-Feb-2019 21:23 GMT
Toolset
ARM
New! RE: HardFault when relocating vector table and code above 0x80010000

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
}

Next Thread | Thread List | Previous Thread Start a Thread | Settings

  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.