DT-Ints latency and other interrupt conciderations


Closed Thread
Results 1 to 40 of 59

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604

    Default DT-Ints latency and other interrupt conciderations

    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.

  2. #2
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Hi Henrik,

    It does take a lot of time to save/restore all of PBP's System variables.
    So, PBP type interrupt handlers are not too good at high frequencies.

    Fortunately, both of your interrupt routines aren't doing anything that requires System variables. And you can just change their "Type" to ASM, without actually writing them in ASM.

    And your ASM routine would only count 8-bits, so I think it might be a bit limiting.

    IF statements with "=", and simple addition/subtraction doesn't use PBP's system vars, so most interrupts that only need to count something can usually be written as PBP, then used as ASM.

    HTH,
    DT

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    Hi Darrel,
    Many thanks, it does help a lot!

    So, can I assume that it takes roughly the same time to "get out of" an ASM interupt as it takes to enter it, in this case 8.4uS? Then, theoretically, the max frequency would be 1/(2*8.4+1uS) = 56kHz - if all it had to do was servicing the INT2 interrupt - which unfortunately still isn't good enough :-( Even going to 40Mhz just barely gets me over the 100kHz target with not much time left to do anything.

    I know the 8bit buffer variable may "look" limiting but because it is "read" by the servo-loop, which is currently run at 1220Hz, it means the actual limit would be ~155kHz - if I can get that I'd be happy. The only concern I have with this approach is that I need to disable the INT2 interrupt while reading and resetting the buffer. But if I'm not mistaken if an interrupt occurs during this time it will get "latched" and serviced as soon as I re-enable it again.

    Thanks again Darrel! I'll give it a go during the day and see what I can get.

    /Henrik.

    PS. I have a comercially available drive that I bought which also uses the 18F2431, it has a claimed step-frequency of 400kHz - I wonder how they do it....

  4. #4
    Join Date
    Jul 2003
    Location
    Colorado Springs
    Posts
    4,959


    Did you find this post helpful? Yes | No

    Default

    Well let's see what we can do here ...

    Since it's an 18F, with "qualified" ASM handlers ...
    You can remove the remaining overhead by removing DT_INTS all together, and using an ASM ISR, written in PBP of course.

    Something like this ...
    Code:
    DEFINE INTHAND _ISR
    DEFINE NO_CLRWDT 1
    
    ;---------------------------------------------------------------------------
    ISR:
      IF INTCON3.1 THEN             ' IF INT2 triggered
    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
        INTCON3.1 = 0               ' clear the int flag
      ENDIF
        
    RollOver:
      IF PIR3.2 = 1 THEN            ' if IC2QEIF triggered
        IF QEICON.5 = 1 then
          Position.Word1 = Position.Word1 + 1    'Position is a LONG
        ELSE
          Position.Word1 = Position.Word1 - 1
        ENDIF
        PIR3.2 = 0                  ' clear the int flag
      ENDIF
    @   RETFIE FAST                 ; return from interrupt with shadow regs
    Setpoint is handled as a LONG, but if you can use a BYTE sized result, you can change it to Setpoint.byte0 to reduce it by a few instructions.

    The NO_CLRWDT drops a couple more instructions, but make sure the WDT is OFF.

    Compiled, it looks like this, including both handlers ...
    Code:
    _ISR
            btfss   INTCON3, 001h
            goto    _RollOver
    _DoStep
            btfss   PORTB, 001h
            goto    L00003
            incf    _Setpoint, F
            clrf    WREG
            addwfc  (_Setpoint) + 1, F
            addwfc  (_Setpoint) + 2, F
            addwfc  (_Setpoint) + 3, F
            goto    L00004
    L00003
            decf    _Setpoint, F
            clrf    WREG
            subwfb  (_Setpoint) + 1, F
            subwfb  (_Setpoint) + 2, F
            subwfb  (_Setpoint) + 3, F
    L00004
            bcf     INTCON3, 001h
    _RollOver
            btfss   PIR3,  002h
            goto    L00005
            btfss   QEICON, 005h
            goto    L00007
            incf    _Position??WORD1, F
            movlw   0
            addwfc  (_Position??WORD1) + 1, F
            goto    L00008
    L00007
            decf    _Position??WORD1, F
            movlw   0
            subwfb  (_Position??WORD1) + 1, F
    L00008
            bcf     PIR3,   002h
    L00005
        RETFIE FAST                 ; return from interrupt with shadow regs
    Hope that gets it closer.
    DT

  5. #5
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,604


    Did you find this post helpful? Yes | No

    Default

    Thanks Darrel,
    Now I'm a bit confused.... Will this allow me to still use DT-Ints for the low-priority interrupts? The actual servo-loop code is, as I said earlier, triggered as a low priority interrupt by TMR2 and I also have a second low priority interrupt for handling USART comms (which isn't used during the tests I've made so far).

    Does the RETFIE FAST automatically restore the STATUS, W etc registers or is that not needed due to the "shadow regs"? As you can see I really suck at the low level stuff...

    Before seeing your message I tried changing the RollOver ISR to type ASM but it didn't make much difference. Up to 20kHz it works fine, above that it starts to fall apart and I can't really see why.

    Your assistance is much apprecited, thanks!

    /Henrik.

  6. #6
    Join Date
    Feb 2005
    Location
    Kolkata-India
    Posts
    563


    Did you find this post helpful? Yes | No

    Default Shadow Fight !!

    Hi,

    Darrel correct me if I am wrong, I am a bit rusty here.

    The shadow registers are not memory mapped but are actually hardware registers, a single level deep hardware stack that can save your context (W,Status, BSR). Optional during <b>call, something s , </b> or a <b>return, something s , </b> and automatic when entering interrupt. You decide whether you want to restore them by Retfie Fast . So when a low priority interrupt (0x0018h) is interrupted by a high priority one, the context saved while entering the low priority is lost. Thus it works best if you are using only HP Ints or using it for only HP Ints.
    Regards

    Sougata

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts