hi Al,
>
> Howeer, if you use int! to set a "Forth" interrupt vector, the default isr
> sets the "T" flag when an interrupt trips. It also stores the current vector
> in
> a location where the interpreter can find it.
>
> When the interpreter is about to dispatch it looks to see if the T flag is
> set
> and, if it is, it forces the XT you set with int! for the given vector.
> Sounds
> good.
And it works for all cases where the hardware does not need to be reset
to some "interrupt-handled" state. e.g. some interrupts need to be
cleared somehow (mostly by reading one or more bytes from pre-defined
IO registers). If that is _not_ done within the ISR, the interrupt will
re-fire immediatly after the reti instruction.
Other interrupt sources such as timer interrupts do not need to
acknowledged and they work absolutly fine with forth words.
>
> However, it seems like using reti in the generic ISR is a bad idea. When an
> interrupt fires, the AVR clears the global interrupt enable in status and it
> stays clear until the reti. But that means you could get a nested interrupt
> which would cause the previous interrupt to be dropped.
> I changed the reti to ret and then, of course, my "Forth" handler has to
> execute +int before it exits to get interrupts back on again. I also added a
> few lines of code so that if the Forth vector is 0, it doesn't try to execute
> it. This all seems to work (although I'm having another apparently unrelated
> problem with the code I actually want to write).
moving the reti instruction to some other place is crazy, but it could
work and could solve the interrupt handling problem.
following algorithm: the forth system executes some code. An interrupt
fires and the ISR routine will start immediatly. Until now, it only sets
the T flag, saves the interrupt number and finishes with reti. This is
changed to a final ret in the generic isr. That means that the
interrupted code will continue to work and whenever the inner
interpreter gets called, the forth-level interrupt code can be executed.
The basic trick is: for the controller the interrupt handling is still
active. Thus no other interrupt will disturb us. Whenever the forth
level interrupt word finishes, the inner interpreter will call the reti
and signals the controller "yeah, interrupt handled".
There are a few downsides: Any primitive word that changes the SREG
flags will need to take care for the externally set t flag. The most
important word is probably i!, which needs both a lot of time and
disables interruptes internally.
The following (not really tested) patch should contain the basic ideas
so far..
diff --git a/core/amforth.asm b/core/amforth.asm
index b339829..c6707c3 100644
--- a/core/amforth.asm
+++ b/core/amforth.asm
@@ -87,15 +87,16 @@ DO_EXECUTE:
DO_INTERRUPT:
; here we deal with interrupts the forth way
clt
+ savetos
lds temp0, intcur
ldi zl, LOW(intvec)
ldi zh, HIGH(intvec)
add zl, temp0
adc zh, zeroh
- ldd wl, Z+0
- ldd wh, Z+1
-
- clt ; clear the t flag to indicate that the interrupt is handled
+ ldd tosl, Z+0
+ ldd tosh, Z+1
+ ldi wl, low(XT_ISREXEC)
+ ldi wl, high(XT_ISREXEC)
rjmp DO_EXECUTE
.include "dict_appl_core.inc"
diff --git a/core/dict_core.inc b/core/dict_core.inc
index 09af97d..624fdc2 100644
--- a/core/dict_core.inc
+++ b/core/dict_core.inc
@@ -3,6 +3,8 @@
.include "words/int-on.asm"
.include "words/int-off.asm"
.include "words/int-restore.asm"
+.include "words/isr-exec.asm"
+.include "words/isr-end.asm"
.include "words/exit.asm"
.include "words/execute.asm"
diff --git a/core/words/isr-end.asm b/core/words/isr-end.asm
new file mode 100644
index 0000000..105a1ca
--- /dev/null
+++ b/core/words/isr-end.asm
@@ -0,0 +1,15 @@
+; ( -- ) Interrupt
+; R( -- )
+; re-enables interrupts in an ISR
+VE_ISREND:
+ .dw $ff07
+ .db "isr-end",0
+ .dw VE_HEAD
+ .set VE_HEAD = VE_ISREND
+XT_ISREND:
+ .dw PFA_ISREND
+PFA_ISREND:
+ rcall PFA_ISREND1 ; clear the interrupt flag for the controller
+ rjmp DO_NEXT
+PFA_ISREND1:
+ reti
diff --git a/core/words/isr-exec.asm b/core/words/isr-exec.asm
new file mode 100644
index 0000000..94851da
--- /dev/null
+++ b/core/words/isr-exec.asm
@@ -0,0 +1,14 @@
+; ( xt -- ) Interrupt
+; R( -- )
+; executes an interrupt service routine
+VE_ISREXEC:
+ .dw $ff08
+ .db "isr-exec"
+ .dw VE_HEAD
+ .set VE_HEAD = VE_ISREXEC
+XT_ISREXEC:
+ .dw DO_COLON
+PFA_ISREXEC:
+ .dw XT_EXECUTE
+ .dw XT_ISREND
+ .dw XT_EXIT
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
Amforth-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/amforth-devel