Page 1 of 2
EhBASIC IRQ support in min_mon.asm
Posted: Mon Jan 28, 2013 4:00 pm
by Klaus2m5
I am trying to implement EhBasic for my little project
viewtopic.php?f=8&t=2407 and have a question regarding IRQ support in min_mon.asm.
Code: Select all
08837 ; EhBASIC IRQ support
08838
08839 IRQ_CODE
08840 FF7D 48 PHA ; save A
08841 FF7E A5 DF LDA IrqBase ; get the IRQ flag byte
08842 FF80 4A LSR ; shift the set b7 to b6, and on down ...
08843 FF81 05 DF ORA IrqBase ; OR the original back in
08844 FF83 85 DF STA IrqBase ; save the new IRQ flag byte
08845 FF85 68 PLA ; restore A
08846 FF86 40 RTI
Shouldn't this code return with interrupt disable set until the ON IRQ target in the BASIC program gets a chance to handle the source of the interrupt? Otherwise the IRQ input would stay low and take another interrupt as soon as the CPU executes the RTI pulling the previous processor state with the I bit off.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Mon Jan 28, 2013 11:29 pm
by teamtempest
Not really a hardware guy, but:
1) setting the I-flag to "disable" would involve pulling the saved status flag off the stack, manipulating it and putting it back, all within the interrupt handler. Messy.
2) the code as shown does, I believe, clear the interrupt source anyway (the write-back to IrqBase). Otherwise you'd be correct in that an uncleared interrupt would trigger again as soon as the RTI executed.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Tue Jan 29, 2013 9:59 am
by Klaus2m5
Thank you for your answer. I should have mentioned, that IrqBase is just an address in zeropage.
IrqBase bits: 7=enabled, 6=IRQ handler setup, 5=interrupt happened
The periodic Ctrl-C (break) handler in EhBASIC picks up the interrupt happened flag and if set performs a GOSUB to the interrupt handler set by ON IRQ. It requires a RETIRQ to reenable the interrupt handler again.
I am missing the connection to the interrupt disable bit in the processor status, which would be required until RETIRQ to prevent the same interrupt source from interrupting again.
To leave IRQ disabled at RTI would be as simple as
Code: Select all
PHA ;save a & x
TXA
PHA
...
TSX ;point x to saved processor status
INX
INX
INX
LDA $100,x ;set interrupt disable on stack
; could use LDA/STA $103,x instead if you assume, that one never uses the bottom of the stack
ORA #4
STA $100,x
...
PLA ;restore x & a
TAX
PLA
But I am asking, since there is also a couple of SEI and CLI required in the EhBASIC code to accomodate this. I might be missing the point why it is not done that way.
edit: as Garth points out in the next post, the saved registers are a problem. So I added 2 more INX, but his solution is better anyway.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Tue Jan 29, 2013 10:45 am
by GARTHWILSON
I didn't say anything earlier because I'm not familiar with EhBASIC and I thought the IrqBase might be some sort of hardware thing and not just a variable. But since this part does not need to be re-entrant, you could simplify things a little by storing the accumulator in a variable instead of on the stack, then do something like I have in my 6502 Forth (showing the RTI as well):
Code: Select all
setirq: ; Use to record IRQ for NEXT. Put this address in MIRQVEC.
STZ irqnot ; Record that interrupt was req'ed by storing 0 in irqnot.
STA tempA ; Temporarily save accumulator in tempA to restore below.
PLA ; Pull saved processor status byte off the μP stack,
ORA #4 ; set the bit corresponding to the interrupt disable,
PHA ; and push the revised status byte back on the stack.
LDA tempA ; Restore the accumulator content.
RTI ; Return from interrupt. μP status gets restored modified.
The way NEXT works, it has to load Y with 0 for interrupt or 1 for non-interrupt continuation anyway, so it's virtually no extra work for it to load from irqnot instead of immediate.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Tue Jan 29, 2013 12:27 pm
by Klaus2m5
Thanks Garth, that is much better than my idea to keep interrupts disabled after an RTI. I will have to correct my example as I forgot about the saved registers on the stack.

