Hi everybody,
(I appologise in advance for this lenghty post but I'll try to give as much info as I can up front).

I'm working on a DC servomotor drive using my incPID routine and DT-Ints on an 18F2431 running at 20Mhz. The input to the drive is step and direction signals, the step-pulse is connected to INT2 and trips a high priority interrupt, the direction signal to PortB.1. Originally I had the following code in the INT2 ISR:
Code:
DoStep:
If PortB.1 = 1 THEN         'Direction signal connected to PortB.1
 Setpoint = Setpoint + 1    'Setpoint is a 32bit variable
ELSE
 Setpoint = Setpoint - 1
ENDIF
This worked fine and I measured the execution time of ISR to 2-2.4uS depending on if the add or subtract code is executed - not to shabby. The problem was that it took 29uS from the rising edge of the step-pulse to the point where the ISR starts to execute. During testing I found that the code tracked the step-input up to 15kHz but above that it started to miss pulses. In practice 10kHz proved to be the limit, above that too much time was taken away from the PID-routine (which is triggered as a low priority interrupt by TMR2 at 1220Hz) resulting in an unstable servo loop.

So, with my VERY limited ASM skills I set out to change the DoStep ISR from PBP to ASM. I decided to not do the 32bit operations in the ISR and instead went to an 8bit "buffer variable". This not only made it possible for me to code the ISR but it'll also allow me to add features like electronic gearing etc in the future. The ASM ISR now looks like this:
Code:
ASM
DoStep
   BSF PORTB,6        ;For timing purposes
   BTFSS PORTB,1      ;Check direction signal
   INCF _StepBuffer   ;Increase
   BTFSC PORTB,1      ;Check direction signal
   DECF _StepBuffer   ;Decrease
   BCF PORTB,6
   INT_RETURN
ENDASM
This alone dropped the latency from 29uS to 8.4uS and the ISR execution time to 1uS.

Is there anything more that can be done to...
A) Lower the latency further and...
B) improve my pathetic attempt at ASM coding above?


In the servo-loop ISR I then have the following code:
Code:
INTCON3.4 = 0                'Temporarily disable INT2 interrupt
TempStepBuffer = StepBuffer  'How many steps has arrived?
StepBuffer= 0                'Reset buffer
INTCON3.4 = 1                'Re-enable INT2 interrupt
The new target position is then calculated by adding or subtracting the ABS value of TempStepBuffer from the current target position.

Now I have reliable operation up to ~20kHz step frequency but above that it occasionally misses pulses. It can run at 25-30kHz for several minutes without missing a pulse but all of a sudden it does. The pulsetrain is generated by software on a PC so depending on the actual frequency the jitter can be more or less severe which may explain the occasional lost pulse. Never the less, I'd like it to perform better than this.... (100kHz preferably)

Apart from the DoStep ISR there's one more high priority interrupt (IC2QEIF_INT) which is fired when the 16 bit QEI counter rolls over. That ISR is still in PBP and looks like this:
Code:
RollOver:
IF QEICON.5 = 1 then
  Position.Word1 = Position.Word1 + 1    'Position is a LONG
ELSE
  Position.Word1 = Position.Word1 - 1
ENDIF
@  INT_RETURN
Can some kind person more knowlagable about ASM than me please show me how the RollOver ISR above could look in ASM?

How many cycles does it take for DT-Ints to "get out of" an ASM ISR?

Any other ideas what I can do to increase the performance? (Except going to 40MHz which will be done).

Again, sorry for the long post and many questions.

Thanks!
/Henrik.