Z180 Timer issues - changing value of reload registers does not change timer frequency

122 views
Skip to first unread message

Nick Tate

unread,
Mar 27, 2022, 8:47:44 PM3/27/22
to retro-comp
Hi,
I'm having serious issues with the Z180 timers... My code sets up mode two interrupts, then writes to the Timer Reload Registers HIGH and LOW, and then set the bits in tthe Timer Control Register to enable the timer interrupt (TIE0) and Timer Down Count Enable (TDE0) 
Then the code ends in a loop (the main task just loops). The interrupt service routine  increments register A and outputs it to a parallel port so I can view activity of BIT 0 on a scope. I get the square waveform on my scope as expected but if I change the value in the Timer Reload Registers the frequency does not change.

I'm using the SC126 with the Z8S18033VSC version of the CPU as supplied with the kit and running at 18.432 MHz. 

I'm completely out of ideas after scouring the internet and reading different versions of Z180 documentation to find ERRATA but can not find any on the timers so I wonder if anybody else has had this issue and has a possible solution.

Thanks
Nick
 

Alastair Patrick

unread,
Mar 27, 2022, 11:57:25 PM3/27/22
to retro-comp
You don't say whether your interrupt service routine acknowledges the interrupt. If it doesn't then that might explain the problem. Once the timer hits zero and the ISR runs it will keep immediately rerunning the ISR until the interrupt is acknowledged, i.e. forever, generating a high frequency square wave. I don't have a Z180 to test with but I believe this is the relevant part of the manual:

"When TMDR0 decrements to 0, TIF0 is set to 1. This generates an interrupt request if enabled by TIE0 = 1. TIF0 is reset to 0 when TCR is read and the higher or lower byte of TMDR0 is read. During RESET, TIF0 is cleared to 0  ."
  
I believe the part in bold explains how to acknowledge the interrupt.

I also note the manual says TIF0 is read-only so trying to acknowledge the interrupt by writing 0 to TIF0 probably doesn't work.

Al

Phillip Stevens

unread,
Mar 28, 2022, 2:14:13 AM3/28/22
to retro-comp
There's some ideas on how to set and reset the Timer Registers here, where it is done for FreeRTOS on the SC126/SC130.

Al wrote:
"When TMDR0 decrements to 0, TIF0 is set to 1. This generates an interrupt request if enabled by TIE0 = 1. TIF0 is reset to 0 when TCR is read and the higher or lower byte of TMDR0 is read. During RESET, TIF0 is cleared to 0  ."

Nick wrote:
I'm having serious issues with the Z180 timers... My code sets up mode two interrupts, then writes to the Timer Reload Registers HIGH and LOW, and then set the bits in tthe Timer Control Register to enable the timer interrupt (TIE0) and Timer Down Count Enable (TDE0) 
Then the code ends in a loop (the main task just loops). The interrupt service routine  increments register A and outputs it to a parallel port so I can view activity of BIT 0 on a scope. I get the square waveform on my scope as expected but if I change the value in the Timer Reload Registers the frequency does not change.

Nick Tate

unread,
Mar 28, 2022, 5:42:54 AM3/28/22
to retro-comp
@alastai
@Phillip

Heres my interrupt routine...

start_isr:
              INC    A
              OUT     (81),   A                       ; Parallel port - scope looking at bit 0.
              EI
              RETI

The code does return back to the main loop afterwards. I think if I understand you correctly is that I have to read the TCR and then a TMDR0 to reset the interrupt state to zero before returning to the main loop. This seems strange after using the Z80 CTC where you can just let it free run and it will interrupt at the time you set in the time constant register without any further intervention.
But it is what it is so I will try your suggestions and report back

Thanks
Nick



 

Nick Tate

unread,
Mar 28, 2022, 6:48:50 AM3/28/22
to retro-comp
Thats great! Working correctly now.. I just added this...

in0 c, (TMCR)
in0 c, (TMDR0)
EI
RETI

Thanks for your help
Nick

Alan Cox

unread,
Mar 28, 2022, 7:10:42 AM3/28/22
to retro-comp

The code does return back to the main loop afterwards. I think if I understand you correctly is that I have to read the TCR and then a TMDR0 to reset the interrupt state to zero before returning to the main loop. This seems strange after using the Z80 CTC where you can just let it free run and it will interrupt at the time you set in the time constant register without any further intervention.

The CTC is cleared by seeing a reti and so requires IM2 or some really clever trickery (because otherwise unrelated RETI instructions lose events). It's actually the anomalous case. Most devices and systems require that you acknowledge timers to clear them.

Alan

Reply all
Reply to author
Forward
0 new messages