From eb14d9a9208a5d42146467802007bfb43c17f0fc Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Mon, 24 Feb 2020 19:12:42 +0100 Subject: [PATCH] Boot-loader: Proper handling of various clocks --- bsb/bootloader/Makefile | 1 + lib/dfu-bootloader.c | 121 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/bsb/bootloader/Makefile b/bsb/bootloader/Makefile index 1f14b90..9ba9617 100644 --- a/bsb/bootloader/Makefile +++ b/bsb/bootloader/Makefile @@ -2,5 +2,6 @@ ROOT=../.. BINARY=bootloader OBJS= LIB_OBJS=util-debug.o dfu-bootloader.o +MAX_SIZE=8192 include $(ROOT)/mk/bluepill.mk diff --git a/lib/dfu-bootloader.c b/lib/dfu-bootloader.c index ce01a41..637db2e 100644 --- a/lib/dfu-bootloader.c +++ b/lib/dfu-bootloader.c @@ -117,6 +117,20 @@ const struct usb_config_descriptor config = { .interface = ifaces, }; +#if 0 // FIXME +static u32 adhoc_checksum(u32 start, uint len) +{ + u32 end = start + len; + u32 sum = 0; + while (start < end) { + sum *= 259309; + sum += *(volatile u32 *)start; + start += 4; + } + return sum; +} +#endif + static byte usbdfu_getstatus(usbd_device *usbd_dev UNUSED, u32 *bwPollTimeout) { switch (usbdfu_state) { @@ -137,7 +151,7 @@ static void program_page(struct prog_info *prog, bool need_erase) { flash_unlock(); u32 baseaddr = BOOTLOADER_APP_START + prog->blocknum * dfu_function.wTransferSize; - DEBUG("DFU: Block %u -> %08x\n", prog->blocknum, (uint) baseaddr); + DEBUG("DFU: Block %u -> %08x + %u\n", prog->blocknum, (uint) baseaddr, prog->len); if (need_erase) flash_erase_page(baseaddr); for (uint i = 0; i < prog->len; i += 2) { @@ -145,6 +159,13 @@ static void program_page(struct prog_info *prog, bool need_erase) flash_program_half_word(baseaddr + i, data); } flash_lock(); +#if 0 + u32 s1 = adhoc_checksum((u32) prog->buf, prog->len); + u32 s2 = adhoc_checksum(baseaddr, prog->len); + DEBUG("\t%08x %08x\n", (uint) s1, (uint) s2); + if (s1 != s2) + DEBUG("\t!!!!!!!!!!!!!!!!!!!!!!!!!\n"); +#endif } static void usbdfu_getstatus_complete(usbd_device *usbd_dev UNUSED, struct usb_setup_data *req UNUSED) @@ -164,8 +185,7 @@ static void usbdfu_getstatus_complete(usbd_device *usbd_dev UNUSED, struct usb_s case STATE_DFU_MANIFEST: // At the very end, program the first page program_page(&prog_header, false); - /* USB device must detach, we just reset... */ - scb_reset_system(); + usbdfu_state = STATE_DFU_MANIFEST_WAIT_RESET; return; /* Will never return. */ default: return; @@ -243,12 +263,84 @@ static void usbdfu_reset(void) usbdfu_state = STATE_DFU_IDLE; } +/* + * This is a modified version of rcc_clock_setup_in_hsi_out_48mhz(), + * which properly turns off the PLL before setting its parameters. + */ +static void my_rcc_clock_setup_in_hsi_out_48mhz(void) +{ + /* Enable internal high-speed oscillator. */ + rcc_osc_on(RCC_HSI); + rcc_wait_for_osc_ready(RCC_HSI); + + /* Select HSI as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK); + + // XXX: Disable PLL + rcc_osc_off(RCC_PLL); + + /* + * Set prescalers for AHB, ADC, ABP1, ABP2. + * Do this before touching the PLL (TODO: why?). + */ + rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); /*Set.48MHz Max.72MHz */ + rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV8); /*Set. 6MHz Max.14MHz */ + rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_DIV2); /*Set.24MHz Max.36MHz */ + rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); /*Set.48MHz Max.72MHz */ + rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_CLK_NODIV); /*Set.48MHz Max.48MHz */ + + /* + * Sysclk runs with 48MHz -> 1 waitstates. + * 0WS from 0-24MHz + * 1WS from 24-48MHz + * 2WS from 48-72MHz + */ + flash_set_ws(FLASH_ACR_LATENCY_1WS); + + /* + * Set the PLL multiplication factor to 12. + * 8MHz (internal) * 12 (multiplier) / 2 (PLLSRC_HSI_CLK_DIV2) = 48MHz + */ + rcc_set_pll_multiplication_factor(RCC_CFGR_PLLMUL_PLL_CLK_MUL12); + + /* Select HSI/2 as PLL source. */ + rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2); + + /* Enable PLL oscillator and wait for it to stabilize. */ + rcc_osc_on(RCC_PLL); + rcc_wait_for_osc_ready(RCC_PLL); + + /* Select PLL as SYSCLK source. */ + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK); + + /* Set the peripheral clock frequencies used */ + rcc_ahb_frequency = 48000000; + rcc_apb1_frequency = 24000000; + rcc_apb2_frequency = 48000000; +} + +static void clock_plain_hsi(void) +{ + // Select HSI as SYSCLK source + rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK); + + // Disable PLL + rcc_osc_off(RCC_PLL); + + // Set prescalers for AHB, ADC, ABP1, ABP2, USB to defaults + rcc_set_hpre(RCC_CFGR_HPRE_SYSCLK_NODIV); + rcc_set_adcpre(RCC_CFGR_ADCPRE_PCLK2_DIV2); + rcc_set_ppre1(RCC_CFGR_PPRE1_HCLK_NODIV); + rcc_set_ppre2(RCC_CFGR_PPRE2_HCLK_NODIV); + rcc_set_usbpre(RCC_CFGR_USBPRE_PLL_VCO_CLK_DIV3); +} + int main(void) { usbd_device *usbd_dev; // Flash programming requires running on the internal oscillator - rcc_clock_setup_in_hsi_out_48mhz(); + my_rcc_clock_setup_in_hsi_out_48mhz(); rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOC); @@ -320,6 +412,12 @@ restart: ; u32 sp = app[0]; u32 pc = app[1]; +#if 0 + uint len = 7140; + u32 sum = adhoc_checksum(BOOTLOADER_APP_START, len); + DEBUG("DFU: Checksum=%08x, len=%u\n", (uint) sum, len); +#endif + DEBUG("DFU: Starting application (sp=%08x, pc=%08x)\n", (uint) sp, (uint) pc); if ((sp & 0x2ffe0000) != 0x20000000) { DEBUG("DFU: Suspicious SP, refusing to start\n"); @@ -331,10 +429,21 @@ restart: ; ; #endif debug_led(0); - cm_disable_interrupts(); + + rcc_periph_clock_disable(RCC_GPIOA); + rcc_periph_clock_disable(RCC_GPIOC); + rcc_periph_clock_disable(RCC_USB); + rcc_periph_clock_disable(RCC_USART1); + + rcc_periph_reset_pulse(RST_GPIOA); + rcc_periph_reset_pulse(RST_GPIOC); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_reset_pulse(RST_USART1); + + clock_plain_hsi(); /* Set vector table base address. */ - SCB_VTOR = BOOTLOADER_APP_START & 0xFFFF; + SCB_VTOR = BOOTLOADER_APP_START; /* Initialize master stack pointer. */ asm volatile("msr msp, %0"::"g" (sp)); -- 2.39.2