1313#include "hardware/xosc.h"
1414#include "hardware/irq.h"
1515#include "hardware/gpio.h"
16+ #include "hardware/ticks.h"
1617
18+ #if PICO_RP2040
19+ // The RTC clock frequency is 48MHz divided by power of 2 (to ensure an integer
20+ // division ratio will be used in the clocks block). A divisor of 1024 generates
21+ // an RTC clock tick of 46875Hz. This frequency is relatively close to the
22+ // customary 32 or 32.768kHz 'slow clock' crystals and provides good timing resolution.
1723#define RTC_CLOCK_FREQ_HZ (USB_CLK_KHZ * KHZ / 1024)
24+ #endif
25+
26+ static void start_all_ticks (void ) {
27+ uint32_t cycles = clock_get_hz (clk_ref ) / MHZ ;
28+ // Note RP2040 has a single tick generator in the watchdog which serves
29+ // watchdog, system timer and M0+ SysTick; The tick generator is clocked from clk_ref
30+ // but is now adapted by the hardware_ticks library for compatibility with RP2350
31+ // npte: hardware_ticks library now provides an adapter for RP2040
32+
33+ for (int i = 0 ; i < (int )TICK_COUNT ; ++ i ) {
34+ tick_start ((tick_gen_num_t )i , cycles );
35+ }
36+ }
1837
1938// Wrap the SDK's clocks_init() function to save code size
20- void __wrap_clocks_init (void ) {
21- clocks_init_optional_usb (true);
39+ void __wrap_runtime_init_clocks (void ) {
40+ runtime_init_clocks_optional_usb (true);
2241}
2342
24- // Copy of clocks_init () from pico-sdk, with USB
43+ // Copy of runtime_init_clocks () from pico-sdk, with USB
2544// PLL and clock init made optional (for light sleep wakeup).
26- void clocks_init_optional_usb (bool init_usb ) {
27- // Start tick in watchdog, the argument is in 'cycles per microsecond' i.e. MHz
28- watchdog_start_tick (XOSC_KHZ / KHZ );
29-
30- // Modification: removed FPGA check here
31-
45+ void runtime_init_clocks_optional_usb (bool init_usb ) {
3246 // Disable resus that may be enabled from previous software
3347 clocks_hw -> resus .ctrl = 0 ;
3448
@@ -46,14 +60,26 @@ void clocks_init_optional_usb(bool init_usb) {
4660 }
4761
4862 /// \tag::pll_init[]
49- pll_init (pll_sys , PLL_COMMON_REFDIV , PLL_SYS_VCO_FREQ_KHZ * KHZ , PLL_SYS_POSTDIV1 , PLL_SYS_POSTDIV2 );
63+ pll_init (pll_sys , PLL_COMMON_REFDIV , PLL_SYS_VCO_FREQ_HZ , PLL_SYS_POSTDIV1 , PLL_SYS_POSTDIV2 );
5064 if (init_usb ) {
51- pll_init (pll_usb , PLL_COMMON_REFDIV , PLL_USB_VCO_FREQ_KHZ * KHZ , PLL_USB_POSTDIV1 , PLL_USB_POSTDIV2 );
65+ pll_init (pll_usb , PLL_COMMON_REFDIV , PLL_USB_VCO_FREQ_HZ , PLL_USB_POSTDIV1 , PLL_USB_POSTDIV2 );
5266 }
5367 /// \end::pll_init[]
5468
5569 // Configure clocks
56- // CLK_REF = XOSC (usually) 12MHz / 1 = 12MHz
70+
71+ // todo amy, what is this N1,2,4 meant to mean?
72+ // RP2040 CLK_REF = XOSC (usually) 12MHz / 1 = 12MHz
73+ // RP2350 CLK_REF = XOSC (XOSC_MHZ) / N (1,2,4) = 12MHz
74+
75+ // clk_ref aux select is 0 because:
76+ //
77+ // - RP2040: no aux mux on clk_ref, so this field is don't-care.
78+ //
79+ // - RP2350: there is an aux mux, but we are selecting one of the
80+ // non-aux inputs to the glitchless mux, so the aux select doesn't
81+ // matter. The value of 0 here happens to be the sys PLL.
82+
5783 clock_configure (clk_ref ,
5884 CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC ,
5985 0 , // No aux mux
@@ -85,18 +111,32 @@ void clocks_init_optional_usb(bool init_usb) {
85111 USB_CLK_KHZ * KHZ ,
86112 USB_CLK_KHZ * KHZ );
87113
114+ #if HAS_RP2040_RTC
88115 // CLK RTC = PLL USB 48MHz / 1024 = 46875Hz
89116 clock_configure (clk_rtc ,
90117 0 , // No GLMUX
91118 CLOCKS_CLK_RTC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB ,
92119 USB_CLK_KHZ * KHZ ,
93120 RTC_CLOCK_FREQ_HZ );
121+ #endif
94122
95- // CLK PERI = clk_sys. Used as reference clock for Peripherals. No dividers so just select and enable
96- // Normally choose clk_sys or clk_usb
123+ // CLK PERI = clk_sys. Used as reference clock for UART and SPI serial.
97124 clock_configure (clk_peri ,
98125 0 ,
99126 CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLK_SYS ,
100127 SYS_CLK_KHZ * KHZ ,
101128 SYS_CLK_KHZ * KHZ );
129+
130+ #if PICO_RP2350
131+ // CLK_HSTX = clk_sys. Transmit bit clock for the HSTX peripheral.
132+ clock_configure (clk_hstx ,
133+ 0 ,
134+ CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLK_SYS ,
135+ SYS_CLK_KHZ * KHZ ,
136+ SYS_CLK_KHZ * KHZ );
137+ #endif
138+
139+ // Finally, all clocks are configured so start the ticks
140+ // The ticks use clk_ref so now that is configured we can start them
141+ start_all_ticks ();
102142}
0 commit comments