CORDIC and interrupts
![ManAtWork](https://forums.parallax.com/uploads/userpics/892/nGFJJ1Y1ML417.jpg)
in Propeller 2
I use interrupts to handle smart pins by using the rising edge on IN event to trigger the interrupt service. But I still like to use the CORDIC solver in my main code.
Is it safe if I limit the use of the CORDIC to one instruction at a time so that the pipeline doesn't stall if interrupts get invoked while the CORDIC solver is working? I guess that interrupts are delayed while GETQX/Y are waiting for a result. But that should do no harm because it's less than 56 cycles and I currently have 256 cycles before I loose samples.
Is it safe if I limit the use of the CORDIC to one instruction at a time so that the pipeline doesn't stall if interrupts get invoked while the CORDIC solver is working? I guess that interrupts are delayed while GETQX/Y are waiting for a result. But that should do no harm because it's less than 56 cycles and I currently have 256 cycles before I loose samples.
Comments
Yeah, it has to be so. Reinstating the GETQX/GETQY after an interrupt would be messy. The docs don't explicitly list GETQX or GETQY but do have the rather generic "The cog must not be stalled in any WAITx instruction".
BTW, I have to say that the P2 is absolutely ingenius and superior over any other microprocessor I have seen so far when it comes to interrupts. I trigger an interrupt every 256 clock cycles. The ISR takes ~120 cycles to complete so the system is almost half occupied but still runs well.
This would never by possible with an ARM procesor. There, it takes ~100 cycles to call an interrupt and another 100 cycles to return from it. Even with 300MHz there is no way servering so many interrupt requests and still doing something useful.
Whatever the result might be, the P2 is an extremely powerful and flexible micro controller, no doubts about it.
Annoyingly, it does seem like getqx will stall interrupts. What we really want is to run the interrupt while we are waiting for the cordic.
There is an easy fix. Just use a simple delay loop while the cordic is running. If you want to maximize performance, have the ISR cancel the delay when it runs.
I flipped a pin every time I completed a cordic operation to benchmark.
' 15.137khz with fixed djnz
' 20.000khz smart djnz
' 24.618khz waitx *isr jitter
' 24.718khz none *isr jitter
The 30 could be reduced a little, but I don't want to risk stalling my interrupt. The smart djnz causes the cordic operations to sync with the interrupt, reducing the count to 28 didn't improve anything.
Branching instructions are four ticks. Meaning, #14 will be heaps.
EDIT: Oh, neat trick with the ISR changing the value. Compensates for the ISR execution time. I didn't notice that at first.
Thanks, @evanh
With #14, I measured 26.670khz on my toggle pin. So, letting the cordic work while the ISR is running increases overall throughput.
Cool. That's compared to 20 KHz before, right?
That was an ATSAME70N21, a Cortex M7. We tried really hard to get a fast interrupt response, programming on the bare metal and placing the IRQ code into fast SRAM. Running at 300MHz we were not able to get under ~600ns total IRQ processing time even if the IRQ routine was only a single assembler instruction toggeling a pin.
Main code was executed in flash memory. Maybe the long response time was caused by a required cache re-fill or flash pre-fetch queue or something. It probably gets better if you switch off the cache and run the main code also from fast SRAM. But that conditions are not realistic. You can never know where the main program counter is when the interrupt happens.
Correct.
Wow! Makes you really appreciate the SX which did great running out of flash.