Shop OBEX P1 Docs P2 Docs Learn Events
Determine interrupt length — Parallax Forums

Determine interrupt length

Matthias09Matthias09 Posts: 47
edited 2010-01-03 02:01 in General Discussion
Hey guys,

have a happy new year, filled with plenty of pleasures in live and lot's of success in programming! smile.gif

I am currently working on a program with cyclical interrupts, with 50Mhz, I run 100000 interrupts per second or 1 interrupt every 10us. Now I have to ensure that within this 10us I can end the interrupt (which is lengthy, see below) and also have time to continue with my actual program.
With 50Mhz, I can do 500 clock cylces between the first and second interrupt, whereas every instruction needs 1-4 clock cycles to be exectuted. Now my question: give the interrupt routine below, how could I find out if 500 cycles are sufficient to finish all instructions before the next interrupt occurs? would I count the amount of instructions, and in worst case scenarios multiply them with 4 clock cylces each? Well you guess, I am a bit clueless smile.gif Help would be as always most appreciated.

Though I write in Basic, I believe it is more helpful to use assembly code for that problem. Nevertheless, Basic code is below as well. As you can see the lenght of the executed interrupt depends on some variables. As I am interested in the maximum amount of clock cylces used, I would just assume that every part of the interrupt is running and not bother about them. (excluding if statements of course)

Thanks guys and happy new year!!!

Matthias

PS: what would happen if one interrupt needs longer than 10us. Would the next one be executed or skipped?




ISR_Start:                       ; ISR_Start:


  INC Tix_LSB                    ; INC Tix                    ' waiting for 1 tix means waiting for 10us
  ADDB Tix_MSB,Z                


                                 ;'-----ULTRASOUND-----

                                 ;'only run, when in measuremend mode in main loop

  MOV FSR,#General_Var+1         ; IF General_Var(1) = 5 THEN             ' status of the USD:  2=wait+start pulse, 3=end pulse + prepare reading, 4=reading
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#5,@__ELSE_1    

  JNB USD_Pin,@__ELSE_2          ;    IF USD_Pin = 1 THEN                ' measuring the ping pulse. count up time variable (rawdata) as long as there is high at the USD

  INC rawdata_LSB                ;     INC rawdata                ' store results in rawdata
  ADDB rawdata_MSB,Z            

__ELSE_2:                        ;    ENDIF
__ENDIF_2:                      

__ELSE_1:                        ; ENDIF
__ENDIF_1:                      




                                 ;'-----ENCODER-----

                                 ;'run in every cycle (maybe not necessary)


  MOV __PARAM1,EncoderP          ; EncVar(3) = EncoderP & %0000_0011         ' reads A and B channel. Filter out for reading only Pin 0, 1
  AND __PARAM1,#%0000_0011      
  MOV FSR,#EncVar+3             
  MOV IND,__PARAM1              
  BANK $00                      

  MOV __PARAM1,EncoderP          ; EncVar(5) = EncoderP & %0000_0100        ' reads Index Channel. Filter out for reading Pin 2
  AND __PARAM1,#%0000_0100      
  MOV FSR,#EncVar+5             
  MOV IND,__PARAM1              
  BANK $00                      


  MOV FSR,#EncVar+5              ; IF EncVar(5) > 0 THEN                ' If index channel is read, then set angle to 90 and leave this interrupt encoder part
  MOV __PARAM1,IND              
  BANK $00                      
  CJBE __PARAM1,#0,@__ELSE_3    

  MOV current_angle_LSB,#9000 & 255 ;     current_angle = 9000            ' actually 90,00.
  MOV current_angle_MSB,#9000 >> 8

  JMP @Exit_Encoder              ;     GOTO Exit_Encoder            ' skip the rest in this cycle as I already have my value

__ELSE_3:                        ; ENDIF 
__ENDIF_3:                      


  MOV FSR,#EncVar+2              ; EncVar(4) = EncVar(2) XOR EncVar(3)        ' test for change: compare old and new measurement. XOR filters out changes (gives out 1 for 0, 1 and 1, 0)
  MOV __PARAM1,IND              
  MOV FSR,#EncVar+3             
  XOR __PARAM1,IND              
  MOV FSR,#EncVar+4             
  MOV IND,__PARAM1              
  BANK $00                      


  MOV FSR,#EncVar+4              ; IF EncVar(4) > 0 THEN                 ' check if something changed, XOR wrote one or several 1 somewhere in EncVar(4). Doesn't matter where, but it's > 0 then
  MOV __PARAM1,IND              
  BANK $00                      
  CJBE __PARAM1,#0,@__ELSE_4    


  MOV FSR,#EncVar+2              ;     EncVar(2) = EncVar(2) << 1        ' adjust old bits
  CLC                           
  RL IND                        
  BANK $00                      

  MOV FSR,#EncVar+3              ;     EncVar(2) = EncVar(2) XOR EncVar(3)    ' test direction, save in same variable to safe space
  MOV __PARAM2,IND              
  MOV FSR,#EncVar+2             
  XOR IND,__PARAM2              
  BANK $00                      


  MOV FSR,#EncVar+2              ;     IF EncVar(2).1 = 1 THEN
  MOV __PARAM1,IND              
  BANK $00                      
  JNB __PARAM1.1,@__ELSE_5      

  ADD current_angle_LSB,#25 & 255 ;        current_angle = current_angle + 25    'increase with 0.25 (4 pulses per 1 circulation, 4 pulses per one degree)
  ADDB current_angle_MSB,C      
  ADD current_angle_MSB,#25 >> 8

  JMP @__ENDIF_5                 ;    ELSE
__ELSE_5:                       

  SUB current_angle_LSB,#25 & 255 ;        current_angle = current_angle - 25    'decrease 
  SUBB current_angle_MSB,/C     
  SUB current_angle_MSB,#25 >> 8

__ENDIF_5:                       ;    ENDIF


  MOV FSR,#EncVar+3              ;    EncVar(2) = EncVar(3)             ' save current reading for next interrupt
  MOV __PARAM2,IND              
  BANK $00                      
  MOV FSR,#EncVar+2             
  MOV IND,__PARAM2              
  BANK $00                      


__ELSE_4:                        ; ENDIF
__ENDIF_4:                      


Exit_Encoder:                    ; Exit_Encoder:



                                 ;'-----STEPPER-----
                                 ;'just run it always.
  MOV FSR,#General_Var+1         ;IF General_Var(1) > 0 THEN
  MOV __PARAM1,IND              
  BANK $00                      
  CJBE __PARAM1,#0,@__ELSE_6    


  MOV FSR,#General_Var+2         ;    INC General_Var(2)                 ' this and 100 below lets you control speed; I leave that to you
  INC IND                       
  BANK $00                      


  MOV FSR,#General_Var+2         ;    IF General_Var(2) >= 255 THEN         ' step once per 18 milliseconds (180 * 100us) = 18000us = 18ms
  MOV __PARAM1,IND              
  BANK $00                      
  CJB __PARAM1,#255,@__ELSE_7   


  MOV FSR,#General_Var+2         ;    General_Var(2) = 0
  CLR IND                       
  BANK $00                      

  CJNE StepperMode,#CW,@__ELSE_8 ;    IF StepperMode = CW THEN 

  MOV FSR,#General_Var+3         ;        INC General_Var(3) 
  INC IND                       
  BANK $00                      

  JMP @__ENDIF_8                 ;    ELSEIF StepperMode = CCW THEN
__ELSE_8:                       
  CJNE StepperMode,#CCW,@__ELSE_9

  MOV FSR,#General_Var+3         ;        DEC General_Var(3) 
  DEC IND                       
  BANK $00                      

  JMP @__ENDIF_8                 ;    ELSEIF StepperMode = Stop THEN
