.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) {
{
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) {
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)
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;
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);
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");
;
#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));