如何使用主应用程序和引导加载程序中的一项功能? (嵌入式)
How can I use one function from main application and bootloader? (embedded)
首先我要说的是我开发的是基于cortex m4的嵌入式设备应用。
我有引导加载程序和主应用程序通用的功能。现在我为引导加载程序和应用程序编译源文件 2 次。但是我 运行 缺少双银行 dfu 的 space,我想在 ROM 中只使用一次这些功能。知道我怎样才能做到这一点?
编辑:
在某些情况下使用函数指针可能会有危险,请检查我的问题 -
这只是部分答案,并假设您可以使用相同的地址 space 从您的主代码跳转到您的引导加载程序。然后,一种常见的技术是将 "bootloader API" 作为函数指针的 table 提供。
例如,您的引导加载程序中有以下功能:
static int do_something(void)
{
return 42;
}
static int do_something_else(int arg)
{
return arg+5;
}
然后你会像这样在 header 中声明你的 API:
struct bootloaderApi
{
int (*do_something)(void);
int (*do_something_else)(int arg);
};
在你的引导加载程序的实现中,你在它自己的部分定义这个table:
// this is GCC syntax, use whatever your compiler provides to specify the section
struct bootloaderApi api __attribute__((section("API"))) = {
do_something,
do_something_else
};
然后在构建引导加载程序时,确保您的部分位于 suitable 固定地址。当例如使用 GNU 链接器,您可以在链接器脚本中使用类似这样的内容:
SECTIONS {
// standard sections, e.g.:
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) *(COMMON) }
// your API table:
.API 0x10000 : { *(.API) }
}
现在假定您的 API table 将被放置在 0x10000
。然后您可以执行以下操作以从主代码访问 API:
struct bootloaderApi *api = (struct bootloaderApi *)0x10000;
api->do_something();
所有这些只是一个草图,旨在让您了解如何以合理的方式执行此操作。这在很大程度上取决于您的目标平台和您使用的工具链。
软件中断是访问引导代码中函数的常用方法。主程序就没有必要知道函数在哪里。通常,一个功能号是固定的pushed/whatever,以便引导代码可以随时检索它并切换到所需的功能。
这样的机制不需要任何特定位置的接口区域,该区域是固定的并且为 boot 和 main 都知道,或者 main 和 boot 代码之间的任何链接。
确切的 mechanism/s 取决于体系结构。
两种可能的情况:
内置引导加载程序。在我所知道的所有 Cortex 内核中。这是从应用程序调用引导加载程序的示例代码。
#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);
}
自定义引导加载程序 - 任何可能的场景
首先我要说的是我开发的是基于cortex m4的嵌入式设备应用。
我有引导加载程序和主应用程序通用的功能。现在我为引导加载程序和应用程序编译源文件 2 次。但是我 运行 缺少双银行 dfu 的 space,我想在 ROM 中只使用一次这些功能。知道我怎样才能做到这一点?
编辑:
在某些情况下使用函数指针可能会有危险,请检查我的问题 -
这只是部分答案,并假设您可以使用相同的地址 space 从您的主代码跳转到您的引导加载程序。然后,一种常见的技术是将 "bootloader API" 作为函数指针的 table 提供。
例如,您的引导加载程序中有以下功能:
static int do_something(void)
{
return 42;
}
static int do_something_else(int arg)
{
return arg+5;
}
然后你会像这样在 header 中声明你的 API:
struct bootloaderApi
{
int (*do_something)(void);
int (*do_something_else)(int arg);
};
在你的引导加载程序的实现中,你在它自己的部分定义这个table:
// this is GCC syntax, use whatever your compiler provides to specify the section
struct bootloaderApi api __attribute__((section("API"))) = {
do_something,
do_something_else
};
然后在构建引导加载程序时,确保您的部分位于 suitable 固定地址。当例如使用 GNU 链接器,您可以在链接器脚本中使用类似这样的内容:
SECTIONS {
// standard sections, e.g.:
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) *(COMMON) }
// your API table:
.API 0x10000 : { *(.API) }
}
现在假定您的 API table 将被放置在 0x10000
。然后您可以执行以下操作以从主代码访问 API:
struct bootloaderApi *api = (struct bootloaderApi *)0x10000;
api->do_something();
所有这些只是一个草图,旨在让您了解如何以合理的方式执行此操作。这在很大程度上取决于您的目标平台和您使用的工具链。
软件中断是访问引导代码中函数的常用方法。主程序就没有必要知道函数在哪里。通常,一个功能号是固定的pushed/whatever,以便引导代码可以随时检索它并切换到所需的功能。
这样的机制不需要任何特定位置的接口区域,该区域是固定的并且为 boot 和 main 都知道,或者 main 和 boot 代码之间的任何链接。
确切的 mechanism/s 取决于体系结构。
两种可能的情况:
内置引导加载程序。在我所知道的所有 Cortex 内核中。这是从应用程序调用引导加载程序的示例代码。
#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); }
自定义引导加载程序 - 任何可能的场景