We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
Hello,
I am struggling to do something that should be very simple: call an assembly function from a C function. Can anyone give me some pointers or an example of how to do this?
I am using uVision 3 with Realview MDK C compiler.
All of the documentation that I am finding points me to use inline assembly commands. However, this won't work, as I need the assembly code to modify the stack pointer.
Here is what I would like the code to:
void ChangeRegion (void) { asm_adjust_sp(0x78000); //call assembly to change the stack pointer } //asm_adjust_spi(Ulong ulAddress) //1. change stack pointer to 0x4000F000 //2. branch to a the address contained by ulAddress
Any help that you can provide would be greatly appreciated.
Thanks!
first
void __asm __swi(0) disable_interrupts(void) ; void __asm __SWI_0 (void) { MRS R1, SPSR ORR R1, R1, #0xC0 // disable IRQ and FIQ MSR SPSR_c, R1 BX LR }
and
disable_interrupts() ;
but you probably can drop the swi directive all together. by the way, changing the stack pointer to very dangerous, unless you are writing a preemptive kernel...
Can anyone give me some pointers or an example of how to do this?
Try the RealView compiler manuals from the ARM website. The Developer guide has a chapter about mixing C and assembly.
infocenter.arm.com/.../DUI0203I_rvct_developer_guide.pdf
Write a C function with the correct prototype.
void asm_adjust_sp(unsigned n) { // some dummy code that accesses the parameter n // and have a side effect, so the compiler doesn't // throws away the code. my_dummy_global_variable = n; }
Look at the assembler listing of the function. Cut the relevant parts and place in an assembler file, and then add your specific action code.
Then add a function prototype in a header file:
void asm_adjust_sp(unsigned);
But as Tamir notes, modifying the stack pointer is not a simple task. It is way more advanced than calling an assembler function from C. With a moved stack pointer, return addresses and auto variables from the current call tree will no longer be available, so you must think twice about returning to previous calling functions.
Before starting on this task: Please specify why you think you have to modify the stack pointer from running C code.
Thanks for the advice everyone.
I am trying to modify the stack pointer before invoking NXP's flash boot loader to flash my LPC2468. The reason for this is that their boot loader does not appear to reset the stack pointer, and if it is invoked when the stack pointer is not towards the top of the memory map, it will end up over writing its own stack.
Have you asked NXP about this?
No, I have not. Do you have some experience with this?
My only reason for believing this to be the case is that I have noticed when my SP is around the mid point of the internal RAM upon entering NXP's bootloader, the micro controller will stop responding at the first 32KB block it gets to.
-Eric
The reason for this is that their boot loader does not appear to reset the stack pointer
you don't need to mess around with the stack to fix this. when passing control from the bootloader to the application, change the processor to SVC mode - or more specifically - make the 'jump to application' function a SWI function. that will allow the addresses of the stacks to be set in the application's startup file code.
Eric,
Are you sure you are using a good startup file?
Hi Tamir,
So for the delay here. We had some fires come up that I had to help take care of.
Actually, I am talking about the IAP/ISP bootloader built into the LPC2300/2400 chips (not a bootloader application). I am passing control to the IAP/ISP bootloader by executing code at address 0x7FFFFFF1.
I have found that launching to this address from supervisor mode is not enough to get the IAP/ISP to take charge of its stack pointer. It will work fine for the first several blocks, but as soon as it gets to a 32KB block, it fails while accepting flash data. However, if I set my stack pointer to point to the top of the internal memory, all is well.
I'm thinking about this. will let you know if I come up with something.
I am passing control to the IAP/ISP bootloader by executing code at address 0x7FFFFFF1.
And does it say anywhere in the documentation that this is sufficient to start the bootloader? As opposed to, say, a genuine reset of the microcontroller?
Yes, actually. I am following an example provided in the documentation for doing this. See LPC24xx user manual chapter 30, section 10.