As of today, the latest version of the software interrupt entry looks like this:
#pragma INTERRUPT(software_interrupt,SWI)
void software_interrupt(Uint32 arg1, Uint32 arg2, Uint32 arg3, Uint8 swi_number)
//void software_interrupt(Uint32 *address, Uint32 data, Uint32 more_data, Uint8 swi_number)
{
//make sure interrupts are disabled
asm(" MRS r4, cpsr "); // get psr
asm(" ORR r4, r4, #0xc0 "); // set interrupt disables
asm(" MSR cpsr_cf, r4"); // restore psr
switch (swi_number) //handle flash write/erase and ROM backdoor first
With some codes and newer versions of the compiler, the compiler is moving a parameter in the software interrupt call into R4, which is then corrupted by the write to the CPSR to disable the interrupts. There are several ways around this:
The safest is to push R4 onto the stack disable the interrupts, and then pop it again when done:
asm (" STMFD SP!, {R4} "); //Store R4
//make sure interrupts are disabled
asm(" MRS r4, cpsr "); // get psr
asm(" ORR r4, r4, #0xc0 "); // set interrupt disables
asm(" MSR cpsr_cf, r4"); // restore psr
asm (" LDMFD SP!, {R4} "); //Restore R4
A faster but riskier option is to use R5 instead. This seemed to be safe on the one code we've tried. Bear in mind that all use of assembly language inside C functions is risky, and can always stop working when new versions of the compiler change how the registers are being used.
For complete safety, and complete assembly language function could be written to disable the interrupts, but this would slow the software interrupt down more.