the documented way for handling interrupts in an CrossCore project is using adi_int.h and adi_int_InstallHandler. For serving an interrupt the CPU pushes STS and branches from the interrupt vector associated with the interrupt to __dispatcher_XXX, where XXX is the name of the interrupt. The dispatcher pushes the registers PX1, PX2, R4 (all 40 bits), R8 (all 40 bits) and R12 (all 40 bits) onto the C runtime stack. Than it branches to the procedure registered with adi_int_InstallHandler. In order not to clobber a DAG2 Index register, this branch is coded as first a push of the procedure's address onto the PC stack and then an RTI instruction.
Saving only these few registers is sufficient for an application where all activities are performed by the interrupt service routines only and the main program consists of an empty infinite loop only. Furthermore nested interrupts are not possible.
For more general systems interrupt service routines must save and restore the contents of all registers they use. CrossCore's C compiler supports this with #pragma interrupt_complete_nesting and #pragma interrupt_complete. The documentation for these however is rather short and sort of discourages their use.
In my opinion the use of adi_int.h ins encouraged without stating the rather severe limitations put on the systems which use it. The more general mechanism using the pragmas is not realy described at all.
What I like to see is an in-depth discussion (including sketches of the machine code) of all possibilities for handling interrupts in CrossCore.
What do you think?
thank you for your reply. The program I'm working on computes spectra from the data acquired from a Michelson interferometer. It runs on a ADSP 21469 based hardware I designed myself. It consists of about 5000 lines of C and assembly code. I have got 6 interrupt service routines, highest priority first:
1. PWM produces sinusoidally modulated PWM, which via a powerstage drives a voice-coil actuator for moving a mirror. Has a rate of 500000 / s, written in assembly, uses the alternative register set.
2. SPORT handles two ADC's (AD7760, connected via an FPGA each for parallel/SPORT conversion) operating at 1.25 Msamples/s each. Rate about 1000/s written in C, uses adi_int.h.
3. DMA engine using EPDMA1 for memory/memory DMA's. Written in assembler, uses alternative register set.
4. Host communication via SPI0. Written in C.
5. SPI engine (SPI1) for controlling and monitoring all sort of stuff (adi_int.h).
6. Timer interrupt for doing timeouts and scheduling periodic activities (adi_int.h).
The last ISR I added was the host communication, which, when using adi_int.h, caused my program to crash in random places. Using the pragma interrupt_complete_nesting fixed the problem. On close examination of the default interrupt dispatcher (after looking in all the wrong places for a a couple of weeks), it seems to me that R2 and a number of other registers where not saved by the dispatcher.
For my taste the pragma I'm using now, makes the compiler saves way more registers than necessary. I plan to eventually replace it with my own dispatcher.