问题
First of all I need to say I develop application for embedded device based on cortex m4.
I have functions that are common for bootloader and main application. For now I compile source files 2 times once for bootloader and app. But I am running short on space for dual bank dfu and I would like to have those functions only once in ROM. Any idea how can I achieve this?
EDIT:
Using functions pointers maybe danger in some cases, check on my problems - Using pointer functions - 2 seperate applications on 1 device
回答1:
This is only a partial answer and assumes you can jump into your bootloader from your main code using the same address space. Then, a common technique is to provide your "bootloader API" as a table of function pointers.
Say for example you have the following functions in your bootloader:
static int do_something(void)
{
return 42;
}
static int do_something_else(int arg)
{
return arg+5;
}
Then you would declare your API in a header like this:
struct bootloaderApi
{
int (*do_something)(void);
int (*do_something_else)(int arg);
};
In the implementation of your bootloader, you define this table in its own section:
// this is GCC syntax, use whatever your compiler provides to specify the section
struct bootloaderApi api __attribute__((section("API"))) = {
do_something,
do_something_else
};
Then when building the bootloader, make sure your section is placed at a suitable fixed address. When e.g. using the GNU linker, you could have something like this in your linker script:
SECTIONS {
// standard sections, e.g.:
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) *(COMMON) }
// your API table:
.API 0x10000 : { *(.API) }
}
This now assumes your API table will be placed at 0x10000
. Then you could do the following to access the API from your main code:
struct bootloaderApi *api = (struct bootloaderApi *)0x10000;
api->do_something();
All of this is just a sketch to give you an idea how to do this in a sensible way. It will heavily depend on your target platform and the toolchain you're using.
回答2:
A software interrupt is a common means of accessing functions in boot code. It is not then necessary for the main program to know where the functions are. Commonly, a function number is pushed/whatever in a fixed manner so that the boot code can always retrieve it and switch to the desired function.
Such a mechanism does not need any specially located interface area that is fixed and know to both boot and main, or any linking between the main and boot code.
The exact mechanism/s are architecture-dependent.
回答3:
Two possible scenarios:
Built in bootloader. In all Cortex cores I know. Here is an example code to invoke the bootloader from the application.
#define SYSFLASH 0x1FFFD800 void __attribute__((noreturn)) StartBootLoader(void) { void (*BootLoad)(void) = (void (*)(void))(SYSFLASH + 4); HAL_RCC_DeInit(); // Only the example foe HAL. PLL has to switched off, peripheral clocks as well HAL_DeInit(); // All interrupts have to be disabled. // if HAL not used uC should be restored to the power-on state SysTick -> CTRL = 0; SysTick -> LOAD = 0; SysTick -> VAL = 0; __set_PRIMASK(1); __set_MSP(*(uint32_t *)SYSFLASH); BootLoad(); while(1); }
Custom bootloader - any scenario possible
来源:https://stackoverflow.com/questions/45459776/how-can-i-use-one-function-from-main-application-and-bootloader-embedded