|
| 1 | +/* |
| 2 | + * SPDX-FileCopyrightText: 2025 Tom Hert < [email protected]> |
| 3 | + * SPDX-FileCopyrightText: 2025 HAW Hamburg |
| 4 | + * SPDX-License-Identifier: LGPL-2.1-only |
| 5 | + */ |
| 6 | + |
| 7 | +/** |
| 8 | + * @ingroup cpu_rp2350 |
| 9 | + * @{ |
| 10 | + * |
| 11 | + * @file |
| 12 | + * @brief Clock configuration implementation for the RP2350 |
| 13 | + * |
| 14 | + * @author Tom Hert < [email protected]> |
| 15 | + */ |
| 16 | + |
| 17 | +#include "periph_cpu.h" |
| 18 | + |
| 19 | +void clock_reset(void) { |
| 20 | + /* Reset the clock system */ |
| 21 | + reset_component(RESET_PLL_SYS, RESET_PLL_SYS); |
| 22 | +} |
| 23 | + |
| 24 | +/** |
| 25 | + * @brief Configures the XOSC and then sets CLK_SYS, PLL_SYS and CLK_PERI to it |
| 26 | + * @warning Make sure to call clock_reset() before this function to reset the |
| 27 | + * clock system |
| 28 | + * @see RP2350 Docs Chapter 8, mostly 8.2 for more details |
| 29 | + */ |
| 30 | +void cpu_clock_init(void) { |
| 31 | + /* Enable the XOSC */ |
| 32 | + xosc_start(); |
| 33 | + |
| 34 | + /* Setup the PLL using the XOSC as the reference clock. */ |
| 35 | + PLL_SYS->FBDIV_INT = |
| 36 | + PLL_FEEDBACK_DIVIDER_VALUE; /* Set the feedback divider */ |
| 37 | + |
| 38 | + /* Set the post-dividers for the PLL output.*/ |
| 39 | + PLL_SYS->PRIM = PDIV; |
| 40 | + /* Turn on PLL */ |
| 41 | + atomic_clear(&PLL_SYS->PWR, |
| 42 | + PLL_PWR_PD_BITS | PLL_PWR_VCOPD_BITS | PLL_PWR_POSTDIVPD_BITS); |
| 43 | + |
| 44 | + /* sleep 10ms to allow the PLL to stabilize */ |
| 45 | + xosc_sleep(10); |
| 46 | + |
| 47 | + /* Based on the description in chapter 8 this is something that should be done |
| 48 | + * However, it appears to cause issues and is not done by other examples on the |
| 49 | + * internet. This needs to be investigated further. */ |
| 50 | + |
| 51 | + /* Wait for lock */ |
| 52 | + /* while (!(PLL_SYS->CS & PLL_CS_LOCK_BITS)) { */ |
| 53 | + /* Wait for the PLL to lock */ |
| 54 | + /* } */ |
| 55 | + |
| 56 | + /* AUXSRC = 0x0 7:5 && SRC == 0x0 0 */ |
| 57 | + CLOCKS->CLK_SYS_CTRL = CLK_SYS_PERI_CTRL_ENABLE_BIT; |
| 58 | + |
| 59 | + /* This register contains one decoded bit for each of the clock sources |
| 60 | + * enumerated in the CTRL SRC field. The bit does not directly correlate with |
| 61 | + * the value of the SRC field For example 0x0 is the first bit while 0x1 is |
| 62 | + * the second bit. In some way this makes sense, in some way I lost too much |
| 63 | + * time on this. */ |
| 64 | + while (CLOCKS->CLK_SYS_SELECTED != CLK_SYS_SELECTED_PERI_FIELD_VALUE) { |
| 65 | + } |
| 66 | + |
| 67 | + /* AUXSRC = 0x0 -> CLK_SYS Indirectly through lower line */ |
| 68 | + CLOCKS->CLK_PERI_CTRL = CLK_PERI_CTRL_ENABLE_BIT; |
| 69 | +} |
| 70 | + |
| 71 | +/** @} */ |
0 commit comments