Skip to content

Commit b0bb15e

Browse files
committed
bluepillplus: Add chip detection and faster PLL configs
* Rely on DBGMCU_IDCODE and SCB_CPUID
1 parent 4289d5c commit b0bb15e

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

src/platforms/bluepillplus/platform.c

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,66 @@
2828
#include <libopencm3/cm3/vector.h>
2929
#include <libopencm3/cm3/scb.h>
3030
#include <libopencm3/stm32/rcc.h>
31+
#include <libopencm3/stm32/dbgmcu.h>
3132

3233
volatile uint32_t magic[2] __attribute__((section(".noinit")));
3334

3435
static void platform_detach_usb(void);
3536

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+
3691
void platform_request_boot(void)
3792
{
3893
magic[0] = BOOTMAGIC0;
@@ -61,7 +116,38 @@ void platform_init(void)
61116
rcc_periph_clock_enable(SWO_DMA_CLK);
62117
#endif
63118

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);
65151

66152
gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_INPUT_FLOAT, TMS_PIN);
67153
gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_INPUT_FLOAT, TCK_PIN);

0 commit comments

Comments
 (0)