In my current project i need to implement a bootloader for firmware update purpose. The bootlaoder is at the beginning of the flash and gets invoked after a power up or reset. If a update is necessary the bootloader updates the application otherwise starts the application at address 0x8000 (32kByte). So far the application is called by the bootloader as expected but behaves different than if programmed without bootloader at address 0x00.
The application has a couple of safety init features enabled like the ESRAM ECC Check (SAFETY INIT tab in HALCoGen) which provokes a data abort interrupt. This resolves to two issues, first the interrupt jumps to the execption vector located at address 0x00 instead of address 0x8000. This I can explain with Anthony F. Seely 's statement in this post http://e2e.ti.com/support/microcontrollers/hercules/f/312/t/124544.aspx. I have to dispatch manually to the applications exception vector. Secondly it's not the data abort interrupt (at address 0x10) which is called but the prefetch abort (at address 0x0C).
Is there anywhere an example how to deal with this matter. Even as the bootloader example http://processors.wiki.ti.com/index.php/RM48_HDK_Kit doesn't show a solution to this an won't work for applications using exception vectors or FIQs.
Thanks in advance
Actually, I had many discussion about this interesting topic recently. The following discussion is based on the assumptions (1) bootloader and application are independent entities such that changes in application will not affect bootloader and vice versa, and (2) bootloader only needs to handle reset and IRQ/FIQ.
There are two types of interrupts on TMS570. The first types are exceptions such as reset, SWI, data and prefetch abort, etc. The second type is IRQs and FIQs.
For IRQs and FIQs, CPU directly fetches the ISR address from VIM module. If the hardware vector mode is enabled, CPU will not even jump to the exception vector at 0x00000018 or 0x0000001c. You can configure VIM module and RAM independently for the bootloader and application. The hardware vector mode can be enabled by the discussion in the following thread.
Since the exception vector table is not relocatable, Every time a reset or an abort happens, CPU will jump to the vectors starting at address 0x0. Assume that your bootloader occupies addresses from 0x0 to 0x7fff, and application starts at 0x8000. you can set up the bootloader vector table at 0x0 as follows,
b _c_int00 ; entry point to bootloader
b 0x8004 ; jump to application vector for processing
b 0x8008 ; jump to application vector for processing
b 0x800c ; jump to application vector for processing
b 0x8010 ; jump to application vector for processing
b 0x8014 ; jump to application vector for processing
In your application project, you need to put the vector table at address 0x8000. In this set up, when an exception occurs, CPU will first jump to the bootlaoder exception vector starting at address 0x0 and then jump to the application exception vector starting at address 0x8000. After a reset, CPU will always enter boot loader first. In the bootloader, you need to use intruction "b 0x8000" to jump to application. If you want to debug your application without bootloader, you can change the vector address in the application link command file from 0x8000 to 0x0.Or you cna change the first instruction in the bootloader vector from "b _cint00' to "b 0x8000".
The limitation of this idea is that you cannot enable ECC for the bootloader because abort handling is not allowed for bootloader.
Please let me know if this idea works for you. Please notify us if you can think of something better out of this discussion.
Thanks and regards,
Thanks for your informative answer. Unfortunately it doesn't solve the problem.
The hardware vector mode is enabled already by HALCoGen with the tick "Enable IRQ Handling via VIC Controller" which produces exactly the assembler code you provided.
The ESRAM ECC Check should trigger a data abort exception. What it does actually is generating a prefetch abort exception. Thats all I see with the debugger. After the instruction "ramread = tcramA2bit;" generated by HALCoGen (sys_selftest.c, in function checkB0RAMECC()) the PC jumps to 0x0C (prefetch abort) and sticks to there. Not even the jump to 0x800C is executed.
Any idea why the appliaction triggers a different exception interrupt and why the PC sticks to that address?
I forgot one thing in my earlier email. Although you do not enable Flash ECC for the bootloader, you need to calculate and ECC for the boot loader S/W. When you purposely generate a data abort in your application by a data read, CPU will generate a data abort and jump to address 0x10. If the ECC is not programmed for address 0x10, a prefetch abort will occur and CPU jumps to address 0xC. If ECC for address 0x C is not programmed, CPU will be locked into prefetch abort and you will see CPU locks to address 0xC. You can put breakpoints at address 0xC and 0x10. You should see CPU first stop at 0x10 and then locks to 0xC.
Thank you, this helped quite a lot to the situation. I won't get any prefetch aborts anymore.
But first, somehow the assembler instruction for the jump from exception vector of the bootloader to the one of the app is weird. For the data abort I have to write
instead of the expected
Do you have any idea why?
Second, now I get a step further in the app but get a undefined exception somewhere later. In the application code i just changed the command file telling the linker to start placing the code from address 0x8000. Do I have to make other modifications, or should this be enough?
Thanks a lot and have a nice weekend
"b #0x77f8" is branch to an offset of 0x8000 from the current location. Branching back to current location is " b #-8". For branching to address 0x8000, you should use "b 0x8000".
CPU always starts at 0x0. If you want to focusing on debugging the application, I would suggest you reserving the space from 0x800 to 0x820 and put the exception vector to 0x0. You can put it back to 0x8000 after everything in the application is working and start integrating with bootloader.
"b 0x8000" doesn't work with the assembler: [E0004] Illegal operand
Everything (Application and Bootloader) works fine with the app's exception vector at 0x00 (what you proposed to do). Something with the jump from 0x00 to 0x8000 seems to crash the system. Any idea?
Branches in ARM-v7R are relative.
You can find this information in the ARM Assembler Reference: http://infocenter.arm.com/help/topic/com.arm.doc.dui0489e/Cihfddaf.html#id4685232
What you also need to know for using the Branch instruction is the following:
In ARM state, the value of the PC is the address of the current instruction plus 8 bytes.
This can be found in the ARM Using the Assembler document: http://infocenter.arm.com/help/topic/com.arm.doc.dui0473e/Cacdbfji.html
Which means if you want to do a branch from address 0x0 to 0x8000 you need an branch instruction with the offset 0x7FF8 (0x8000 - 0x0 - 0x8 ; Destination - Source (PC) - 0x8)
One more thing I forget to add: In the TI assembler each immediate value has to start with #
~~~ If a post answers your question, please mark it with the Verify Answer button. ~~~
Do you use "b #0x7ff8" at address 0x0 to jump to address 0x8000? Can you put "b #-8" at address 0x8000 to check if branch occurs correctly? After a power-on-reset, CPU will starts at address 0x0. When you connect debugger to CPU, you should see PC at 0x8000. To branch to 0x8000 from the bootloader, you can call an assembly function from c-code. The assembly function can be constructed as follows assuming that you use eabi compiling option.
.global branch2address.textbranch2address: b r0 ;no need to to save any register because CPU branches to a new application bx lr.end
Calling in C:
extern void branch2address(unsigned int address);
Ok, I found the solution. My exception table in the bootloader looks now like this:
b _c_int00 ;0x00 b #0x7FF8 ;0x04, undefined instruction b #0x7FF8 ;0x08, Software interrupt b #0x7FF8 ;0x0C, Abort (prefetch) b #0x7FF8 ;0x10, Abort (data) b #0x7FF8 ;0x14 ldr pc,[pc,#-0x1b0] ;0x18 IRQ ldr pc,[pc,#-0x1b0] ;0x1C FIQ
The last two entries were missing (IRQ and FIQ). The ADC interrupts are configured in FIQ mode and if triggered jump to 0x1C. So long so good, but why is this? You said that the IRQs and FIQs are reallocated to VIM by hardware, this seems not to be the case for FIQ. Furthemore what does instruction "ldr pc,[pc,#-0x1b0]" and why is a simple "b #0x7FF8" not working here?
Hopefully you can bring some light into the dark.
we have three different possibilities to react on interrupts:
The default setup in HALCoGen is to use #3 for IRQ and #2 for FIQ.
The "LDR PC, [PC, #-0x1B0]" instruction is necessary for #2. In this mode the CPU has to load the vector address from the VIM register IRQVECREG for IRQ's and FIQVECREG for FIQ's.
IRQVECREG is at 0xFFFF_FE70
FIQVECREG is at 0xFFFF_FE74
The coding for the LDR instruction is similar as for the branches I described in my post before.
"LDR PC, [PC, #-0x1B0]" at address 0x18 resolves to a load from address 0xFFFF_FE70. (-0x1B0 == 0xFFFF_FE50 --> 0xFFFF_FE50 + 0x18 + 0x8 = 0xFFFF_FE70)
So you do not need to forward IRQ and FIQ exception vectors to 0x8018 and 0x801C, as you don't need to write a software dispatcher for these if you use #2 or #3.
Thanks for the satisfying explanation, it helps a lot.
There is no possibility to use #3 for FIQ, is that right?
Yes, this VIC Port is only available for IRQ and not for FIQ.The following is from the ARM Cortex-R4 TRM:
All content and materials on this site are provided "as is". TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with regard to these materials, including but not limited to all implied warranties and conditions of merchantability, fitness for a particular purpose, title and non-infringement of any third party intellectual property right. TI and its respective suppliers and providers of content make no representations about the suitability of these materials for any purpose and disclaim all warranties and conditions with respect to these materials. No license, either express or implied, by estoppel or otherwise, is granted by TI. Use of the information on this site may require a license from a third party, or a license from TI.
TI is a global semiconductor design and manufacturing company. Innovate with 100,000+ analog ICs andembedded processors, along with software, tools and the industry’s largest sales/support staff.