I got the code USB secondary ISP bootloader for LPC23xx from NXP working fine with none RTX kernel but It does not working with RTX kernel. If anyone know more detail please help.
Thank you.
I found more problem with startup file when running after bootloader, that required workaround. In startup file (LPC2300.S) there is code that setup stacks for each ARM mode. To do that the program is trying to enter each mode with MSR instruction and changing the value of SP (stack) register.
But, after bootloader this code will not work, and all special mode stacks will remain as setup by the boot loader, and probably will overwrite program memory every time the ARM enter to special mode (For example - every IRQ call and every task switching).
This problem seem to occurs because MSR instruction (switch ARM mode) doesn't work when ARM is in User mode, only when ARM in special (supervisor) mode.
After ARM reset the MCU run in Supervisor mode, so this code run well. but after bootloader the ARM run in User mode.
My solution was to force ARM to enter supervisor mode before running stacks setup code by calling to SWI. This require changing of SWI vector, that was easy after remapping vector table to RAM.
Here the updated code:
; Setup Stack for each mode ---------------------------------------------------- ; Stack setup code will not run when MCU in User mode ; as occur when this code run after secondary boot loader ; The following code will do fake calling to Software interrupt to enter Supervisor mode ; so stacks init code will work properly. SWI_RAM_ADDR EQU 0x40000028 LDR R8, =SWI_RAM_ADDR ; LDR R7, [R8] ;Save SWI_Handler address LDR R9, =Stack_Set_Addr STR R9, [R8] ;Replace SWI_Handler (for next command) with Stack_Set_Addr SWI 11 ;Just jump to Stack_Set_Addr in Supervisor mode Stack_Set_Addr DCD Stack_Setup Stack_Setup STR R7, [R8] ;Restore SWI_Handler address ;End of edit LDR R0, =Stack_Top
yes you are right - of the jump to the application can be done in a SWI function.
How can you change the SWI vector in bootloader?
is the bootloader performs a SWI, and the application later remaps the vector using the macros, does it matter?
I hope this piece of code will clarify what I mean:
// switch to supervisor mode so that stacks in the next startup file can be set (once is // user mode, only an exception can bring the processor out of it. SWI is such an exception.) void __swi(0) jump_to_application_code(void); void __SWI_0 (void) { void (*lp_application_start)(void); // interrupt vectors are mapped using the RAM_INTVEC REMAP RAM_MODE macros in the ASM tab of uv3 lp_application_start = (void (*)(void))APPLICATION_FLASH_START; lp_application_start(); } int main(void) { jump_to_application_code() ; }
I don't fully understand. If this code will placed in the bootloader, why do you need to add vectors remapping to bootloader also?
P.S. You need to be sure that your bootloader don't use this software interrupts.
the comments are misleading a little; the remapping occurs in the application.
You need to be sure that your bootloader don't use this software interrupts
Could you explain why? I'm not sure I fully understand.
I think that to use with SWI in the bootloader your code isn't enough. You need to change SWI_Handler in bootloader startup file to jump to SWI target code.
If you already use with SWI in bootloader code - you need to add something like SWI_Table.s also to your bootloader.
For details see - Help file->RealView Compilation Tools Instruction->Embedded Programs->Software Interrupt Handler.
of course, as was done.
I have a question about how to debug the 2nd Bootloader/Application model. As Moshe Tal pointed out, there are some problems that require workaround. One of them is: the 2nd Bootloader jumps to the Application in the User Mode, so when the Application starts, it fails to setup the stacks of special CPU modes. I can use the uVision to debug the 2nd bootloader or to debug the Application. But how can I debug both the 2nd Bootloader and the Application? If the main purpose is to make sure how the 2nd Bootloader affects the Application. I mean, run the 2nd Bootloader, get the state while the 2nd Bootloader just finishes its work, then start the debugging of the Application?
if the bootloader and the application are separate binaries, you cannot do what you describe. but why would you? they are separate entities anyway, that should not affect each other (unless software is updated).
http://www.keil.com/support/man/docs/rlarm/rlarm_ar_svc_func.htm
SVC functions can still be interrupted.
http://www.keil.com/support/man/docs/rlarm/rlarm_ar_swi_func.htm
Software Interrupt (SWI) functions are functions that run in Supervisor Mode of ARM7â„¢ and ARM9â„¢ core and are interrupt protected.
SWI functions can still be interrupted by FIQ interrupts.
Is there a SWI_Handler provided by KEIL, that can be included without RTX kernle?
If we use the SWI function with RTX kernel and its SWI_Handler to jump to the application, will the later interrputs work?
if you remember how RTX is configured, you will know that RTX imports the RTL SWI handler. you can always add your SWI.s file to define your own SWI functions, as explained in the user manual of RTX.
Hi Tamir,
Thanks for your responses.
I will do some simple tests to make sure some basic points.
Looks like you use the RTX kernel on BOTH your Bootloader and Application?
My bootloader is as simple as it can be; it either jumps (via a SWI) to the application or updates the application software. No RTX there, just an infinite loop.
I use the LPC23xx USB Bootloader from NXP directly, I do not modify anything of it. I download the Memory.bin (Bootloader) into my LPC2378. And I have an application with RTX kernel, I follow the solutions mentioned in the above of this thread.
1. Set IROM1 Start: 0x2000 Size: 0x7E000 2. Set IRAM1 Start: 0x40000200 Size: 0x7E00 3. On the Startup file of my application: Set Options-> Asm-> Conditional Assembly Control Symbols: RAM_INTVEC REMAP RAM_MODE 4. Add the below code into the Startup file of my application.
; Setup Stack for each mode ---------------------------------------------------- ; Stack setup code will not run when MCU in User mode ; as occur when this code run after secondary boot loader ; The following code will do fake calling to Software interrupt to enter Supervisor mode ; so stacks init code will work properly. ; Start of edit SWI_RAM_ADDR EQU 0x40000028 LDR R8, =SWI_RAM_ADDR ; LDR R7, [R8] ;Save SWI_Handler address LDR R9, =Stack_Set_Addr STR R9, [R8] ;Replace SWI_Handler (for next command) with Stack_Set_Addr SWI 11 ;Just jump to Stack_Set_Addr in Supervisor mode Stack_Set_Addr DCD Stack_Setup Stack_Setup STR R7, [R8] ;Restore SWI_Handler address ; End of edit LDR R0, =Stack_Top
After all of that, I start my Debug Session. The Disassembly Window shows the Machine Code/ASM Code of the Bootloader (without the Source Code). Then, the Bootloader jumps to my application. So that, I get the state while the Bootloader just finishes its work, and pass the control to my application. I can observe the CPSR and the R13/SP of Supervisor Mode etc, to see if the solutions works properly.
My problem is: sometimes the "memory re-mapping" works fine, sometimes the "memory re-mapping" just doesn't work; it seems it is related to the breakpoints I set; but I am not so sure.
Does anyone else encounter the same problem? And How do people debug your Bootloader/Application?