__ELSE_9:                       
  CJNE StepperMode,#Stop,@__ELSE_10

  JMP @StopStepper               ;        GOTO StopStepper

__ELSE_10:                       ;    ENDIF
__ENDIF_8:                      


  MOV FSR,#General_Var+3         ;    General_Var(3) = General_Var(3) & %111     ' Filter out 0-7. E.g. 15 = %1111 becomes %111 = 7. The 3 LST repeat after 8. That's what I need.
  AND IND,#%111                 
  BANK $00                      


  MOV FSR,#General_Var+3         ;    IF General_Var(3) = 1 THEN 
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#1,@__ELSE_11   

  MOV StepperP,#%1000            ;        StepperP = %1000        

  JMP @__ENDIF_11                ;    ELSEIF General_Var(3) = 2 THEN 
__ELSE_11:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#2,@__ELSE_12   

  MOV StepperP,#%1001            ;        StepperP = %1001        

  JMP @__ENDIF_11                ;    ELSEIF General_Var(3) = 3 THEN 
__ELSE_12:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#3,@__ELSE_13   

  MOV StepperP,#%0001            ;        StepperP = %0001        

  JMP @__ENDIF_11                ;    ELSEIF General_Var(3) = 4 THEN
__ELSE_13:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#4,@__ELSE_14   

  MOV StepperP,#%0101            ;        StepperP = %0101

  JMP @__ENDIF_11                ;    ELSEIF General_Var(3) = 5 THEN
__ELSE_14:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#5,@__ELSE_15   

  MOV StepperP,#%0100            ;        StepperP = %0100        

  JMP @__ENDIF_11                ;      ELSEIF General_Var(3) = 6 THEN
__ELSE_15:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#6,@__ELSE_16   

  MOV StepperP,#%0110            ;        StepperP = %0110        

  JMP @__ENDIF_11                ;      ELSEIF General_Var(3) = 7 THEN
__ELSE_16:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#7,@__ELSE_17   

  MOV StepperP,#%0010            ;        StepperP = %0010        

  JMP @__ENDIF_11                ;      ELSEIF General_Var(3) = 8 THEN
__ELSE_17:                      
  MOV FSR,#General_Var+3        
  MOV __PARAM1,IND              
  BANK $00                      
  CJNE __PARAM1,#8,@__ELSE_18   

  MOV StepperP,#%1010            ;        StepperP = %1010        

__ELSE_18:                       ;    ENDIF
__ENDIF_11:                     


StopStepper:                     ;    StopStepper:


__ELSE_7:                        ;    ENDIF
__ENDIF_7:                      


__ELSE_6:                        ; ENDIF
__ENDIF_6:                      


ISR_Exit:                        ; ISR_Exit:


  MOV FSR,#__INTPARAMFSR         ; RETURNINT                     ' end of interrupt handler
  MOV M,IND                     
  INC FSR                       
  MOV __PARAM1,IND              
  INC FSR                       
  MOV __PARAM2,IND              
  INC FSR                       
  MOV __PARAM3,IND              
  INC FSR                       
  MOV __PARAM4,IND              
  MOV W,#6                      
  RETIW                         





INTERRUPT 100_000                ' 100000 interrupts per sec, or: 1 interrupt every 10us

 GOTO INTERRUPT_CODE            ' write routine below after the definition of the subroutines. they have to be defined in the 1st half page of the memory
                        ' and lengthy interrupt is pushing them downwards into 2nd half which makes them not callable anymore


'============## SUBROUTINES ##======================================================================================================================================
 
 STEPPER_TEST         SUB 0
 DRIVE_SERVO         SUB 1
  
 PROGRAM Start                    ' indicates the program starts at the label "start"
                        ' this command must appear after the interrupt definition


'============## INTERRUPT CODE ##======================================================================================================================================

 INTERRUPT_CODE:

 ISR_Start:

 INC Tix                    ' waiting for 1 tix means waiting for 10us

'-----ULTRASOUND-----
    
