EASy68K  
It is currently Mon Feb 24, 2020 9:03 pm

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
 Post subject: ISR modifying return?
PostPosted: Tue Dec 17, 2019 10:36 pm 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
So, I have a situation where I have 3 functions, that are prioritized on execution, the execution is called from an ISR.

Now normally, you would just simply run the ISR when an IRQ comes in, and just do a simple call to subroutine, let it do its thing and return.

Trouble is, I dont know how the ISR works in that when your still executing code inside the ISR, since technically calling a JSR in the ISR means its still in the exception.

If something triggers the IRQ again while your still inside the ISR, Does it re-execute the ISR while your in the middle of it? or does it wait until the ISR is complete? (like an atmel avr)

Reason I ask is if I call the ISR from an IRQ, it goes off and starts executing a foreground function, then boom, a background request message comes in and triggers the same IRQ/ISR, it needs to interrupt whats going on, perform its thing, and then return back to what its doing.

My first thought was simply modifying the return address to point to a different sub before the RTE opcode, but the issue with that is, I cant handle the restoration of registers to the subroutine thats still waiting. Plus, itll clobber the SR since I dont know if I can push and pop the SR on the stack.

any ideas? Thanks!


Top
 Profile  
 
PostPosted: Wed Dec 18, 2019 12:47 am 
Offline
User avatar

Joined: Thu Dec 16, 2004 6:42 pm
Posts: 1118
Good question.

While an interrupt is in progress only a higher level interrupt will be acknowledged. Interrupts of the same level or lower are ignored.

Make the function recursive safe. That is, save all of the local variables on the stack, not in variables. Multiple calls to the same function from IRQ routines will be processed in the correct sequence.

_________________
Prof. Kelly


Top
 Profile  
 
PostPosted: Wed Dec 18, 2019 12:58 am 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
Well saving the registers, etc isnt my issue. I do that anyways.

I was hoping the ISR was re-entrant. Meaning if there is code being executed inside the ISR, that same ISR could fire again.

Because I am trying to have two to three command pipelines.

The lowest priority command handler is easy. Simply trip the ISR, set a flag in a global variable for the mainloop to see, "Hey, I have something I need to do. so im going to go do it".

Then the ISR can fire again while mainloop is mid-way in the function, and of course it can do some tests. if the low priority subroutine is busy, it wont be allowed for use. it can simply return. HOWEVER the trick is if the ISR is called to do something higher priority. Then instead of returning back to mainloop, the ISR can go off and do some other function before resuming what it was doing.

The trick is if a 3rd call comes in. like a highest priority command channel. If the ISR is executing a 2nd function, and a 3rd comes in, it needs to be able to still interrupt, and re-run the same ISR and handle the 3rd function. OF course, if all 3 functions are in use, the ISR will simply return because it needs to catch up. Cant have an overrun.

But the trick is how do I handle the ISR so it can re-fire? I feel as if the ISR needs to return to a different sub (to start its task) instead of where it was when the interrupt occured. but I dont know how to keep track of the register and the SR/CCR if I do this.

Basically its almost like asking how Task Switching works on a 68K.


Top
 Profile  
 
PostPosted: Wed Dec 18, 2019 1:48 pm 
Offline
User avatar

Joined: Thu Dec 16, 2004 6:42 pm
Posts: 1118
The ISR handler can read and save the necessary machine state in a structure then save that structure in a Queue and RTE from the interrupt. The main loop can check the Queue for jobs and process them.

_________________
Prof. Kelly


Top
 Profile  
 
PostPosted: Wed Dec 18, 2019 8:08 pm 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
That wont work though if the mainloop is already in the middle of processing one from a different "channel"

it has to be interrupted, redirected to run a higher priority function, then come back.

I am trying to create something with 2, maybe 3 channels. the primary channel is just simply a set flag from ISR, return from ISR, mainloop sees it, and goes off to handle it. Simple.

But if a priority 1 message comes in, itll come in on the other channel. Say if mainloop has already branched off handling the non-priority message, ISR triggers again, Now it has a priority one message.

it needs to handle that, interrupting the mainloop function entirely, And while its handling that message, another message COULD come in as a prioirty 1 message as well. which will interrupt the current message.

Almost like Nested interrupted functions. Then the function finishes executing, returns, finishes the previous one, and then keeps going until its all finished.

Kinda sounds like an RTOS without the whole bloat of an RTOS.


Top
 Profile  
 
PostPosted: Wed Dec 18, 2019 9:53 pm 
Offline
User avatar

Joined: Thu Dec 16, 2004 6:42 pm
Posts: 1118
The 68000 has 6 different interrupt priority levels. How about using those to control the job priority.

_________________
Prof. Kelly


Top
 Profile  
 
PostPosted: Thu Dec 19, 2019 12:27 am 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
I thought about that, but the hardware is designed to use IRQ5 from another CPU card to signal this one.


Top
 Profile  
 
PostPosted: Thu Dec 19, 2019 3:52 pm 
Offline

Joined: Fri Oct 25, 2019 8:15 pm
Posts: 18
Did some more reading on the 68000/68010 and yea the SR does get masked off during the IACK cycle.

So, maybe a little trickery to abuse the CPU's RTE function might work. I havent tested it yet, but I came up with this:

Code:
HandleCPU:
   movem.l   d0-d7/a0-a6, -(sp)   | Save Registers into the Stack before performing operation 
   move   #0x2700, sr         | Disable interrupts as the incoming operation is Atomic.
   move.l   #0, d0            | Clear our Parameter Register.
   move.b  0x200002, d7         | Reset Watchdog
   move.b   #0x10, 0x200001      | Set VMEUpper to point to $20XXXX (Atomic Write Only register)
    move.b  0xE00002, d0      | Grab Master Command
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
   move.b   0xE00003, d0      | Grab Master Status
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
    move.b  0xE00004, d0      | Grab Foreground Command
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
   move.b   0xE00005, d0      | Grab Foreground Status
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
    move.b  0xE00006, d0      | Grab Background Command
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
   move.b   0xE00007, d0      | Grab Background Status
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
    move.b  0xE00008, d0      | Grab Immediate Command
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.
   move.b   0xE00009, d0      | Grab Immediate Status   
   move.l   d0, -(sp)         | Save Value as Parameter to be passed.   
   |move   #0x2500, sr         | Restore interrupts.
   
   jsr   SYM(DataVector)         | Call the C routine, Pass our parameters. Returns value in D0.
   lea     (sp, 32), sp      | Free up stack pointer.   
   tst.l   d0               | Check D0 for a 0, if a 0, we return normally.
   beq      ReturnNormal      | Go return normally.    
   
   | Create a false Exception return frame to allow it to return for launching a new subroutine. Old return stack unmodified.
   move.l   #0x01E0, d1         | Create exception format of IRQ6 Vector.
   move.w   d1, -(sp)         | Save onto the stack.
   move.l   d0, -(sp)         | Save new return address onto stack
   move.l   #0x2400, d1         | Create a false stack frame for RTE, it will return to a new address :-)
   move.w   d1, -(sp)         | Save fake status register onto stack.
   rte                     | Return to new subroutine to launch it. The launched subroutine must be responsible for restoring the register and another RTE.
   
ReturnNormal:               | Exit IRQ processing in a normal manner.
   movem.l (sp)+, d0-d7/a0-a6    | Restore registers from stack before returning
   rte      


Maybe this will work. All I can do is try. :-)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group