For way too long I have been chasing a problem where the multiplier result is corrupted when using the USB. It is not a problem limited to the USB, but is a problem whenever an ISR accesses an array or preforms a multiply. CCS MAY use the multiplier to calculate the address of a value stored in an array. (Sometimes it uses the multiplier to multiply the size of an element in the array by the index into the array by calling __mpyi_f5hw. Sometimes it uses shifts. I have not figured out what its criteria is.) This is not obvious looking at the c code, which makes it hard to find that multiply, but, when looking at the disassemble, it starts to become easier to see. Thus if an ISR is executed when the main code is in the middle of the use of the multiplier, which could be when the code is accessing an array or when it is explicitly doing a multiply and that ISR accesses an array the multiply result may be wrong.
This can cause trouble if you are using the code supplied by TI to do the USB and you are using arrays in your code even if you never use the multiplier explicitly because you are using it when you access arrays.
The solution is for ISRs that use arrays or the multiplier to save the multiplier registers (on the stack) at the beginning of the ISR and restore them at the end. This is described in Section 23.2.7.1 Save and Restore, of slau208j.
I edited the USB ISR iUsbInterruptHandler(VOID) in UsbIsr.c to do that store and restore.
Here is what I did:
typedef struct {
int mpy32ctl0;
int res3;
int res2;
int res1;
int res0;
int mpy32h;
int mpy32l;
int opl2h;
int opl2l;
}MULTIPLY_REG_TYPE;
At the beginning of the ISR
//Save multiplier registers so that its values may be restored at end of ISR
//See section 23.2.7.1 Save and Restore in SLAU208
MULTIPLY_REG_TYPE mreg;
mreg.mpy32ctl0 = MPY32CTL0;// Save multiplier mode, etc.
MPY32CTL0 &= ~(MPYSAT | MPYFRAC);// Clear MPYSAT+MPYFRAC
mreg.res3=RES3;// Save result 3
mreg.res2=RES2;// Save result 2
mreg.res1=RES1;// Save result 1
mreg.res0=RES0;// Save result 0
mreg.mpy32h=MPY32H;//Save operand 1, high word
mreg.mpy32l=MPY32L;// Save operand 1, low word
mreg.opl2h=OP2H;//Save operand 2, high word
mreg.opl2l=OP2L;// Save operand 2, low word
At the end of the ISR
//restore multiplier registers
OP2L=mreg.opl2l;//Restore operand 2, low word
OP2H=mreg.opl2h;//Restore operand 2, high word
MPY32L=mreg.mpy32l;// Restore operand 1, low word
MPY32H=mreg.mpy32h;// Restore operand 1, high word
RES0=mreg.res0;// Restore result 0
RES1=mreg.res1;// Restore result 1
RES2=mreg.res2;// Restore result 2
RES3=mreg.res3;// Restore result 3
MPY32CTL0=mreg.mpy32ctl0;// Restore multiplier mode, etc.
The compiler puts the data on the stack
Another solution would be to modify __mpyi_f5hw so that it stop interrupts during its execution. You would have to do the same when explicitly using the multiplier.
Good luck
Kent