diff --git a/boards.txt b/boards.txt index 65074d3a9f..928e85bff6 100644 --- a/boards.txt +++ b/boards.txt @@ -580,7 +580,7 @@ Disco.name=Discovery Disco.build.core=arduino Disco.build.board=Disco -Disco.build.extra_flags=-D{build.product_line} {build.enable_usb} {build.xSerial} +Disco.build.extra_flags=-D{build.product_line} {build.enable_usb} {build.xSerial} {build.bootloader_flags} # DISCO_F030R8 board Disco.menu.pnum.DISCO_F030R8=STM32F030R8-DISCVL @@ -596,7 +596,7 @@ Disco.menu.pnum.DISCO_F030R8.build.cmsis_lib_gcc=arm_cortexM0l_math # DISCO_F072RB board Disco.menu.pnum.DISCO_F072RB=STM32F072B-DISCOVERY -Disco.menu.pnum.DISCO_F072RB.node="No_mass_storage_for_this_board_Use_STLink_upload_method" +Disco.menu.pnum.DISCO_F072RB.node="No_mass_storage_for_this_board_Use_STLink_upload_method_or_softdfu_upload" Disco.menu.pnum.DISCO_F072RB.upload.maximum_size=131072 Disco.menu.pnum.DISCO_F072RB.upload.maximum_data_size=16384 Disco.menu.pnum.DISCO_F072RB.build.mcu=cortex-m0 @@ -605,6 +605,9 @@ Disco.menu.pnum.DISCO_F072RB.build.series=STM32F0xx Disco.menu.pnum.DISCO_F072RB.build.product_line=STM32F072xB Disco.menu.pnum.DISCO_F072RB.build.variant=DISCO_F072RB Disco.menu.pnum.DISCO_F072RB.build.cmsis_lib_gcc=arm_cortexM0l_math +Disco.menu.pnum.DISCO_F072RB.build.startup_file=-DCUSTOM_STARTUP_FILE +Disco.menu.pnum.DISCO_F072RB.build.bootloader_flags=-DVARIANT_SUPPORT_SOFTDFU +Disco.menu.pnum.DISCO_F072RB.build.enable_usb={build.usb_flags} -DUSBD_USE_CDC #DISCO_F100RB board Disco.menu.pnum.DISCO_F100RB=STM32F100RB-DISCVL @@ -729,6 +732,12 @@ Disco.menu.upload_method.dfuMethod.upload.protocol=2 Disco.menu.upload_method.dfuMethod.upload.options=-g Disco.menu.upload_method.dfuMethod.upload.tool=stm32CubeProg +Disco.menu.upload_method.dfusMethod=Soft-DFU Upload +Disco.menu.upload_method.dfusMethod.upload.protocol=softdfu +Disco.menu.upload_method.dfusMethod.upload.tool=softdfu_upload +Disco.menu.upload_method.dfusMethod.upload.usbID=0483:df11 +Disco.menu.upload_method.dfusMethod.upload.altID=0 + ################################################################################ # Eval boards diff --git a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c index c09675f95e..c10b60dd9d 100644 --- a/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c +++ b/cores/arduino/stm32/usb/cdc/usbd_cdc_if.c @@ -55,6 +55,10 @@ __IO uint32_t lineState = 0; __IO bool receivePended = true; static uint32_t transmitStart = 0; +#ifdef VARIANT_SUPPORT_SOFTDFU + void variant_soft_dfu_hook(uint8_t *Buf, uint32_t *Len); +#endif + #ifdef DTR_TOGGLING_SEQ /* DTR toggling sequence management */ extern void dtr_togglingHook(uint8_t *buf, uint32_t *len); @@ -222,6 +226,9 @@ static int8_t USBD_CDC_Control(uint8_t cmd, uint8_t *pbuf, uint16_t length) */ static int8_t USBD_CDC_Receive(uint8_t *Buf, uint32_t *Len) { +#ifdef VARIANT_SUPPORT_SOFTDFU + variant_soft_dfu_hook(Buf, Len); +#endif #ifdef DTR_TOGGLING_SEQ if (dtr_toggling > 3) { dtr_togglingHook(Buf, Len); diff --git a/platform.txt b/platform.txt index 49dc9a3ea8..30e9e4c793 100644 --- a/platform.txt +++ b/platform.txt @@ -208,3 +208,13 @@ tools.remoteproc_gen.script=run_arduino_gen.sh tools.remoteproc_gen.upload.params.verbose= tools.remoteproc_gen.upload.params.quiet= tools.remoteproc_gen.upload.pattern="{busybox}" sh "{path}/{script}" generate "{build.path}/{build.project_name}.elf" "{build.path}/run_arduino_{build.project_name}.sh" + +# STM32 built-in DFU upload with Soft-DFU protocol +tools.softdfu_upload.cmd=softdfu_upload.sh +tools.softdfu_upload.cmd.windows=softdfu_upload.bat +tools.softdfu_upload.path={runtime.tools.STM32Tools.path}/tools/win +tools.softdfu_upload.path.macosx={runtime.tools.STM32Tools.path}/tools/macosx +tools.softdfu_upload.path.linux={runtime.tools.STM32Tools.path}/tools/linux +tools.softdfu_upload.upload.params.verbose= +tools.softdfu_upload.upload.params.quiet= +tools.softdfu_upload.upload.pattern="{path}/{cmd}" {serial.port.file} {upload.altID} {upload.usbID} "{build.path}/{build.project_name}.bin" \ No newline at end of file diff --git a/variants/DISCO_F072RB/startup_stm32f072xb_softdfu.S b/variants/DISCO_F072RB/startup_stm32f072xb_softdfu.S new file mode 100644 index 0000000000..07c4669407 --- /dev/null +++ b/variants/DISCO_F072RB/startup_stm32f072xb_softdfu.S @@ -0,0 +1,296 @@ +/** + ****************************************************************************** + * @file startup_stm32f072xb.s + * @author MCD Application Team + * @brief STM32F072x8/STM32F072xB devices vector table for GCC toolchain. + * This module performs: + * - Set the initial SP + * - Set the initial PC == Reset_Handler, + * - Set the vector table entries with the exceptions ISR address + * - Branches to main in the C library (which eventually + * calls main()). + * After Reset the Cortex-M0 processor is in Thread mode, + * priority is Privileged, and the Stack is set to Main. + ****************************************************************************** + * @attention + * + *

