Mode register causing weird perpetual interrupt.
Bill Franke
Posts: 20
I sure hope someone can help me out here. I wish to use the SX52 timer 1 as a count up timer. (I had this working at one time, but somehow fouled it up and can’t get it going again so I know this works.) I have a 3ms clock pulse that is triggering an interrupt. That part works fine. I want to clear a timer every time the interrupt occurs by detecting flag conditions in T1CNTA. (I set R2 to zero so it will just inc. R1.) But something weird is going on here. If I simply direct the mode register as in the following code, it locks up the SX52. This happens even when the actual write has been rem’ed out like below. I have been fooling with this for four days and am at my wits end. I’ve tried every possible combination I can think of. These are supposed to be valid mode registers according to the books. Why would it cause such a foul up? By putting a port monitor inside my code, I’ve determined that it is causing perpetual interrupts. But I have all the interrupt settings for the timers turned off (see Start code.)
NOTE THAT THE PROGRAM WORKS FINE UNTIL I INSERT ONLY THESE MODE REGISTER CHANGES. (In red, below)
Thanks for any help on this.
Bill Franke
TimerClr
mov BitPointer, #8
clr FifoPointer ; make zero
clr BitWaste
mov BitCount, #32
mov w, #$17
mov m, w
clr w ;clear all the flags of timer 1
; mov !rb, w ;write T1CNTA
mov w, #$10
mov m, w
clr w
; mov !rb, w ;clear timer 1
mov w,#$1F ; redirect the mode reg.
mov m,w
jmp TimerClrRet
Start
bank $10 ; ;added
mov w,#$1A ; set trigger reg. ;added
mov m,w
mov !rb,#%00000000 ; trigger on rising edge (A port) ;added
mov w,#$1f
mov m,w
mov w,#%11000111 ;Option Register Setup
mov !OPTION,W
mov ra, #%00000001 ;Set port A output latch initial state
mov !ra,#%00001100 ;Set port A input/output direction
mov !rb,#%11111111 ;Set port B to input direction
mov !rc,#%11111111 ;Set port C to input direction
mov !rd,#%11111111 ;Set port D to input direction
mov !re,#%11111111 ;Set port E to input direction
clr bits ;Clear bits register
mov w, #$12
mov m, w
clr w ;clear it
mov !rb, w ;write T1R2CML
mov w, #$13
mov m, w
clr w ;clear it
mov !rb, w ;write T1R2CMH
mov w, #$14
mov m, w
mov w, #$09 ;low byte compare timer value 1 (3.3mS)
mov !rb, w ;write T1R1CML
mov w, #$15
mov m, w
mov w, #$05 ;high byte compare timer value 1 (3.3mS)
mov !rb, w ;write T1R1CMH
mov w, #$16
mov m, w
mov w, #%01111100 ;divide by 128, software timer mode
mov !rb, w ;write T1CNTB
mov w, #$17
mov m, w
clr w ;clear it all
mov !rb, w ;write T1CNTA
clr w
mov !rc, w ;write T2CNTA (just to be sure there are no interrupts)
mov w,#$1F ; restore mode reg.
mov m,w
jmp @Main
NOTE THAT THE PROGRAM WORKS FINE UNTIL I INSERT ONLY THESE MODE REGISTER CHANGES. (In red, below)
Thanks for any help on this.
Bill Franke
TimerClr
mov BitPointer, #8
clr FifoPointer ; make zero
clr BitWaste
mov BitCount, #32
mov w, #$17
mov m, w
clr w ;clear all the flags of timer 1
; mov !rb, w ;write T1CNTA
mov w, #$10
mov m, w
clr w
; mov !rb, w ;clear timer 1
mov w,#$1F ; redirect the mode reg.
mov m,w
jmp TimerClrRet
Start
bank $10 ; ;added
mov w,#$1A ; set trigger reg. ;added
mov m,w
mov !rb,#%00000000 ; trigger on rising edge (A port) ;added
mov w,#$1f
mov m,w
mov w,#%11000111 ;Option Register Setup
mov !OPTION,W
mov ra, #%00000001 ;Set port A output latch initial state
mov !ra,#%00001100 ;Set port A input/output direction
mov !rb,#%11111111 ;Set port B to input direction
mov !rc,#%11111111 ;Set port C to input direction
mov !rd,#%11111111 ;Set port D to input direction
mov !re,#%11111111 ;Set port E to input direction
clr bits ;Clear bits register
mov w, #$12
mov m, w
clr w ;clear it
mov !rb, w ;write T1R2CML
mov w, #$13
mov m, w
clr w ;clear it
mov !rb, w ;write T1R2CMH
mov w, #$14
mov m, w
mov w, #$09 ;low byte compare timer value 1 (3.3mS)
mov !rb, w ;write T1R1CML
mov w, #$15
mov m, w
mov w, #$05 ;high byte compare timer value 1 (3.3mS)
mov !rb, w ;write T1R1CMH
mov w, #$16
mov m, w
mov w, #%01111100 ;divide by 128, software timer mode
mov !rb, w ;write T1CNTB
mov w, #$17
mov m, w
clr w ;clear it all
mov !rb, w ;write T1CNTA
clr w
mov !rc, w ;write T2CNTA (just to be sure there are no interrupts)
mov w,#$1F ; restore mode reg.
mov m,w
jmp @Main
Comments
Ray
Debugging hardware problem is almost impossible without the exact setup you have.
You also need to post the ABSOLUTE MINIMUM code that causes the problem.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"SX-Video·Module"·available from Parallax for only $28.95 http://www.parallax.com/detail.asp?product_id=30012
"SX-Video OSD module"·available from Parallax for only·$49.95 http://www.parallax.com/detail.asp?product_id=30015
Product web site: www.sxvm.com
Coming soon... Cheap 4-digit LED display with driver IC·www.hc4led.com
"Sometimes it is better to remain silent and be thought a fool, than to speak and remove all doubt."
Post Edited (Bean (Hitt Consulting)) : 3/24/2006 3:46:29 PM GMT
I totally agree with you, but would suggest to expand your last sentence to say........
"You need to post the FULL ABSOLUTE MINIMUM code that causes the problem". This includes the initializations, orgs etc as often the problem lies not in the poster's main code, but in some more obscure spot in his set-up.
Cheers,
Peter (pjv)
(Mode register is at $1F coming into this.)
mov w, #$17
mov m, w
mov w, #$10
mov m, w
mov w,#$1F ; redirect the mode reg. back to 1F
mov m, w
cause an interrupt? Again, I am simply changing the mode register to one of these values, and back again. I took out the actual register write and it still causes problems.
Why would this code effect anything else no matter what the code? If I reduce what I have to this snippet, and insert it either into the interrupt or outside of the interrupt, it locks up the uProc.
I don’t have to change both $17 and $10, either one by itself will cause lockup merely by inserting in (it seems) anywhere in my code. I am modifying the mode register a lot in this program. Why would these particular registers cause this? The documentation for the timers is rather limited and I am hoping someone might have experienced something similar to this.
One more note which I should have mentioned earlier. The lockup occurs when I do a write to port D, 4 pins of which are input, and 4 of which are output.
By the way, if your familiar with it, I am modifying the code from Elexol’s USB I/O 24 data acquisition board. Neat little board with 24 I/O lines that uses USB for data transfer.
If no one has any experience like this to share, then I’ll try to come up with a bare minimum that you guys can try. But it will take me awhile as I have other commitments right now.
Thanks,
Bill Franke
This code runs just fine and does NOT lockup, you can single step it or walk it in the debugger.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"SX-Video·Module"·available from Parallax for only $28.95 http://www.parallax.com/detail.asp?product_id=30012
"SX-Video OSD module"·available from Parallax for only·$49.95 http://www.parallax.com/detail.asp?product_id=30015
Product web site: www.sxvm.com
Coming soon... Cheap 4-digit LED display with driver IC·www.hc4led.com
"Sometimes it is better to remain silent and be thought a fool, than to speak and remove all doubt."
·
Bill
· I missed the part about writing to port D.
· If you do find the problem yourself, please let us know. You might be able to help someone else.
· From what you have posted so far I don't see anything obvious.
· I find that many times trying to isolate the problem does in fact cause it to reveal itself.
Bean.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
"SX-Video·Module"·available from Parallax for only $28.95 http://www.parallax.com/detail.asp?product_id=30012
"SX-Video OSD module"·available from Parallax for only·$49.95 http://www.parallax.com/detail.asp?product_id=30015
Product web site: www.sxvm.com
Coming soon... Cheap 4-digit LED display with driver IC·www.hc4led.com
"Sometimes it is better to remain silent and be thought a fool, than to speak and remove all doubt."
·
But there is a curious thing here. I have to put a NOP right before the RETI or it doesn’t work right for me. I believe this is due to pipeline issues since the last thing I do is write to the port register, but I’m not sure. Anyway, I posted the code for my interrupt in case anyone else has experienced this same thing or can explain why a NOP would be needed there.
Thanks,
Bill
org $10
;$10 should be available. fifo never actually uses it.
FIFO = $
ds 9
Temp ds 1
BitPointer ds 1 ; this is the bit pointer for each byte (8 max);
FifoPointer ds 1 ; this is the current byte
BitWaste ds 1 ; needed to get rid of non-data clock pulses in interupt and final pass
WasteClk ds 1 ; same
VoltBits ds 1
org $000
;
; ISR
; FIFO interupt - Triggers off the clock pulse (Port 'A' pin '7') and captures the data (Port 'A' pin '8')
; after a 36 count display flash is complete and captured, this transfers the final 4 bytes into another
; 4 bytes that are read by FifoSend
;
bank $10
inc BitWaste
stc
cjb BitWaste,WasteClk,FillPointerRet ; we want to loose the first 3 clock pulses (they have no data)
mov w, #FIFO ; indirect address the FIFO memory
add w, FifoPointer ; FIFO pointer
mov fsr, w
movb c,rb.7 ; capture the data into carry
rl ind ; rotate c into the current FIFO
dec BitPointer
snz
jmp FillPointer
FillPointerRet
mov w,#$19 ; enable pending reg.
mov m,w
mov !rb,#%10111111 ; clear the pending register so we can do this again.
nop ; needed apparently because of pipeline problems
reti
FillPointer
mov BitPointer, #8
dec FifoPointer
sz
jmp FillPointerRet
mov BitWaste, #$FF ; have to waste the final bit also
mov FifoPointer, #4 ; use this variable temporarily as a loop counter
:loop
mov w, #FIFO ; indirect address the FIFO memory
add w, FifoPointer
mov fsr, w
mov Temp, ind ; temporarily save the value
add fsr, #4 ; incr 4
mov ind, Temp ; store it
decsz FifoPointer
jmp :loop ; loop four times
mov FifoPointer, #4
jmp FillPointerRet
History: I was attempting to use one of the internal timers of the SX52 (the RTCC was already in use) by detecting flag conditions in T1CNTA. I set R2 to zero so it would just increment R1 and set it to software timer mode. With each detection of the compare flag, I just cleared the timer and the flag and then was able to use the elapsed time for my designed purposes. But some odd things were happening as I worked on this. . .
As it turns out, it had nothing to do with the timer or how I was using it. It had to do with code placement. It is fairly well documented that subroutines must be placed within the first half of a program page so the CALL can access it. This I had done. What I failed to recognize however, was that a lookup table using PC+W must also be located in the first half. As I wrote code for my interrupt, I inadvertently moved my lookup table into the second half. The lookup table was the code that wrote to a port, thus causing a lockup condition whenever I tried to access the port. I finally found a notation concerning this phenomena on page 132 of the “Development System Manuel.” It may be listed elsewhere too. If so, I never saw it.
If I could offer a suggestion to those who write the books. Perhaps a page listing all of the exceptions associated with the SX would be helpful. A glance through a page like that would have saved me literally weeks of work. But I’m not complaining, It all works very well now, and I did get a good education through all my debugging.
Now, on to other things. . .
Bill Franke
Cool move to offer some additional info on what went wrong, how you found it, and how you fixed it.
Regarding the suggestions for the manual, you're probably right - except it seems that most people don't read the docs and manual in the first place. That's not a reason to not implement your suggestion, it's just a sad fact that it still won't help as many people as it could.
Thanks, PeterM
They just examine the current addr and check for top half of page.·· Something like this...
_pc_check·MACRO·0
·IF ($ & $100)
··ERROR 'ERROR!! ADD PC,W instruction at invalid addr'
·ENDIF
·ENDM
_retw_check·MACRO·0
·if (( $ & $1ff ) > $101 )
··ERROR 'RETW data table not at top of code page.'
·ENDIF
·ENDM
I use a lot of conditional assembler/compiler directives that require my code to be as page independent as possible. These macros keep me from spending hours hunting down this type of table/page placement error.
I keep these macros in the same include file as my _mode and _ back macros, and register/mode definitions.
I hope this helps,
-AGM-
·