]> mj.ucw.cz Git - home-hw.git/commitdiff
Boot-loader: Proper handling of various clocks
authorMartin Mares <mj@ucw.cz>
Mon, 24 Feb 2020 18:12:42 +0000 (19:12 +0100)
committerMartin Mares <mj@ucw.cz>
Mon, 24 Feb 2020 18:12:42 +0000 (19:12 +0100)
bsb/bootloader/Makefile
lib/dfu-bootloader.c

index 1f14b9013d77b77b82252b1b1a6d11671a069d69..9ba9617d3e4c6f26aca42f6559e8fe5fbeede169 100644 (file)
@@ -2,5 +2,6 @@ ROOT=../..
 BINARY=bootloader
 OBJS=
 LIB_OBJS=util-debug.o dfu-bootloader.o
+MAX_SIZE=8192
 
 include $(ROOT)/mk/bluepill.mk
index ce01a41c5173872c6c4dd45ec738a6e360fd8caa..637db2eb15540fd5edb45c40a04b1bbffaa3e9e7 100644 (file)
@@ -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));