rp23 Part60
rp23 Part60
60 }
61
62 int main() {
63 stdio_init_all();
64 printf("Timer lowlevel!\n");
65
66 // Set alarm every 2 seconds
67 while (1) {
68 alarm_fired = false;
69 alarm_in_us(1000000 * 2);
70 // Wait for alarm to fire
71 while (!alarm_fired);
72 }
73 }
If you don’t want to use an alarm to wait for a period of time, use a while loop instead. The SDK provides various
busy_wait_ functions to do this:
115 hi = timer->timerawh;
116 tight_loop_contents();
117 }
118 while (hi == hi_target && timer->timerawl < (uint32_t) target) {
119 hi = timer->timerawh;
120 tight_loop_contents();
121 }
122 }
56 return 0;
57 }
0x10 ALARM0 Arm alarm 0, and configure the time it will fire.
Once armed, the alarm fires when TIMER_ALARM0 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
0x14 ALARM1 Arm alarm 1, and configure the time it will fire.
Once armed, the alarm fires when TIMER_ALARM1 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
0x18 ALARM2 Arm alarm 2, and configure the time it will fire.
Once armed, the alarm fires when TIMER_ALARM2 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
0x1c ALARM3 Arm alarm 3, and configure the time it will fire.
Once armed, the alarm fires when TIMER_ALARM3 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
0x24 TIMERAWH Raw read from bits 63:32 of time (no side effects)
0x28 TIMERAWL Raw read from bits 31:0 of time (no side effects)
0x2c DBGPAUSE Set bits high to enable pause when the corresponding debug
ports are active
0x38 SOURCE Selects the source for the timer. Defaults to the normal tick
configured in the ticks block (typically configured to 1
microsecond). Writing to 1 will ignore the tick and count clk_sys
cycles instead.
31:0 Arm alarm 0, and configure the time it will fire. RW 0x00000000
Once armed, the alarm fires when TIMER_ALARM0 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
31:0 Arm alarm 1, and configure the time it will fire. RW 0x00000000
Once armed, the alarm fires when TIMER_ALARM1 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
31:0 Arm alarm 2, and configure the time it will fire. RW 0x00000000
Once armed, the alarm fires when TIMER_ALARM2 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
31:0 Arm alarm 3, and configure the time it will fire. RW 0x00000000
Once armed, the alarm fires when TIMER_ALARM3 == TIMELR.
The alarm will disarm itself once it fires, and can
be disarmed early using the ARMED status register.
31:4 Reserved. - -
Table 1236.
Bits Description Type Reset
TIMERAWH Register
31:0 Raw read from bits 63:32 of time (no side effects) RO 0x00000000
Table 1237.
Bits Description Type Reset
TIMERAWL Register
31:0 Raw read from bits 31:0 of time (no side effects) RO 0x00000000
Description
Set bits high to enable pause when the corresponding debug ports are active
Table 1238.
Bits Description Type Reset
DBGPAUSE Register
31:3 Reserved. - -
0 Reserved. - -
31:1 Reserved. - -
31:1 Reserved. - -
Description
Selects the source for the timer. Defaults to the normal tick configured in the ticks block (typically configured to 1
microsecond). Writing to 1 will ignore the tick and count clk_sys cycles instead.
31:1 Reserved. - -
0 CLK_SYS RW 0x0
Enumerated values:
0x0 → TICK
0x1 → CLK_SYS
Description
Raw Interrupts
31:4 Reserved. - -
3 ALARM_3 WC 0x0
2 ALARM_2 WC 0x0
1 ALARM_1 WC 0x0
0 ALARM_0 WC 0x0
Description
Interrupt Enable
31:4 Reserved. - -
3 ALARM_3 RW 0x0
2 ALARM_2 RW 0x0
1 ALARM_1 RW 0x0
0 ALARM_0 RW 0x0
Description
Interrupt Force
31:4 Reserved. - -
3 ALARM_3 RW 0x0
2 ALARM_2 RW 0x0
1 ALARM_1 RW 0x0
0 ALARM_0 RW 0x0
Offset: 0x48
Description
Interrupt status after masking & forcing
31:4 Reserved. - -
3 ALARM_3 RO 0x0
2 ALARM_2 RO 0x0
1 ALARM_1 RO 0x0
0 ALARM_0 RO 0x0
12.9. Watchdog
12.9.1. Overview
The watchdog is a countdown timer which can be configured to reset selected components when it reaches zero. In
normal operation it is periodically loaded with a non-zero value to prevent the reset occuring. If the chip locks up or
software gets stuck in a loop, the reset allows recovery.
The watchdog is reset by any chip-level reset (see Section 7.3). The sources of the chip-level reset are:
As on RP2040 the watchdog can trigger a PSM (Power-on State Machine) sequence to reset system components or it
can be used to reset selected subsystem components. On RP2350, the watchdog can also trigger a chip level reset.
NOTE
Additional general-purpose scratch registers are available in POWMAN SCRATCH0 through SCRATCH7. These
registers also survive power cycling the switched core domain.
60 if (!delay_ms) {
61 hw_set_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_TRIGGER_BITS);
62 } else {
63 load_value = delay_ms * 1000;
64 if (load_value > WATCHDOG_LOAD_BITS)
65 load_value = WATCHDOG_LOAD_BITS;
66
67 watchdog_update();
68
69 hw_set_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_ENABLE_BITS);
70 }
71 }
12.9.6.3. Usage
The Pico Examples repository provides a hello_watchdog example that uses the hardware_watchdog to demonstrate use of
the watchdog.
11 int main() {
12 stdio_init_all();
13
14 if (watchdog_caused_reboot()) {
15 printf("Rebooted by Watchdog!\n");
16 return 0;
17 } else {
18 printf("Clean boot\n");
19 }
20
21 // Enable the watchdog, requiring the watchdog to be updated every 100ms or the chip will
reboot
22 // second arg is pause on debug which means the watchdog will pause when stepping through
code
23 watchdog_enable(100, 1);
24
25 for (uint i = 0; i < 5; i++) {
26 printf("Updating watchdog %d\n", i);
27 watchdog_update();
28 }
29
30 // Wait in an infinite loop and don't update the watchdog so it reboots us
31 printf("Waiting to be rebooted by watchdog\n");
32 while(1);
33 }
0x04 LOAD Load the watchdog timer. The maximum setting is 0xffffff which
corresponds to approximately 16 seconds.
0x08 REASON Logs the reason for the last reset. Both bits are zero for the case
of a hardware reset.
0x0c SCRATCH0 Scratch register. Information persists through soft reset of the
chip.
0x10 SCRATCH1 Scratch register. Information persists through soft reset of the
chip.
0x14 SCRATCH2 Scratch register. Information persists through soft reset of the
chip.
0x18 SCRATCH3 Scratch register. Information persists through soft reset of the
chip.
0x1c SCRATCH4 Scratch register. Information persists through soft reset of the
chip.
0x20 SCRATCH5 Scratch register. Information persists through soft reset of the
chip.
0x24 SCRATCH6 Scratch register. Information persists through soft reset of the
chip.
0x28 SCRATCH7 Scratch register. Information persists through soft reset of the
chip.
Description
Watchdog control
The rst_wdsel register determines which subsystems are reset when the watchdog is triggered.
The watchdog can be triggered in software.
29:27 Reserved. - -
26 PAUSE_DBG1: Pause the watchdog timer when processor 1 is in debug mode RW 0x1
25 PAUSE_DBG0: Pause the watchdog timer when processor 0 is in debug mode RW 0x1
24 PAUSE_JTAG: Pause the watchdog timer when JTAG is accessing the bus RW 0x1
fabric
23:0 TIME: Indicates the time in usec before a watchdog reset will be triggered RO 0x000000
31:24 Reserved. - -
23:0 Load the watchdog timer. The maximum setting is 0xffffff which corresponds WF 0x000000
to approximately 16 seconds.
Description
Logs the reason for the last reset. Both bits are zero for the case of a hardware reset.
Additionally, as of RP2350, a debugger warm reset of either core (SYSRESETREQ or hartreset) will also clear the
watchdog reason register, so that software loaded under the debugger following a watchdog timeout will not continue
to see the timeout condition.
31:2 Reserved. - -
1 FORCE RO 0x0
0 TIMER RO 0x0
Table 1250.
Bits Description Type Reset
SCRATCH0,
SCRATCH1, …,
31:0 Scratch register. Information persists through soft reset of the chip. RW 0x00000000
SCRATCH6,
SCRATCH7 Registers
12.10.1. Overview
The always-on timer (AON Timer) is the only timer that operates in all power modes. It can be used as a real-time
counter or an interval timer and incorporates an alarm which can be used to trigger a power-up event or an interrupt. It
incorporates a 64-bit counter intended to count 1ms ticks, but the tick generator can be configured to run faster or
slower if required. Note that the AON Timer tick generator is independent of all other tick generators on the chip.
The default tick source is the 32kHz on-chip low-power oscillator (LPOSC), see Section 8.4. The LPOSC frequency is not
precise and may vary with voltage and temperature. When the chip core is powered, the tick source can be switched to
the on-chip crystal oscillator (XOSC) for greater precision. If greater precision is also required when the chip core is
unpowered, then a 32kHz clock or a 1ms tick can be supplied from an external source. Alternatively, the AON Timer can
be synchronised to an external 1Hz source.
The AON Timer is integrated with the power manager (POWMAN) and shares the POWMAN register block. Writes are
limited to 16 bits because a key (0x5afe) is required in the top 16 bits to prevent erroneous writes from locking up the
chip. Most AON Timer registers can be enabled for write by Non-secure software, unlike other POWMAN registers.
However, the registers used to select an external clock, select an external tick source, and enable power-up on alarm
can only be written by Secure software.
To read the current 64-bit AON Timer value, use the following 2 × 32-bit read-only registers:
• READ_TIME_UPPER
• READ_TIME_LOWER
Because the AON Timer can increment during a read, use the following procedure to protect against erroneous reads:
1. Read READ_TIME_UPPER
2. Read READ_TIME_LOWER
3. Read READ_TIME_UPPER
4. If the READ_TIME_UPPER value changes between steps 1 and 3, repeat the whole procedure
When used as a real time clock, the 64-bit time value is set using 4 × 16-bit registers. These registers can only be written
when the AON Timer is stopped by writing a 0 to TIMER.RUN:
• SET_TIME_63TO48
• SET_TIME_47TO32
• SET_TIME_31TO16
• SET_TIME_15TO0
These registers cannot be used to read the time value.
When used as an interval timer, write a 1 to TIMER.CLEAR to clear the timer value. It is not necessary to stop the AON
Timer to do this. The TIMER.CLEAR register is self-clearing: it returns to 0 when the operation completes. This allows
easy implementation of an alarm that wakes the chip or generates an interrupt at regular intervals.
• ALARM_TIME_63TO48
• ALARM_TIME_47TO32
• ALARM_TIME_31TO16
• ALARM_TIME_15TO0
To avoid false alarms, disable the alarm before setting the alarm time.
When the alarm fires, the AON Timer sets the alarm status flag TIMER.ALARM.
To clear the alarm status flag, write a 1 to the alarm status flag.
To configure the alarm to trigger a power-up, set TIMER.PWRUP_ON_ALARM. This feature is not available to Non-secure
code.
The alarm can be configured to trigger an interrupt. The interrupt is handled in the standard way using the following
register fields:
NOTE
LPOSC is the default source and can be used in all power modes. It nominally runs at 32.768kHz and can only be tuned
to 1% accuracy. The AON Timer derives the 1ms tick from the LPOSC using a 6.16 bit fractional divider whose divisor is
initialised to 32.768. The divisor can be modified to achieve greater accuracy. Because the LPOSC frequency varies with
supply voltage and temperature, accuracy is limited unless supply voltage and temperature are stable. To modify the
divisor, write to the following registers:
If the tick source is not LPOSC, you can switch it back to LPOSC by writing a 1 to TIMER.USE_LPOSC. It is not necessary
to stop the AON Timer to do this. The newly selected tick will be synchronised to the current tick, so the operation may
take up to 1 tick cycle (1ms in normal operation). When the operation is complete, TIMER.USE_LPOSC will self-clear and
TIMER.USING_LPOSC will be set. Due to sampling, a small error of up to 2 periods of the newly selected clock will be
subtracted from the time. When switching to LPOSC at 32kHz, an error of up to 62μs will be subtracted.
If LPOSC is not sufficiently accurate, an external 32.768kHz clock can be used. This will be multiplexed onto the internal
low-power clock and will therefore drive all components that are driven by that clock, including the power sequencer
components. The external clock can be used in all power modes. When an external clock is in use, you can stop the
LPOSC (see Section 8.4).
2. Switch to the external LPOSC by setting EXT_TIME_REF.DRIVE_LPCK. This register should only be written when
TIMER.RUN = 0 and the power sequencer is inactive. You can only write to this register from Secure code.
The external 32kHz clock replaces the clock from LPOSC. Therefore the same registers are used for AON Timer
configuration (see Section 12.10.5.1):
• TIMER.USE_LPOSC
• TIMER.USING_LPOSC
• LPOSC_FREQ_KHZ_INT
• LPOSC_FREQ_KHZ_FRAC
The XOSC clock is provided via the reference clock (clk_ref). The user must ensure the reference clock is being driven
from the XOSC before selecting it as the source of the AON Timer tick. This is the normal configuration following boot.
To check, look for CLK_REF_SELECTED = 0x4. The reference clock may be a divided version of the XOSC. The divisor
defaults to 1 and can be read from CLK_REF_DIV.INT. If the chip is operated with a faster XOSC, the clock sent to the
AON Timer must not exceed 29MHz.
The AON Timer derives the 1ms tick from the XOSC using a 16.16 bit fractional divider whose divisor is initialised to
12000.0. This assumes a 12MHz crystal is used and the reference clock divisor is 1. If that is not the case, the divisor in
the AON Timer can be modified by writing to the following registers:
To select the XOSC as the AON Timer tick source, write a 1 to TIMER.USE_XOSC. It is not necessary to stop the AON
Timer to do this. The newly selected tick will be synchronised to the current tick, so the operation may take up to 1 tick
cycle (1ms in normal operation). When the operation is complete TIMER.USE_XOSC will self-clear and
TIMER.USING_XOSC will be set. Due to sampling, a small error of up to 2 periods of the newly selected clock will be
subtracted from the time. When switching to XOSC at 12MHz an error of up to 167ns will be subtracted.
When the chip core is powered down the XOSC will stop. If TIMER.USING_XOSC is set, the power-down sequencer
automatically reverts to TIMER.USING_LPOSC before the XOSC stops.
To select an external 1ms tick source, configure the GPIO source as described in Section 12.10.7. Then, write a 1 to
TIMER.USE_GPIO_1KHZ. It is not necessary to stop the AON Timer to do this, however the newly selected tick will not be
synchronised to the current tick, so the operation so the operation will advance the time by up to 1ms. If using an
external 1ms tick it is recommended to set the time after selecting the source. When the operation is complete
TIMER.USE_GPIO_1KHZ will self-clear and TIMER.USING_GPIO_1KHZ will be set.
The tick is triggered from the falling edge of the selected GPIO. For correct sampling, the GPIO pulse width and interval
must both be greater than the period of LPOSC (>31us). This limits the maximum frequency of the external tick to
16kHz.
If the LPOSC is fast, the ms counter pauses at a 1 second step until the 1s tick is received. If the LPOSC is slow, the 1s
tick causes the ms counter to run very quickly until reaching the 1 second step. This ensures that all ms values are
counted, ensuring that any alarm set to ms precision will fire. A more sophisticated synchronisation method can be
implemented in software.
To use the hardware synchronisation feature, configure the GPIO source as described in Section 12.10.7. Then, enable
the feature by writing a 1 to TIMER.USE_GPIO_1HZ. This can be set at any time, it is not necessary to stop the AON
Timer. When the operation is complete TIMER.USE_GPIO_1HZ will self-clear and TIMER.USING_GPIO_1HZ will be set.
The tick is triggered from the falling edge of the selected GPIO. For correct sampling, the GPIO pulse width and interval
must be greater than the period of LPOSC (>31us).
• EXT_TIME_REF.SOURCE_SEL = 0 → GPIO12
• EXT_TIME_REF.SOURCE_SEL = 1 → GPIO20
• EXT_TIME_REF.SOURCE_SEL = 2 → GPIO14
• EXT_TIME_REF.SOURCE_SEL = 3 → GPIO22
As described previously, the external tick is limited to 16kHz, so the maximum upscaling using this method is also 16.
This gives a time resolution of 1/16th of 1 ms (62.5μs).
These limitations can be overcome either by using a faster external clock (see Section 12.10.5.2) or keeping the chip
core powered so the AON Timer is always running from the XOSC. If a faster external clock is used then the power
sequencer timings will also need to be adjusted.
For example, suppose 1μsec timer precision is required. The user could supply an external 2-25MHz clock in place of
the LPOSC and program both the LPOSC and XOSC frequency registers in MHz units rather than kHz. The maximum
frequency of the external clock is 29MHz.
• SET_TIME_63TO48
• SET_TIME_47TO32
• SET_TIME_31TO16
• SET_TIME_15TO0
• READ_TIME_UPPER
• READ_TIME_LOWER
• ALARM_TIME_63TO48
• ALARM_TIME_47TO32
• ALARM_TIME_31TO16
• ALARM_TIME_15TO0
• TIMER
12.11. HSTX
The high-speed serial transmit (HSTX) streams data from the system clock domain to up to 8 GPIOs at a rate
independent of the system clock. On RP2350, GPIOs 12 through 19 are HSTX-capable. HSTX is output-only.
HSTX drives data through GPIOs using DDR output registers to transfer up to two bits per clock cycle per pin. The HSTX
balances all delays to GPIO outputs within 300 picoseconds, minimising common-mode components when using
neighbouring GPIOs as a pseudo-differential driver. This also helps maintain destination setup and hold time when a
clock is driven alongside the output data.
The maximum frequency for the HSTX clock is 150 MHz, the same as the system clock. With DDR output operation, this
is a maximum data rate of 300 Mb/s per pin. There are no limits on the frequency ratio of the system and HSTX clocks,
however each clock must be individually fast enough to maintain your required throughput. Very low system clock
frequencies coupled with very high HSTX frequencies may encounter system DMA bandwidth limitations, since the
DMA is capped at one HSTX FIFO write per system clock cycle.
The FIFO is accessed through a bus interface separate from the control registers (Section 12.11.7), which take multiple
cycles to access due to the asynchronous bus crossing. This design avoids incurring bus stalls on the system DMA or
the FASTPERI arbiter when accessing the FIFO.
The HSTX side also pops 32 bits at a time from the FIFO. The word data stream from the FIFO is optionally manipulated
by the command expander (Section 12.11.5) before being passed to the output shift register.
The HSTX’s internal data paths are 32 bits wide, but the output is narrower: no more than 16 bits can be output per
HSTX cycle (8 GPIOs × DDR). The output shift register adapts these mismatched data widths. The output shift register
is a 32-bit shift register, which always refills 32 bits at a time, either from the command expander output or directly from
the data FIFO.
The source of data for the output shift register is configured by the CSR.EXPAND_EN field:
• when set, the command expander interposes the FIFO and the output shift register
• when clear, the command expander is bypassed, popping the FIFO directly into the shift register
Whenever CSR.EN is low, the shift register is flushed to empty. Once HSTX has been configured, and EN is set high, the
shift register is ready to accept data, and will pop data as soon as it becomes available.
After popping the first data word, the shift register will now shift every HSTX clock cycle until it becomes empty. The
shift behaviour is configured by:
• CSR.N_SHIFTS, which determines how many times to shift before the register is considered empty
• CSR.SHIFT, which is a right-rotate applied to the shift register every cycle
CSR.N_SHIFTS and CSR.SHIFT must only be changed when CSR.EN is low. It is safe to change these fields in the same
register write that sets EN from low to high.
SHIFT × N_SHIFTS is not necessarily less than or equal to 32. For example, a SHIFT of 31 might be used to shift the register
left by one bit per cycle, since right-rotate is a modular operation, and -1 is equal to 31 under a modulus of 32.
When the shift register is about to become empty, it will immediately refill with fresh data from the command expander
or FIFO if data is available. When data is available, the shift register is never empty for any cycle. If data is not available,
the shift register becomes empty and stops shifting until more data is provided. Once data is provided, the shift register
refills and begins shifting once again.
• BITx.SEL_P selects which shift register bit (0 through 31) is output for the first half of each HSTX clock cycle
• BITx.SEL_N selects which shift register bit (0 through 31) is output for the second half of each clock cycle
• BITx.INV inverts the output (logical NOT)
• BITx.CLK indicates that this pin should be connected to the clock generator (Section 12.11.4) rather than the output
shift register
To disable DDR behaviour set SEL_N equal to SEL_P. To implement a differential output, configure two pins identically
except for the INV bit, which should be set for one pin and clear for the other.
Together with the SHIFT and N_SHIFTS controls for the shift register, the pin configuration determines the data layout
passed through the HSTX. Since not all of us are accustomed to thinking in four dimensions, it’s worth going through
some examples with a single pin:
◦ Same as the previous, but repeats the 8-cycle pattern four times before refreshing the shift register.
◦ Rotating by 32 restores the original value that was popped into the shift register from the FIFO or command
expander.
The separation of shift register and bit crossbar allows both zipped and unzipped multi-bit records, once multiple pins
are involved. For example, compare these two configurations:
◦ The shift register advances by two every cycle, introducing a new bit-pair to bits 1:0 for the BIT0 pin, and also
introducing a new bit-pair to bits 17:16 for the BIT1 pin.
Depending on software needs, it may be preferable to pack together all of the bits output on the same cycle (zipped
records), or all of the bits that go through the same pin (unzipped records), so HSTX supports both.
As a final, concrete example, take TMDS (used in DVI): here each 32-bit word contains 3 × 10-bit TMDS symbols, each of
which is serialised to a differential pair over the course of 10 TMDS bit times. For performance, it’s preferable to make
each HSTX clock period equal to two TMDS bit periods, by leveraging the DDR capability. A possible configuration would
therefore be:
The clock generator increments on cycles where the output shift register is shifted. Generally, the clock period will be a
divisor of CSR.N_SHIFTS so that clock and data maintain a consistent alignment. In the TMDS example in the previous
section, a CLKDIV of 5 would be suitable, so that the clock repeats every time the shift register refreshes. This matches
the requirement for a TMDS clock period of 10 bit periods, since two bits are transferred every cycle.
The clock generator output is connected to any pin whose BITx.CLK bit is set (e.g. BIT0.CLK). To produce differential