Topic : Bootloader Failure w/ Data Abort Exception

Forum : ARM

Original Post
Post Information Post
February 1, 2008 - 12:19am
Guest

I am testing a bootloader with a main application built in RIDE on a STR912FAW44X6 processor. When I program the FLASH directly using RFLASHER and Bank 0 set at address 0, everything works fine. After loading it using the bootloader, I get Data Abort Exceptions. (The bootloader is loaded in Bank 1 and the Bank 1 is set at address 0 using CAPS.) I have checked the code using Varify in RFLASHER and the bootloader is loading the code correctly. I also have been working with ST Micro and I am setting my FMI registers correctly also. When the boot loader starts Bank 1 is set to address 0. Right before the jump into the main application I set Bank 0 to address 0.

Are there settings in RIDE that I have overlooked that take in accout when booting from Bank 1 and running in Bank 0?

I have noticed that the default settings for the RAM in the Options>Target>Options widow are not correct. it says the starting address for RAM is 50000000, It should be 4000000.

Replies
Post Information Post
+1
0
-1
February 1, 2008 - 10:19am
Raisonance Support Team

Hi,

If I understand your description of the system correctly, then you should configure RIDE as if you were working with Bank 0 at address 0. Is that what you did? There should be no need for any special manipulation.
You just have to be careful in case the normal execution of your application includes any system reset. Does it?
Your problem could come from a mistake in the changing of bank 0 to address 0. I suggest you write a test program for validating this part. Or maybe you already did?
And of course, you cannot debug when you are using such a bootloader. Is that what you were trying to do?

The RAM is seen by the CPU at 0x04000000, 0x40000000 and also at 0x50000000. By default, the linker script uses 0x50000000. If you want to change that, you should just have to modify this file:
C:\RIDE\LIB\STRX\STR91xF44_DEF.ld
Or use your own linker script.
(see the GettingStartedARM and the GCC documentation for more information on linker scripts)
But you have to be aware that these three addresses do not behave exactly the same, and changing this might lead to problems. See the STR9 reference manual for information on the differences. We only validated address 0x50000000, and we know that there are problems if using address 0x40000000. Address 0x04000000 should work, but we do not guarantee it.

Best Regards,

Vincent

+1
0
-1
February 20, 2008 - 11:37pm
Guest

Vincent,

Thank you for the info. I will answer your questions in order.

Yes I am set with Bank 0 at address 0.

Yes I have written a test progam. The main app used to work very well untill it began to get larger. I'm at 175k now. This is the odd thing; I get different problems depending on how the code lays in memory. I could add a Printf function in the middle of my code somewhere and it would change the way it acts. Sometimes it would work fine, sometimes it would lock up, sometimes I would get Abort or Undefined exceptions. It would appear that the pipeline is not flushing when I make the jump because I would see peaces of arbitrary code being run before the main app would start initialization. I tried putting lots of NOPs after my jump with no effect. A sample of the jump function is as follows:

#pragma optimize=none
RAM_exe void ExecuteApplication(void)
{
FMI->BBSR = 0;
FMI->NBBSR = 6;
FMI->BBADR = 0x20000;
FMI->NBBADR = 0;
/* Jump to the user application and execute it */
asm("NOP");
asm("NOP");

asm("MOV PC,#0");

asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
asm("NOP");
}

I believe it must be still in the main application.

I will try setting the RAM address back to 50000000.

Joe

+1
0
-1
February 22, 2008 - 11:43pm
Guest

One added thing. I have been doing a bit more debugging and found that the problem might be with the jump out of the init code (ie. B main). I put some test code before this line and the code makes it to this point. I put the same debug code in the first line of main and do not see it when it is run.

The debug code looks like this

LDR R0, =0x5800E004
LDR R1, =0
STR R1, [R0]

I am thinking that it could be a long jump issue. I am looking into it now, but the map file says it should be OK.

+1
0
-1
February 25, 2008 - 9:57pm
Guest

Just for a senity check I looked at the jump code at the end of my init routine. The op code looks like this:

0xEA000012 According to the ARM spec the jump address is left shifed twice and added to the current PC + 8.

0x12 << 2 = 0x48

PC = 0x0268

0x0268 + 8 + 0x48 = 0x02B8

According to my map file this is correct. I placed debug code at the beginning of main and I am not seeing it.

By the way, How do I put inline assmebly code into a C file. The following code get errors.

asm("LDR R0,=0x5800E004");
asm("LDR R1,=0");
asm("STR R1,[R0]");

+1
0
-1
February 26, 2008 - 11:04am
Raisonance Support Team

Hi,

If the application works when programmed directly by RFlasher, and that you could verify it, then I think you can be confident that the problem is NOT in the application itself. Here is a test you can perform that will give us more hints: Erase the flash and program the bootloader (in bank1) with RFlasher. Using the bootloader, program the main app and launch its execution, which will fail. Then, using RFlasher, erase the configuration only and reprogram it for placing Bank0 at address 0. Then, reset the chip by a power-on and check that the application is running correctly. Tell me if this works or not.

My guess is that your bootloader configures some peripheral and does not uninitialize it before calling the main app, which leads to problems when the main app starts executing and either tries to configure this peripheral or does not handle the associated interrupts.

I would check that the bootloader resets all the registers that it uses to their initial value.

