Difference between revisions of "84PCE:Ports:6000"

From WikiTI
Jump to: navigation, search
(Renamed to watchdog timer and documented registers)
(Document proper initialization sequence)
 
(One intermediate revision by the same user not shown)
Line 16: Line 16:
 
** 32-bit counter register.
 
** 32-bit counter register.
 
* 6004-6007 (R/W):
 
* 6004-6007 (R/W):
** 32-bit load register. The counter is loaded with this value when it reaches 0 or the restart register is used.
+
** 32-bit load register. The counter is loaded with this value after it reaches 0 or the reload register is used.
* 6008-6009 (W):
+
* 6008 (W):
** 16-bit restart register. When the value 5AB9h is written here, the counter is restarted. The bytes can be written individually.
+
** 8-bit reload register. When the value B9h is written here, the counter is reloaded with the value of the load register.
 
* 600C (R/W):
 
* 600C (R/W):
 
** Bit 0: Timer enable. Set to make the counter count down.
 
** Bit 0: Timer enable. Set to make the counter count down.
Line 26: Line 26:
 
** Bit 4: Clock source. Set to 1 to use the 32768Hz clock, or 0 to use the CPU clock.
 
** Bit 4: Clock source. Set to 1 to use the 32768Hz clock, or 0 to use the CPU clock.
 
* 6010 (R):
 
