I have an interesting problem with the dsPIC33FJ128GP802.
I have it configured as a slave SPI device connected to an Arduino acting as the master.
Timer1 is set up to trigger an interrupt at specific times in a certain sequence.
One of the sequences of interrupts takes about 50µs to execute. Yes, I know it's not "good practice" to have in interrupt routine lasting that long, but there is only the one interrupt being used in the system, and timing restraints mean that it has to take that long.
Now, it's all working - the SPI is running and receiving commands from the Arduino. The Timer1 is triggering the interrupt at just the right times, and everything is looking good.
Except, I am seeing corruption on the SPI. I can only assume that it is due to the interrupt for Timer1 firing during the SPI transfer. If I disable the timer and its interrupt I get no problems with the SPI transfer at all.
From what I understand of interrupts, all the registers etc are supposed to be in exactly the same state when the ISR returns as they were when the interrupt was triggered. That is certainly what the C30 user manual claims.
I have tried re-writing my C code for the SPI reception in assembly, but the problem still persists.
Here is a snippet of my C code:
while(PORTAbits.RA3==1); // Wait for a transfer to be requested SPI1STATbits.SPIEN=1; // Enable the SPI module SPI1BUF=0x0; // Prime the buffer to start a transfer LATAbits.LATA1=0; // Signal to the master it may transfer while(PORTAbits.RA3==0); // Wait for the master to signal it has transferred in = SPI1BUF; // Store the resultant word SPI1STATbits.SPIEN=0; // Turn off the SPI module ... perform operations depending on SPI command received ... LATAbits.LATA1=1; // Signal to the master the command has finished and it may transfer again.
- RA3 is the Slave Select pin for the SPI
- LATA4 is reverse handshaking back from the slave to the master
Both are active-low.
As you can see I am using more handshaking than normal SPI, as I need to feed back from the slave to the master when it is safe to start transferring another SPI command.
My ISR is defined as:
void __attribute__((__interrupt__,no_auto_psv)) _T1Interrupt(void)
I have tried adding the
__shadow__ attribute to use the shadow registers, but it has had no effect.
So what actually happens to the SPI in this chip when a timer interrupt is triggered? As it's clocked independently from the main CPU, and just shifts bits in/out of a shift register, surely it should be unaffected by interrupts.
It's doing my nut, so any pointers would be most welcome.