|
28 | 28 | #include <libopencm3/cm3/vector.h> |
29 | 29 | #include <libopencm3/cm3/scb.h> |
30 | 30 | #include <libopencm3/stm32/rcc.h> |
| 31 | +#include <libopencm3/stm32/dbgmcu.h> |
31 | 32 |
|
32 | 33 | volatile uint32_t magic[2] __attribute__((section(".noinit"))); |
33 | 34 |
|
34 | 35 | static void platform_detach_usb(void); |
35 | 36 |
|
| 37 | +#define RCC_CFGR_USBPRE_SHIFT 22 |
| 38 | +#define RCC_CFGR_USBPRE_MASK (0x3 << RCC_CFGR_USBPRE_SHIFT) |
| 39 | +#define RCC_CFGR_USBPRE_PLL_CLK_DIV1_5 0x0 |
| 40 | +#define RCC_CFGR_USBPRE_PLL_CLK_NODIV 0x1 |
| 41 | +#define RCC_CFGR_USBPRE_PLL_CLK_DIV2_5 0x2 |
| 42 | +#define RCC_CFGR_USBPRE_PLL_CLK_DIV2 0x3 |
| 43 | + |
| 44 | +static const struct rcc_clock_scale rcc_hse_config_hse8_120mhz = { |
| 45 | + /* hse8, pll to 120 */ |
| 46 | + .pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL15, |
| 47 | + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, |
| 48 | + .hpre = RCC_CFGR_HPRE_NODIV, |
| 49 | + .ppre1 = RCC_CFGR_PPRE_DIV2, |
| 50 | + .ppre2 = RCC_CFGR_PPRE_NODIV, |
| 51 | + .adcpre = RCC_CFGR_ADCPRE_DIV8, |
| 52 | + .flash_waitstates = 5, /* except WSEN is 0 and WSCNT don't care */ |
| 53 | + .prediv1 = RCC_CFGR2_PREDIV_NODIV, |
| 54 | + .usbpre = RCC_CFGR_USBPRE_PLL_CLK_DIV1_5, /* libopencm3_stm32f1 hack */ |
| 55 | + .ahb_frequency = 120000000, |
| 56 | + .apb1_frequency = 60000000, |
| 57 | + .apb2_frequency = 120000000, |
| 58 | +}; |
| 59 | + |
| 60 | +static const struct rcc_clock_scale rcc_hse_config_hse8_96mhz = { |
| 61 | + /* hse8, pll to 96 */ |
| 62 | + .pll_mul = RCC_CFGR_PLLMUL_PLL_CLK_MUL12, |
| 63 | + .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, |
| 64 | + .hpre = RCC_CFGR_HPRE_NODIV, |
| 65 | + .ppre1 = RCC_CFGR_PPRE_DIV2, |
| 66 | + .ppre2 = RCC_CFGR_PPRE_NODIV, |
| 67 | + .adcpre = RCC_CFGR_ADCPRE_DIV8, |
| 68 | + .flash_waitstates = 3, /* except WSEN is 0 and WSCNT don't care */ |
| 69 | + .prediv1 = RCC_CFGR2_PREDIV_NODIV, |
| 70 | + .usbpre = RCC_CFGR_USBPRE_PLL_CLK_NODIV, /* libopencm3_stm32f1 hack */ |
| 71 | + .ahb_frequency = 96000000, |
| 72 | + .apb1_frequency = 48000000, |
| 73 | + .apb2_frequency = 96000000, |
| 74 | +}; |
| 75 | + |
| 76 | +/* Set USB CK48M prescaler on GD32F30x before enabling RCC_APB1ENR_USBEN */ |
| 77 | +static void rcc_set_usbpre_gd32f30x(uint32_t usbpre) |
| 78 | +{ |
| 79 | +#if 1 |
| 80 | + /* NuttX style */ |
| 81 | + uint32_t regval = RCC_CFGR; |
| 82 | + regval &= ~RCC_CFGR_USBPRE_MASK; |
| 83 | + regval |= (usbpre << RCC_CFGR_USBPRE_SHIFT); |
| 84 | + RCC_CFGR = regval; |
| 85 | +#else |
| 86 | + /* libopencm3 style */ |
| 87 | + RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_USBPRE_MASK) | (usbpre << RCC_CFGR_USBPRE_SHIFT); |
| 88 | +#endif |
| 89 | +} |
| 90 | + |
36 | 91 | void platform_request_boot(void) |
37 | 92 | { |
38 | 93 | magic[0] = BOOTMAGIC0; |
@@ -61,7 +116,38 @@ void platform_init(void) |
61 | 116 | rcc_periph_clock_enable(SWO_DMA_CLK); |
62 | 117 | #endif |
63 | 118 |
|
64 | | - rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]); |
| 119 | + /* Detect platform chip */ |
| 120 | + const uint32_t device_id = DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK; |
| 121 | + const uint32_t cpu_id = SCB_CPUID & SCB_CPUID_PARTNO; |
| 122 | + /* STM32F103CB: 0x410 (Medium density) is readable as 0x000 (errata) without debugger. So default to 72 MHz. */ |
| 123 | + const struct rcc_clock_scale *clock = &rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]; |
| 124 | + /* |
| 125 | + * Pick one of 72/96/120 MHz PLL configs. |
| 126 | + * Disable USBD clock (after bootloaders) |
| 127 | + * then change USBDPSC[1:0] the CK_USBD prescaler |
| 128 | + * and finally enable PLL. |
| 129 | + */ |
| 130 | + if ((device_id == 0x410 || device_id == 0x000) && cpu_id == 0xc230 && SCB_CPUID == 0x411fc231) { |
| 131 | + /* STM32F103CB: 0x410 (Medium density), 0x411fc231 (Cortex-M3 r1p1) */ |
| 132 | + clock = &rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]; |
| 133 | + } |
| 134 | + if (device_id == 0x410 && cpu_id == 0xc230 && SCB_CPUID == 0x412fc231) { |
| 135 | + /* GD32F103CB: 0x410 (Medium Density), 0x412fc231 (Cortex-M3 r2p1) */ |
| 136 | + clock = &rcc_hse_config_hse8_96mhz; |
| 137 | + rcc_periph_clock_disable(RCC_USB); |
| 138 | + /* Set 96/2=48MHz USB divisor before enabling PLL */ |
| 139 | + rcc_set_usbpre_gd32f30x(RCC_CFGR_USBPRE_PLL_CLK_DIV2); |
| 140 | + } |
| 141 | + if (device_id == 0x414 && cpu_id == 0xc240 && SCB_CPUID == 0x410fc241) { |
| 142 | + /* GD32F303CC: 0x414 (High density) 0x410fc241 (Cortex-M4F r0p1) */ |
| 143 | + clock = &rcc_hse_config_hse8_120mhz; |
| 144 | + rcc_periph_clock_disable(RCC_USB); |
| 145 | + /* Set 120/2.5=48MHz USB divisor before enabling PLL */ |
| 146 | + rcc_set_usbpre_gd32f30x(RCC_CFGR_USBPRE_PLL_CLK_DIV2_5); |
| 147 | + } |
| 148 | + |
| 149 | + /* Enable PLL */ |
| 150 | + rcc_clock_setup_pll(clock); |
65 | 151 |
|
66 | 152 | gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_INPUT_FLOAT, TMS_PIN); |
67 | 153 | gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_INPUT_FLOAT, TCK_PIN); |
|
0 commit comments