Announcement

Collapse
No announcement yet.

ISR in PB DOS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • ISR in PB DOS

    Has anyone successfully created an Interrupt Service Routine in a PB DOS
    Program? I have been toying around with it for a few days and cannot get
    it to work. I do know that the ISR Sub is executing because the Int gets
    reset just fine, and if I REM out that portion of the code the Int does
    not get reset. But the program crashes imediately afterward when it
    executes the ! IRET statement as far as I can tell. If I make an Int
    handler in Turbo C, and then link the OBJ to the PBDOS program it works
    just fine, but if I Write the ISR routine in PBDOS, it hangs on the exit
    of the routine. I even made a routine with nothing in it but the ! IRET
    statement and it still crashes. If I leave the ! IRET statement out, then
    the whole system hangs as expected...

    I know that in the ISR code you cannot do anything that will genereate
    another interrupt (such as using alot of the BASIC keywords), and that ASM
    statements are the best way to do it. This isn't a major project, just an
    experiment more or less. But I was just wondering if it can be done and if
    anyone has written one with any success.


    Scott


    ------------------
    Scott Slater
    Summit Computer Networks, Inc.
    www.summitcn.com

  • #2
    PB/DOS is not reentrant. You can write ISRs using the inline assembler,
    but you must use only assembly language-- you can't mix in BASIC code
    and expect to get away with it.

    A BASIC SUB or FUNCTION requires initialization and shutdown code.
    Exiting a SUB or FUNCTION with an asm RET or IRET will avoid the necessary
    shutdown code, with unfortunate consequences. So, your ISR must start at
    a line label, not by getting the address of a SUB or FUNCTION.

    If that doesn't help, perhaps you could post an example.

    ------------------
    Tom Hanlin
    PowerBASIC Staff

    Comment


    • #3
      Scott,
      below is a program that works. It's written in PB/DOS assembler and intercepts the INT7 interupt, does a trivial task (increment a counter and pulse one output) then clears the interrupt and returns.
      I suspect you are forgetting to clear the interrupt before you exit the ISR.

      Hope this gives you some pointers on how to do it in your case.

      Paul.

      Code:
      REM measure interrupt latency
      REM signal generator is putting square wave onto ISA int7 line
      REM scope is looking at port 128 o/p
      
      cls
      
      mmr%=inp(&h21)
      
      ?"mask register"=hex$ (mmr%)
      ?"isr="isr%
      ?"irr="irr%
      
      dim p1 as dword ptr, p2 as dword ptr ,p3 as dword ptr
      p3=codeptr32(x)
      
      REM swap vectors
      p1=codeptr32(test)+1	:'exit from my interrupt routine
      p2=&h0000003c		:'vector to intercept..int7
      
      @[email protected]			:rem point my exit to old irq vector
      !cli
      @p2=codeptr32(start) 	:rem point irq vector at my start
      out &h21,mmr% and &h7f  :rem enable int7
      !mov al,&h67		;clear pending 1nt7 if any
      !out &h20,al
      !sti
      
      @p3=0 :rem init counter
      
      rem during this loop the interrupts can be seen to be working as the counter @p3 increments
      do
      [email protected]
      
      loop until instat
      
      !cli
      @[email protected] :rem put irq vector back
      out &h21,mmr% or &h80  :rem disable int7
      !sti
      
      ?"finished"
      
      end
      
      rem the interrupt routine
      start:
      
      !pushf		;save flags
      !push ax	;save ax
      !inc word x	;counter to let me see it's working
      !mov al,255	;pulse port 128 to trigger scope
      !out 128,al
      !mov al,0
      !out 128,al
      !mov al,&h67	;clear pending int7
      !out &h20,al
      !pop ax		;restore ax
      !popf		;restore flags
      
      test:
      
      !jmp far test   ;leave via original int7 vector
      !nop
      !nop
      !nop
      !nop
      !nop
      !nop
      !nop
      !nop
      
      x:
      !dd 0
      
      end
      
      function irr%
      REM read the interrupr request register
      
      rem get irr
      out &h20,&h0a
      irr%=inp(&h20)
      END function
      
      Function isr%
      REM read the interrupt being serviced register
      
      rem get isr
      out &h20,&h0b
      isr%=inp(&h20)
      end function

      Comment

      Working...
      X