Tool/software: TI C/C++ Compiler
I need to understand what exactly happens why the following code gives a hardfault
int main()
{
void (*FP)() = 0x4;
FP();
while(1)
{
}
}
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Tool/software: TI C/C++ Compiler
I need to understand what exactly happens why the following code gives a hardfault
int main()
{
void (*FP)() = 0x4;
FP();
while(1)
{
}
}
I think the address of the Reset_ Handler is saved there. so what is the difference between me calling it and the processor calling it ?
AFAIU, you tried jumped to address 4 and executed what you found there. You need another level of indirection. You need to set a pointer to 4 and then use another pointer to store that.
something like:
void *ptr = 4;
void (*FP)() = *ptr; // load FP with the address that 4 points to.
You are correct, it is the address of the reset handler, it is not the reset handler itself. What happens on a CPU reset (among other things) is that the value stored at address 0x4 is placed in the program counter. The code you wrote puts 0x4 in the program counter. On reset the CPU is doing the equivalent of an indirect branch. Your code is trying to do a direct branch. Try:
(*((void (*)(void))(*(uint32_t *)0x4)))();
EDIT: Ignore the following. Keith was correct.
As a result try changing to call the Reset_Handler in THUMB mode by setting the least significant bit of the address:
void (*FP)() = 0x5;
Another way to think of it is that what is stored at address 4 is a vector to the reset routine, not the code of the reset routine itself.
While ruminating on this last night, I came up with another solution.
This might not work - but I wish it does - , so be warned. It is also worthy of an obfuscated C contest.
void (*FP)() = NULL[5];
Interesting idea, but the compilers don't like it.Keith Barkley said:This might not work - but I wish it does - , so be warned.
arm-none-eabi-gcc-7.3.1 reports:
../main.c:5:24: warning: dereferencing 'void *' pointer
void (*FP)() = NULL[5];
^
../main.c:5:20: error: void value not ignored as it ought to be
void (*FP)() = NULL[5];
^~~~
And ti-cgt-arm_20.2.1.LTS reports:
"../main.c", line 5: error #143: expression must have pointer-to-object type
void (*FP)() = NULL[5];
^
Darn. Though one is just a warning.
Strangely, one of the few confusions we get on these boards is over the NULL pointer, it is just not used much.