Moreover, you say that printf sometimes has some influence on the problem. If your bootloader uses the same UART as the printf, (does it?) then I think this is an important clue and I advise to check the uninitialization of the UART by your bootloader before it calls the main app.

Also, keep in mind that from the moment you change the banks addresses, then the interrupt vectors of the bootloader are no longer mapped at the correct address. Therefore, you must be sure, before switching the banks addresses, that all the interrupts that the bootloader has enabled are now disabled, and cleared if they have been triggered. My advice is to never use interrupts in a bootloader if it can be avoided.

I hope it helps.

Best Regards,

Vincent

+1
0
-1
February 26, 2008 - 8:27pm
Guest

Vincent,

I have tried these tests, but just as a sanity check I went back and did them again. I found one bug in my Linker file that I remadied. I had my top of stack at 0x50018000, this is out of range. Then I changed it to 0x50017FFF which I beleive would cause a data about exception. I finally settled on 0x50017FFC.

The first test was to see if the application worked after fixing the bug in the linker file and changing my FMI registers I loaded it using flasher. It ran fine.

Next I loaded it using the bootloader. I checked it using Varify in Flasher. This passed, so I know the boatloader was loading it fine.

Next I cleared the boot bank bit in the configuration and restarted. The application ran fine as loaded by the bootloader.

Next I went back changed the settings in the FMI registers, set the boot bank bit, and reloaded using the bootloader and jumping from there. IT FAILED

Next I erasted the application loaded it using Flasher and restarted. The bootloader saw a valid application and jump into it. FAILED AGAIN

Just for sanity's sake, I will include the FMI register setup just before the jump for your review. It is according to ST Micro's library and I beleive it is correct.

#pragma optimize=none
RAM_exe void ExecuteApplication(void)
{
FMI->BBADR = 0x20000;
// 0 = 32k, 4 = 512k
FMI->BBSR = 0;
FMI->NBBADR = 0;
// 2 = 32k, 6 = 512k
FMI->NBBSR = 6;
/* Jump to the user application and execute it */
asm("MOV PC,#0");
}

I will try your other helps and get back to you,

Thanks,

Joe

+1
0
-1
February 26, 2008 - 10:40pm
Guest

Progress!

I decided to remove the one interrupt I had in the bootloader. I am now able to jump to the main application every time. I am now running into new issues. It seems to be having problems at times doing a funtion call. I appears that right before a function call (and it does not mean every function call) I get a Undefined Instruction Exception. Still looking into it further.

Joe

+1
0
-1
February 27, 2008 - 8:39am
Guest

I see that you are using RAM_exe before ExecuteApplication(void) function. What's the definition of this RAM_exe?
I think you need also to verify that you have configured correctly the bank 1 @ 0x0 and Bank 0 @ 0x80000 in the startup of your bootloader.
Rgds

+1
0
-1
February 27, 2008 - 10:42am
Raisonance Support Team

Hi,

Just a few hints, sorry I forgot to tell you before:

Are you using the default startup file from RIDE? If yes, then you have to modify it because it initializes the banks.
In your main app, which is built like if it was using bank 0 as boot bank, the default startup will initialize the banks this way, which is not correct in your case. you should remove the banks initialization in your main app's startup, considering your bootloader has already done this init. Or maybe you already did this?

In the same context, if your bootloader is linked using the default startup, then you must be aware that this startup initializes the banks. Maybe you should remove this initialization. Or maybe you need to use a different order to initialize the banks registers in your ExecuteApplication function, considering that these registers are already initialized.

Best Regards,

Vincent

+1
0
-1
February 28, 2008 - 12:29am
Guest

We are working for now (knock on wood). I added the following function to the bootloader right before I call my jump routine listed above.

void SystemReset(void)
{
SCU_APBPeriphReset(__SSP0, ENABLE);
SCU_APBPeriphClockConfig(__SSP0, DISABLE);
SCU_APBPeriphReset(__UART0, ENABLE);
SCU_APBPeriphClockConfig(__UART0, DISABLE);
SCU_APBPeriphReset(__GPIO5, ENABLE);
SCU_APBPeriphClockConfig(__GPIO5, DISABLE);
SCU_APBPeriphReset(__GPIO7, ENABLE);
SCU_APBPeriphClockConfig(__GPIO7, DISABLE);
SCU_APBPeriphReset(__GPIO8, ENABLE);
SCU_APBPeriphClockConfig(__GPIO8, DISABLE);
SCU_APBPeriphReset(__GPIO9, ENABLE);
SCU_APBPeriphClockConfig(__GPIO9, DISABLE);
SCU_PFQBCCmd(DISABLE);
SCU_MCLKSourceConfig(SCU_MCLK_OSC);
}

As for RAM_exe, it is defined as __ramfunc which is a IAR directive.

I am using a demo version of IAR to create the bootloader. Eventually I will be porting it to RIDE.

As for the initialization functions, the bank set up is fine in both initialization files. I do leave the code in the main app initialization because I can change it quickly and run it as boot code when I am testing. Otherwise I repeat the configuration that is in the jump routine listed above.

One last thing, how do you run inline assembly code in RIDE C files.

asm(" asm code "); does not work.

Peace,

Joe

+1
0
-1
February 28, 2008 - 10:07am
Raisonance Support Team

Hi,

asm("..."); compiles fine here.
Can you send me (support@raisonance.com) a project that shows a problem on inline assembly?

Best Regards,

Vincent