Re: EhBASIC IRQ support in min_mon.asm
Posted: Mon Sep 16, 2013 4:47 am
by Rob Finch
I'm trying to implement IRQ's but when I set the IrqBase flags I get syntax errors in BASIC. If I comment out the code then BASIC seems to work fine. Has anybody else run into a syntax error problem ?
Note that I clear the source of the interrupt in this routine so there's no need to mess with the interrupt enable flag on the stack.
Note also this is RTF65002 code.
Code: Select all
;------------------------------------------------------------------------------
; 100 Hz interrupt
; - takes care of "flashing" the cursor
;------------------------------------------------------------------------------
;
p100Hz:
cld ; clear extended precision mode
pha
phx
phy
; support EhBASIC's IRQ functionality
; code derived from minimon.asm
; lda #3 ; Timer is IRQ #3
; sta IrqSource ; stuff a byte indicating the IRQ source for PEEK()
; lb r1,IrqBase ; get the IRQ flag byte
; lsr ; shift the set b7 to b6, and on down ...
; orb r1,r1,IrqBase ; OR the original back in
; sb r1,IrqBase ; save the new IRQ flag byte
; support tiny basic's IRQ rout
inc IRQFlag
inc TEXTSCR+83
stz 0xFFDCFFFC ; clear interrupt
; flash the cursor
lda CursorFlash
beq p100Hz1
jsr CalcScreenLoc
tay
lda $10000,y
ldx IRQFlag
and r2,r2,#$0F
and #$F0
or r1,r1,r2
sta $10000,y
p100Hz1
ply
plx
pla
rti
Re: EhBASIC IRQ support in min_mon.asm
Posted: Mon Sep 16, 2013 1:20 pm
by Klaus2m5
When I modified minmon.asm for use with my emulator I remember seeing syntax errors as well when interrupts occured faster than the Basic program could service them. I decided to change the way EHBasic inserts and removes bits in IRQBase from shifts to ORA/AND immediate ops. You may still loose interrupts but IRQBase will not be trashed.
The modifications are here:
http://2m5.de/6502_Emu/ehbasic.zip
Re: EhBASIC IRQ support in min_mon.asm
Posted: Thu Sep 19, 2013 1:45 am
by Rob Finch
Okay, I tried the simpler ORA/AND logic and it improved things. I no longer get syntax errors. Instead I get:
"mjReadymj" as the ready prompt. The carriage return and line feed are substituted with the characters 'm' and 'j'.
This looks like the string is being bit fiddled by the interrupt routine somehow. But it's only the carriage return and line feed.
It looks almost like the IrqBase is being or'd with the characters. Resulting in 6D? and 6A? instead of 0D, and 0A.
I tried slowing the interrupts down from 100 Hz to 50 Hz, but it didn't make a difference.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Thu Sep 19, 2013 6:04 am
by Klaus2m5
One of the problems of adding code in EhBASIC is the hardcoded zeropage addresses. I would suspect an address conflict between character output and interrupt handling in page zero.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Thu Sep 19, 2013 8:30 am
by Rob Finch
I would suspect an address conflict between character output and interrupt handling in page zero.
It's a good thought, but I've tripled checked, and checked again. I leave zero page addresses $00 to $FF strictly to EhBASIC. With a 4KW zero page space in 32 bit mode, I placed the other zero page locations at the high end of the 4KW space.
Code: Select all
200 = 000000DC NmiBase EQU 0xDC
201 = 000000DF IrqBase EQU 0xDF
205 = 00000500 SP8Save EQU 0x500 ; SP8Save area $500 to $5FF
206 = 00000600 SPSave EQU 0x600 ; SPSave area $600 to $6FF
; TinyBasic AREA = 0x700 to 0x77F
209 = 00000780 HeadRdy0 EQU 0x780
210 = 00000781 HeadRdy1 EQU HeadRdy0+1
211 = 00000782 HeadRdy2 EQU HeadRdy1+1
212 = 00000783 HeadRdy3 EQU HeadRdy2+1
I tried to manually trace through the code to see how the 'syntax error' would show up, to see if I could get hints to this problem.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Thu Sep 19, 2013 9:50 am
by Klaus2m5
There are two things, that are a bit strange about the output modification of the Ready string.
The "R" in Ready does not get modified to lower case. If it is true, that the string output is ored with IrqBase somehow, the string shoud be "mjreadymj". The string is sent by EhBASIC as a whole and it doesn't make sense that only cr & lf get modified but not "R".
IrqBase should never be allowed to contain the enable bit set (bit 6) without the setup bit (bit 7). So I would expect some strange characters from the language dependent part of the ASCII character set above $80. Of course your terminal program may mask the most significant bit and only display characters in the range of 0-$7f instead.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Thu Sep 19, 2013 9:54 pm
by Rob Finch
The "R" in Ready does not get modified to lower case. If it is true,
Yes, it's true. The 'R' does not get modified to lower case.
I dumped the ROM to make sure it wasn't being overwritten somehow. Nope. ROM contents look good.
I use a wide 'or' function on the databus input to the cpu. I thought maybe another device was being enabled somehow. But I don't see how.
If I write a little program to print text to the screen, then the CR/LF come out okay. It seems to be just the ready prompt that's screwy.
Re: EhBASIC IRQ support in min_mon.asm
Posted: Fri Sep 20, 2013 6:45 am
by Klaus2m5
When printing the ready message in EhBASIC the IrqBase gets cleared. It is hard to see how IrqBase can influence the message itsself.
Code: Select all
; BASIC warm start entry point
; wait for Basic command
LAB_1274
; clear ON IRQ/NMI bytes
LDA #$00 ; clear A
STA IrqBase ; clear enabled byte
STA NmiBase ; clear enabled byte
CLI ; allow interrupts
LDA #<LAB_RMSG ; point to "Ready" message low byte
LDY #>LAB_RMSG ; point to "Ready" message high byte
JSR LAB_18C3 ; go do print string
However, in my version interrupts are enabled at the same time because I do set interrupt disable in the PS on stack just before RTI to prevent flooding with interrupts if there are some that do not get silenced in the minmon interrupt handler. I will CLI in the CTRL-C check to allow just one interrupt per BASIC program line.
The original version enables interrupts when it sees an ON IRQ statement and never disables them again. It would be interrupted after every machine instruction in EhBASIC until the interrupt gets silenced by the interrupt handler in the BASIC program. I consider this to be a bug.
Could you please post your complete minmon.asm and tell me which EhBASIC you are using, mine, Lee's or yours (additional modifications)?
Re: EhBASIC IRQ support in min_mon.asm
Posted: Fri Sep 20, 2013 10:18 am
by Rob Finch
Could you please post your complete minmon.asm and tell me which EhBASIC you are using, mine, Lee's or yours (additional modifications)?
Umm, urr, my "minimon.asm" is 6,000 lines of code (including 3,000 for TinyBasic). I'm trying to evolve it into a multi-tasking kernel. There's very few lines of code required to support EhBASIC though.
I'm using Lee's version of EhBASIC, with a minor modification in startup to set the V_INPT and V_OUTP vectors.
I included the V_INPT and V_OUTP routines in the basic.asm file.
The following is the ISR.
* It could still be a processor bug.
Code: Select all
strStartQue:
db 1,0,0,0,2,0,0,0,3,1,0,0,4,0,0,0
;------------------------------------------------------------------------------
; 100 Hz interrupt
; - takes care of "flashing" the cursor
; - switching tasks
;------------------------------------------------------------------------------
;
p100Hz:
; Handle every other interrupt because 100Hz interrupts may be too fast.
pha
lda IRQFlag
ina
sta IRQFlag
ror
bcc p100Hz11
pla
rti
p100Hz11:
cld ; clear extended precision mode
; save off regs on the stack
phx
phy
push r4
push r5
push r6
push r7
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
ldx TaskNo
and r2,r2,#$FF
tsa ; save off the stack pointer
sta TCB_SPSave,x
tsr sp8,r1 ; and the eight bit mode stack pointer
sta TCB_SP8Save,x
; support EhBASIC's IRQ functionality
; code derived from minimon.asm
lda #3 ; Timer is IRQ #3
sta IrqSource ; stuff a byte indicating the IRQ source for PEEK()
lb r1,IrqBase ; get the IRQ flag byte
ora #$20 ; set IRQ pending bit
sb r1,IrqBase
inc TEXTSCR+83 ; update IRQ live indicator on screen
stz 0xFFDCFFFC ; clear interrupt
; flash the cursor
lda CursorFlash ; test if we want a flashing cursor
beq p100Hz1a
jsr CalcScreenLoc ; compute cursor location in memory
tay
lda $10000,y ; get color code $10000 higher in memory
ldx IRQFlag ; get counter
and r2,r2,#$0F ; limit to low order nybble
and #$F0 ; prepare to or in new value, mask off foreground color
or r1,r1,r2 ; set new foreground color for cursor
sta $10000,y ; store the color code back to memory
p100Hz1a
; Check the timeout list to see if there are items ready to be removed from
; the list. Also decrement the timeout of the item at the head of the list.
p100Hz15:
ldx TimeoutList
bmi p100Hz12 ; are there any entries in the timeout list ?
lda TCB_Timeout,x
bne p100Hz14 ; has this entry timed out ?
txa
jsr RemoveFromTimeoutList
jsr AddTaskToReadyList
bra p100Hz15 ; go back and see if there's another task to be removed
p100Hz14:
dea ; decrement the entries timeout
sta TCB_Timeout,x
p100Hz12:
; Search the ready queues for a ready task.
; The search is occasionally started at a lower priority queue in order
; to prevent starvation of lower priority tasks. This is managed by
; using a tick count as an index to a string containing the start que.
ld r6,#5 ; number of queues to search
ldy IRQFlag ; use the IRQFlag as a buffer index
lsr r3,r3,#1 ; the LSB is always the same
and r3,r3,#$0F ; counts from 0 to 15
lb r3,strStartQue,y ; get the queue to start search at
p100Hz2:
lda HeadRdy0,y
bmi p100Hz1
; Move the head of the ready queue to the tail
ldx TailRdy0,y
sta TCB_NxtRdy,x
sta TailRdy0,y
lda HeadRdy0,y
tax
lda TCB_NxtRdy,x
php
ld r4,#-1
st r4,TCB_NxtRdy,x
plp
bpl p100Hz4
; here there is no next ready task
; so we just stay with the same task
lda HeadRdy0,y
p100Hz4:
sta HeadRdy0,y
sta TaskNo
bra p100Hz3
p100Hz1:
iny
cpy #5
bne p100Hz5
ldy #0
p100Hz5
dec r6
bne p100Hz2
; here there were no tasks ready
stz TaskNo ; select BIOS task
p100Hz3:
p100Hz10
ldx TaskNo
and r2,r2,#$FF
lda TCB_SP8Save,x ; get back eight bit stack pointer
trs r1,sp8
ldx TCB_SPSave,x ; get back stack pointer
txs
; restore registers
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop r7
pop r6
pop r5
pop r4
ply
plx
pla
rti
;------------------------------------------------------------------------------
; 1000 Hz interrupt
; This IRQ must be fast.
; Increments the millisecond counter
;------------------------------------------------------------------------------
;
p1000Hz:
stz 0xFFDCFFFD ; acknowledge interrupt
inc Milliseconds ; increment milliseconds count
rti
Re: EhBASIC IRQ support in min_mon.asm
Posted: Fri Sep 20, 2013 3:17 pm
by Klaus2m5
V_OUTP routine would also be of interest. However, I do not see how adding just this part of the code
Code: Select all
; support EhBASIC's IRQ functionality
; code derived from minimon.asm
lda #3 ; Timer is IRQ #3
sta IrqSource ; stuff a byte indicating the IRQ source for PEEK()
lb r1,IrqBase ; get the IRQ flag byte
ora #$20 ; set IRQ pending bit
sb r1,IrqBase
could cause the bug you are seeing, unless it is directly related to the memory locations and registers altered in this part of the code. r1 is synonymous for the 8-bit accumulator I suppose? PHA/PLA saves r1 completely?