* 6010 (R):
** Status register. Bit 0 is set after the timer has reached 0, otherwise reset.
+
** Status register. Bit 0 becomes set after the counter reaches 0 and the timer switches to pulse mode (see [[#Detailed Operation|Detailed Operation]]).
* 6014 (W):
+
* 6014-6017 (W):
** Status clear register. Write 1 to reset bit 0 of the status register.
+
** Status clear register. Write any value to any of these bytes to reset bit 0 of the status register.
 
* 6018 (R/W):
 
* 6018 (R/W):
** 8-bit interrupt length register. Controls the amount of time an interrupt is signaled.
+
** 8-bit pulse width register. Write with the number of CPU cycles to pulse the configured signals, minus 1 (this immediately reloads the pulse counter). Reads the current value of the pulse counter, which counts down to 0 during a pulse.
 +
* 6019-601B (W):
 +
** Upper bytes of the pulse width register. Write any value to any of these bytes to reload the pulse counter with the value last written to the low byte.
 
* 601C-601F (R):
 
* 601C-601F (R):
 
** 32-bit revision register. Reads a constant 0x00010602, which corresponds to revision 1.6.2.
 
** 32-bit revision register. Reads a constant 0x00010602, which corresponds to revision 1.6.2.
 +
 +
== Detailed Operation ==
 +
The watchdog timer operates in two modes, counter mode and pulse mode. 1 CPU cycle after the counter reaches 0, it reloads the counter, sets the status bit, and switches to pulse mode. In pulse mode, if the timer is enabled, it asserts the configured signals and counts down the pulse counter each CPU cycle until it reaches 0. The main counter does not count down in this mode. 1 CPU cycle after the pulse counter reaches 0, it reloads the pulse counter with the pulse width register and switches back to counter mode.
 +
 +
Effectively this means that when configured with the CPU clock, the counter has a period of the load register plus 1, plus the pulse width register plus 1. When configured with the 32768Hz clock, the counter has a period of the load register, plus 1 if the pulse width register plus 2 CPU cycles exceeds the length of a 32768Hz tick (which is only possible if the CPU clock is set to 6MHz).
 +
 +
== Watchdog Initialization ==
 +
Care should be taken when initializing the watchdog timer, because it's possible for the timer to be stopped while in pulse mode, and writing to the reload register does not switch back to counter mode. Thus, it is possible to accidentally trigger a reset or NMI when starting the timer for the first time, depending on previous usage.
 +
 +
However, it is possible to take advantage of the fact that the pulse counter being 0 will switch to counter mode, even if the timer is not enabled. But be aware that the main counter being 0 will also similarly switch to pulse mode, so ensure it is non-zero first.
 +
 +
Thus, an effective initialization order is:
 +
* Write 0 to the control register to disable the timer
 +
* Write the desired (non-zero) load value to the load register
 +
* Write B9h to the reload register to load the counter
 +
* Write 0 to the pulse width register to reload the pulse counter with 0 and switch out of pulse mode if needed
 +
* Write the desired pulse width value to the pulse width register (if the desired value is non-zero)
 +
* Write to the control register to enable the timer and any desired signals

Latest revision as of 14:55, 11 July 2024

Synopsis

Port Number: 6000-601F

Memory-mapped address: F10000

Function: Watchdog timer

This range of ports is a watchdog timer (appears to be model FTWDT010). Its primary feature is a 32-bit looping downward counter which can be set to either 32768Hz or the CPU frequency. It can also be used to reset the calculator or trigger a non-maskable interrupt (which typically will also reset the calculator). It is unknown whether it can trigger a maskable interrupt.

Registers

All registers are little-endian.

  • 6000-6003 (R):
    • 32-bit counter register.
  • 6004-6007 (R/W):
    • 32-bit load register. The counter is loaded with this value after it reaches 0 or the reload register is used.
  • 6008 (W):
    • 8-bit reload register. When the value B9h is written here, the counter is reloaded with the value of the load register.
  • 600C (R/W):
    • Bit 0: Timer enable. Set to make the counter count down.
    • Bit 1: System reset enable. Set to reboot the calculator when the counter reaches 0.
    • Bit 2: System reset interrupt enable. Set to trigger a non-maskable interrupt when the counter reaches 0.
    • Bit 3: External signal enable. Set to enable the external signal when the counter reaches 0 (this may have no effect).
    • Bit 4: Clock source. Set to 1 to use the 32768Hz clock, or 0 to use the CPU clock.
  • 6010 (R):
    • Status register. Bit 0 becomes set after the counter reaches 0 and the timer switches to pulse mode (see Detailed Operation).
  • 6014-6017 (W):
    • Status clear register. Write any value to any of these bytes to reset bit 0 of the status register.
  • 6018 (R/W):
    • 8-bit pulse width register. Write with the number of CPU cycles to pulse the configured signals, minus 1 (this immediately reloads the pulse counter). Reads the current value of the pulse counter, which counts down to 0 during a pulse.
  • 6019-601B (W):
    • Upper bytes of the pulse width register. Write any value to any of these bytes to reload the pulse counter with the value last written to the low byte.
  • 601C-601F (R):
    • 32-bit revision register. Reads a constant 0x00010602, which corresponds to revision 1.6.2.

Detailed Operation

The watchdog timer operates in two modes, counter mode and pulse mode. 1 CPU cycle after the counter reaches 0, it reloads the counter, sets the status bit, and switches to pulse mode. In pulse mode, if the timer is enabled, it asserts the configured signals and counts down the pulse counter each CPU cycle until it reaches 0. The main counter does not count down in this mode. 1 CPU cycle after the pulse counter reaches 0, it reloads the pulse counter with the pulse width register and switches back to counter mode.

Effectively this means that when configured with the CPU clock, the counter has a period of the load register plus 1, plus the pulse width register plus 1. When configured with the 32768Hz clock, the counter has a period of the load register, plus 1 if the pulse width register plus 2 CPU cycles exceeds the length of a 32768Hz tick (which is only possible if the CPU clock is set to 6MHz).

Watchdog Initialization

Care should be taken when initializing the watchdog timer, because it's possible for the timer to be stopped while in pulse mode, and writing to the reload register does not switch back to counter mode. Thus, it is possible to accidentally trigger a reset or NMI when starting the timer for the first time, depending on previous usage.

However, it is possible to take advantage of the fact that the pulse counter being 0 will switch to counter mode, even if the timer is not enabled. But be aware that the main counter being 0 will also similarly switch to pulse mode, so ensure it is non-zero first.

Thus, an effective initialization order is:

  • Write 0 to the control register to disable the timer
  • Write the desired (non-zero) load value to the load register
  • Write B9h to the reload register to load the counter
  • Write 0 to the pulse width register to reload the pulse counter with 0 and switch out of pulse mode if needed
  • Write the desired pulse width value to the pulse width register (if the desired value is non-zero)
  • Write to the control register to enable the timer and any desired signals