UCD3138 Family - Software Interrupt arguments getting corrupted by interrupt disable code

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. 

Happy Debugging,

Ian Bower

6 Replies