I don't understand what address to use to start the program after updating code using CAN ISP. The Cortex-M Reset vector (vector 1) looks like it is expecting to have the MSP set to the value in vector 0, the starting value of the MSP. The CAN ISP commands do not have the option to load the stack pointer, so I don't understand what address should be used as the starting address for the CAN ISP Go command.
Any help would be greatly appreciated.
Greg
Use SDO Execution Address (Index: 0x5070) to specify the execution address first, then use
SDO Program Control (Index: 0x1F51, value = 0x01) to run from above address + 1(Thumb mode).
Yes, I know how to do it, I don't know what address to set it to.
On power up the processor jumps to the address contained in vector 1 (address 0x0004), with the MSP (Stack Pointer) set to the address contained in vector 0 (address 0x0000). While it is easily possible to jump to the address in vector 1, i.e. set OD5070:0 to vector 1. There is no way to set the MSP to the value in vector 0. If the code expects the MSP to be set on entry, then the code is not going to execute properly if the MSP is not set to the correct value. If the Reset code pointed to by vector 1 loads the MSP itself, then everything will work properly, but I do not know of any documentation that says that that is the case.
That is the crux of my question, what address to jump to the get the processor to execute properly after updating the code.
Of course, a reset of the processor would work also, but that doesn't seem to be possible either.
The execution address should be the beginning address of your RO region when you build your application.
The user code should reload the stack pointer(SP) yourself, if you don't do that, the SP is pointing to somewhere used by the CAN ISP. See 34.3.6.3 "RAM used by ISP command handler".
On an ARM Cortex-M3 the beginning of the Flash is the interrupt vector table, not code. On the LPC15 elf files that I've dumped the 'text' section starts at address 0x0000, which is the interrupt vector table. User code starts at some address after the interrupt vectors. The start up code is not necessarily the first code after the vector table, that's why vector 1 points to the 'reset' vector, or code to execute on coming out of reset.
As far as the 'user' code setting up the stack pointer, that is handled by the startup code provided by NXP's & ARM's libraries, the 'user' has no control over how that works and no visibilty as far as I know, I haven't seen source code for the start up. The LPC15 User Manual (UM10736 @ 5.4.2) doesn't say if the boot code sets up the Stack Pointer from vector 0, just that it executes the user app, which according to ARM is pointed to by vector 1.
In the 'M3 Guide' written by Joseph Yui, in section 3.7 RESET SEQUENCE, it says that the processor reads address 0, the starting value of MSP, and address 4, the Reset vector, and that the MSP is loaded by hardware so that exceptions can be handled immediately. So, on a hard power up the MSP is initialized by hardware and software does not need to initialize it. I would expect that the ROM boot up code needs to follow the same procedure and initialize the MSP before executing user code.
So I still don't know if it is possible to just start execution at the address in vector 1, it would seem that it isn't.
Let me clarify it.
When MCU is powered up, it will follow the reset sequence which is illustrated in the section 3.7 RESET SEQUENCE as you mentioned. And the MCU can load the MSP and fetch the reset vector automatically after reset.
To enter or jump secondary application code, you also need to follow the same sequence:
1) Updating the stack pointer (SP)
2) Program counter (PC) register
And I'd like to share a jump function, and you can refer to it.
// the parameter means the first address of the target application
__asm void boot_jump( uint32_t address ){
LDR SP, [R0] ; //Load new stack pointer address
LDR PC, [R0, #4] ;//Load new program counter address
}
Hope this is clear.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Yes, I understand that it is necessary to set up the stack pointer and the execution address. The problem comes in that i'm trying to do this across the CAN bus with the the CAN ISP functions.
If what you are trying to say is that I should add this function to my code and then have the ISP Go call execute this function, how am I supposed to find the address for this function so that I can have the Go function execute it
In my opinion, the CAN go command is the trigger which is used to execute the jump function to start application, and the jump function just likes the __asm void boot_jump( uint32_t address ), it has already loaded new stack pointer address before jump to the application code, so you needn't to do this kind of job before send the Go command.
Hope this is clear.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Ping,
I've got what the function does, How do I figure out what the address of the function is so that I can get the Go command to jump to it.
Regards,
Greg
The function is located in the ROM area, and you needn't know the exactly address of the function,
the command would call the function automatically.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi Ping,
I do not find a boot_jump() function listed as one of the functions that can be executed from the CAN ISP interface, so the question still becomes if I add the function in my code, how do I find its address so that I can give it to the GO command to execute it?
jeremyzhou provided the source code in one of the first replies above. The code (extracted from one of the messages in this thread) is:
// the parameter means the first address of the target application
__asm void boot_jump( uint32_t address ){
LDR SP, [R0] ; //Load new stack pointer address
LDR PC, [R0, #4] ;//Load new program counter address
}
Hi Con Verse,
I understand that jeremyzhou showed the routine to add to my code to restart the system. There are still two problem. 1, where does the routine get loaded to, i.e. what address do I pass to the Go command. 2, as written, the routine takes a parameter that can't be passed with the Go command.
Number 2 is relatively easy to solve, just change the routine to load R0 with the proper address.
Number 1 is more difficult, do I have to force the Linker to put the routine at a fixed address so that it's possible to have an address to give to the Go command to execute?
Greg
Let me introduce the appropriate flow of jumping to the specific address via Go command.
1. Enter in the ISP mode firstly.
2. You should write a boot_jump function which be used to jump the specific address smoothly, and you also need to get the binary code after parse the function.
3. Write the binary code to RAM via the Write to RAM command, then the function will reside in the RAM after done.
4. Finally, using the Go command to execute the function, then complete the jump operation.
Hope this is clear.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Here is my function:
void boot_jump(void)
{
__asm__("MOV R0, #0x0"); // load vector base address
__asm__("LDR SP, [R0]"); // Load new stack pointer address
__asm__("LDR PC, [R0, #4]"); // Load new program counter address
}
From your comment I am assuming that if I take the hex code for this function it is going to be position independent and I can put it anywhere in Ram and it will execute correctly?
Hi Greg,
Did you ever get this to work? If so how did you do it?
Thank you,
Gary
Hi Gary,
What I'm doing is downloading the boot_jump() code to an address in ram and using the Go Command to jump to it. The Go command works when the processor is booted into the CAN ISP mode but doesn't when I use the Reinvoke command to enter CAN ISP mode, NXP Tech Support is still looking into that problem.
Greg
Thanks for your reply.
Yes, the crucial step is writing the binary code of the boot_jump to the specific address in the RAM, then you can execute it correctly via the Go command.
Have a great day,
Ping
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------