Reputation: 4508
I have just seen a very interesting C code in the boot loader of a small embedded product.
The code consists of two parts: boot loader and the main code. The start of the main code address is stored in a function pointer. Below is the code I'm talking about
typedef struct {
uint32_t myOtherField;
void (*mainCodeStartAddress)(void);
} MyStruct;
MyStruct myStruct = {0x89ABCDEF, 0x12345678};
void main(void) {
// Some code
...
myStruct.mainCodeStartAddress(); // Jump to the start of the application
}
I can't figure out why this works? Why does a machine go to the application code? Any help is appreciated.
Upvotes: 0
Views: 83
Reputation: 93476
If the application code is built with a start address of 0x12345678
(an unlikely address that I assume you have made up for illustration?), then the bootloader need only jump to that start address to start the application. This can be achieved in C code by setting a function-pointer specifically to that address to that a priori known start address value and issuing a call via that function-pointer. A pointer of any kind is merely a memory address, a function pointer is the address of some code, and a call to a void function is simple a call to some address.
Whether this is implemented by a jump, call, or branch instruction is architecture and instruction set dependent; but that does not matter in this case. Neither does it matter that the start address is not a "function" as such, since this function will never return - the separately compiled and linked application code will run it's own C runtime start-up and establish a new stack and static initialisation, destroying the runtime environment of the bootloader. All that is required is that the processor's program-counter is set to the specific address, and that is achieved by calling the function via a pointer. It could equally be achieved for example by:
typedef void(*tStartAddress)(void);
((tStartAddress)(0x12345678)() ; // Set PC to start address
Upvotes: 1
Reputation: 6126
The construct void (*mainCodeStartAddress)(void)
declares a function pointer named mainCodeStartAddress
. It will point to a function taking no arguments and that doesn't return anything.
You can assign any function of the same type to a function pointer, for example:
void some_function(void)
{
// Do something useful
}
mystruct.mainCodeStartAddress = some_function;
Then you can call it like this:
mystruct.mainCodeStartAddress(); // Same as calling some_function();
In your example a fixed address is assigned to the function pointer, so when you call the function it points to it jumps to that address and executes it.
Upvotes: 6