© Copyright (c) 2016 STMicroelectronics. + * All rights reserved.

+ * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ****************************************************************************** + */ + + .syntax unified + .cpu cortex-m0 + .fpu softvfp + .thumb + +.global g_pfnVectors +.global Default_Handler + +/* start address for the initialization values of the .data section. +defined in linker script */ +.word _sidata +/* start address for the .data section. defined in linker script */ +.word _sdata +/* end address for the .data section. defined in linker script */ +.word _edata +/* start address for the .bss section. defined in linker script */ +.word _sbss +/* end address for the .bss section. defined in linker script */ +.word _ebss + + .section .text.Reset_Handler + .weak Reset_Handler + .type Reset_Handler, %function +Reset_Handler: + ldr r0, =_estack + mov sp, r0 /* set stack pointer */ + + bl __initialize_hardware_early /* check for DFU soft boot */ + +/* Copy the data segment initializers from flash to SRAM */ + ldr r0, =_sdata + ldr r1, =_edata + ldr r2, =_sidata + movs r3, #0 + b LoopCopyDataInit + +CopyDataInit: + ldr r4, [r2, r3] + str r4, [r0, r3] + adds r3, r3, #4 + +LoopCopyDataInit: + adds r4, r0, r3 + cmp r4, r1 + bcc CopyDataInit + +/* Zero fill the bss segment. */ + ldr r2, =_sbss + ldr r4, =_ebss + movs r3, #0 + b LoopFillZerobss + +FillZerobss: + str r3, [r2] + adds r2, r2, #4 + +LoopFillZerobss: + cmp r2, r4 + bcc FillZerobss + +/* Call the clock system intitialization function.*/ + bl SystemInit +/* Call static constructors */ + bl __libc_init_array +/* Call the application's entry point.*/ + bl main + +LoopForever: + b LoopForever + + +.size Reset_Handler, .-Reset_Handler + +/** + * @brief This is the code that gets called when the processor receives an + * unexpected interrupt. This simply enters an infinite loop, preserving + * the system state for examination by a debugger. + * + * @param None + * @retval : None +*/ + .section .text.Default_Handler,"ax",%progbits +Default_Handler: +Infinite_Loop: + b Infinite_Loop + .size Default_Handler, .-Default_Handler +/****************************************************************************** +* +* The minimal vector table for a Cortex M0. Note that the proper constructs +* must be placed on this to ensure that it ends up at physical address +* 0x0000.0000. +* +******************************************************************************/ + .section .isr_vector,"a",%progbits + .type g_pfnVectors, %object + .size g_pfnVectors, .-g_pfnVectors + + +g_pfnVectors: + .word _estack + .word Reset_Handler + .word NMI_Handler + .word HardFault_Handler + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word 0 + .word SVC_Handler + .word 0 + .word 0 + .word PendSV_Handler + .word SysTick_Handler + .word WWDG_IRQHandler /* Window WatchDog */ + .word PVD_VDDIO2_IRQHandler /* PVD and VDDIO2 through EXTI Line detect */ + .word RTC_IRQHandler /* RTC through the EXTI line */ + .word FLASH_IRQHandler /* FLASH */ + .word RCC_CRS_IRQHandler /* RCC and CRS */ + .word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */ + .word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */ + .word EXTI4_15_IRQHandler /* EXTI Line 4 to 15 */ + .word TSC_IRQHandler /* TSC */ + .word DMA1_Channel1_IRQHandler /* DMA1 Channel 1 */ + .word DMA1_Channel2_3_IRQHandler /* DMA1 Channel 2 and Channel 3 */ + .word DMA1_Channel4_5_6_7_IRQHandler /* DMA1 Channel 4, Channel 5, Channel 6 and Channel 7*/ + .word ADC1_COMP_IRQHandler /* ADC1, COMP1 and COMP2 */ + .word TIM1_BRK_UP_TRG_COM_IRQHandler /* TIM1 Break, Update, Trigger and Commutation */ + .word TIM1_CC_IRQHandler /* TIM1 Capture Compare */ + .word TIM2_IRQHandler /* TIM2 */ + .word TIM3_IRQHandler /* TIM3 */ + .word TIM6_DAC_IRQHandler /* TIM6 and DAC */ + .word TIM7_IRQHandler /* TIM7 */ + .word TIM14_IRQHandler /* TIM14 */ + .word TIM15_IRQHandler /* TIM15 */ + .word TIM16_IRQHandler /* TIM16 */ + .word TIM17_IRQHandler /* TIM17 */ + .word I2C1_IRQHandler /* I2C1 */ + .word I2C2_IRQHandler /* I2C2 */ + .word SPI1_IRQHandler /* SPI1 */ + .word SPI2_IRQHandler /* SPI2 */ + .word USART1_IRQHandler /* USART1 */ + .word USART2_IRQHandler /* USART2 */ + .word USART3_4_IRQHandler /* USART3 and USART4 */ + .word CEC_CAN_IRQHandler /* CEC and CAN */ + .word USB_IRQHandler /* USB */ + +/******************************************************************************* +* +* Provide weak aliases for each Exception handler to the Default_Handler. +* As they are weak aliases, any function with the same name will override +* this definition. +* +*******************************************************************************/ + + .weak NMI_Handler + .thumb_set NMI_Handler,Default_Handler + + .weak HardFault_Handler + .thumb_set HardFault_Handler,Default_Handler + + .weak SVC_Handler + .thumb_set SVC_Handler,Default_Handler + + .weak PendSV_Handler + .thumb_set PendSV_Handler,Default_Handler + + .weak SysTick_Handler + .thumb_set SysTick_Handler,Default_Handler + + .weak WWDG_IRQHandler + .thumb_set WWDG_IRQHandler,Default_Handler + + .weak PVD_VDDIO2_IRQHandler + .thumb_set PVD_VDDIO2_IRQHandler,Default_Handler + + .weak RTC_IRQHandler + .thumb_set RTC_IRQHandler,Default_Handler + + .weak FLASH_IRQHandler + .thumb_set FLASH_IRQHandler,Default_Handler + + .weak RCC_CRS_IRQHandler + .thumb_set RCC_CRS_IRQHandler,Default_Handler + + .weak EXTI0_1_IRQHandler + .thumb_set EXTI0_1_IRQHandler,Default_Handler + + .weak EXTI2_3_IRQHandler + .thumb_set EXTI2_3_IRQHandler,Default_Handler + + .weak EXTI4_15_IRQHandler + .thumb_set EXTI4_15_IRQHandler,Default_Handler + + .weak TSC_IRQHandler + .thumb_set TSC_IRQHandler,Default_Handler + + .weak DMA1_Channel1_IRQHandler + .thumb_set DMA1_Channel1_IRQHandler,Default_Handler + + .weak DMA1_Channel2_3_IRQHandler + .thumb_set DMA1_Channel2_3_IRQHandler,Default_Handler + + .weak DMA1_Channel4_5_6_7_IRQHandler + .thumb_set DMA1_Channel4_5_6_7_IRQHandler,Default_Handler + + .weak ADC1_COMP_IRQHandler + .thumb_set ADC1_COMP_IRQHandler,Default_Handler + + .weak TIM1_BRK_UP_TRG_COM_IRQHandler + .thumb_set TIM1_BRK_UP_TRG_COM_IRQHandler,Default_Handler + + .weak TIM1_CC_IRQHandler + .thumb_set TIM1_CC_IRQHandler,Default_Handler + + .weak TIM2_IRQHandler + .thumb_set TIM2_IRQHandler,Default_Handler + + .weak TIM3_IRQHandler + .thumb_set TIM3_IRQHandler,Default_Handler + + .weak TIM6_DAC_IRQHandler + .thumb_set TIM6_DAC_IRQHandler,Default_Handler + + .weak TIM7_IRQHandler + .thumb_set TIM7_IRQHandler,Default_Handler + + .weak TIM14_IRQHandler + .thumb_set TIM14_IRQHandler,Default_Handler + + .weak TIM15_IRQHandler + .thumb_set TIM15_IRQHandler,Default_Handler + + .weak TIM16_IRQHandler + .thumb_set TIM16_IRQHandler,Default_Handler + + .weak TIM17_IRQHandler + .thumb_set TIM17_IRQHandler,Default_Handler + + .weak I2C1_IRQHandler + .thumb_set I2C1_IRQHandler,Default_Handler + + .weak I2C2_IRQHandler + .thumb_set I2C2_IRQHandler,Default_Handler + + .weak SPI1_IRQHandler + .thumb_set SPI1_IRQHandler,Default_Handler + + .weak SPI2_IRQHandler + .thumb_set SPI2_IRQHandler,Default_Handler + + .weak USART1_IRQHandler + .thumb_set USART1_IRQHandler,Default_Handler + + .weak USART2_IRQHandler + .thumb_set USART2_IRQHandler,Default_Handler + + .weak USART3_4_IRQHandler + .thumb_set USART3_4_IRQHandler,Default_Handler + + .weak CEC_CAN_IRQHandler + .thumb_set CEC_CAN_IRQHandler,Default_Handler + + .weak USB_IRQHandler + .thumb_set USB_IRQHandler,Default_Handler + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ + diff --git a/variants/DISCO_F072RB/variant.cpp b/variants/DISCO_F072RB/variant.cpp index 0b5ec54da5..495d4de6fe 100644 --- a/variants/DISCO_F072RB/variant.cpp +++ b/variants/DISCO_F072RB/variant.cpp @@ -34,6 +34,12 @@ extern "C" { #endif +#define SYSMEM_RESET_VECTOR 0x1FFFC804 +#define RESET_TO_BOOTLOADER_MAGIC_CODE 0xDEADBEEF +#define BOOTLOADER_STACK_POINTER 0x20002250 + +uint32_t dfu_reset_to_bootloader_magic; + // Pin number const PinName digitalPin[] = { //P2 connector Right side (top view) @@ -121,6 +127,37 @@ const PinName digitalPin[] = { extern "C" { #endif +void __initialize_hardware_early(void) +{ + if (dfu_reset_to_bootloader_magic == RESET_TO_BOOTLOADER_MAGIC_CODE) { + void (*bootloader)(void) = (void (*)(void))(*((uint32_t *) SYSMEM_RESET_VECTOR)); + dfu_reset_to_bootloader_magic = 0; + __set_MSP(BOOTLOADER_STACK_POINTER); + bootloader(); + while (42); + } +} + +void variant_soft_dfu_hook(uint8_t *Buf, uint32_t *Len) +{ + uint32_t i; + static unsigned char passkey[] = "1EAF"; + static unsigned char passkey_index = 0; + + for (i = 0; i < *Len; i++) { + /* reading buffer for a sequential bytes that form a pass key */ + if (*(Buf + i) == passkey[passkey_index]) + passkey_index++; + else + passkey_index = 0; + /* jump to DFU mode when the pass key found */ + if (passkey_index == 4) { + dfu_reset_to_bootloader_magic = RESET_TO_BOOTLOADER_MAGIC_CODE; + NVIC_SystemReset(); + } + } +} + /** * @brief System Clock Configuration * @param None