From 36931962069b7f1245e91e74d21f0ee92310215b Mon Sep 17 00:00:00 2001 From: ALTracer Date: Sun, 25 Jun 2023 23:53:47 +0300 Subject: [PATCH 1/7] common/blackpill-f4/usbdfu: Enable heartbeat on PC13 in BMP DFU * Set up SysTick interrupt to blink both LED_IDLE_RUN and LED_BOOTLOADER --- src/platforms/common/blackpill-f4/usbdfu.c | 29 +++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/platforms/common/blackpill-f4/usbdfu.c b/src/platforms/common/blackpill-f4/usbdfu.c index b32afce068d..05e4a7fe08b 100644 --- a/src/platforms/common/blackpill-f4/usbdfu.c +++ b/src/platforms/common/blackpill-f4/usbdfu.c @@ -19,9 +19,10 @@ #include #include +#include +#include #include #include -#include #include #include "usbdfu.h" @@ -31,6 +32,8 @@ uintptr_t app_address = 0x08004000U; volatile uint32_t magic[2] __attribute__((section(".noinit"))); +static void sys_tick_init(void); + void dfu_detach(void) { scb_reset_system(); @@ -53,8 +56,11 @@ int main(void) /* Assert blue LED as indicator we are in the bootloader */ rcc_periph_clock_enable(RCC_GPIOC); - gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_BOOTLOADER); - gpio_set(LED_PORT, LED_BOOTLOADER); + gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_BOOTLOADER | LED_IDLE_RUN); + gpio_clear(LED_PORT, LED_BOOTLOADER | LED_IDLE_RUN); + + /* Run heartbeat on blue LED */ + sys_tick_init(); /* Enable peripherals */ rcc_periph_clock_enable(RCC_OTGFS); @@ -76,3 +82,20 @@ int main(void) void dfu_event(void) { } + +static void sys_tick_init(void) +{ + /* Use SysTick at 10Hz to toggle-blink the blue LED at 5 Hz */ + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); + systick_set_reload(rcc_ahb_frequency / 8U / 10U); + /* SYSTICK_IRQ with low priority */ + nvic_set_priority(NVIC_SYSTICK_IRQ, 14U << 4U); + systick_interrupt_enable(); + /* Start the heartbeat timer */ + systick_counter_enable(); +} + +void sys_tick_handler(void) +{ + gpio_toggle(LED_PORT, LED_BOOTLOADER | LED_IDLE_RUN); +} From a814abd06a4ee0f08df0fc9e7ecf7e96e057bfa5 Mon Sep 17 00:00:00 2001 From: ALTracer Date: Mon, 8 Jan 2024 17:42:00 +0300 Subject: [PATCH 2/7] common/blackpill-f4/usbdfu: Run a slow LED show in BMP DFU * Drop the toggling of LED_BOOTLOADER in favor of SET_IDLE_STATE() * Tone down the blinking from 10 Hz, 50% duty cycle to 1 Hz, 10% duty cycle --- src/platforms/common/blackpill-f4/usbdfu.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/platforms/common/blackpill-f4/usbdfu.c b/src/platforms/common/blackpill-f4/usbdfu.c index 05e4a7fe08b..8988a58b758 100644 --- a/src/platforms/common/blackpill-f4/usbdfu.c +++ b/src/platforms/common/blackpill-f4/usbdfu.c @@ -97,5 +97,20 @@ static void sys_tick_init(void) void sys_tick_handler(void) { - gpio_toggle(LED_PORT, LED_BOOTLOADER | LED_IDLE_RUN); + static uint32_t count = 0U; + switch (count) { + case 0U: + /* Reload downcounter */ + count = 10U; + SET_IDLE_STATE(false); + break; + case 1U: + count--; + /* Blink like a very slow PWM */ + SET_IDLE_STATE(true); + break; + default: + count--; + break; + } } From 64d308b3ede76749f307d700675cafd46da9fb4c Mon Sep 17 00:00:00 2001 From: ALTracer Date: Mon, 8 Jan 2024 17:43:00 +0300 Subject: [PATCH 3/7] common/stm32/dfu_f4: Use dfu_event() for feature parity with dfu_f1 --- src/platforms/common/stm32/dfu_f4.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/platforms/common/stm32/dfu_f4.c b/src/platforms/common/stm32/dfu_f4.c index 60f22886510..765144edfcb 100644 --- a/src/platforms/common/stm32/dfu_f4.c +++ b/src/platforms/common/stm32/dfu_f4.c @@ -75,6 +75,9 @@ void dfu_flash_program_buffer(const uint32_t baseaddr, const void *const buf, co const uint32_t *const buffer = (const uint32_t *)buf; for (size_t i = 0; i < len; i += 4U) flash_program_word(baseaddr + i, buffer[i >> 2U]); + + /* Call the platform specific dfu event callback. */ + dfu_event(); } uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) From 330d819ff64571f0b0448d485a697415c778d203 Mon Sep 17 00:00:00 2001 From: ALTracer Date: Mon, 8 Jan 2024 17:44:00 +0300 Subject: [PATCH 4/7] common/blackpill-f4/usbdfu: Enable dynamic blinking in write phase of BMP DFU * Implement the dfu_event callback and make it inhibit the show for 1 second * Toggle the platform Idle LED on every callback hit (usually 1 KiB) --- src/platforms/common/blackpill-f4/usbdfu.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/platforms/common/blackpill-f4/usbdfu.c b/src/platforms/common/blackpill-f4/usbdfu.c index 8988a58b758..b6f5cfa8991 100644 --- a/src/platforms/common/blackpill-f4/usbdfu.c +++ b/src/platforms/common/blackpill-f4/usbdfu.c @@ -31,6 +31,7 @@ uintptr_t app_address = 0x08004000U; volatile uint32_t magic[2] __attribute__((section(".noinit"))); +static uint32_t dfu_activity_counter; static void sys_tick_init(void); @@ -81,6 +82,12 @@ int main(void) void dfu_event(void) { + static bool idle_state = false; + /* Ask systick to pause blinking for 1 second */ + dfu_activity_counter = 10U; + /* Toggle-blink it ourself */ + SET_IDLE_STATE(idle_state); + idle_state = !idle_state; } static void sys_tick_init(void) @@ -98,15 +105,19 @@ static void sys_tick_init(void) void sys_tick_handler(void) { static uint32_t count = 0U; + if (dfu_activity_counter > 0U) { + dfu_activity_counter--; + return; + } switch (count) { case 0U: - /* Reload downcounter */ + /* Reload downcounter and disable LED */ count = 10U; SET_IDLE_STATE(false); break; case 1U: count--; - /* Blink like a very slow PWM */ + /* Enable LED for 1/10th of cycle */ SET_IDLE_STATE(true); break; default: From 25e277a9da6d4fc65480096291894115da9dc617 Mon Sep 17 00:00:00 2001 From: ALTracer Date: Sun, 7 Jan 2024 15:00:00 +0300 Subject: [PATCH 5/7] common/stm32/dfu_f4: Extract sector erase time constants into an enum --- src/platforms/common/stm32/dfu_f4.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/platforms/common/stm32/dfu_f4.c b/src/platforms/common/stm32/dfu_f4.c index 765144edfcb..b1d80169def 100644 --- a/src/platforms/common/stm32/dfu_f4.c +++ b/src/platforms/common/stm32/dfu_f4.c @@ -41,7 +41,29 @@ static uint32_t sector_addr[] = { 0, }; -static uint16_t sector_erase_time[] = {500, 500, 500, 500, 1100, 2600, 2600, 2600, 2600, 2600, 2600, 2600, 2600}; +/* Sector erase times in milliseconds, max, for x32 parallelism at 2.7-3.6v */ +typedef enum erase_times_f4 { + ERASE_TIME_16KB = 500, + ERASE_TIME_64KB = 1100, + ERASE_TIME_128KB = 2600, +} erase_times_f4_e; + +static erase_times_f4_e sector_erase_time[] = { + ERASE_TIME_16KB, + ERASE_TIME_16KB, + ERASE_TIME_16KB, + ERASE_TIME_16KB, + ERASE_TIME_64KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, + ERASE_TIME_128KB, +}; + static uint8_t sector_num = 0xff; static_assert(ARRAY_LENGTH(sector_erase_time) == ARRAY_LENGTH(sector_addr) - 1U, From 7a3a04b58e80cecc7c7b244dc8fb47af91cd2086 Mon Sep 17 00:00:00 2001 From: ALTracer Date: Mon, 8 Jan 2024 16:00:00 +0300 Subject: [PATCH 6/7] common/stm32/dfu_f4: Reduce erase and write delays advertised by BMP DFU * Previous timings corresponded to max delays per datasheets "guaranteed by characterization results" * It is safe to back off the host for less time and then deal with polling * Use typical times (which happen to be twice as short for erase and 25x for write) from same datasheets --- src/platforms/common/stm32/dfu_f4.c | 44 +++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/platforms/common/stm32/dfu_f4.c b/src/platforms/common/stm32/dfu_f4.c index b1d80169def..790246061ef 100644 --- a/src/platforms/common/stm32/dfu_f4.c +++ b/src/platforms/common/stm32/dfu_f4.c @@ -17,6 +17,32 @@ * along with this program. If not, see . */ +/* + * References, ST datasheets: + * + * DS8626 - STM32F405xx/407xx Rev 9 pg108, Table 40. Flash memory programming + * https://www.st.com/resource/en/datasheet/stm32f407vg.pdf + * (f4discovery:stm32f407vg, 128/1024 KiB; + * hydrabus:stm32f405rg, 128/1024 KiB) + * + * DS9716 - STM32F401xB/xC Rev 11 pg85, Table 45. Flash memory programming + * https://www.st.com/resource/en/datasheet/stm32f401cb.pdf + * (blackpill-f4:stm32f401cc, 64/256 KiB) + * + * DS10086 - STM32F401xD/xE Rev 3 pg86, Table 45. Flash memory programming + * https://www.st.com/resource/en/datasheet/stm32f401re.pdf + * (blackpill-f4:stm32f401ce, 96/512 KiB; + * 96b_carbon:stm32f401re, 96/512 KiB) + * + * DS10314 - STM32F411xC/xE Rev 7 pg92, Table 45. Flash memory programming + * https://www.st.com/resource/en/datasheet/stm32f411ce.pdf + * (blackpill-f4:stm32f411ce, 128/512 KiB) + * + * DS11853 - STM32F722xx/723xx Rev 9 pg138, Table 53. Flash memory programming + * https://www.st.com/resource/en/datasheet/stm32f723ie.pdf + * (stlinkv3:stm32f723ie, 256/512 KiB; and F7 has slightly smaller timings than F4 family) + */ + #include "general.h" #include "usbdfu.h" @@ -41,11 +67,11 @@ static uint32_t sector_addr[] = { 0, }; -/* Sector erase times in milliseconds, max, for x32 parallelism at 2.7-3.6v */ +/* Sector erase times in milliseconds, typ, for x32 parallelism at 2.7-3.6v */ typedef enum erase_times_f4 { - ERASE_TIME_16KB = 500, - ERASE_TIME_64KB = 1100, - ERASE_TIME_128KB = 2600, + ERASE_TIME_16KB = 250, /* 500 * 0.5 */ + ERASE_TIME_64KB = 550, /* 1100 * 0.5 */ + ERASE_TIME_128KB = 1000, /* 2000 * 0.5 */ } erase_times_f4_e; static erase_times_f4_e sector_erase_time[] = { @@ -104,16 +130,18 @@ void dfu_flash_program_buffer(const uint32_t baseaddr, const void *const buf, co uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) { - /* Erase for big pages on STM2/4 needs "long" time - Try not to hit USB timeouts*/ + /* + * Sector erase for big pages of STM32 F2/F4/F7 needs "long" time, + * up to 1-2 seconds. Try not to hit USB timeouts. + */ if (blocknum == 0 && cmd == CMD_ERASE) { get_sector_num(addr); if (addr == sector_addr[sector_num]) return sector_erase_time[sector_num]; } - /* Programming 256 word with 100 us(max) per word*/ - return 26U; + /* Programming 256 words (32-bit) with 16 us(typ), 100 us(max) per word */ + return 16U * 1024U / 4U / 1000U; } void dfu_protect(bool enable) From aec136df6a58d5c3310e91ba10a824fea65721fe Mon Sep 17 00:00:00 2001 From: ALTracer Date: Sun, 7 Jan 2024 14:28:56 +0300 Subject: [PATCH 7/7] common/blackpill-f4: Refresh voodoo * Drop RCC_OTGFS enabling because it happens in stm32f107_usbd_init, and move RCC_CRC up to GPIOs * Drop GPIO_OSPEEDR setting of PA1/13/14 because that mapping is obsolete * Bump OSPEEDR setting from 2MHz to 25MHz for GPIO TAP pins * Reduce default "max" frequency for robust UX --- .../common/blackpill-f4/blackpill-f4.c | 21 ++++++++----------- src/platforms/common/blackpill-f4/usbdfu.c | 4 +--- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/platforms/common/blackpill-f4/blackpill-f4.c b/src/platforms/common/blackpill-f4/blackpill-f4.c index 6080f1eb6e4..d5aaf747aba 100644 --- a/src/platforms/common/blackpill-f4/blackpill-f4.c +++ b/src/platforms/common/blackpill-f4/blackpill-f4.c @@ -45,10 +45,11 @@ volatile uint32_t magic[2] __attribute__((section(".noinit"))); void platform_init(void) { - /* Enable GPIO peripherals */ + /* Enable peripherals */ rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOC); rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_CRC); #ifndef BMP_BOOTLOADER /* Blackpill board has a floating button on PA0. Pull it up and use as active-low. */ @@ -73,26 +74,19 @@ void platform_init(void) #endif rcc_clock_setup_pll(&rcc_hse_25mhz_3v3[PLATFORM_CLOCK_FREQ]); - /* Enable peripherals */ - rcc_periph_clock_enable(RCC_OTGFS); - rcc_periph_clock_enable(RCC_CRC); - /* Set up DM/DP pins. PA9/PA10 are not routed to USB-C. */ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12); gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12); - GPIOA_OSPEEDR &= 0x3c00000cU; - GPIOA_OSPEEDR |= 0x28000008U; - /* Set up TDI, TDO, TCK and TMS pins */ gpio_mode_setup(TDI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TDI_PIN); gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TDO_PIN); gpio_mode_setup(TCK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TCK_PIN); gpio_mode_setup(TMS_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TMS_PIN); - gpio_set_output_options(TDI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, TDI_PIN); - gpio_set_output_options(TDO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, TDO_PIN); - gpio_set_output_options(TCK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, TCK_PIN); - gpio_set_output_options(TMS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, TMS_PIN); + gpio_set_output_options(TDI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, TDI_PIN); + gpio_set_output_options(TDO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, TDO_PIN); + gpio_set_output_options(TCK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, TCK_PIN); + gpio_set_output_options(TMS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, TMS_PIN); /* Set up LED pins */ gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); @@ -114,6 +108,9 @@ void platform_init(void) /* https://github.com/libopencm3/libopencm3/pull/1256#issuecomment-779424001 */ OTG_FS_GCCFG |= OTG_GCCFG_NOVBUSSENS | OTG_GCCFG_PWRDWN; OTG_FS_GCCFG &= ~(OTG_GCCFG_VBUSBSEN | OTG_GCCFG_VBUSASEN); + + /* By default, do not drive the SWD bus too fast. */ + platform_max_frequency_set(3000000); } void platform_nrst_set_val(bool assert) diff --git a/src/platforms/common/blackpill-f4/usbdfu.c b/src/platforms/common/blackpill-f4/usbdfu.c index b6f5cfa8991..d5d205ea968 100644 --- a/src/platforms/common/blackpill-f4/usbdfu.c +++ b/src/platforms/common/blackpill-f4/usbdfu.c @@ -42,6 +42,7 @@ void dfu_detach(void) int main(void) { + /* Enable GPIO peripherals */ rcc_periph_clock_enable(RCC_GPIOA); /* Blackpill board has a floating button on PA0. Pull it up and use as active-low. */ @@ -63,9 +64,6 @@ int main(void) /* Run heartbeat on blue LED */ sys_tick_init(); - /* Enable peripherals */ - rcc_periph_clock_enable(RCC_OTGFS); - /* Set up USB Pins and alternate function*/ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO11 | GPIO12); gpio_set_af(GPIOA, GPIO_AF10, GPIO11 | GPIO12);