cancel
Showing results for 
Search instead for 
Did you mean: 

How to jump from bank 1 to bank0

jmullens
Associate II
Posted on November 17, 2008 at 16:43

How to jump from bank 1 to bank0

8 REPLIES 8
jmullens
Associate II
Posted on May 17, 2011 at 09:51

I figured out how to jump from bank1 to bank0:

typedef void (*pFunction)(void);

__ramfunc void Execute_STR9Application(void)

{

pFunction Jump_To_Application;

/* Disable the prefetch-queue and the Branch-cache for the Flash.

When remapping the flash, there might be some instructions that are still in the queue, and need to be flushed out, or else I might be trying to access an invalid flash address. Without this, there is a chance that I may get a fatal exception */

SCU_PFQBCCmd(DISABLE);

/* Disable all of the registers in the vector-interrupt controller. An interrupt might happen right before I jump to the other bank, and may try to access an invalid flash address, and crash. */

SCU_AHBPeriphReset(__VIC, ENABLE); /* VIC peripheral is under Reset (disables all interrupts)*/

/* prepare bank0 for user operation */

FMI->BBSR = 0;

FMI->NBBSR = 6;

FMI->BBADR = 0x20000; //0x80000 >> 2

FMI->NBBADR = 0x0;

FMI->CR |= 0x18; /* Enable banks 0 & 1 */

Jump_To_Application = (pFunction) BANK0_START_ADDR;

Jump_To_Application();

}

Please note, in the application you wish to jump to, you'll need to change the FMI registers in 91x_init.s . You'll also need to make sure that ''#define Remap_Bank_1'' is uncommented in 91x_fmi.h, and you must also make sure that FMI_Config is put in SRAM (via __ramfunc with the IAR compiler)

LDR R6, =0x54000000

LDR R7, =0x0

STR R7, [R6]

LDR R6, =0x54000004 ; non boot bank size

LDR R7, =0x6 ; 512K

STR R7, [R6]

LDR R6, =0x5400000C ; boot bank address = Bank 1

LDR R7, =0x20000

STR R7, [R6]

LDR R6, =0x54000010 ; non boot bank address = Bank 0

LDR R7, =0x0

STR R7, [R6]

LDR R6, =0x54000018 ; enable Non Boot bank

LDR R7, =0x18

STR R7, [R6]

Please note:

When booting from bank 1, and jumping to bank 0, and then soft-resetting the processor while in bank0, this will then hang the processor. I will need to change my exception handler to deal with this case ..(e.g. remapping the address, and jumping back to address 0x0 in the boot-bank)

[ This message was edited by: jmullens on 31-03-2008 07:12 ]

jjacobsen
Associate II
Posted on May 17, 2011 at 09:51

I found that I had to make the Jump_To_Application function execute as a software interrupt in order to get the CPU back to supervisory mode. It needs to be in supervisory mode so that the init code in bank0 can do everything it needs to do, like initialize the CPU mode stacks.

I also have not been able to get bank0 code to remap and restart bank1 code. Have you resolved this?

As a test, I found that bank1 cannot restart itself (SWI jump to 0) without any remapping. In the restart, a prefetch abort occurs well into the init code when doing a ''write flash configuration'' command (write 0x60 to a bank1 address). This works fine on power up but not when it restarts. Still trying to see what setting changed to make this not work.

jmullens
Associate II
Posted on May 17, 2011 at 09:51

If you look at the errata for the chip, ''rev H'' apparently resolves this issue.

Link to the errata sheet:

http://62.193.238.133/download2.php?file=12944.pdf&info=STR912FAW44%20Errata%20Sheet%20STR91xFA&url=http://www.st.com/stonline/products/literature/es/12944.pdf

from the errata sheet:

Workaround using revision G:

Do not remap the banks after IAP (keep secondary bank at address 0x0), and in the secondary bank redirect ARM interrupts to be handled in the primary bank.

This limitation is fixed in revision H devices by clearing all FMI registers (including bank base address and bank size) after a System Reset.

''

I have ordered samples of the ''rev H'' part from the a major distributor and will try it out. Apparently none of these chips were in stock, and needed to be specially shipped from Germany. I hope that the ''rev G'' parts get flushed out of the system soon..

joshh
Associate II
Posted on May 17, 2011 at 09:51

How did you change your startup code? Did you change it in your bank 1 or bank 0 program?

jjacobsen
Associate II
Posted on May 17, 2011 at 09:51

I have Rev H. It didn't help. Rev H should have fixed a problem with a system reset (from reset pin). But in a jump-to-zero 'soft reset' there's no difference that I can see between Rev G and Rev H.

I haven't had a chance yet to investigate why Bank1 can't restart itself, but will post if I ever do figure this one out.

jjacobsen
Associate II
Posted on May 17, 2011 at 09:51

I've got all jump-to-zero's working ok. Changed startup code to always write to flash config registers while executing from ram. This was ok executing from flash at reset but not at restart, assuming the wait state change was the cause of this. Also, I had to better manage the active peripherals at the time the jump is done so that on restart they will be ok.

jjacobsen
Associate II
Posted on May 17, 2011 at 09:51

I had to change the code in Keil's startup file (Keil's code) to not write to the Flash Configuration register. Instead, I did this later in Main where it is done as a ram-executed function. This function is just ST's

FMI_Config() modified to set only the Flash Config register.

I did this in bank1, the bootloader code. I didn't have a problem writing to the Flash Config register from bank0. I was told by ST not to write to bank1 from bank1 code.

mark9
Associate II
Posted on May 17, 2011 at 09:51

I had trouble with Bank0 jumps to Bank1 (ie the main application requests to enter the Bootloader) ... It would work sometimes and then not othertimes. The issue comes from the fact that Bank1 goes haywire if you do not enable write protection after any writes to it. I am using Bank1 (0-3FFF) for DFU bootloader, and Bank1 (4000-7FFF) for parameter storage. I was writing to parameter storage in the main application.

In short, be sure to call

FMI_WriteProtectionCmd(xxx, ENABLE);

when you are done writing to bank1 flash.

This is basically my code:

static __ramfunc void BSP_JumpToBootloader(void) {

// there are two ways of doing this. one is to enable the watchdog and then timeout.

// The other is to jump to the BANK1 reset vector.

// I'll try the later one...

typedef void (*pFunction)(void);

pFunction Jump_To_Application;

FMI->BBSR = FMI_BOOT_BANK_Size;

FMI->NBBSR = FMI_NON_BOOT_BANK_Size;

FMI->BBADR = FMI_LOW_FLASH_BANK >> 2;

FMI->NBBADR = FMI_HIGH_FLASH_BANK >> 2 ;

Jump_To_Application = (pFunction) FMI_LOW_FLASH_BANK ; // should be zero

#pragma diag_suppress=Ta022 // we are jumping from RAM to ROM, and the compiler is issuing a warning. We can ignore it.

Jump_To_Application();

}

void BSP_Reset(void) {

__disable_interrupt();

SCU_PFQBCCmd(DISABLE);

while(FMI->SR & 0x10) ; // wait till PFQBC is disabled

SCU_AHBPeriphReset(__VIC, ENABLE); // disable VIC, hold in reset.

BSP_JumpToBootloader();

}