5#include "libxr_def.hpp"
6#include DEF2STR(LIBXR_CH32_CONFIG_FILE)
8namespace LibXR::CH32UsbRcc
11inline uint32_t GetSysclkHz()
13 RCC_ClocksTypeDef clk{};
14 RCC_GetClocksFreq(&clk);
15 return clk.SYSCLK_Frequency;
18inline void ConfigureUsb48MFromSysclk()
23 const uint32_t sysclk_hz = GetSysclkHz();
25#if defined(RCC_USBCLKSource_PLLCLK_Div1) && defined(RCC_USBCLKSource_PLLCLK_Div2) && \
26 defined(RCC_USBCLKSource_PLLCLK_Div3)
27 if (sysclk_hz == 144000000u)
29 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3);
32 if (sysclk_hz == 96000000u)
34 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
37 if (sysclk_hz == 48000000u)
39 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);
42#if defined(RCC_USB5PRE_JUDGE) && defined(RCC_USBCLKSource_PLLCLK_Div5)
43 if (sysclk_hz == 240000000u)
45 ASSERT(RCC_USB5PRE_JUDGE() == SET);
46 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div5);
50#elif defined(RCC_USBCLK48MCLKSource_PLLCLK) && \
51 defined(RCC_USBFSCLKSource_PLLCLK_Div1) && \
52 defined(RCC_USBFSCLKSource_PLLCLK_Div2) && defined(RCC_USBFSCLKSource_PLLCLK_Div3)
53 RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_PLLCLK);
55 if (sysclk_hz == 144000000u)
57 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div3);
60 if (sysclk_hz == 96000000u)
62 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div2);
65 if (sysclk_hz == 48000000u)
67 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div1);
75#if defined(RCC_HSBHSPLLCLKSource_HSE) && defined(RCC_USBPLL_Div1) && \
76 defined(RCC_USBPLL_Div2) && defined(RCC_USBPLL_Div3) && defined(RCC_USBPLL_Div4) && \
77 defined(RCC_USBPLL_Div5) && defined(RCC_USBPLL_Div6) && defined(RCC_USBPLL_Div7) && \
78 defined(RCC_USBPLL_Div8) && defined(RCC_USBHSPLLCKREFCLK_3M) && \
79 defined(RCC_USBHSPLLCKREFCLK_4M) && defined(RCC_USBHSPLLCKREFCLK_5M) && \
80 defined(RCC_USBHSPLLCKREFCLK_8M)
83 uint32_t divider_cfg = 0u;
84 uint32_t ref_cfg = 0u;
87struct UsbHsPllTableEntry
90 uint32_t divider_cfg = 0u;
91 uint32_t ref_cfg = 0u;
94inline bool TryGetUsbHsPllConfigForHse(uint32_t hse_hz, UsbHsPllConfig& cfg)
100 constexpr UsbHsPllTableEntry table[] = {
101 {3000000u, RCC_USBPLL_Div1, RCC_USBHSPLLCKREFCLK_3M},
102 {4000000u, RCC_USBPLL_Div1, RCC_USBHSPLLCKREFCLK_4M},
103 {5000000u, RCC_USBPLL_Div1, RCC_USBHSPLLCKREFCLK_5M},
104 {6000000u, RCC_USBPLL_Div2, RCC_USBHSPLLCKREFCLK_3M},
105 {8000000u, RCC_USBPLL_Div2, RCC_USBHSPLLCKREFCLK_4M},
106 {9000000u, RCC_USBPLL_Div3, RCC_USBHSPLLCKREFCLK_3M},
107 {10000000u, RCC_USBPLL_Div2, RCC_USBHSPLLCKREFCLK_5M},
108 {12000000u, RCC_USBPLL_Div3, RCC_USBHSPLLCKREFCLK_4M},
109 {15000000u, RCC_USBPLL_Div3, RCC_USBHSPLLCKREFCLK_5M},
110 {16000000u, RCC_USBPLL_Div4, RCC_USBHSPLLCKREFCLK_4M},
111 {18000000u, RCC_USBPLL_Div6, RCC_USBHSPLLCKREFCLK_3M},
112 {20000000u, RCC_USBPLL_Div5, RCC_USBHSPLLCKREFCLK_4M},
113 {21000000u, RCC_USBPLL_Div7, RCC_USBHSPLLCKREFCLK_3M},
114 {24000000u, RCC_USBPLL_Div6, RCC_USBHSPLLCKREFCLK_4M},
115 {25000000u, RCC_USBPLL_Div5, RCC_USBHSPLLCKREFCLK_5M},
116 {28000000u, RCC_USBPLL_Div7, RCC_USBHSPLLCKREFCLK_4M},
117 {30000000u, RCC_USBPLL_Div6, RCC_USBHSPLLCKREFCLK_5M},
118 {32000000u, RCC_USBPLL_Div8, RCC_USBHSPLLCKREFCLK_4M},
119 {35000000u, RCC_USBPLL_Div7, RCC_USBHSPLLCKREFCLK_5M},
120 {40000000u, RCC_USBPLL_Div8, RCC_USBHSPLLCKREFCLK_5M},
121 {48000000u, RCC_USBPLL_Div6, RCC_USBHSPLLCKREFCLK_8M},
122 {56000000u, RCC_USBPLL_Div7, RCC_USBHSPLLCKREFCLK_8M},
123 {64000000u, RCC_USBPLL_Div8, RCC_USBHSPLLCKREFCLK_8M},
126 for (
const auto& entry : table)
128 if (entry.hse_hz != hse_hz)
132 cfg.divider_cfg = entry.divider_cfg;
133 cfg.ref_cfg = entry.ref_cfg;
140inline void ConfigureUsbHsPhyFromHse()
146 UsbHsPllConfig cfg = {};
147 const uint32_t hse_hz =
static_cast<uint32_t
>(HSE_VALUE);
148 ASSERT(TryGetUsbHsPllConfigForHse(hse_hz, cfg));
150 RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE);
151 RCC_USBHSConfig(cfg.divider_cfg);
152 RCC_USBHSPLLCKREFCLKConfig(cfg.ref_cfg);
153 RCC_USBHSPHYPLLALIVEcmd(ENABLE);
157inline void ConfigureUsb48M()
159#if defined(RCC_USBCLK48MCLKSource_USBPHY) && defined(RCC_HSBHSPLLCLKSource_HSE)
164 ConfigureUsbHsPhyFromHse();
165 RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_USBPHY);
169 ConfigureUsb48MFromSysclk();