2014-12-17 04:46 AM
Hello,
I'm working with the STM32f103RB and I'm trying to jump to a section of flash where I will begin executing another program there My code should look like this (variable ApplicationAddress is 0x08008000) :__disable_irq();
JumpAddress = (uint32_t) (void *) ApplicationAddress + 4; Jump_To_Application = (pFunction) JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) ApplicationAddress;Jump_To_Application();
But I will executing another program with paramaters (like main(int argc, char * argv[]) Is it possible ? Have you some idea to do that ? Thank you #stm32f1xx #jump-address-flash2014-12-17 06:10 AM
typedef void(*pfunc_arg)(int argc, char * argv[]);
(( pfunc_arg )0x08008000)(1, arg);
But it is not quite a good idea to jump directly to main(). Before jumping to it the compiler first initializes the global variables, which will not be done if you jump directly.
2014-12-17 07:09 AM
Thumb code addresses would be ODD, parameters for most ABI will use R0..R3 for the first 4 parameters.
You would change the function pointer to define parameters, as you would with the classic qsort() function passing scheme. As Ivan indicates main() really isn't the first thing called, typically some C run time start up code initializes statics (copies or zeros RAM based data). If you expect the call to return you should also be careful that the RAM regions between the two do not overlap. A common method to pass command line data would be to have a memory structure the both loader/app share. This could be a fixed location carved out of the memory space they would otherwise use.2014-12-17 07:11 AM
MyTestFunc(int n_argc, char * n_argv[])
I do thisconst char* n_argv[] = { ''param0'', ''param1'', ''param2'' };
const int n_argc = 3; (( pfunc_arg )0x08008000)(n_argc, n_argv); But inMyTestFunc(...)
, it seemsn_argc
&n_argv
contain no values, not initialize ?2014-12-17 07:15 AM
A common method to pass command line data would be to have a memory structure the both loader/app share. This could be a fixed location carved out of the memory space they would otherwise use.
clive1, do you have some example to do that ?2014-12-17 08:44 AM
clive1, do you have some example to do that ?
I write code for a living...typedef struct _PARMS {
int argc;
char *argv[32]; // Enough to hold # parameters
char *allocptr;
char buffer[512]; // Enough to hold parameter strings
} PARMS;
PARMS *parms = (PARMS *)0x2000FC00; // 1KB at the end of 64KB
void buildparms(int argc, char *argv[])
{
int i;
memset(parms, 0x00, sizeof(PARMS));
parms->allocptr = parms->buffer;
parms->argc = argc;
for(i=0; i<
argc
; i++)
{
parms->argv[i] = parms->allocptr;
strcpy(parms->argv[i], argv[i]);
parms->allocptr += strlen(argv[i]) + 1;
}
} // sourcer32@gmail.com
2014-12-17 11:50 AM
Thumb code addresses would be ODD
Yes, it was my oversight.2014-12-17 12:11 PM
With STM32F103 : 128 Kbytes of Flash & 20 Kbytes of SRAM
/* Flash Memory */ #define FLASH_START (0x08000000) #define FLASH_SIZE (0x00020000) // 128 KBytes /* SRAMMemory */ #define SRAM_START (0x20000000) #define SRAM_SIZE (0x00005000) // 20 KBytes #define PAGE_SIZE (0x400) // 1 KbyteFrom
your example
, I madethis code
.Program.bin
=>Load Updater.bin
in Flash memory (at address:0x0801c400
) => Loaddemo_key.bin
(at address:0x08000000
)but
, in Updater.bin,it does not work
if use directlyParamsUpdater.FlashMemoryAdress
. If initializeParamsUpdater.FlashMemoryAdress
to0x08000000
, It's OKProgram.bin========= typedef void (*pFunction)(void); uint32_t JumpAddress; pFunction Jump_To_Application; typedef struct { // Name of the program to load char ProgrammName[11]; // Address where program is loaded in flash memory uint32_t FlashMemoryAdress; // if is equal to 1 then software reset uint8_t SoftReset; // if is equal to 1 then call program uint8_t StartProgramm; } structParamsUpdater; #define AdressParamsUpdater (*((structParamsUpdater *) (SRAM_START + SRAM_SIZE - 0x14))) // Reserved 20 bytes => sizeof(structParamsUpdater) int main(void) { structParamsUpdater ParamsUpdater = AdressParamsUpdater; memset(&ParamsUpdater, 0x00, sizeof(structParamsUpdater)); strcpy(ParamsUpdater.ProgrammName,''demo_key.bin''); ParamsUpdater.FlashMemoryAdress = 0x08000000; ParamsUpdater.SoftReset = 1; ParamsUpdater.StartProgramm = 2; // Program to load in flash is programmed starting from this address uint32_t ProgramLoadAddress = (FLASH_START + FLASH_SIZE - 15 * PAGE_SIZE); if (FLASH_LoadBin(''Updater.bin'', ProgramLoadAddress) == FLASH_OK) { // User loaded in Flash and programmed starting from address ''ProgramLoadAddress'' if (((*(volatile uint32_t*)ProgramLoadAddress) & 0x2FFE0000 ) == 0x20000000) { // Initialize user application's Stack Pointer __set_MSP(*(volatile uint32_t*) ProgramLoadAddress); // Jump to user application uint32_t JumpAddress = *(volatile uint32_t*) (ProgramLoadAddress + 4); pFunction Jump_To_Application = (pFunction) JumpAddress; Jump_To_Application(); } } return 0; }Updater.bin
=========
typedef void (*pFunction)(void);
uint32_t JumpAddress; pFunction Jump_To_Application; typedef struct { char ProgrammName[11]; uint32_t FlashMemoryAdress; uint8_t SoftReset; uint8_t StartProgramm; } structParamsUpdater; #define AdressParamsUpdater (*((structParamsUpdater *) (SRAM_START + SRAM_SIZE - 0x14))) // Reserved 20 bytes => sizeof(structParamsUpdater) int main() { // When generating bin, make sure to // 1- To compile the image at correct address (0x0801c400 in this case) => Configuration Memory Area Start : 0x0801c400 // 2- Call function NVIC_SetVectorTable(NVIC_VectTab_FLASH, OffsetAddress) with correct offset (0x1c400 in this case) => NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x1c400); // Program to load in flash is programmed starting from this address: 0x0801c400 uint32_t ProgramAddress = (FLASH_START + FLASH_SIZE - 15 * PAGE_SIZE); uint32_t OffsetAddress = ProgramAddress - FLASH_START; NVIC_SetVectorTable(NVIC_VectTab_FLASH, OffsetAddress); structParamsUpdater ParamsUpdater = AdressParamsUpdater; //ParamsUpdater.FlashMemoryAdress = 0x08000000; // => It's OK if (FLASH_LoadBin(''demo_key.bin'', ParamsUpdater.FlashMemoryAdress) == FLASH_OK) { // => It''s KO // Initialize user application's Stack Pointer __set_MSP(*(volatile uint32_t*) ParamsUpdater.FlashMemoryAdress); // Jump to user application uint32_t JumpAddress = *(volatile uint32_t*) (ParamsUpdater.FlashMemoryAdress + 4); pFunction Jump_To_Application = (pFunction) JumpAddress; Jump_To_Application(); } return 0; }2014-12-17 11:34 PM
char ProgrammName[11];
but the names you write there are longer. It's true that
ParamsUpdater.FlashMemoryAdress is initialized after the string, but anyway.
2014-12-19 06:20 AM
clive1, Thanks for your example. With this I found my error.
It's OK with this code typedef struct { // Name of the program to load char ProgrammName[12]; // Address where program is loaded in flash memory uint32_t FlashMemoryAdress; // if is equal to 1 then software reset uint8_t SoftReset; // if is equal to 1 then call program uint8_t StartProgramm; } structParamsUpdater;Program.bin ========= structParamsUpdater *parms = (structParamsUpdater *) (SRAM_START + SRAM_SIZE - sizeof(structParamsUpdater)); // at the end of 20KB memset(parms, 0x00, sizeof(structParamsUpdater)); strcpy(parms->ProgrammName,''demo_key.bin''); parms->FlashMemoryAdress = 0x08000000; parms->SoftReset = 1; parms->StartProgramm = 2;Updater.bin=========
structParamsUpdater *parms = (structParamsUpdater *) (SRAM_START + SRAM_SIZE - sizeof(structParamsUpdater));
if (FLASH_LoadBin(parms->ProgrammName, parms->FlashMemoryAdress) == FLASH_OK) { .... }