My application uses the Modulus downcounter to generate interrupts when the count reaches zero to update a real time clock. Calling a subroutine in ppage $22 hangs up the micro unless Modulus interrupts are disabled. The interrupt service routine is in a non-paged location. The same thing happens with serial communications to a LCD display. I've had to change serial operations to a polling mode to avoid those interrupts.
Why can't interrupts be used with the CALL function? The RTI instruction does not seem to restore the ppage value and this may be the reason. Can anyone shed some light on this problem?
The processor is a MC9S12DP512.
Solved! Go to Solution.
OOPS!!!! Problem solved and my face is RED. Careful examination of the program code revealed an incorrect value in setting up the Modulus module. When corrected as shown in the above code snippet, the interrupt hang-up disappeared.
I'm truly sorry for the confusion I may have caused.
Do you exit from paged routine with RTS? CALL'ing routines from ISR is OK, provided you exit back to ISR with RTC instruction. Also if your ISR writes to and modifies PPAGE, then you should restore PPAGE before return from interrupt.
Yes, my paged subroutine was indeed ended with RTC, and the interrupt ISR did not touch PPAGE, it only updated the real time clock variables in un-paged RAM. The serial transmissions to the LCD display also took place in un-paged Flash memory. Changing the serial operations from interrupt to polled and disabling the Modulus interrupts solved the problem.
Does anyone else use the CALL function with ongoing interrupts? I would be most interested in comparing systems.
My application is a telescope control sytem that uses the Modulus module to generate interrupts for a real time clock. It is setup with the following code:
; modulus downcounter setup
bset MCCTL,#modmc+mcen ;enable modulus mode
bset MCCTL,#mczi+mcpr1+mcpr0 ;enable modulus ints, set
; prescaler to divide bus clock by 16
; bus clock = PLLCLK/2 = 24MHz
bset MCCTL,#flmc ;force load reg into mod count reg
movw #50000,MCCNT ;set load reg for 30 interrupts/sec
The Modulus ISR is:
modulus_irq: equ * ;modulus int service routine, 30/sec
bset MCFLG,mczf ;clears the modulus interrupt flag by writing
; a 1 to the mczf bit7, all other bits reserved
dec point5 ;0.5 sec timer
bne mi1
movb #15,point5 ;reload 0.5 sec timer
jsr clock ;update date/time variables by 0.5 sec
movb #$FF,time ;set time flag
mi1: rti
The application program loaded in non-paged Flash $3F contains the statement:
call get_star_coord,$22 ;(uses only global variables)
The following code segment is loaded in ppage $22:
org $8000
get_star_coord: equ * ;converts ascii coord to fp degrees
std temp_fp ;d points to ascii seconds value
jsr ASCFLT ;convert ascii seconds to fp in FPACC1
ldx #fp_60 ;constant 60 converts seconds to minutes
jsr GETFPAC2
................
jsr FLTDIV ;convert seconds to fractional minutes
jsr UINT2FLT ;convert degrees to fp in FPACC1
jsr PULFPAC2 ;retrieve fractional degrees on stack
jsr FLTADD ;add fractional degrees
rtc ;return (get_star_coord,$22) with fp degrees in FPACC1
The subroutine is doing coordinate calculations in floating point using other subroutines in non-paged Flash but is being interrupted periodically by the Modulus system. There is not enough space in non-paged Flash to load this sub or others. I hope this makes clear what the program is doing. I'll be happy to explain further, if needed.
OOPS!!!! Problem solved and my face is RED. Careful examination of the program code revealed an incorrect value in setting up the Modulus module. When corrected as shown in the above code snippet, the interrupt hang-up disappeared.
I'm truly sorry for the confusion I may have caused.