'only run, when in measuremend mode in main loop

 IF General_Var(1) = 5 THEN             ' status of the USD:  2=wait+start pulse, 3=end pulse + prepare reading, 4=reading
    IF USD_Pin = 1 THEN                ' measuring the ping pulse. count up time variable (rawdata) as long as there is high at the USD
     INC rawdata                ' store results in rawdata
    ENDIF
 ENDIF



'-----ENCODER-----

'run in every cycle (maybe not necessary)


 EncVar(3) = EncoderP & %0000_0011         ' reads A and B channel. Filter out for reading only Pin 0, 1
 EncVar(5) = EncoderP & %0000_0100        ' reads Index Channel. Filter out for reading Pin 2

 IF EncVar(5) > 0 THEN                ' If index channel is read, then set angle to 90 and leave this interrupt encoder part
     current_angle = 9000            ' actually 90,00.
     GOTO Exit_Encoder            ' skip the rest in this cycle as I already have my value
 ENDIF 

 EncVar(4) = EncVar(2) XOR EncVar(3)        ' test for change: compare old and new measurement. XOR filters out changes (gives out 1 for 0, 1 and 1, 0)

 IF EncVar(4) > 0 THEN                 ' check if something changed, XOR wrote one or several 1 somewhere in EncVar(4). Doesn't matter where, but it's > 0 then

     EncVar(2) = EncVar(2) << 1        ' adjust old bits
     EncVar(2) = EncVar(2) XOR EncVar(3)    ' test direction, save in same variable to safe space

     IF EncVar(2).1 = 1 THEN
        current_angle = current_angle + 25    'increase with 0.25 (4 pulses per 1 circulation, 4 pulses per one degree)
    ELSE
        current_angle = current_angle - 25    'decrease 
    ENDIF

    EncVar(2) = EncVar(3)             ' save current reading for next interrupt

 ENDIF

 Exit_Encoder:


'-----STEPPER-----
'just run always
IF General_Var(1) > 0 THEN

    INC General_Var(2)                 ' this and 100 below lets you control speed; I leave that to you
    
    IF General_Var(2) >= 255 THEN         ' step once per 18 milliseconds (180 * 100us) = 18000us = 18ms
    
    General_Var(2) = 0
    IF StepperMode = CW THEN 
        INC General_Var(3) 
    ELSEIF StepperMode = CCW THEN
        DEC General_Var(3) 
    ELSEIF StepperMode = Stop THEN
        GOTO StopStepper
    ENDIF
    
    General_Var(3) = General_Var(3) & %111     ' Filter out 0-7. E.g. 15 = %1111 becomes %111 = 7. The 3 LST repeat after 8. That's what I need.

    IF General_Var(3) = 1 THEN 
        StepperP = %1000        
    ELSEIF General_Var(3) = 2 THEN 
        StepperP = %1001        
    ELSEIF General_Var(3) = 3 THEN 
        StepperP = %0001        
    ELSEIF General_Var(3) = 4 THEN
        StepperP = %0101
    ELSEIF General_Var(3) = 5 THEN
        StepperP = %0100        
      ELSEIF General_Var(3) = 6 THEN
        StepperP = %0110        
      ELSEIF General_Var(3) = 7 THEN
        StepperP = %0010        
      ELSEIF General_Var(3) = 8 THEN
        StepperP = %1010        
    ENDIF

    StopStepper:
    
    ENDIF
 
 ENDIF

 ISR_Exit:

 RETURNINT                     ' end of interrupt handler



Post Edited (Matthias09) : 1/3/2010 1:13:32 PM GMT

Comments

  • BeanBean Posts: 8,129
    edited 2010-01-03 02:01
    The simulator will show how many clocks the interrupt too.
    It will also tell you if there are too many clocks used in the interrupt.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Use BASIC on the Propeller with the speed of assembly language.

    PropBASIC thread http://forums.parallax.com/showthread.php?p=867134·
Sign In or Register to comment.