Omnimaga
Calculator Community => TI Calculators => ASM => Topic started by: Xeda112358 on October 12, 2011, 05:36:19 pm
-
Okay, I have this code that is causing a crash for me and I am trying to figure out why:
interrupt:
push af
push bc
push de
push hl
ld hl,(progPtr)
push hl
.db 21h
IprogPtr:
.dw 0
ld a,h \ or l
ld (progPtr),hl
call nz,ParserNext
EndExec:
pop hl
ld (progPtr),hl
pop hl
pop de
pop bc
pop af
ret
interrupt_end:
This is for Grammer which is why I am asking. (progPtr) is the program counter and calling ParserNext will parse the data at progPtr.
I also disable interrupts and switch it back to mode 1 before exiting the program in case I need to do that
-
Your forgetting to set the interupt mask would be my guess
try tacking this before you restore progptr
Xor a
out (3),a
ld a,%00001011 ; this set interupts to go on with hardware timer 1 the on key and the link port
out (3),a
more info on port 3 is here
http://wikiti.brandonw.net/index.php?title=83Plus:Ports:03
hopefully that helps ^_^
Edit:
you may also want to look at port four bits 1 and 2
http://wikiti.brandonw.net/index.php?title=83Plus:Ports:04
used for setting the speed of the hardware timers ^^
-
Along with Geekboy's suggestion. You also need to reenable interrupts. When the interrupt fires, there is an automatic DI that gets run, so you need to undo it.
-
Along with Geekboy's suggestion. You also need to reenable interrupts. When the interrupt fires, there is an automatic DI that gets run, so you need to undo it.
Wow i missed this while reading my own code >.<
-
Hmm, I have tried these suggestions, but they aren't working. I also notice that whenever I open the debugger in Wabbit, the interrupt is executing. I feel like it might be activating too often. Does the interrupt automatically execute after certain conditions?
EDIT: Here is the installer code:
di
ld hl,interrupt
ld de,8A8Ah
ld bc,interrupt_end - interrupt
ldir
ld hl,8000h
ld de,8001h
ld bc,256
ld (hl),8Ah
ldir
ld a,80h
ld i,a
im 2
It is inline which is why there is no "ei" or "ret" (the ei comes later).
-
di
ld hl,interrupt
ld de,8A8Ah
ld bc,interrupt_end - interrupt
ldir
ld hl,8000h
ld de,8001h
ld bc,257
ld (hl),8Ah
ldir
ld a,%00001011
out (3),a
ld a,80h
ld i,a
im 2
made a few changes thats the only differences in my code from yours :/ if that doesnt do it idk what it is :/
-
What's your current interrupt routine?
-
The current one is the one up at the top with the changes suggested.
-
It helps to see the code as it is now, because when interacting with hardware it can be pretty important that everything is done in the right order. Just wanted to make sure.
-
Okay, well this is the current version that I am toying with. I added some code because it seemed to recursively call itself and I wanted to fix that a little.
interrupt:
; or a \ ret nc
push af
push bc
push de
push hl
ld hl,(progPtr)
push hl
.db 21h
IprogPtr:
.dw 0
ld a,h \ or l
jr z,EndExec
jr nz,$
ld (progPtr),hl
ld (IprogPtr2),hl
sbc hl,hl \ ld (IprogPtr),hl
call ParserNext
.db 21h
IprogPtr2:
.dw 0
ld (IprogPtr),hl
EndExec:
sub a
out (3),a
ld a,%00001011
out (3),a
pop hl
ld (progPtr),hl
pop hl
pop de
pop bc
pop af
ei
ret
interrupt_end:
EDIT: I have the jr nz,$ for debugging puproses
-
After the call to ParserNext, IprogPtr is never updated. I'm not sure if ParserNext is supposed to advance any pointers, but it certainly won't here. Also, for those of us who don't have the Z80 opcode table memorized, you should add a comment for .db 21h that says ; ld hl, imm16
The only other thing that comes to mind is that you need to make ensure that ParseNext completes quickly or else the main code won't run. Also, make sure that the routine never EIs. Check to make sure the interrupt vector table is correct. And don't even think of running that from flash.
-
After the call to ParserNext, IprogPtr is never updated. I'm not sure if ParserNext is supposed to advance any pointers, but it certainly won't here. Also, for those of us who don't have the Z80 opcode table memorized, you should add a comment for .db 21h that says ; ld hl, imm16
The only other thing that comes to mind is that you need to make ensure that ParseNext completes quickly or else the main code won't run. Also, make sure that the routine never EIs. Check to make sure the interrupt vector table is correct. And don't even think of running that from flash.
Okay, thanks! The call actually takes care of the progPtr stuff and that is working fine, but the routine does in fact use EI, so I will try to work around that.
I have ideas >.>
Thanks much! I will see if this works :)
EDIT: It works! Here is how I fixed it:
In the interrupt, I set a flag and then reset it as it finishes
In the program code, whenever I need to EI, I check that flag first to see if it is okay
And it works now :) I am now executing Grammer code as an interrupt that updates the LCD
Is there a better way to check if an interrupt is currently executing? I am pretty sure I saw a way, so I will check.
-
You can check whether interrupts are enabled, but there's a bug in the Z80:
# If a LD A,I or LD A,R (which copy IFF2 to the P/V flag) is interrupted, then the P/V flag is reset, even if interrupts were enabled beforehand.
-
Is there a way to check if an interrupt is currently being executed, though?
-
easiest way i can think of is to just set a flag at the start of hte interupt and reset it at the end? you might be able to do something with a port to check though i forget :/
-
Yeah, I am currently setting a flag to do it, but that takes up more memory. I was thinking of setting or resetting the upper bit of the r register and using the s flag in some way.
-
well if you are succsesfully masking the bits on port 3 and 4 you can probably just check port 4 to see if a interrupt is running. i think im reading the wiki page right.