├── .gitmodules ├── .gitignore ├── src ├── debug.cfg ├── stm32l1 │ ├── generic │ │ └── config.h │ ├── stm32l1-standard.ld │ ├── backup.h │ ├── backup.c │ ├── stm32l1-base.ld │ └── target_stm32l1.c ├── webusb.h ├── winusb.h ├── stm32f103 │ ├── stm32f103x8_high.ld │ ├── stm32f103xb_high.ld │ ├── stm32f103xc_high.ld │ ├── backup.h │ ├── stm32f103x8.ld │ ├── backup.c │ ├── stlink │ │ └── config.h │ ├── generic │ │ └── config.h │ ├── bluepillplus │ │ └── config.h │ ├── bluepillplus-gd32 │ │ └── config.h │ ├── bluepill │ │ └── config.h │ ├── maplemini │ │ └── config.h │ ├── olimexstm32h103 │ │ └── config.h │ ├── stm32f1.ld │ ├── skrminie3v2 │ │ └── config.h │ └── target_stm32f103.c ├── dfu_defs.h ├── dfu.h ├── dapboot.h ├── target.h ├── webusb_defs.h ├── usb_conf.h ├── Makefile ├── dummy.c ├── dapboot.c ├── webusb.c ├── winusb.c ├── targets.mk ├── usb_conf.c ├── winusb_defs.h ├── rules.mk └── dfu.c ├── .github └── workflows │ └── build-firmware.yml ├── util └── install-toolchain.sh ├── release.Makefile ├── README.md └── LICENSE /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libopencm3"] 2 | path = libopencm3 3 | url = https://github.com/devanlai/libopencm3.git 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore GNU global files 2 | GPATH 3 | GRTAGS 4 | GSYMS 5 | GTAGS 6 | 7 | # ignore build artifacts 8 | *.d 9 | *.o 10 | *.bin 11 | *.hex 12 | *.elf 13 | *.axf 14 | *.map 15 | 16 | # ignore local makefile settings 17 | src/local.mk -------------------------------------------------------------------------------- /src/debug.cfg: -------------------------------------------------------------------------------- 1 | gdb_port pipe 2 | gdb_memory_map disable 3 | 4 | $_TARGETNAME configure -event gdb-attach { 5 | echo "Halting target" 6 | halt 7 | } 8 | 9 | $_TARGETNAME configure -event gdb-detach { 10 | echo "Resetting target" 11 | reset 12 | } -------------------------------------------------------------------------------- /src/stm32l1/generic/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 2020 - Karl Palsson 3 | * Considered to be released into the public domain, or where not available 4 | * under your choice of the following spdx identifiers: 5 | * MIT, ISC, Apache-2.0, BSD-1-Clause, BSD-2-Clause, BSD-3-Clause, 6 | * CC-BY-4.0, GPL-2.0-or-later, LGPL-2.0-or-later 7 | * Pick whatever makes your integration life easier 8 | * 9 | * defauly config.h settings 10 | */ 11 | 12 | #pragma once 13 | 14 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 15 | #define FLASH_PAGE_SIZE 128 16 | #define DFU_UPLOAD_AVAILABLE 1 17 | #define DFU_DOWNLOAD_AVAILABLE 1 18 | #define TARGET_DFU_WTRANSFERSIZE 128 19 | 20 | #define HAVE_LED 0 21 | #define HAVE_BUTTON 0 22 | #define HAVE_USB_PULLUP_CONTROL 0 23 | -------------------------------------------------------------------------------- /src/stm32l1/stm32l1-standard.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * 2020 - Karl Palsson 3 | * Considered to be released into the public domain, or where not available 4 | * under your choice of the following spdx identifiers: 5 | * MIT, ISC, Apache-2.0, BSD-1-Clause, BSD-2-Clause, BSD-3-Clause, 6 | * CC-BY-4.0, GPL-2.0-or-later, LGPL-2.0-or-later 7 | * Pick whatever makes your integration life easier 8 | * 9 | * Linker script for STM32L1 parts. Bootloader only for 8k, and all parts 10 | * have at least 10k RAM, (-A parts have 32K RAM, but 10 is enough) 11 | */ 12 | 13 | /* Define memory regions. */ 14 | MEMORY 15 | { 16 | vectors (rx) : ORIGIN = 0x08000000, LENGTH = 0x150 17 | rom (rx) : ORIGIN = 0x08000150, LENGTH = 0x1EB0 18 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 10K 19 | } 20 | 21 | /* Include the common ld script. */ 22 | INCLUDE stm32l1/stm32l1-base.ld 23 | -------------------------------------------------------------------------------- /src/webusb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef WEBUSB_H_INCLUDED 20 | #define WEBUSB_H_INCLUDED 21 | 22 | #include "webusb_defs.h" 23 | 24 | // Arbitrary 25 | #define WEBUSB_VENDOR_CODE 0x01 26 | 27 | extern const struct webusb_platform_descriptor webusb_platform; 28 | extern void webusb_setup(usbd_device* usbd_dev); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/winusb.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef WINUSB_H_INCLUDED 20 | #define WINUSB_H_INCLUDED 21 | 22 | #include "winusb_defs.h" 23 | 24 | /* Arbitrary, but must be equivalent to the last character in 25 | the special OS descriptor string */ 26 | #define WINUSB_MS_VENDOR_CODE 0x21 27 | 28 | extern void winusb_setup(usbd_device* usbd_dev); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /src/stm32l1/backup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef BACKUP_H_INCLUDED 20 | #define BACKUP_H_INCLUDED 21 | 22 | enum BackupRegister { 23 | BKP0 = 0, 24 | BKP1, 25 | BKP2, 26 | BKP3, 27 | BKP4, 28 | }; 29 | 30 | extern void backup_write(enum BackupRegister reg, uint32_t value); 31 | extern uint32_t backup_read(enum BackupRegister reg); 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/stm32f103/stm32f103x8_high.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2015 Karl Palsson 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Linker script for STM32F103x8, 64k flash, 20k RAM. */ 21 | 22 | /* Define memory regions. */ 23 | MEMORY 24 | { 25 | vectors (rx) : ORIGIN = 0x08000000, LENGTH = 0x150 26 | rom (rx) : ORIGIN = 0x0800E400, LENGTH = 0x1C00 27 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 28 | } 29 | 30 | /* Include the common ld script. */ 31 | INCLUDE stm32f103/stm32f1.ld 32 | -------------------------------------------------------------------------------- /src/stm32f103/stm32f103xb_high.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2015 Karl Palsson 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Linker script for STM32F103xB, 128k flash, 20k RAM. */ 21 | 22 | /* Define memory regions. */ 23 | MEMORY 24 | { 25 | vectors (rx) : ORIGIN = 0x08000000, LENGTH = 0x150 26 | rom (rx) : ORIGIN = 0x0801E400, LENGTH = 0x1C00 27 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 28 | } 29 | 30 | /* Include the common ld script. */ 31 | INCLUDE stm32f103/stm32f1.ld 32 | -------------------------------------------------------------------------------- /src/stm32f103/stm32f103xc_high.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2015 Karl Palsson 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Linker script for STM32F103xC, 256k flash, 48k RAM. */ 21 | 22 | /* Define memory regions. */ 23 | MEMORY 24 | { 25 | vectors (rx) : ORIGIN = 0x08000000, LENGTH = 0x150 26 | rom (rx) : ORIGIN = 0x0803E400, LENGTH = 0x1C00 27 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 48K 28 | } 29 | 30 | /* Include the common ld script. */ 31 | INCLUDE stm32f103/stm32f1.ld 32 | -------------------------------------------------------------------------------- /src/dfu_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef DFU_DEFS_H_INCLUDED 20 | #define DFU_DEFS_H_INCLUDED 21 | 22 | #include 23 | 24 | struct dfu_getstatus_response { 25 | uint8_t bStatus; 26 | uint8_t bwPollTimeout[3]; 27 | uint8_t bState; 28 | uint8_t iString; 29 | } __attribute__((packed)); 30 | 31 | struct dfu_getstate_response { 32 | uint8_t bState; 33 | } __attribute__((packed)); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/stm32f103/backup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef BACKUP_H_INCLUDED 20 | #define BACKUP_H_INCLUDED 21 | 22 | enum BackupRegister { 23 | BKP1, 24 | BKP2, 25 | BKP3, 26 | BKP4, 27 | BKP5, 28 | BKP6, 29 | BKP7, 30 | BKP8, 31 | BKP9, 32 | BKP10, 33 | }; 34 | 35 | extern void backup_write(enum BackupRegister reg, uint16_t value); 36 | extern uint16_t backup_read(enum BackupRegister reg); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /.github/workflows/build-firmware.yml: -------------------------------------------------------------------------------- 1 | name: Build Firmware 2 | on: [push] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - name: Checkout source 8 | uses: actions/checkout@v3 9 | with: 10 | submodules: recursive 11 | 12 | - name: Cache Toolchain 13 | id: cache-toolchain 14 | uses: actions/cache@v3 15 | env: 16 | cache-name: cache-toolchain 17 | with: 18 | path: ~/toolchains/ 19 | key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('util/install-toolchain.sh') }} 20 | restore-keys: | 21 | ${{ runner.os }}-build-${{ env.cache-name }}- 22 | ${{ runner.os }}-build- 23 | ${{ runner.os }}- 24 | 25 | - if: ${{ steps.cache-toolchain.outputs.cache-hit != 'true' }} 26 | name: Download toolchain 27 | run: ./util/install-toolchain.sh 28 | 29 | - name: Build Firmware 30 | run: make -f release.Makefile -k all 31 | env: 32 | PREFIX: ~/toolchains/gcc-arm-embedded/bin/arm-none-eabi- 33 | 34 | - name: Archive Firmware 35 | uses: actions/upload-artifact@v4 36 | with: 37 | name: firmware-bin 38 | path: build/*.bin 39 | -------------------------------------------------------------------------------- /util/install-toolchain.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | if [ `uname` == 'Darwin' ]; then 5 | TOOLCHAIN_ARCH=mac 6 | else 7 | TOOLCHAIN_ARCH=x86_64-linux 8 | fi 9 | TOOLCHAIN_REV=9-2019q4 10 | TOOLCHAIN=gcc-arm-none-eabi-9-2019-q4-major 11 | URL=https://developer.arm.com/-/media/Files/downloads/gnu-rm/${TOOLCHAIN_REV}/${TOOLCHAIN}-${TOOLCHAIN_ARCH}.tar.bz2 12 | TOOLCHAINS=$HOME/toolchains 13 | TOOLCHAIN_MISSING=0 14 | GCC=${TOOLCHAINS}/gcc-arm-embedded/bin/arm-none-eabi-gcc 15 | if [[ ! -d "${TOOLCHAINS}/gcc-arm-embedded" ]]; then 16 | TOOLCHAIN_MISSING=1 17 | fi; 18 | if [[ ! -f ${GCC} ]]; then 19 | TOOLCHAIN_MISSING=1 20 | fi; 21 | 22 | if [ $TOOLCHAIN_MISSING -eq 1 ]; then 23 | echo "Installing $TOOLCHAIN from $URL to ${TOOLCHAINS}" 24 | mkdir -p ${TOOLCHAINS} 25 | wget -qO- $URL | tar xj -C ${TOOLCHAINS} 26 | rm -rf ${TOOLCHAINS}/gcc-arm-embedded 27 | ln -s $TOOLCHAIN ${TOOLCHAINS}/gcc-arm-embedded 28 | fi; 29 | 30 | EXISTING_TOOLCHAIN=`readlink "${TOOLCHAINS}/gcc-arm-embedded"` 31 | echo "Current toolchain is $EXISTING_TOOLCHAIN" 32 | 33 | if [ $TOOLCHAIN_ARCH != 'mac' ]; then 34 | if ! ldd ${GCC} >/dev/null; then 35 | echo "${GCC} does not appear to be executable on this machine" 36 | exit 1 37 | fi; 38 | fi; 39 | 40 | TOOLCHAIN_VER=`${GCC} --version | head -n 1` 41 | echo "Installed toolchain version is $TOOLCHAIN_VER" 42 | -------------------------------------------------------------------------------- /src/stm32f103/stm32f103x8.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2015 Karl Palsson 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Linker script for STM32F103x8, 64k flash, 20k RAM. 21 | * This script also works for the STM32F103xB and the STM32F103xC, 22 | * as the bootloader only uses the first 8kB of flash. */ 23 | 24 | /* Define memory regions. */ 25 | MEMORY 26 | { 27 | vectors (rx) : ORIGIN = 0x08000000, LENGTH = 0x150 28 | rom (rx) : ORIGIN = 0x08000150, LENGTH = 0x1EB0 29 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 20K 30 | } 31 | 32 | /* Include the common ld script. */ 33 | INCLUDE stm32f103/stm32f1.ld 34 | -------------------------------------------------------------------------------- /src/stm32l1/backup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 2020, Karl Palsson, ported to L1 4 | * 5 | * Permission to use, copy, modify, and/or distribute this software 6 | * for any purpose with or without fee is hereby granted, provided 7 | * that the above copyright notice and this permission notice 8 | * appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 14 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 16 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 17 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "backup.h" 25 | 26 | void backup_write(enum BackupRegister reg, uint32_t value) 27 | { 28 | rcc_periph_clock_enable(RCC_PWR); 29 | pwr_disable_backup_domain_write_protect(); 30 | RTC_BKPXR(reg) = value; 31 | pwr_enable_backup_domain_write_protect(); 32 | } 33 | 34 | uint32_t backup_read(enum BackupRegister reg) 35 | { 36 | return RTC_BKPXR(reg); 37 | } 38 | -------------------------------------------------------------------------------- /src/stm32f103/backup.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include "backup.h" 24 | 25 | #define RTC_BKP_DR(reg) MMIO16(BACKUP_REGS_BASE + 4 + (4 * (reg))) 26 | 27 | void backup_write(enum BackupRegister reg, uint16_t value) { 28 | rcc_periph_clock_enable(RCC_PWR); 29 | rcc_periph_clock_enable(RCC_BKP); 30 | 31 | pwr_disable_backup_domain_write_protect(); 32 | RTC_BKP_DR((int)reg) = value; 33 | pwr_enable_backup_domain_write_protect(); 34 | } 35 | 36 | uint16_t backup_read(enum BackupRegister reg) { 37 | return RTC_BKP_DR((int)reg); 38 | } 39 | -------------------------------------------------------------------------------- /src/dfu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef DFU_H_INCLUDED 20 | #define DFU_H_INCLUDED 21 | 22 | #include 23 | #include 24 | 25 | // For WebUSB compatibility 26 | #ifndef DFU_WILL_DETACH 27 | #define DFU_WILL_DETACH 1 28 | #endif 29 | 30 | extern const struct usb_dfu_descriptor dfu_function; 31 | 32 | typedef bool (*ManifestationCallback)(void); 33 | typedef void (*StateChangeCallback)(enum dfu_state); 34 | typedef void (*StatusChangeCallback)(enum dfu_status); 35 | 36 | extern void dfu_setup(usbd_device* usbd_dev, 37 | ManifestationCallback on_manifest_request, 38 | StateChangeCallback on_state_change, 39 | StatusChangeCallback on_status_change); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/dapboot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef DAPBOOT_H_INCLUDED 20 | #define DAPBOOT_H_INCLUDED 21 | 22 | extern bool validate_application(void); 23 | 24 | #ifdef BOOTLOADER_HIGH 25 | /* Definitions for high memory bootloader */ 26 | #define APP_INITIAL_STACK vector_table.reserved_x001c[0] 27 | #define APP_ENTRY_POINT vector_table.reserved_x001c[1] 28 | #define APP_RELOCATE_VECTORS 0 29 | #define DFU_PATCH_VECTORS 1 30 | #define BOOTLOADER_OFFSET 0 31 | 32 | #else 33 | /* Definitions for low memory (standard) bootloader */ 34 | #define APP_INITIAL_STACK ((vector_table_t*)APP_BASE_ADDRESS)->initial_sp_value 35 | #define APP_ENTRY_POINT ((vector_table_t*)APP_BASE_ADDRESS)->reset 36 | #define APP_RELOCATE_VECTORS 1 37 | #define DFU_PATCH_VECTORS 0 38 | #define BOOTLOADER_OFFSET 0x00002000 39 | 40 | #endif 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/target.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef TARGET_H_INCLUDED 20 | #define TARGET_H_INCLUDED 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | extern void target_clock_setup(void); 27 | extern void target_gpio_setup(void); 28 | extern const usbd_driver* target_usb_init(void); 29 | extern bool target_get_force_bootloader(void); 30 | extern void target_get_serial_number(char* dest, size_t max_chars); 31 | extern size_t target_get_max_firmware_size(void); 32 | extern void target_log(const char* str); 33 | extern void target_relocate_vector_table(void); 34 | extern void target_flash_unlock(void); 35 | extern void target_flash_lock(void); 36 | extern bool target_flash_program_array(uint16_t* dest, const uint16_t* data, size_t half_word_count); 37 | 38 | extern void target_pre_main(void); 39 | extern void target_post_setup(void); 40 | extern void target_pre_detach(bool manifested); 41 | extern size_t target_get_timeout(void); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/stm32f103/stlink/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_SIZE_OVERRIDE 26 | #define FLASH_SIZE_OVERRIDE 0x20000 27 | #endif 28 | #ifndef FLASH_PAGE_SIZE 29 | #define FLASH_PAGE_SIZE 1024 30 | #endif 31 | #ifndef DFU_UPLOAD_AVAILABLE 32 | #define DFU_UPLOAD_AVAILABLE 1 33 | #endif 34 | #ifndef DFU_DOWNLOAD_AVAILABLE 35 | #define DFU_DOWNLOAD_AVAILABLE 1 36 | #endif 37 | 38 | #ifndef HAVE_LED 39 | #define HAVE_LED 1 40 | #endif 41 | #ifndef LED_GPIO_PORT 42 | #define LED_GPIO_PORT GPIOA 43 | #endif 44 | #ifndef LED_GPIO_PIN 45 | #define LED_GPIO_PIN GPIO9 46 | #endif 47 | #ifndef LED_OPEN_DRAIN 48 | #define LED_OPEN_DRAIN 0 49 | #endif 50 | 51 | #ifndef HAVE_BUTTON 52 | #define HAVE_BUTTON 0 53 | #endif 54 | 55 | #ifndef HAVE_USB_PULLUP_CONTROL 56 | #define HAVE_USB_PULLUP_CONTROL 0 57 | #endif 58 | 59 | #ifndef USES_GPIOA 60 | #define USES_GPIOA 1 61 | #endif 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/webusb_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef WEBUSB_DEFS_H_INCLUDED 20 | #define WEBUSB_DEFS_H_INCLUDED 21 | 22 | #include 23 | 24 | #define WEBUSB_REQ_GET_URL 0x02 25 | 26 | #define WEBUSB_DT_URL 3 27 | 28 | #define WEBUSB_URL_SCHEME_HTTP 0 29 | #define WEBUSB_URL_SCHEME_HTTPS 1 30 | 31 | struct webusb_platform_descriptor { 32 | uint8_t bLength; 33 | uint8_t bDescriptorType; 34 | uint8_t bDevCapabilityType; 35 | uint8_t bReserved; 36 | uint8_t platformCapabilityUUID[16]; 37 | uint16_t bcdVersion; 38 | uint8_t bVendorCode; 39 | uint8_t iLandingPage; 40 | } __attribute__((packed)); 41 | 42 | #define WEBUSB_PLATFORM_DESCRIPTOR_SIZE sizeof(struct webusb_platform_descriptor) 43 | 44 | #define WEBUSB_UUID {0x38, 0xB6, 0x08, 0x34, 0xA9, 0x09, 0xA0, 0x47,0x8B, 0xFD, 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65} 45 | 46 | struct webusb_url_descriptor { 47 | uint8_t bLength; 48 | uint8_t bDescriptorType; 49 | uint8_t bScheme; 50 | char URL[]; 51 | } __attribute__((packed)); 52 | 53 | #define WEBUSB_DT_URL_DESCRIPTOR_SIZE 3 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /src/usb_conf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef USB_CONF_H_INCLUDED 20 | #define USB_CONF_H_INCLUDED 21 | 22 | #include 23 | 24 | #ifndef USB_VID 25 | #define USB_VID 0x1209 26 | #endif 27 | 28 | #ifndef USB_VENDOR_STRING 29 | #define USB_VENDOR_STRING "Devanarchy" 30 | #endif 31 | 32 | #ifndef USB_PID 33 | #define USB_PID 0xdb42 34 | #endif 35 | 36 | // The DFU interface doesn't have any special alternate setting by default 37 | #ifndef USB_DFU_ALTN 38 | #define USB_DFU_ALTN 0 39 | #endif 40 | 41 | #ifndef USB_PRODUCT_STRING 42 | 43 | #ifdef BOOTLOADER_HIGH 44 | #define USB_PRODUCT_STRING "DAPBoot High-Memory DFU Bootloader" 45 | #else 46 | #define USB_PRODUCT_STRING "DAPBoot DFU Bootloader" 47 | #endif 48 | 49 | #endif 50 | 51 | #ifndef USB_INTERFACE_STRING 52 | #define USB_INTERFACE_STRING "DAPBoot DFU" 53 | #endif 54 | 55 | #define USB_CONTROL_BUF_SIZE 1024 56 | #define USB_SERIAL_NUM_LENGTH 24 57 | #define INTF_DFU 0 58 | 59 | extern void usb_set_serial_number(const char* serial); 60 | extern usbd_device* usb_setup(void); 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2016, Devan Lai 2 | ## 3 | ## Permission to use, copy, modify, and/or distribute this software 4 | ## for any purpose with or without fee is hereby granted, provided 5 | ## that the above copyright notice and this permission notice 6 | ## appear in all copies. 7 | ## 8 | ## THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 9 | ## WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 10 | ## WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 11 | ## AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 12 | ## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | ## LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 14 | ## NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 | ## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | -include local.mk 18 | 19 | BINARY = dapboot 20 | OPENCM3_DIR = ../libopencm3 21 | 22 | TARGET ?= STM32F103 23 | include targets.mk 24 | 25 | SRCS := $(wildcard *.c) 26 | SRCS += $(wildcard $(TARGET_COMMON_DIR)/*.c) 27 | SRCS += $(wildcard $(TARGET_SPEC_DIR)/*.c) 28 | 29 | OBJS += $(SRCS:.c=.o) 30 | DEPS = $(SRCS:.c=.d) 31 | 32 | .DEFAULT_GOAL := $(BINARY).bin 33 | 34 | clean:: 35 | @rm -f $(OBJS) 36 | @rm -f $(DEPS) 37 | 38 | include rules.mk 39 | 40 | size: $(OBJS) $(BINARY).elf 41 | @$(PREFIX)size $(OBJS) $(BINARY).elf 42 | 43 | debug: $(BINARY).elf 44 | -$(GDB) --tui --eval "target remote | $(OOCD) -f $(OOCD_INTERFACE) -f $(OOCD_BOARD) -f debug.cfg" $(BINARY).elf 45 | 46 | erase: 47 | $(OOCD) -f $(OOCD_INTERFACE) -f $(OOCD_BOARD) \ 48 | -c "init" -c "reset init" \ 49 | -c "stm32f1x unlock 0; reset halt" \ 50 | -c "flash erase_sector 0 0 last" -c "reset" -c "shutdown" 51 | 52 | .PHONY += debug size erase 53 | 54 | OBJS := $(sort $(OBJS)) 55 | 56 | # Add the base directory to the header search path 57 | CPPFLAGS += -I. 58 | 59 | # Add target config directory to the header search path 60 | CPPFLAGS += -I$(TARGET_COMMON_DIR)/ 61 | CPPFLAGS += -I$(TARGET_SPEC_DIR)/ 62 | -------------------------------------------------------------------------------- /src/stm32f103/generic/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_SIZE_OVERRIDE 26 | #define FLASH_SIZE_OVERRIDE 0x20000 27 | #endif 28 | #ifndef FLASH_PAGE_SIZE 29 | #define FLASH_PAGE_SIZE 1024 30 | #endif 31 | #ifndef DFU_UPLOAD_AVAILABLE 32 | #define DFU_UPLOAD_AVAILABLE 1 33 | #endif 34 | #ifndef DFU_DOWNLOAD_AVAILABLE 35 | #define DFU_DOWNLOAD_AVAILABLE 1 36 | #endif 37 | 38 | #ifndef HAVE_LED 39 | #define HAVE_LED 0 40 | #endif 41 | // #ifndef LED_OPEN_DRAIN 42 | // #define LED_OPEN_DRAIN 0 43 | // #endif 44 | // #ifndef LED_GPIO_PORT 45 | // #define LED_GPIO_PORT GPIOA 46 | // #endif 47 | // #ifndef LED_GPIO_PIN 48 | // #define LED_GPIO_PIN GPIO0 49 | // #endif 50 | 51 | #ifndef HAVE_BUTTON 52 | #define HAVE_BUTTON 0 53 | #endif 54 | // #ifndef BUTTON_ACTIVE_HIGH 55 | // #define BUTTON_ACTIVE_HIGH 0 56 | // #endif 57 | // #ifndef BUTTON_GPIO_PORT 58 | // #define BUTTON_GPIO_PORT GPIOA 59 | // #endif 60 | // #ifndef BUTTON_GPIO_PIN 61 | // #define BUTTON_GPIO_PIN GPIO0 62 | // #endif 63 | 64 | #ifndef BUTTON_SAMPLE_DELAY_CYCLES 65 | #define BUTTON_SAMPLE_DELAY_CYCLES 1440000 66 | #endif 67 | 68 | #ifndef HAVE_USB_PULLUP_CONTROL 69 | #define HAVE_USB_PULLUP_CONTROL 0 70 | #endif 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /src/dummy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* Default dummy implementations for optional target functions */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | void target_get_serial_number(char* dest, size_t max_chars) __attribute__((weak)); 26 | void target_log(const char* str) __attribute__((weak)); 27 | void target_pre_main(void) __attribute__((weak)); 28 | void target_pre_detach(bool manifested) __attribute__((weak)); 29 | void target_post_setup(void) __attribute__((weak)); 30 | size_t target_get_timeout(void) __attribute__((weak)); 31 | 32 | void target_get_serial_number(char* dest, size_t max_chars) { 33 | (void)max_chars; 34 | if (dest) { 35 | dest[0] = '\0'; 36 | } 37 | } 38 | 39 | void target_log(const char* str) { 40 | (void)str; 41 | } 42 | 43 | void target_pre_main(void) 44 | { 45 | 46 | } 47 | 48 | void target_post_setup(void) 49 | { 50 | /* This runs just before starting to listen to USB */ 51 | } 52 | 53 | 54 | void target_pre_detach(bool manifested) { 55 | /* This runs just before executing a reboot in response to a USB bus reset 56 | or a detach request. 57 | If new firmware was successfully downloaded, manifested is set to true. 58 | This can be used to set flags or blink LEDs before rebooting. 59 | */ 60 | (void)manifested; 61 | } 62 | 63 | size_t target_get_timeout(void) 64 | { 65 | return 100; 66 | } 67 | -------------------------------------------------------------------------------- /src/stm32f103/bluepillplus/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_SIZE_OVERRIDE 26 | #define FLASH_SIZE_OVERRIDE 0x20000 27 | #endif 28 | #ifndef FLASH_PAGE_SIZE 29 | #define FLASH_PAGE_SIZE 1024 30 | #endif 31 | #ifndef DFU_UPLOAD_AVAILABLE 32 | #define DFU_UPLOAD_AVAILABLE 1 33 | #endif 34 | #ifndef DFU_DOWNLOAD_AVAILABLE 35 | #define DFU_DOWNLOAD_AVAILABLE 1 36 | #endif 37 | 38 | #ifndef HAVE_LED 39 | #define HAVE_LED 1 40 | #endif 41 | #ifndef LED_OPEN_DRAIN 42 | #define LED_OPEN_DRAIN 0 43 | #endif 44 | #ifndef LED_GPIO_PORT 45 | #define LED_GPIO_PORT GPIOB 46 | #endif 47 | #ifndef LED_GPIO_PIN 48 | #define LED_GPIO_PIN GPIO2 49 | #endif 50 | 51 | #ifndef HAVE_BUTTON 52 | #define HAVE_BUTTON 1 53 | #endif 54 | #ifndef BUTTON_ACTIVE_HIGH 55 | #define BUTTON_ACTIVE_HIGH 1 56 | #endif 57 | #ifndef BUTTON_GPIO_PORT 58 | #define BUTTON_GPIO_PORT GPIOA 59 | #endif 60 | #ifndef BUTTON_GPIO_PIN 61 | #define BUTTON_GPIO_PIN GPIO0 62 | #endif 63 | #ifndef BUTTON_USES_PULL 64 | #define BUTTON_USES_PULL 1 65 | #endif 66 | #ifndef BUTTON_SAMPLE_DELAY_CYCLES 67 | #define BUTTON_SAMPLE_DELAY_CYCLES 1440000 68 | #endif 69 | 70 | #ifndef HAVE_USB_PULLUP_CONTROL 71 | #define HAVE_USB_PULLUP_CONTROL 0 72 | #endif 73 | 74 | #ifndef USES_GPIOA 75 | #define USES_GPIOA 1 76 | #endif 77 | #ifndef USES_GPIOB 78 | #define USES_GPIOB 1 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/stm32f103/bluepillplus-gd32/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_SIZE_OVERRIDE 26 | #define FLASH_SIZE_OVERRIDE 0x20000 27 | #endif 28 | #ifndef FLASH_PAGE_SIZE 29 | #define FLASH_PAGE_SIZE 2048 30 | #endif 31 | #ifndef DFU_UPLOAD_AVAILABLE 32 | #define DFU_UPLOAD_AVAILABLE 1 33 | #endif 34 | #ifndef DFU_DOWNLOAD_AVAILABLE 35 | #define DFU_DOWNLOAD_AVAILABLE 1 36 | #endif 37 | 38 | #ifndef HAVE_LED 39 | #define HAVE_LED 1 40 | #endif 41 | #ifndef LED_OPEN_DRAIN 42 | #define LED_OPEN_DRAIN 0 43 | #endif 44 | #ifndef LED_GPIO_PORT 45 | #define LED_GPIO_PORT GPIOB 46 | #endif 47 | #ifndef LED_GPIO_PIN 48 | #define LED_GPIO_PIN GPIO2 49 | #endif 50 | 51 | #ifndef HAVE_BUTTON 52 | #define HAVE_BUTTON 1 53 | #endif 54 | #ifndef BUTTON_ACTIVE_HIGH 55 | #define BUTTON_ACTIVE_HIGH 1 56 | #endif 57 | #ifndef BUTTON_GPIO_PORT 58 | #define BUTTON_GPIO_PORT GPIOA 59 | #endif 60 | #ifndef BUTTON_GPIO_PIN 61 | #define BUTTON_GPIO_PIN GPIO0 62 | #endif 63 | #ifndef BUTTON_USES_PULL 64 | #define BUTTON_USES_PULL 1 65 | #endif 66 | #ifndef BUTTON_SAMPLE_DELAY_CYCLES 67 | #define BUTTON_SAMPLE_DELAY_CYCLES 1440000 68 | #endif 69 | 70 | #ifndef HAVE_USB_PULLUP_CONTROL 71 | #define HAVE_USB_PULLUP_CONTROL 0 72 | #endif 73 | 74 | #ifndef USES_GPIOA 75 | #define USES_GPIOA 1 76 | #endif 77 | #ifndef USES_GPIOB 78 | #define USES_GPIOB 1 79 | #endif 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/stm32f103/bluepill/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_SIZE_OVERRIDE 26 | #define FLASH_SIZE_OVERRIDE 0x20000 27 | #endif 28 | #ifndef FLASH_PAGE_SIZE 29 | #define FLASH_PAGE_SIZE 1024 30 | #endif 31 | #ifndef DFU_UPLOAD_AVAILABLE 32 | #define DFU_UPLOAD_AVAILABLE 1 33 | #endif 34 | #ifndef DFU_DOWNLOAD_AVAILABLE 35 | #define DFU_DOWNLOAD_AVAILABLE 1 36 | #endif 37 | 38 | #ifndef HAVE_LED 39 | #define HAVE_LED 1 40 | #endif 41 | #ifndef LED_OPEN_DRAIN 42 | #define LED_OPEN_DRAIN 1 43 | #endif 44 | #ifndef LED_GPIO_PORT 45 | #define LED_GPIO_PORT GPIOC 46 | #endif 47 | #ifndef LED_GPIO_PIN 48 | #define LED_GPIO_PIN GPIO13 49 | #endif 50 | 51 | #ifndef HAVE_BUTTON 52 | #define HAVE_BUTTON 1 53 | #endif 54 | #ifndef BUTTON_ACTIVE_HIGH 55 | #define BUTTON_ACTIVE_HIGH 1 56 | #endif 57 | #ifndef BUTTON_GPIO_PORT 58 | #define BUTTON_GPIO_PORT GPIOB 59 | #endif 60 | #ifndef BUTTON_GPIO_PIN 61 | #define BUTTON_GPIO_PIN GPIO2 62 | #endif 63 | // Blue-Pull has 100k resistors on PB2, so we can't use weak pulls to read it. 64 | #ifndef BUTTON_USES_PULL 65 | #define BUTTON_USES_PULL 0 66 | #endif 67 | 68 | #ifndef BUTTON_SAMPLE_DELAY_CYCLES 69 | #define BUTTON_SAMPLE_DELAY_CYCLES 1440000 70 | #endif 71 | 72 | #ifndef HAVE_USB_PULLUP_CONTROL 73 | #define HAVE_USB_PULLUP_CONTROL 0 74 | #endif 75 | 76 | #ifndef USES_GPIOB 77 | #define USES_GPIOB 1 78 | #endif 79 | 80 | #ifndef USES_GPIOC 81 | #define USES_GPIOC 1 82 | #endif 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /src/stm32f103/maplemini/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_PAGE_SIZE 26 | #define FLASH_PAGE_SIZE 1024 27 | #endif 28 | #ifndef DFU_UPLOAD_AVAILABLE 29 | #define DFU_UPLOAD_AVAILABLE 1 30 | #endif 31 | #ifndef DFU_DOWNLOAD_AVAILABLE 32 | #define DFU_DOWNLOAD_AVAILABLE 1 33 | #endif 34 | 35 | #ifndef HAVE_LED 36 | #define HAVE_LED 1 37 | #endif 38 | #ifndef LED_GPIO_PORT 39 | #define LED_GPIO_PORT GPIOB 40 | #endif 41 | #ifndef LED_GPIO_PIN 42 | #define LED_GPIO_PIN GPIO1 43 | #endif 44 | #ifndef LED_OPEN_DRAIN 45 | #define LED_OPEN_DRAIN 0 46 | #endif 47 | 48 | /* Technically, there is a button on PB8, but the button is 49 | also shorted to BOOT0, so it's not very useful for us to 50 | sample PB8 on boot, since pulling it high will already 51 | trigger the ROM serial bootloader and prevent us from 52 | running anyways. */ 53 | #ifndef HAVE_BUTTON 54 | #define HAVE_BUTTON 0 55 | #endif 56 | 57 | #ifndef HAVE_USB_PULLUP_CONTROL 58 | #define HAVE_USB_PULLUP_CONTROL 1 59 | #endif 60 | #ifndef USB_PULLUP_GPIO_PORT 61 | #define USB_PULLUP_GPIO_PORT GPIOB 62 | #endif 63 | #ifndef USB_PULLUP_GPIO_PIN 64 | #define USB_PULLUP_GPIO_PIN GPIO9 65 | #endif 66 | #ifndef USB_PULLUP_ACTIVE_HIGH 67 | #define USB_PULLUP_ACTIVE_HIGH 0 68 | #endif 69 | #ifndef USB_PULLUP_OPEN_DRAIN 70 | #define USB_PULLUP_OPEN_DRAIN 1 71 | #endif 72 | 73 | #ifndef USES_GPIOA 74 | #define USES_GPIOA 0 75 | #endif 76 | #ifndef USES_GPIOB 77 | #define USES_GPIOB 1 78 | #endif 79 | #ifndef USES_GPIOC 80 | #define USES_GPIOC 0 81 | #endif 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/stm32f103/olimexstm32h103/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Jean THOMAS 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_PAGE_SIZE 26 | #define FLASH_PAGE_SIZE 1024 27 | #endif 28 | #ifndef DFU_UPLOAD_AVAILABLE 29 | #define DFU_UPLOAD_AVAILABLE 1 30 | #endif 31 | #ifndef DFU_DOWNLOAD_AVAILABLE 32 | #define DFU_DOWNLOAD_AVAILABLE 1 33 | #endif 34 | 35 | #ifndef HAVE_LED 36 | #define HAVE_LED 1 37 | #endif 38 | #ifndef LED_GPIO_PORT 39 | #define LED_GPIO_PORT GPIOC 40 | #endif 41 | #ifndef LED_GPIO_PIN 42 | #define LED_GPIO_PIN GPIO12 43 | #endif 44 | #ifndef LED_OPEN_DRAIN 45 | #define LED_OPEN_DRAIN 1 46 | #endif 47 | 48 | /* "BUT" button on on PA0, pulled high by R18 */ 49 | #ifndef HAVE_BUTTON 50 | #define HAVE_BUTTON 1 51 | #endif 52 | #ifndef BUTTON_ACTIVE_HIGH 53 | #define BUTTON_ACTIVE_HIGH 0 54 | #endif 55 | #ifndef BUTTON_GPIO_PORT 56 | #define BUTTON_GPIO_PORT GPIOA 57 | #endif 58 | #ifndef BUTTON_GPIO_PIN 59 | #define BUTTON_GPIO_PIN GPIO0 60 | #endif 61 | #ifndef BUTTON_USES_PULL 62 | #define BUTTON_USES_PULL 0 63 | #endif 64 | #ifndef BUTTON_SAMPLE_DELAY_CYCLES 65 | #define BUTTON_SAMPLE_DELAY_CYCLES 1440000 66 | #endif 67 | 68 | #ifndef HAVE_USB_PULLUP_CONTROL 69 | #define HAVE_USB_PULLUP_CONTROL 1 70 | #endif 71 | #ifndef USB_PULLUP_GPIO_PORT 72 | #define USB_PULLUP_GPIO_PORT GPIOC 73 | #endif 74 | #ifndef USB_PULLUP_GPIO_PIN 75 | #define USB_PULLUP_GPIO_PIN GPIO11 76 | #endif 77 | #ifndef USB_PULLUP_ACTIVE_HIGH 78 | #define USB_PULLUP_ACTIVE_HIGH 0 79 | #endif 80 | #ifndef USB_PULLUP_OPEN_DRAIN 81 | #define USB_PULLUP_OPEN_DRAIN 1 82 | #endif 83 | 84 | #ifndef USES_GPIOA 85 | #define USES_GPIOA 1 86 | #endif 87 | #ifndef USES_GPIOB 88 | #define USES_GPIOB 0 89 | #endif 90 | #ifndef USES_GPIOC 91 | #define USES_GPIOC 1 92 | #endif 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/dapboot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include "dapboot.h" 23 | #include "target.h" 24 | #include "config.h" 25 | #include "usb_conf.h" 26 | #include "dfu.h" 27 | #include "webusb.h" 28 | #include "winusb.h" 29 | 30 | static inline void __set_MSP(uint32_t topOfMainStack) { 31 | asm("msr msp, %0" : : "r" (topOfMainStack)); 32 | } 33 | 34 | bool validate_application(void) { 35 | return ((uint32_t)(APP_INITIAL_STACK) & 0x2FFE0000) == 0x20000000; 36 | } 37 | 38 | static void jump_to_application(void) __attribute__ ((noreturn)); 39 | 40 | static void jump_to_application(void) { 41 | 42 | /* Use the application's vector table */ 43 | if (APP_RELOCATE_VECTORS) 44 | target_relocate_vector_table(); 45 | 46 | /* Do any necessary early setup for the application */ 47 | target_pre_main(); 48 | 49 | /* Initialize the application's stack pointer */ 50 | __set_MSP((uint32_t)(APP_INITIAL_STACK)); 51 | 52 | /* Jump to the application entry point */ 53 | APP_ENTRY_POINT(); 54 | 55 | while (1); 56 | } 57 | 58 | int main(void) { 59 | /* Setup clocks */ 60 | target_clock_setup(); 61 | 62 | /* Initialize GPIO/LEDs if needed */ 63 | target_gpio_setup(); 64 | 65 | if (target_get_force_bootloader() || !validate_application()) { 66 | /* Setup USB */ 67 | { 68 | char serial[USB_SERIAL_NUM_LENGTH+1]; 69 | serial[0] = '\0'; 70 | target_get_serial_number(serial, USB_SERIAL_NUM_LENGTH); 71 | usb_set_serial_number(serial); 72 | } 73 | 74 | usbd_device* usbd_dev = usb_setup(); 75 | dfu_setup(usbd_dev, validate_application, NULL, NULL); 76 | webusb_setup(usbd_dev); 77 | winusb_setup(usbd_dev); 78 | target_post_setup(); 79 | 80 | while (1) { 81 | usbd_poll(usbd_dev); 82 | } 83 | } else { 84 | jump_to_application(); 85 | } 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /src/stm32f103/stm32f1.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Generic linker script for STM32 targets using libopencm3. */ 21 | 22 | /* Memory regions must be defined in the ld script which includes this one. */ 23 | 24 | /* Enforce emmition of the vector table. */ 25 | EXTERN (vector_table) 26 | 27 | /* Define the entry point of the output file. */ 28 | ENTRY(reset_handler) 29 | 30 | /* Define sections. */ 31 | SECTIONS 32 | { 33 | .vectors : { 34 | *(.vectors) /* Vector table */ 35 | } >vectors 36 | 37 | .text : { 38 | *(.text*) /* Program code */ 39 | . = ALIGN(4); 40 | *(.rodata*) /* Read-only data */ 41 | . = ALIGN(4); 42 | } >rom 43 | 44 | /* C++ Static constructors/destructors, also used for __attribute__ 45 | * ((constructor)) and the likes */ 46 | .preinit_array : { 47 | . = ALIGN(4); 48 | __preinit_array_start = .; 49 | KEEP (*(.preinit_array)) 50 | __preinit_array_end = .; 51 | } >rom 52 | .init_array : { 53 | . = ALIGN(4); 54 | __init_array_start = .; 55 | KEEP (*(SORT(.init_array.*))) 56 | KEEP (*(.init_array)) 57 | __init_array_end = .; 58 | } >rom 59 | .fini_array : { 60 | . = ALIGN(4); 61 | __fini_array_start = .; 62 | KEEP (*(.fini_array)) 63 | KEEP (*(SORT(.fini_array.*))) 64 | __fini_array_end = .; 65 | } >rom 66 | 67 | /* 68 | * Another section used by C++ stuff, appears when using newlib with 69 | * 64bit (long long) printf support 70 | */ 71 | .ARM.extab : { 72 | *(.ARM.extab*) 73 | } >rom 74 | .ARM.exidx : { 75 | __exidx_start = .; 76 | *(.ARM.exidx*) 77 | __exidx_end = .; 78 | } >rom 79 | 80 | . = ALIGN(4); 81 | _etext = .; 82 | 83 | .data : { 84 | _data = .; 85 | *(.data*) /* Read-write initialized data */ 86 | . = ALIGN(4); 87 | _edata = .; 88 | } >ram AT >rom 89 | _data_loadaddr = LOADADDR(.data); 90 | 91 | .bss : { 92 | *(.bss*) /* Read-write zero initialized data */ 93 | *(COMMON) 94 | . = ALIGN(4); 95 | _ebss = .; 96 | } >ram 97 | 98 | /* 99 | * The .eh_frame section appears to be used for C++ exception handling. 100 | * You may need to fix this if you're using C++. 101 | */ 102 | /DISCARD/ : { *(.eh_frame) } 103 | 104 | . = ALIGN(4); 105 | end = .; 106 | } 107 | 108 | PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); 109 | 110 | -------------------------------------------------------------------------------- /src/stm32l1/stm32l1-base.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the libopencm3 project. 3 | * 4 | * Copyright (C) 2009 Uwe Hermann 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Generic linker script for STM32 targets using libopencm3. */ 21 | 22 | /* Memory regions must be defined in the ld script which includes this one. */ 23 | 24 | /* Enforce emmition of the vector table. */ 25 | EXTERN (vector_table) 26 | 27 | /* Define the entry point of the output file. */ 28 | ENTRY(reset_handler) 29 | 30 | /* Define sections. */ 31 | SECTIONS 32 | { 33 | .vectors : { 34 | *(.vectors) /* Vector table */ 35 | } >vectors 36 | 37 | .text : { 38 | *(.text*) /* Program code */ 39 | . = ALIGN(4); 40 | *(.rodata*) /* Read-only data */ 41 | . = ALIGN(4); 42 | } >rom 43 | 44 | /* C++ Static constructors/destructors, also used for __attribute__ 45 | * ((constructor)) and the likes */ 46 | .preinit_array : { 47 | . = ALIGN(4); 48 | __preinit_array_start = .; 49 | KEEP (*(.preinit_array)) 50 | __preinit_array_end = .; 51 | } >rom 52 | .init_array : { 53 | . = ALIGN(4); 54 | __init_array_start = .; 55 | KEEP (*(SORT(.init_array.*))) 56 | KEEP (*(.init_array)) 57 | __init_array_end = .; 58 | } >rom 59 | .fini_array : { 60 | . = ALIGN(4); 61 | __fini_array_start = .; 62 | KEEP (*(.fini_array)) 63 | KEEP (*(SORT(.fini_array.*))) 64 | __fini_array_end = .; 65 | } >rom 66 | 67 | /* 68 | * Another section used by C++ stuff, appears when using newlib with 69 | * 64bit (long long) printf support 70 | */ 71 | .ARM.extab : { 72 | *(.ARM.extab*) 73 | } >rom 74 | .ARM.exidx : { 75 | __exidx_start = .; 76 | *(.ARM.exidx*) 77 | __exidx_end = .; 78 | } >rom 79 | 80 | . = ALIGN(4); 81 | _etext = .; 82 | 83 | .data : { 84 | _data = .; 85 | *(.data*) /* Read-write initialized data */ 86 | *(.ramtext*) /* code, that needs to be in ram */ 87 | . = ALIGN(4); 88 | _edata = .; 89 | } >ram AT >rom 90 | _data_loadaddr = LOADADDR(.data); 91 | 92 | .bss : { 93 | *(.bss*) /* Read-write zero initialized data */ 94 | *(COMMON) 95 | . = ALIGN(4); 96 | _ebss = .; 97 | } >ram 98 | 99 | /* 100 | * The .eh_frame section appears to be used for C++ exception handling. 101 | * You may need to fix this if you're using C++. 102 | */ 103 | /DISCARD/ : { *(.eh_frame) } 104 | 105 | . = ALIGN(4); 106 | end = .; 107 | } 108 | 109 | PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); 110 | 111 | -------------------------------------------------------------------------------- /src/stm32f103/skrminie3v2/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2021, Dennis Marttinen 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef CONFIG_H_INCLUDED 20 | #define CONFIG_H_INCLUDED 21 | 22 | #ifndef APP_BASE_ADDRESS 23 | #define APP_BASE_ADDRESS (0x08000000 + BOOTLOADER_OFFSET) 24 | #endif 25 | #ifndef FLASH_PAGE_SIZE 26 | /* The BTT SKR MINI E3 V2.0 uses an STM32F103RC with 256 KiB of flash and 2 KiB pages */ 27 | #define FLASH_PAGE_SIZE 2048 28 | #endif 29 | #ifndef DFU_UPLOAD_AVAILABLE 30 | #define DFU_UPLOAD_AVAILABLE 1 31 | #endif 32 | #ifndef DFU_DOWNLOAD_AVAILABLE 33 | #define DFU_DOWNLOAD_AVAILABLE 1 34 | #endif 35 | #ifndef DFU_WILL_DETACH 36 | #define DFU_WILL_DETACH 0 37 | #endif 38 | 39 | /* STATUS LED */ 40 | #ifndef HAVE_LED 41 | #define HAVE_LED 1 42 | #endif 43 | #ifndef LED_OPEN_DRAIN 44 | #define LED_OPEN_DRAIN 0 45 | #endif 46 | #ifndef LED_GPIO_PORT 47 | #define LED_GPIO_PORT GPIOA 48 | #endif 49 | #ifndef LED_GPIO_PIN 50 | #define LED_GPIO_PIN GPIO13 51 | #endif 52 | 53 | /* Display encoder button (BTN-ENC) on PA15, no external pullup */ 54 | #ifndef HAVE_BUTTON 55 | #define HAVE_BUTTON 1 56 | #endif 57 | #ifndef BUTTON_ACTIVE_HIGH 58 | #define BUTTON_ACTIVE_HIGH 0 59 | #endif 60 | #ifndef BUTTON_GPIO_PORT 61 | #define BUTTON_GPIO_PORT GPIOA 62 | #endif 63 | #ifndef BUTTON_GPIO_PIN 64 | #define BUTTON_GPIO_PIN GPIO15 65 | #endif 66 | #ifndef BUTTON_USES_PULL 67 | #define BUTTON_USES_PULL 1 68 | #endif 69 | #ifndef BUTTON_SAMPLE_DELAY_CYCLES 70 | #define BUTTON_SAMPLE_DELAY_CYCLES 1440000 71 | #endif 72 | 73 | #ifndef HAVE_USB_PULLUP_CONTROL 74 | #define HAVE_USB_PULLUP_CONTROL 1 75 | #endif 76 | #ifndef USB_PULLUP_GPIO_PORT 77 | #define USB_PULLUP_GPIO_PORT GPIOA 78 | #endif 79 | #ifndef USB_PULLUP_GPIO_PIN 80 | #define USB_PULLUP_GPIO_PIN GPIO14 81 | #endif 82 | #ifndef USB_PULLUP_ACTIVE_HIGH 83 | #define USB_PULLUP_ACTIVE_HIGH 0 84 | #endif 85 | #ifndef USB_PULLUP_OPEN_DRAIN 86 | #define USB_PULLUP_OPEN_DRAIN 1 87 | #endif 88 | 89 | #ifndef USES_GPIOA 90 | #define USES_GPIOA 1 91 | #endif 92 | 93 | /* For stm32duino bootloader compatibility, the following options enable bootloader flashing using Klipper: 94 | * https://github.com/Klipper3d/klipper/blob/6d48adf9ef5d17632acf53a7e3a07964f6cfd642/src/stm32/stm32f1.c#L238 */ 95 | #ifndef REG_BOOT 96 | #define REG_BOOT BKP10 97 | #endif 98 | 99 | #ifndef CMD_BOOT 100 | #define CMD_BOOT 1 101 | #endif 102 | 103 | #ifndef USB_DFU_ALTN 104 | #define USB_DFU_ALTN 2 105 | #endif 106 | 107 | #endif 108 | -------------------------------------------------------------------------------- /src/webusb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include "webusb.h" 21 | 22 | #include "config.h" 23 | #include "usb_conf.h" 24 | 25 | #ifndef LANDING_PAGE_URL 26 | #define LANDING_PAGE_URL "devanlai.github.io/webdfu/dfu-util/" 27 | #endif 28 | 29 | #define LANDING_PAGE_DESCRIPTOR_SIZE (WEBUSB_DT_URL_DESCRIPTOR_SIZE \ 30 | + sizeof(LANDING_PAGE_URL) - 1) 31 | 32 | _Static_assert((LANDING_PAGE_DESCRIPTOR_SIZE < 256), 33 | "Landing page URL is too long"); 34 | 35 | const struct webusb_platform_descriptor webusb_platform = { 36 | .bLength = WEBUSB_PLATFORM_DESCRIPTOR_SIZE, 37 | .bDescriptorType = USB_DT_DEVICE_CAPABILITY, 38 | .bDevCapabilityType = USB_DC_PLATFORM, 39 | .bReserved = 0, 40 | .platformCapabilityUUID = WEBUSB_UUID, 41 | .bcdVersion = 0x0100, 42 | .bVendorCode = WEBUSB_VENDOR_CODE, 43 | .iLandingPage = 1 44 | }; 45 | 46 | static const struct webusb_url_descriptor landing_url_descriptor = { 47 | .bLength = LANDING_PAGE_DESCRIPTOR_SIZE, 48 | .bDescriptorType = WEBUSB_DT_URL, 49 | .bScheme = WEBUSB_URL_SCHEME_HTTPS, 50 | .URL = LANDING_PAGE_URL 51 | }; 52 | 53 | static enum usbd_request_return_codes 54 | webusb_control_vendor_request(usbd_device *usbd_dev, 55 | struct usb_setup_data *req, 56 | uint8_t **buf, uint16_t *len, 57 | usbd_control_complete_callback* complete) { 58 | (void)complete; 59 | (void)usbd_dev; 60 | 61 | if (req->bRequest != WEBUSB_VENDOR_CODE) { 62 | return USBD_REQ_NEXT_CALLBACK; 63 | } 64 | 65 | enum usbd_request_return_codes status = USBD_REQ_NOTSUPP; 66 | switch (req->wIndex) { 67 | case WEBUSB_REQ_GET_URL: { 68 | if (req->wValue != 1) { 69 | break; 70 | } 71 | *buf = (uint8_t*)(&landing_url_descriptor); 72 | *len = landing_url_descriptor.bLength; 73 | status = USBD_REQ_HANDLED; 74 | break; 75 | } 76 | default: { 77 | status = USBD_REQ_NOTSUPP; 78 | break; 79 | } 80 | } 81 | 82 | return status; 83 | } 84 | 85 | static void webusb_set_config(usbd_device* usbd_dev, uint16_t wValue) { 86 | (void)wValue; 87 | usbd_register_control_callback( 88 | usbd_dev, 89 | USB_REQ_TYPE_VENDOR | USB_REQ_TYPE_DEVICE, 90 | USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, 91 | webusb_control_vendor_request); 92 | } 93 | 94 | void webusb_setup(usbd_device* usbd_dev) { 95 | usbd_register_set_config_callback(usbd_dev, webusb_set_config); 96 | } 97 | -------------------------------------------------------------------------------- /src/winusb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include "winusb.h" 21 | 22 | #include "config.h" 23 | #include "usb_conf.h" 24 | 25 | static const struct winusb_compatible_id_descriptor winusb_wcid = { 26 | .dwLength = (WINUSB_COMPATIBLE_ID_HEADER_SIZE + 27 | 1*WINUSB_COMPATIBLE_ID_FUNCTION_SECTION_SIZE), 28 | .bcdVersion = 0x0100, 29 | .wIndex = 0x0004, 30 | .bNumSections = 1, 31 | .reserved = { 0, 0, 0, 0, 0, 0, 0 }, 32 | .functions = { 33 | { 34 | .bInterfaceNumber = 0, 35 | .reserved0 = { 1 }, 36 | .compatibleId = "WINUSB", 37 | .subCompatibleId = "", 38 | .reserved1 = { 0, 0, 0, 0, 0, 0} 39 | }, 40 | } 41 | }; 42 | 43 | static enum usbd_request_return_codes 44 | winusb_control_vendor_request(usbd_device *usbd_dev, 45 | struct usb_setup_data *req, 46 | uint8_t **buf, uint16_t *len, 47 | usbd_control_complete_callback* complete) { 48 | (void)complete; 49 | (void)usbd_dev; 50 | 51 | if (req->bRequest != WINUSB_MS_VENDOR_CODE) { 52 | return USBD_REQ_NEXT_CALLBACK; 53 | } 54 | 55 | enum usbd_request_return_codes status = USBD_REQ_NOTSUPP; 56 | if (((req->bmRequestType & USB_REQ_TYPE_RECIPIENT) == USB_REQ_TYPE_DEVICE) && 57 | (req->wIndex == WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR)) { 58 | *buf = (uint8_t*)(&winusb_wcid); 59 | if (*len > winusb_wcid.dwLength) { 60 | *len = winusb_wcid.dwLength; 61 | } 62 | status = USBD_REQ_HANDLED; 63 | } else if (((req->bmRequestType & USB_REQ_TYPE_RECIPIENT) == USB_REQ_TYPE_INTERFACE) && 64 | (req->wIndex == WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR)) { 65 | status = USBD_REQ_NOTSUPP; 66 | } else { 67 | status = USBD_REQ_NOTSUPP; 68 | } 69 | 70 | return status; 71 | } 72 | 73 | static void winusb_set_config(usbd_device* usbd_dev, uint16_t wValue) { 74 | (void)wValue; 75 | usbd_register_control_callback( 76 | usbd_dev, 77 | USB_REQ_TYPE_VENDOR, 78 | USB_REQ_TYPE_TYPE, 79 | winusb_control_vendor_request); 80 | } 81 | 82 | void winusb_setup(usbd_device* usbd_dev) { 83 | static const char msft_extra_string[] = {'M', 'S', 'F', 'T', '1', '0', '0', WINUSB_MS_VENDOR_CODE, '\0'}; 84 | usbd_register_extra_string(usbd_dev, 0xEE, msft_extra_string); 85 | usbd_register_set_config_callback(usbd_dev, winusb_set_config); 86 | 87 | /* Windows probes the compatible ID before setting the configuration, 88 | so also register the callback now */ 89 | 90 | usbd_register_control_callback( 91 | usbd_dev, 92 | USB_REQ_TYPE_VENDOR, 93 | USB_REQ_TYPE_TYPE, 94 | winusb_control_vendor_request); 95 | } 96 | -------------------------------------------------------------------------------- /src/targets.mk: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2016, Devan Lai 2 | ## 3 | ## Permission to use, copy, modify, and/or distribute this software 4 | ## for any purpose with or without fee is hereby granted, provided 5 | ## that the above copyright notice and this permission notice 6 | ## appear in all copies. 7 | ## 8 | ## THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 9 | ## WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 10 | ## WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 11 | ## AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 12 | ## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | ## LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 14 | ## NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 | ## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | ifeq ($(TARGET),STM32F103) 18 | TARGET_COMMON_DIR := ./stm32f103 19 | TARGET_SPEC_DIR := ./stm32f103/generic 20 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 21 | ARCH = STM32F1 22 | endif 23 | ifeq ($(TARGET),BLUEPILL) 24 | TARGET_COMMON_DIR := ./stm32f103 25 | TARGET_SPEC_DIR := ./stm32f103/bluepill 26 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 27 | ARCH = STM32F1 28 | endif 29 | ifeq ($(TARGET),BLUEPILL_HIGH) 30 | TARGET_COMMON_DIR := ./stm32f103 31 | TARGET_SPEC_DIR := ./stm32f103/bluepill 32 | LDSCRIPT := ./stm32f103/stm32f103x8_high.ld 33 | ARCH = STM32F1 34 | DEFS += -DBOOTLOADER_HIGH 35 | endif 36 | ifeq ($(TARGET),BLUEPILL_HIGH_128) 37 | TARGET_COMMON_DIR := ./stm32f103 38 | TARGET_SPEC_DIR := ./stm32f103/bluepill 39 | LDSCRIPT := ./stm32f103/stm32f103xb_high.ld 40 | ARCH = STM32F1 41 | DEFS += -DBOOTLOADER_HIGH 42 | endif 43 | ifeq ($(TARGET),MAPLEMINI) 44 | TARGET_COMMON_DIR := ./stm32f103 45 | TARGET_SPEC_DIR := ./stm32f103/maplemini 46 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 47 | ARCH = STM32F1 48 | endif 49 | ifeq ($(TARGET),MAPLEMINI_HIGH) 50 | TARGET_COMMON_DIR := ./stm32f103 51 | TARGET_SPEC_DIR := ./stm32f103/maplemini 52 | LDSCRIPT := ./stm32f103/stm32f103x8_high.ld 53 | ARCH = STM32F1 54 | DEFS += -DBOOTLOADER_HIGH 55 | endif 56 | ifeq ($(TARGET),MAPLEMINI_HIGH_128) 57 | TARGET_COMMON_DIR := ./stm32f103 58 | TARGET_SPEC_DIR := ./stm32f103/maplemini 59 | LDSCRIPT := ./stm32f103/stm32f103xb_high.ld 60 | ARCH = STM32F1 61 | DEFS += -DBOOTLOADER_HIGH 62 | endif 63 | ifeq ($(TARGET),STLINK) 64 | TARGET_COMMON_DIR := ./stm32f103 65 | TARGET_SPEC_DIR := ./stm32f103/stlink 66 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 67 | ARCH = STM32F1 68 | endif 69 | ifeq ($(TARGET),STLINK_HIGH) 70 | TARGET_COMMON_DIR := ./stm32f103 71 | TARGET_SPEC_DIR := ./stm32f103/stlink 72 | LDSCRIPT := ./stm32f103/stm32f103x8_high.ld 73 | ARCH = STM32F1 74 | DEFS += -DBOOTLOADER_HIGH 75 | endif 76 | ifeq ($(TARGET),STLINK_HIGH_128) 77 | TARGET_COMMON_DIR := ./stm32f103 78 | TARGET_SPEC_DIR := ./stm32f103/stlink 79 | LDSCRIPT := ./stm32f103/stm32f103xb_high.ld 80 | ARCH = STM32F1 81 | DEFS += -DBOOTLOADER_HIGH 82 | endif 83 | ifeq ($(TARGET),OLIMEXSTM32H103) 84 | TARGET_COMMON_DIR := ./stm32f103 85 | TARGET_SPEC_DIR := ./stm32f103/olimexstm32h103 86 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 87 | ARCH = STM32F1 88 | endif 89 | ifeq ($(TARGET),OLIMEXSTM32H103_HIGH) 90 | TARGET_COMMON_DIR := ./stm32f103 91 | TARGET_SPEC_DIR := ./stm32f103/olimexstm32h103 92 | LDSCRIPT := ./stm32f103/stm32f103x8_high.ld 93 | ARCH = STM32F1 94 | DEFS += -DBOOTLOADER_HIGH 95 | endif 96 | ifeq ($(TARGET),OLIMEXSTM32H103_HIGH_128) 97 | TARGET_COMMON_DIR := ./stm32f103 98 | TARGET_SPEC_DIR := ./stm32f103/olimexstm32h103 99 | LDSCRIPT := ./stm32f103/stm32f103xb_high.ld 100 | ARCH = STM32F1 101 | DEFS += -DBOOTLOADER_HIGH 102 | endif 103 | ifeq ($(TARGET),BLUEPILLPLUSSTM32) 104 | TARGET_COMMON_DIR := ./stm32f103 105 | TARGET_SPEC_DIR := ./stm32f103/bluepillplus 106 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 107 | ARCH = STM32F1 108 | endif 109 | ifeq ($(TARGET),BLUEPILLPLUSSTM32_HIGH) 110 | TARGET_COMMON_DIR := ./stm32f103 111 | TARGET_SPEC_DIR := ./stm32f103/bluepillplus 112 | LDSCRIPT := ./stm32f103/stm32f103x8_high.ld 113 | ARCH = STM32F1 114 | DEFS += -DBOOTLOADER_HIGH 115 | endif 116 | ifeq ($(TARGET),BLUEPILLPLUSSTM32_HIGH_128) 117 | TARGET_COMMON_DIR := ./stm32f103 118 | TARGET_SPEC_DIR := ./stm32f103/bluepillplus 119 | LDSCRIPT := ./stm32f103/stm32f103xb_high.ld 120 | ARCH = STM32F1 121 | DEFS += -DBOOTLOADER_HIGH 122 | endif 123 | ifeq ($(TARGET),BLUEPILLPLUSGD32) 124 | TARGET_COMMON_DIR := ./stm32f103 125 | TARGET_SPEC_DIR := ./stm32f103/bluepillplus-gd32 126 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 127 | ARCH = STM32F1 128 | endif 129 | ifeq ($(TARGET),BTTSKRMINIE3V2) 130 | TARGET_COMMON_DIR := ./stm32f103 131 | TARGET_SPEC_DIR := ./stm32f103/skrminie3v2 132 | LDSCRIPT := ./stm32f103/stm32f103x8.ld 133 | ARCH = STM32F1 134 | endif 135 | ifeq ($(TARGET),BTTSKRMINIE3V2_HIGH_256) 136 | TARGET_COMMON_DIR := ./stm32f103 137 | TARGET_SPEC_DIR := ./stm32f103/skrminie3v2 138 | LDSCRIPT := ./stm32f103/stm32f103xc_high.ld 139 | ARCH = STM32F1 140 | DEFS += -DBOOTLOADER_HIGH 141 | endif 142 | ifeq ($(TARGET),STM32L1_GENERIC) 143 | TARGET_COMMON_DIR := ./stm32l1 144 | TARGET_SPEC_DIR := ./stm32l1/generic 145 | LDSCRIPT := ./stm32l1/stm32l1-standard.ld 146 | ARCH = STM32L1 147 | DEFS += -DNDEBUG 148 | endif 149 | 150 | ifndef ARCH 151 | $(error Unknown target $(TARGET)) 152 | endif 153 | -------------------------------------------------------------------------------- /src/usb_conf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include "target.h" 25 | #include "webusb.h" 26 | 27 | #include "config.h" 28 | #include "usb_conf.h" 29 | #include "dfu.h" 30 | 31 | static const struct usb_device_descriptor dev = { 32 | .bLength = USB_DT_DEVICE_SIZE, 33 | .bDescriptorType = USB_DT_DEVICE, 34 | .bcdUSB = 0x0210, 35 | .bDeviceClass = 0, 36 | .bDeviceSubClass = 0, 37 | .bDeviceProtocol = 0, 38 | .bMaxPacketSize0 = 64, 39 | .idVendor = USB_VID, 40 | .idProduct = USB_PID, 41 | .bcdDevice = 0x0111, 42 | .iManufacturer = 1, 43 | .iProduct = 2, 44 | .iSerialNumber = 3, 45 | .bNumConfigurations = 1, 46 | }; 47 | 48 | // Macro to create a dummy (no-op) USB interface descriptor with the given alternate setting 49 | #define ALT_DUMMY(N) { \ 50 | .bLength = USB_DT_INTERFACE_SIZE, \ 51 | .bDescriptorType = USB_DT_INTERFACE, \ 52 | .bInterfaceNumber = INTF_DFU, \ 53 | .bAlternateSetting = (N), \ 54 | .bNumEndpoints = 0, \ 55 | .bInterfaceClass = 0, \ 56 | .bInterfaceSubClass = 0, \ 57 | .bInterfaceProtocol = 0, \ 58 | .iInterface = 0, \ 59 | .endpoint = NULL, \ 60 | .extra = NULL, \ 61 | .extralen = 0, \ 62 | }, 63 | 64 | // Functionality for creating repetitive ALT_DUMMY structs with an increasing count during compile time. 65 | // It doesn't look very nice, but C doesn't allow loops in preprocessor macros, so this needs to be hard-coded. 66 | #define ALT0 67 | #define ALT1 ALT_DUMMY(0) 68 | #define ALT2 ALT1 ALT_DUMMY(1) 69 | #define ALT3 ALT2 ALT_DUMMY(2) 70 | #define ALT4 ALT3 ALT_DUMMY(3) 71 | #define ALT5 ALT4 ALT_DUMMY(4) 72 | #define ALTW(n) ALT##n // Wrapper macro for expansion 73 | #define ALTN(n) ALTW(n) 74 | 75 | static const struct usb_interface_descriptor altsettings[] = { 76 | ALTN(USB_DFU_ALTN) // Prepend USB_DFU_ALTN dummy USB interface descriptors to "pad" the real one 77 | { 78 | .bLength = USB_DT_INTERFACE_SIZE, 79 | .bDescriptorType = USB_DT_INTERFACE, 80 | .bInterfaceNumber = INTF_DFU, 81 | .bAlternateSetting = USB_DFU_ALTN, 82 | .bNumEndpoints = 0, 83 | .bInterfaceClass = 0xFE, 84 | .bInterfaceSubClass = 1, 85 | .bInterfaceProtocol = 2, 86 | .iInterface = 4, 87 | 88 | .endpoint = NULL, 89 | 90 | .extra = &dfu_function, 91 | .extralen = sizeof(dfu_function), 92 | } 93 | }; 94 | 95 | // Tracking this is mandatory if exposing multiple altsettings 96 | static uint8_t cur_altsetting = 0; 97 | 98 | static const struct usb_interface interfaces[] = { 99 | /* DFU interface */ 100 | { 101 | .cur_altsetting = &cur_altsetting, 102 | .num_altsetting = USB_DFU_ALTN + 1, 103 | .altsetting = (const struct usb_interface_descriptor*)&altsettings, 104 | } 105 | }; 106 | 107 | static const struct usb_config_descriptor config = { 108 | .bLength = USB_DT_CONFIGURATION_SIZE, 109 | .bDescriptorType = USB_DT_CONFIGURATION, 110 | .wTotalLength = 0, 111 | .bNumInterfaces = sizeof(interfaces)/sizeof(struct usb_interface), 112 | .bConfigurationValue = 1, 113 | .iConfiguration = 0, 114 | .bmAttributes = 0xC0, 115 | .bMaxPower = 0x32, 116 | 117 | .interface = interfaces, 118 | }; 119 | 120 | static const struct usb_device_capability_descriptor* capabilities[] = { 121 | (const struct usb_device_capability_descriptor*)&webusb_platform, 122 | }; 123 | 124 | static const struct usb_bos_descriptor bos = { 125 | .bLength = USB_DT_BOS_SIZE, 126 | .bDescriptorType = USB_DT_BOS, 127 | .wTotalLength = USB_DT_BOS_SIZE + sizeof(webusb_platform), 128 | .bNumDeviceCaps = sizeof(capabilities)/sizeof(capabilities[0]), 129 | .capabilities = capabilities 130 | }; 131 | 132 | static char serial_number[USB_SERIAL_NUM_LENGTH+1]; 133 | 134 | static const char *usb_strings[] = { 135 | USB_VENDOR_STRING, 136 | USB_PRODUCT_STRING, 137 | serial_number, 138 | USB_INTERFACE_STRING 139 | }; 140 | 141 | /* Buffer to be used for control requests. */ 142 | static uint8_t usbd_control_buffer[USB_CONTROL_BUF_SIZE] __attribute__ ((aligned (2))); 143 | 144 | void usb_set_serial_number(const char* serial) { 145 | serial_number[0] = '\0'; 146 | if (serial) { 147 | strncpy(serial_number, serial, USB_SERIAL_NUM_LENGTH); 148 | serial_number[USB_SERIAL_NUM_LENGTH] = '\0'; 149 | } 150 | } 151 | 152 | usbd_device* usb_setup(void) { 153 | int num_strings = sizeof(usb_strings)/sizeof(const char*); 154 | 155 | const usbd_driver* driver = target_usb_init(); 156 | usbd_device* usbd_dev = usbd_init(driver, &dev, &config, &bos, 157 | usb_strings, num_strings, 158 | usbd_control_buffer, sizeof(usbd_control_buffer)); 159 | 160 | return usbd_dev; 161 | } 162 | -------------------------------------------------------------------------------- /src/winusb_defs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #ifndef WINUSB_DEFS_H_INCLUDED 20 | #define WINUSB_DEFS_H_INCLUDED 21 | 22 | #include 23 | 24 | /* Microsoft OS 1.0 descriptors */ 25 | 26 | /* Extended Compat ID OS Feature Descriptor Specification */ 27 | #define WINUSB_REQ_GET_COMPATIBLE_ID_FEATURE_DESCRIPTOR 0x04 28 | #define WINUSB_REQ_GET_EXTENDED_PROPERTIES_OS_FEATURE_DESCRIPTOR 0x05 29 | 30 | /* Table 2. Function Section */ 31 | struct winusb_compatible_id_function_section { 32 | uint8_t bInterfaceNumber; 33 | uint8_t reserved0[1]; 34 | const char compatibleId[8]; 35 | const char subCompatibleId[8]; 36 | uint8_t reserved1[6]; 37 | } __attribute__((packed)); 38 | 39 | #define WINUSB_COMPATIBLE_ID_FUNCTION_SECTION_SIZE 24 40 | 41 | /* Table 1. Header Section */ 42 | struct winusb_compatible_id_descriptor { 43 | uint32_t dwLength; 44 | uint16_t bcdVersion; 45 | uint16_t wIndex; 46 | uint8_t bNumSections; 47 | uint8_t reserved[7]; 48 | struct winusb_compatible_id_function_section functions[]; 49 | } __attribute__((packed)); 50 | 51 | #define WINUSB_COMPATIBLE_ID_HEADER_SIZE 16 52 | 53 | /* Microsoft OS 2.0 Descriptors Specification */ 54 | 55 | /* Table 8. Microsoft OS 2.0 descriptor wIndex values */ 56 | #define WINUSB_REQ_MS_OS_20_DESCRIPTOR_INDEX 0x07 57 | #define WINUSB_REQ_MS_OS_20_SET_ALT_ENUMERATION 0x08 58 | 59 | /* Table 9. Microsoft OS 2.0 descriptor wDescriptorType values */ 60 | #define WINUSB_DT_MS_OS_20_SET_HEADER_DESCRIPTOR 0x00 61 | #define WINUSB_DT_MS_OS_20_SUBSET_HEADER_CONFIGURATION 0x01 62 | #define WINUSB_DT_MS_OS_20_SUBSET_HEADER_FUNCTION 0x02 63 | #define WINUSB_DT_MS_OS_20_FEATURE_COMPATIBLE_ID 0x03 64 | #define WINUSB_DT_MS_OS_20_FEATURE_REG_PROPERTY 0x04 65 | #define WINUSB_DT_MS_OS_20_FEATURE_MIN_RESUME_TIME 0x05 66 | #define WINUSB_DT_MS_OS_20_FEATURE_MODEL_ID 0x06 67 | #define WINUSB_DT_MS_OS_20_FEATURE_CCGP_DEVICE 0x07 68 | 69 | /* Table 3. Microsoft OS 2.0 descriptor platform capability UUID */ 70 | #define WINUSB_OS_20_UUID {0xDF, 0x60, 0xDD, 0xD8, 0x89, 0x45, 0xC7, 0x4C, 0x9C, 0xD2, 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F} 71 | 72 | /* Table 5. Descriptor set information structure */ 73 | struct winusb_descriptor_set_information { 74 | uint32_t dwWindowsVersion; 75 | uint16_t wMSOSDescriptorSetTotalLength; 76 | uint8_t bMS_VendorCode; 77 | uint8_t bAltEnumCode; 78 | } __attribute__((packed)); 79 | 80 | /* Table 4. Microsoft OS 2.0 platform capability descriptor header */ 81 | struct winusb_platform_descriptor { 82 | uint8_t bLength; 83 | uint8_t bDescriptorType; 84 | uint8_t bDevCapabilityType; 85 | uint8_t bReserved; 86 | uint8_t platformCapabilityUUID[16]; 87 | struct winusb_descriptor_set_information descriptor_set_information[]; 88 | } __attribute__((packed)); 89 | 90 | /* Table 10. Microsoft OS 2.0 descriptor set header */ 91 | struct winusb_descriptor_set_header { 92 | uint16_t wLength; 93 | uint16_t wDescriptorType; 94 | uint32_t dwWindowsVersion; 95 | uint16_t wTotalLength; 96 | } __attribute__((packed)); 97 | 98 | /* Table 11. Configuration subset header */ 99 | struct winusb_configuration_subset_header { 100 | uint16_t wLength; 101 | uint16_t wDescriptorType; 102 | uint8_t bConfigurationValue; 103 | uint8_t bReserved; 104 | uint16_t wTotalLength; 105 | } __attribute__((packed)); 106 | 107 | /* Table 12. Function subset header */ 108 | struct winusb_function_subset_header { 109 | uint16_t wLength; 110 | uint16_t wDescriptorType; 111 | uint8_t bFirstInterface; 112 | uint8_t bReserved; 113 | uint16_t wSubsetLength; 114 | } __attribute__((packed)); 115 | 116 | /* Table 13. Microsoft OS 2.0 compatible ID descriptor */ 117 | struct winusb_20_compatible_id_feature_descriptor { 118 | uint16_t wLength; 119 | uint16_t wDescriptorType; 120 | const char compatibleId[8]; 121 | const char subCompatibleId[8];; 122 | } __attribute__((packed)); 123 | 124 | /* Table 15. wPropertyDataType values for the Microsoft OS 2.0 registry property descriptor */ 125 | #define WINUSB_PROP_DATA_TYPE_REG_SZ 1 126 | #define WINUSB_PROP_DATA_TYPE_REG_EXPAND_SZ 2 127 | #define WINUSB_PROP_DATA_TYPE_REG_BINARY 3 128 | #define WINUSB_PROP_DATA_TYPE_REG_DWORD_LITTLE_ENDIAN 4 129 | #define WINUSB_PROP_DATA_TYPE_REG_DWORD_BIG_ENDIAN 5 130 | #define WINUSB_PROP_DATA_TYPE_REG_LINK 6 131 | #define WINUSB_PROP_DATA_TYPE_REG_REG_MULTI_SZ 7 132 | 133 | /* Table 16. Microsoft OS 2.0 minimum USB recovery time descriptor */ 134 | struct winusb_minimum_recovery_time_descriptor { 135 | uint16_t wLength; 136 | uint16_t wDescriptorType; 137 | uint8_t bResumeRecoveryTime; 138 | uint8_t bResumeSignalingTime; 139 | } __attribute__((packed)); 140 | 141 | /* Table 16. Microsoft OS 2.0 model ID descriptor */ 142 | struct winusb_model_id_descriptor { 143 | uint16_t wLength; 144 | uint16_t wDescriptorType; 145 | uint8_t modelId[16]; 146 | } __attribute__((packed)); 147 | 148 | /* Table 17. Microsoft OS 2.0 CCGP device descriptor */ 149 | struct winusb_ccgp_device_descriptor { 150 | uint16_t wLength; 151 | uint16_t wDescriptorType; 152 | } __attribute__((packed)); 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /release.Makefile: -------------------------------------------------------------------------------- 1 | ## Copyright (c) 2017, Devan Lai 2 | ## 3 | ## Permission to use, copy, modify, and/or distribute this software 4 | ## for any purpose with or without fee is hereby granted, provided 5 | ## that the above copyright notice and this permission notice 6 | ## appear in all copies. 7 | ## 8 | ## THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 9 | ## WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 10 | ## WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 11 | ## AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 12 | ## CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 | ## LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 14 | ## NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 15 | ## CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 | 17 | # This Makefile builds all official targets and places the firmware 18 | # bin files in the build/ directory. 19 | # 20 | # For normal development, use the Makefile in the src/ directory. 21 | 22 | # Be silent per default, but 'make V=1' will show all compiler calls. 23 | ifneq ($(V),1) 24 | Q := @ 25 | NULL := 2>/dev/null 26 | MAKE := $(MAKE) --no-print-directory 27 | endif 28 | export V 29 | 30 | BUILD_DIR ?= ./build 31 | 32 | all: dapboot-bluepill.bin \ 33 | dapboot-maplemini.bin \ 34 | dapboot-stlink.bin \ 35 | dapboot-olimexstm32h103.bin \ 36 | dapboot-bluepillplusstm32.bin \ 37 | dapboot-bttskrminie3v2.bin \ 38 | dapboot-bluepill-high.bin \ 39 | dapboot-maplemini-high.bin \ 40 | dapboot-stlink-high.bin \ 41 | dapboot-olimexstm32h103-high.bin \ 42 | dapboot-bluepillplusstm32-high.bin \ 43 | dapboot-bluepill-high-128.bin \ 44 | dapboot-maplemini-high-128.bin \ 45 | dapboot-stlink-high-128.bin \ 46 | dapboot-olimexstm32h103-high-128.bin \ 47 | dapboot-bluepillplusstm32-high-128.bin \ 48 | dapboot-bttskrminie3v2-high-256.bin 49 | 50 | clean: 51 | $(Q)$(RM) $(BUILD_DIR)/*.bin 52 | $(Q)$(MAKE) -C src/ clean 53 | 54 | .PHONY = all clean 55 | 56 | $(BUILD_DIR): 57 | $(Q)mkdir -p $(BUILD_DIR) 58 | 59 | dapboot-bluepill.bin: | $(BUILD_DIR) 60 | @printf " BUILD $(@)\n" 61 | $(Q)$(MAKE) TARGET=BLUEPILL -C src/ clean 62 | $(Q)$(MAKE) TARGET=BLUEPILL -C src/ 63 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 64 | 65 | dapboot-stlink.bin: | $(BUILD_DIR) 66 | @printf " BUILD $(@)\n" 67 | $(Q)$(MAKE) TARGET=STLINK -C src/ clean 68 | $(Q)$(MAKE) TARGET=STLINK -C src/ 69 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 70 | 71 | dapboot-maplemini.bin: | $(BUILD_DIR) 72 | @printf " BUILD $(@)\n" 73 | $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ clean 74 | $(Q)$(MAKE) TARGET=MAPLEMINI -C src/ 75 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 76 | 77 | dapboot-olimexstm32h103.bin: | $(BUILD_DIR) 78 | @printf " BUILD $(@)\n" 79 | $(Q)$(MAKE) TARGET=OLIMEXSTM32H103 -C src/ clean 80 | $(Q)$(MAKE) TARGET=OLIMEXSTM32H103 -C src/ 81 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 82 | 83 | dapboot-bluepillplusstm32.bin: | $(BUILD_DIR) 84 | @printf " BUILD $(@)\n" 85 | $(Q)$(MAKE) TARGET=BLUEPILLPLUSSTM32 -C src/ clean 86 | $(Q)$(MAKE) TARGET=BLUEPILLPLUSSTM32 -C src/ 87 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 88 | 89 | dapboot-bttskrminie3v2.bin: | $(BUILD_DIR) 90 | @printf " BUILD $(@)\n" 91 | $(Q)$(MAKE) TARGET=BTTSKRMINIE3V2 -C src/ clean 92 | $(Q)$(MAKE) TARGET=BTTSKRMINIE3V2 -C src/ 93 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 94 | 95 | dapboot-bluepill-high.bin: | $(BUILD_DIR) 96 | @printf " BUILD $(@)\n" 97 | $(Q)$(MAKE) TARGET=BLUEPILL_HIGH -C src/ clean 98 | $(Q)$(MAKE) TARGET=BLUEPILL_HIGH -C src/ 99 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 100 | 101 | dapboot-stlink-high.bin: | $(BUILD_DIR) 102 | @printf " BUILD $(@)\n" 103 | $(Q)$(MAKE) TARGET=STLINK_HIGH -C src/ clean 104 | $(Q)$(MAKE) TARGET=STLINK_HIGH -C src/ 105 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 106 | 107 | dapboot-maplemini-high.bin: | $(BUILD_DIR) 108 | @printf " BUILD $(@)\n" 109 | $(Q)$(MAKE) TARGET=MAPLEMINI_HIGH -C src/ clean 110 | $(Q)$(MAKE) TARGET=MAPLEMINI_HIGH -C src/ 111 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 112 | 113 | dapboot-olimexstm32h103-high.bin: | $(BUILD_DIR) 114 | @printf " BUILD $(@)\n" 115 | $(Q)$(MAKE) TARGET=OLIMEXSTM32H103_HIGH -C src/ clean 116 | $(Q)$(MAKE) TARGET=OLIMEXSTM32H103_HIGH -C src/ 117 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 118 | 119 | dapboot-bluepillplusstm32-high.bin: | $(BUILD_DIR) 120 | @printf " BUILD $(@)\n" 121 | $(Q)$(MAKE) TARGET=BLUEPILLPLUSSTM32_HIGH -C src/ clean 122 | $(Q)$(MAKE) TARGET=BLUEPILLPLUSSTM32_HIGH -C src/ 123 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 124 | 125 | dapboot-bluepill-high-128.bin: | $(BUILD_DIR) 126 | @printf " BUILD $(@)\n" 127 | $(Q)$(MAKE) TARGET=BLUEPILL_HIGH_128 -C src/ clean 128 | $(Q)$(MAKE) TARGET=BLUEPILL_HIGH_128 -C src/ 129 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 130 | 131 | dapboot-stlink-high-128.bin: | $(BUILD_DIR) 132 | @printf " BUILD $(@)\n" 133 | $(Q)$(MAKE) TARGET=STLINK_HIGH_128 -C src/ clean 134 | $(Q)$(MAKE) TARGET=STLINK_HIGH_128 -C src/ 135 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 136 | 137 | dapboot-maplemini-high-128.bin: | $(BUILD_DIR) 138 | @printf " BUILD $(@)\n" 139 | $(Q)$(MAKE) TARGET=MAPLEMINI_HIGH_128 -C src/ clean 140 | $(Q)$(MAKE) TARGET=MAPLEMINI_HIGH_128 -C src/ 141 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 142 | 143 | dapboot-olimexstm32h103-high-128.bin: | $(BUILD_DIR) 144 | @printf " BUILD $(@)\n" 145 | $(Q)$(MAKE) TARGET=OLIMEXSTM32H103_HIGH_128 -C src/ clean 146 | $(Q)$(MAKE) TARGET=OLIMEXSTM32H103_HIGH_128 -C src/ 147 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 148 | 149 | dapboot-bluepillplusstm32-high-128.bin: | $(BUILD_DIR) 150 | @printf " BUILD $(@)\n" 151 | $(Q)$(MAKE) TARGET=BLUEPILLPLUSSTM32_HIGH_128 -C src/ clean 152 | $(Q)$(MAKE) TARGET=BLUEPILLPLUSSTM32_HIGH_128 -C src/ 153 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 154 | 155 | dapboot-bttskrminie3v2-high-256.bin: | $(BUILD_DIR) 156 | @printf " BUILD $(@)\n" 157 | $(Q)$(MAKE) TARGET=BTTSKRMINIE3V2_HIGH_256 -C src/ clean 158 | $(Q)$(MAKE) TARGET=BTTSKRMINIE3V2_HIGH_256 -C src/ 159 | $(Q)cp src/dapboot.bin $(BUILD_DIR)/$(@) 160 | -------------------------------------------------------------------------------- /src/stm32l1/target_stm32l1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 2020 - Karl Palsson 3 | * Considered to be released into the public domain, or where not available 4 | * under your choice of the following spdx identifiers: 5 | * MIT, ISC, Apache-2.0, BSD-1-Clause, BSD-2-Clause, BSD-3-Clause, 6 | * CC-BY-4.0, GPL-2.0-or-later, LGPL-2.0-or-later 7 | * Pick whatever makes your integration life easier 8 | * 9 | * STM32L1 generic target side portions for dapboot. 10 | * There's no "standard" l1 board, so you're always going 11 | * to want to edit this... 12 | */ 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "dapboot.h" 26 | #include "target.h" 27 | #include "config.h" 28 | #include "backup.h" 29 | 30 | #ifndef REG_BOOT 31 | #define REG_BOOT BKP1 32 | #endif 33 | 34 | #ifndef CMD_BOOT 35 | #define CMD_BOOT 0x544F4F42UL 36 | #endif 37 | 38 | //#define CMD_FAST_BOOT 0xfa57b007 39 | 40 | void target_clock_setup(void) { 41 | 42 | //#define MODERN_LOCM3 43 | /* Clock struct for "any" board with a 16Mhz crystal */ 44 | const struct rcc_clock_scale myclock_16m_hse = { 45 | .pll_source = RCC_CFGR_PLLSRC_HSE_CLK, 46 | .pll_mul = RCC_CFGR_PLLMUL_MUL6, 47 | .pll_div = RCC_CFGR_PLLDIV_DIV3, 48 | .hpre = RCC_CFGR_HPRE_SYSCLK_NODIV, 49 | .ppre1 = RCC_CFGR_PPRE1_HCLK_NODIV, 50 | .ppre2 = RCC_CFGR_PPRE2_HCLK_NODIV, 51 | .voltage_scale = PWR_SCALE1, 52 | .flash_waitstates = 1, 53 | .ahb_frequency = 32e6, 54 | .apb1_frequency = 32e6, 55 | .apb2_frequency = 32e6, 56 | }; 57 | 58 | rcc_clock_setup_pll(&myclock_16m_hse); 59 | } 60 | 61 | void target_gpio_setup(void) 62 | { 63 | /* TODO: if you need buttons or gpios, turn them on here */ 64 | #if HAVE_LED 65 | #endif 66 | #if HAVE_BUTTON 67 | #endif 68 | } 69 | 70 | const usbd_driver* target_usb_init(void) 71 | { 72 | rcc_periph_reset_pulse(RST_USB); 73 | 74 | /* Enable built in USB pullup on L1, note, this is out of spec on older revs! */ 75 | rcc_periph_clock_enable(RCC_SYSCFG); 76 | /* Compat for old library */ 77 | #ifndef SYSCFG_PMC_USB_PU 78 | #define SYSCFG_PMC_USB_PU (1<<0) 79 | #endif 80 | SYSCFG_PMC |= SYSCFG_PMC_USB_PU; 81 | 82 | return &st_usbfs_v1_usb_driver; 83 | } 84 | 85 | /* This implementation will always start in bootloader, unless the app 86 | * has asked it to skipp straight forwards 87 | * You may wish to fill in button handling... 88 | */ 89 | bool target_get_force_bootloader(void) 90 | { 91 | bool enter_bl = false; 92 | uint32_t cmd = backup_read(REG_BOOT); 93 | if (cmd == CMD_BOOT) { 94 | enter_bl = true; 95 | } 96 | backup_write(REG_BOOT, 0); 97 | 98 | #if HAVE_BUTTON 99 | #warning HAVE_BUTTON not implemented for L1 100 | #endif 101 | 102 | return enter_bl; 103 | } 104 | 105 | void target_get_serial_number(char* dest, size_t max_chars) 106 | { 107 | /* TODO, but not available in old locm3... 108 | assert(max_chars > 6); 109 | desig_get_unique_id_as_dfu(dest); 110 | */ 111 | desig_get_unique_id_as_string(dest, max_chars+1); 112 | } 113 | 114 | size_t target_get_max_firmware_size(void) 115 | { 116 | /* L1, unlike magical fairy land F1, tells it like it is */ 117 | /* mask is working around bug upstream for L1 */ 118 | size_t flash = desig_get_flash_size() & 0xff; 119 | size_t total = flash * 1024; 120 | #ifdef BOOTLOADER_HIGH 121 | #error bootloader high memory mode not supported on L1 122 | #endif 123 | return total - BOOTLOADER_OFFSET; 124 | } 125 | 126 | 127 | #ifndef MODERN_LOCM3 128 | /* These two are proposed upstream, but we need them here now */ 129 | static void flash_erase_page(uint32_t page_address) 130 | { 131 | FLASH_PECR |= FLASH_PECR_ERASE | FLASH_PECR_PROG; 132 | /* L1 requires first word in page, L0 doesn't care, user take care */ 133 | MMIO32(page_address) = 0; 134 | while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY); 135 | FLASH_PECR &= ~(FLASH_PECR_ERASE | FLASH_PECR_PROG); 136 | } 137 | 138 | /* Must be run from RAM (per ref manual), and because it's in ram, more 139 | * than 64MB away from flash address space, must be a long_call. 140 | * (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78903 for noinline) */ 141 | void flash_program_half_page(uint32_t *dst, const uint32_t *buf); 142 | __attribute__ ((noinline, long_call, section (".ramtext"))) 143 | void flash_program_half_page(uint32_t *dst, const uint32_t *buf) 144 | { 145 | const uint32_t *src = buf; 146 | 147 | /* Enable half page writes to program memory */ 148 | FLASH_PECR |= FLASH_PECR_FPRG | FLASH_PECR_PROG; 149 | while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY); 150 | #ifndef FLASH_HALF_PAGE_SIZE 151 | #define FLASH_HALF_PAGE_SIZE 32 /* For L1, 16 for L0 */ 152 | #endif 153 | for (int i = 0; i < FLASH_HALF_PAGE_SIZE; i++) { 154 | *dst++ = *src++; 155 | } 156 | while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY); 157 | FLASH_PECR &= ~(FLASH_PECR_FPRG | FLASH_PECR_PROG); 158 | } 159 | #endif 160 | 161 | static bool target_flash_program_array_nice(uint32_t dest, const uint32_t* data, size_t word_count) 162 | { 163 | /* whole page was erased, you're doing the full half page */ 164 | (void)word_count; 165 | assert(word_count <= 32); 166 | if ((dest & (256-1)) == 0) { 167 | flash_erase_page(dest); 168 | } 169 | cm_disable_interrupts(); 170 | flash_program_half_page((uint32_t *)dest, data); 171 | cm_enable_interrupts(); 172 | return true; 173 | } 174 | 175 | /** 176 | * The API is (forrealz?!) tied to the F1 16bit halfwords! 177 | * backconvert, and call a "nicer" api 178 | */ 179 | bool target_flash_program_array(uint16_t* dest, const uint16_t* data, size_t half_word_count) 180 | { 181 | return target_flash_program_array_nice((uint32_t)dest, (const uint32_t *)data, half_word_count / 2); 182 | } 183 | 184 | /* L1 does shorter transfers, and writes half pages at a time, 185 | * can/should be polled more frequently */ 186 | size_t target_get_timeout(void) 187 | { 188 | return 5; 189 | } 190 | 191 | /* this is all common code below, extract for upstream? */ 192 | void target_relocate_vector_table(void) { 193 | SCB_VTOR = APP_BASE_ADDRESS & 0xFFFF; 194 | } 195 | 196 | void target_flash_unlock(void) { 197 | flash_unlock(); 198 | } 199 | 200 | void target_flash_lock(void) { 201 | flash_lock(); 202 | } 203 | 204 | -------------------------------------------------------------------------------- /src/rules.mk: -------------------------------------------------------------------------------- 1 | ## 2 | ## This file is derived from the libopencm3 project. 3 | ## 4 | ## Copyright (C) 2009 Uwe Hermann 5 | ## Copyright (C) 2010 Piotr Esden-Tempski 6 | ## Copyright (C) 2013 Frantisek Burian 7 | ## Copyright (C) 2016 Devan Lai 8 | ## 9 | ## This library is free software: you can redistribute it and/or modify 10 | ## it under the terms of the GNU Lesser General Public License as published by 11 | ## the Free Software Foundation, either version 3 of the License, or 12 | ## (at your option) any later version. 13 | ## 14 | ## This library is distributed in the hope that it will be useful, 15 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ## GNU Lesser General Public License for more details. 18 | ## 19 | ## You should have received a copy of the GNU Lesser General Public License 20 | ## along with this library. If not, see . 21 | ## 22 | 23 | # Be silent per default, but 'make V=1' will show all compiler calls. 24 | ifneq ($(V),1) 25 | Q := @ 26 | NULL := 2>/dev/null 27 | endif 28 | 29 | #################################################################### 30 | # Target Architecture flags 31 | ifeq ($(ARCH),STM32F0) 32 | LIBNAME = opencm3_stm32f0 33 | DEFS += -DSTM32F0 34 | FP_FLAGS ?= -msoft-float 35 | ARCH_FLAGS = -mthumb -mcpu=cortex-m0 $(FP_FLAGS) 36 | OOCD_BOARD ?= target/stm32f0x.cfg 37 | OPENCM3_TARGET = "stm32/f0" 38 | endif 39 | ifeq ($(ARCH),STM32F1) 40 | LIBNAME = opencm3_stm32f1 41 | DEFS += -DSTM32F1 42 | FP_FLAGS ?= -msoft-float 43 | ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd 44 | OOCD_BOARD ?= target/stm32f1x.cfg 45 | OPENCM3_TARGET = "stm32/f1" 46 | endif 47 | ifeq ($(ARCH),STM32L1) 48 | LIBNAME = opencm3_stm32l1 49 | DEFS += -DSTM32L1 50 | FP_FLAGS ?= -msoft-float 51 | ARCH_FLAGS = -mthumb -mcpu=cortex-m3 $(FP_FLAGS) -mfix-cortex-m3-ldrd 52 | OOCD_BOARD ?= target/stm32l1.cfg 53 | OPENCM3_TARGET = "stm32/l1" 54 | endif 55 | 56 | LIBNAME ?= opencm3_stm32f0 57 | DEFS ?= -DSTM32F0 58 | FP_FLAGS ?= -msoft-float 59 | ARCH_FLAGS ?= -mthumb -mcpu=cortex-m0 $(FP_FLAGS) 60 | OPENCM3_TARGET ?= "stm32/f0" 61 | 62 | #################################################################### 63 | # Semihosting support 64 | SEMIHOSTING ?= 0 65 | 66 | ifeq ($(SEMIHOSTING),1) 67 | LDFLAGS += --specs=rdimon.specs 68 | LDLIBS += -lrdimon 69 | DEFS += -DSEMIHOSTING=1 70 | else 71 | DEFS += -DSEMIHOSTING=0 72 | endif 73 | 74 | #################################################################### 75 | # OpenOCD specific variables 76 | 77 | OOCD ?= openocd 78 | OOCD_INTERFACE ?= interface/cmsis-dap.cfg 79 | OOCD_BOARD ?= target/stm32f1x.cfg 80 | 81 | #################################################################### 82 | # Executables 83 | 84 | PREFIX ?= arm-none-eabi- 85 | 86 | CC := $(PREFIX)gcc 87 | CXX := $(PREFIX)g++ 88 | LD := $(PREFIX)gcc 89 | AR := $(PREFIX)gcc-ar 90 | AS := $(PREFIX)as 91 | OBJCOPY := $(PREFIX)objcopy 92 | OBJDUMP := $(PREFIX)objdump 93 | GDB := $(PREFIX)gdb 94 | STFLASH = $(shell which st-flash) 95 | 96 | #################################################################### 97 | # Source files 98 | 99 | INCLUDE_DIR = $(OPENCM3_DIR)/include 100 | LIB_DIR = $(OPENCM3_DIR)/lib 101 | 102 | #################################################################### 103 | # C flags 104 | 105 | CFLAGS += -Os -flto -g -std=gnu11 106 | CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration 107 | CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes 108 | CFLAGS += -fno-common -ffunction-sections -fdata-sections 109 | 110 | #################################################################### 111 | # C++ flags 112 | 113 | CXXFLAGS += -Os -flto -g 114 | CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++ 115 | CXXFLAGS += -fno-common -ffunction-sections -fdata-sections 116 | 117 | #################################################################### 118 | # C & C++ preprocessor common flags 119 | 120 | CPPFLAGS += -MD 121 | CPPFLAGS += -Wall -Wundef 122 | CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS) 123 | 124 | #################################################################### 125 | # Linker flags 126 | 127 | LDFLAGS += -flto -Os -g --static -nostartfiles 128 | LDFLAGS += -specs=nano.specs 129 | LDFLAGS += -L$(LIB_DIR) 130 | LDFLAGS += -T$(LDSCRIPT) 131 | LDFLAGS += -Wl,-Map=$(*).map 132 | LDFLAGS += -Wl,--gc-sections 133 | ifeq ($(V),99) 134 | LDFLAGS += -Wl,--print-gc-sections 135 | endif 136 | 137 | #################################################################### 138 | # Used libraries 139 | 140 | LDLIBS += -l$(LIBNAME) 141 | LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group 142 | 143 | #################################################################### 144 | #################################################################### 145 | #################################################################### 146 | 147 | .SUFFIXES: .elf .bin .hex .srec .list .map .images 148 | .SECONDEXPANSION: 149 | .SECONDARY: 150 | 151 | all: elf 152 | 153 | elf: $(BINARY).elf 154 | bin: $(BINARY).bin 155 | hex: $(BINARY).hex 156 | srec: $(BINARY).srec 157 | list: $(BINARY).list 158 | 159 | images: $(BINARY).images 160 | flash: $(BINARY).flash 161 | 162 | $(LDSCRIPT): 163 | ifeq (,$(wildcard $(LDSCRIPT))) 164 | $(error Unable to find specified linker script: $(LDSCRIPT)) 165 | endif 166 | 167 | $(OPENCM3_DIR)/Makefile: 168 | $(Q)git submodule update --init $(OPENCM3_DIR) 169 | 170 | # If overriding the toolchain, use it when building LOCM3 171 | export PREFIX 172 | 173 | $(LIB_DIR)/lib$(LIBNAME).a: $(OPENCM3_DIR)/Makefile 174 | $(Q)$(MAKE) -C $(OPENCM3_DIR) AR=$(AR) CFLAGS="-flto -g" TARGETS=$(OPENCM3_TARGET) 175 | 176 | locm3: $(LIB_DIR)/lib$(LIBNAME).a 177 | 178 | %.images: %.bin %.hex %.srec %.list %.map 179 | @#printf "*** $* images generated ***\n" 180 | 181 | %.bin: %.elf 182 | @#printf " OBJCOPY $(*).bin\n" 183 | $(Q)$(OBJCOPY) -Obinary --gap-fill=0xff $(*).elf $(*).bin 184 | 185 | %.hex: %.elf 186 | @#printf " OBJCOPY $(*).hex\n" 187 | $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex 188 | 189 | %.srec: %.elf 190 | @#printf " OBJCOPY $(*).srec\n" 191 | $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec 192 | 193 | %.list: %.elf 194 | @#printf " OBJDUMP $(*).list\n" 195 | $(Q)$(OBJDUMP) -S $(*).elf > $(*).list 196 | 197 | %.elf %.map: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a 198 | @#printf " LD $(*).elf\n" 199 | $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(*).elf 200 | 201 | %.o: %.c $(LIB_DIR)/lib$(LIBNAME).a 202 | @#printf " CC $(*).c\n" 203 | $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).c 204 | 205 | %.o: %.cxx $(LIB_DIR)/lib$(LIBNAME).a 206 | @#printf " CXX $(*).cxx\n" 207 | $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx 208 | 209 | %.o: %.cpp $(LIB_DIR)/lib$(LIBNAME).a 210 | @#printf " CXX $(*).cpp\n" 211 | $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp 212 | 213 | clean:: 214 | @#printf " CLEAN\n" 215 | $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map 216 | 217 | %.stlink-flash: %.bin 218 | @printf " FLASH $<\n" 219 | $(Q)$(STFLASH) write $(*).bin 0x08000000 220 | 221 | %.flash: %.elf 222 | @printf " FLASH $<\n" 223 | $(Q)$(OOCD) -f $(OOCD_INTERFACE) \ 224 | -f $(OOCD_BOARD) \ 225 | -c "program $(*).elf verify reset exit" \ 226 | $(NULL) 227 | 228 | .PHONY: images clean elf bin hex srec list locm3 229 | 230 | -include $(OBJS:.o=.d) 231 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dapboot 2 | The dapboot project is an open-source USB [Device Firmware Upgrade](http://www.usb.org/developers/docs/devclass_docs/DFU_1.1.pdf) (DFU) bootloader for STM32 devices. 3 | 4 | Currently, the only targets officially supported are the STM32F103x series. 5 | 6 | ## Build instructions 7 | The default target is a generic STM32F103 dev board with an LED on PC13, commonly referred to as a "bluepill" board. 8 | 9 | To build other targets, you can override the 10 | `TARGET` variable when invoking `make`. 11 | 12 | cd src/ 13 | make clean 14 | make TARGET=STLINK 15 | 16 | ### Targets 17 | 18 | | Target Name | Description | Link | 19 | | ----------- | ----------- |----- | 20 | |`BLUEPILL` | Cheap dev board | https://stm32duinoforum.com/forum/wiki_subdomain/index_title_Blue_Pill.html | 21 | |`MAPLEMINI` | LeafLabs Maple Mini board and clone derivatives | https://stm32duinoforum.com/forum/wiki_subdomain/index_title_Maple_Mini.html | 22 | |`STLINK` | STLink/v2 hardware clones | https://wiki.paparazziuav.org/wiki/STLink#Clones | 23 | |`OLIMEXSTM32H103` | Olimex STM32-H103 | https://www.olimex.com/Products/ARM/ST/STM32-H103/ | 24 | |`BLUEPILLPLUSSTM32` | Bluepill with USB C | https://github.com/WeActTC/BluePill-Plus/ | 25 | |`BTTSKRMINIE3V2` | BigTreeTech SKR MINI E3 V2.0 (3D printer motherboard) | https://github.com/bigtreetech/BIGTREETECH-SKR-mini-E3 | 26 | 27 | For the above targets there are some potential variants that can be added to the target name based on what the target supports: 28 | 29 | | Target Variant | Description | 30 | | -------------- | ------------------------------------------------------- | 31 | |` ` | Standard bootloader, using first 8 KiB of flash | 32 | |`_HIGH` | High memory bootloader for 64 KiB chips (experimental) | 33 | |`_HIGH_128` | High memory bootloader for 128 KiB chips (experimental) | 34 | |`_HIGH_256` | High memory bootloader for 256 KiB chips (experimental) | 35 | 36 | The high memory bootloader is a variation that doesn't require the application to be at an offset, the bootloader resides in the top 7 KiB of ROM and hides its reset and stack vectors inside unused entries of the application vector table. As an example, to compile for a Bluepill board with 128 KiB flash, use: 37 | 38 | make clean 39 | make TARGET=BLUEPILL_HIGH_128 40 | 41 | 42 | ## Flash instructions 43 | The `make flash` target will use openocd to upload the bootloader to an attached board. By default, the Makefile assumes you're using a [CMSIS-DAP](http://www.arm.com/products/processors/cortex-m/cortex-microcontroller-software-interface-standard.php) based probe, but you can override this by overriding `OOCD_INTERFACE` variable. For example: 44 | 45 | make OOCD_INTERFACE=interface/stlink-v2.cfg flash 46 | 47 | ## Overriding defaults 48 | Local makefile settings can be set by creating a `local.mk`, which is automatically included. 49 | 50 | Here is an example `local.mk` that changes the default target to the STLink/v2 and uses an unmodified STLink/v2 to flash it. 51 | 52 | TARGET ?= STLINK 53 | OOCD_INTERFACE ?= interface/stlink-v2.cfg 54 | 55 | You can also use the env variable `DEFS` to override default configuration for a target, like: 56 | 57 | # Disable LED on BluePill 58 | DEFS="-DHAVE_LED=0" make TARGET=BLUEPILL 59 | 60 | # Allow access to all Flash on MapleMini and change the app base address 61 | DEFS="-DFLASH_SIZE_OVERRIDE=0x20000 -DAPP_BASE_ADDRESS=0x08004000" make TARGET=MAPLEMINI LDSCRIPT="/some/folder/stm32f103x8-16kb-boot.ld" 62 | 63 | ## Using the bootloader 64 | ### Building for the bootloader 65 | The standard bootloader occupies the lower 8KiB of flash, so your application must offset its flash contents by 8KiB. This can be done by modifying your linker script or flags as appropriate. 66 | 67 | The high memory bootloaders do not use the lower part of the flash, so you only need to make sure your application leaves 7 KiB of flash free. 68 | 69 | 70 | ### Switching to the bootloader 71 | The bootloader can be built to look for arbitrary patterns, but the default looks for a magic value stored in the RTC backup registers. Writing the magic value and then resetting will run the bootloader instead of the main application. 72 | 73 | In version v1.11 and earlier, the bootloader for STM32F103 targets looks for `0x544F` in RTC backup register 2 and `0x4F42` in RTC backup register 1 (together they spell "BOOT" in ASCII). From v1.20 on, the bootloader will only use RTC backup register 1 and check for `0x4F42` on targets with 16-bit backup registers and `0x544F4F42` on targets with 32-bit backup registers. 74 | 75 | The backup register and bootloader command word can be customized with the `REG_BOOT` and `CMD_BOOT` defines respectively. 76 | 77 | You can also use a button to stay in bootloader while booting. It's configured using `HAVE_BUTTON` define. If your button has a debounce capacitor, you can use `BUTTON_SAMPLE_DELAY_CYCLES` define to specify how many cycles to wait before sampling the I/O pin, by default it is approximately 20ms in a 72Mhz MCU. 78 | 79 | On the bluepill boards, the default is using the BOOT1 input (available on jumper in the board) to enter the bootloader. 80 | 81 | ### WebUSB 82 | This bootloader implements the draft [WebUSB](https://wicg.github.io/webusb/) specification, which allows web pages to access the bootloader (after presenting the user with a device picker dialog). 83 | 84 | For a demo implementing dfu-util features in the browser, see https://devanlai.github.io/webdfu/dfu-util/ 85 | 86 | To customize the WebUSB landing page, you can use the `LANDING_PAGE_URL` define. To set it from the command line, you can use the `DEFS` environment variable: 87 | 88 | DEFS='-DLANDING_PAGE_URL=\"example.com/dfu-util/\"' make 89 | 90 | Note that the URL scheme shoul not be part of the `LANDING_PAGE_URL` string. As of this writing, it is hardcoded to HTTPS. 91 | 92 | ### Manifestation behavior 93 | There are two different manifestation behaviors that can be selected using the `DFU_WILL_DETACH` define. By default, `DFU_WILL_DETACH` is set to 1 for backwards compatibility with existing behavior. 94 | 95 | When `DFU_WILL_DETACH` is enabled, the bootloader autonomously reboot into the new firmware after it has been successfully downloaded and passes the basic validation check. This can be helpful on platforms such as Windows where it is not possible to generate a USB bus reset to signal that the bootloader should switch to the application. 96 | 97 | When `DFU_WILL_DETACH` is disabled, the bootloader will return to the idle state after validating the firmware. The DFU host application can then perform other operations or reboot the target into the new firmware by issuing a DFU detach request or generating a USB bus reset. (This can be done with `dfu-util` by passing the `-R` flag). 98 | 99 | ## USB VID/PID 100 | The default USB VID/PID pair ([1209/DB42](http://pid.codes/1209/DB42/)) is allocated through the [pid.codes](http://pid.codes/) open-source USB PID program. 101 | 102 | To use a custom VID/PID pair, you need to set the macros `USB_VID` and `USB_PID`. One way to do this is by setting the `DEFS` environment variable when compiling: 103 | 104 | DEFS="-DUSB_VID=0x1209 -DUSB_PID=0xCAFE" make 105 | 106 | 107 | ## USB Vendor, Product, and Interface strings 108 | 109 | To customize the USB vendor, product, and interface strings that DAPBoot reports to the USB host, you may set the macros `USB_VENDOR_STRING`, `USB_PRODUCT_STRING`, and `USB_INTERFACE_STRING`, respectively. You can do this by setting the `DEFS` environment variable or including these macros in your board's `config.h` 110 | 111 | 112 | ## Licensing 113 | All contents of the dapboot project are licensed under terms that are compatible with the terms of the GNU Lesser General Public License version 3. 114 | 115 | Non-libopencm3 related portions of the dapboot project are licensed under the less restrictive ISC license, except where otherwise specified in the headers of specific files. 116 | 117 | See the LICENSE file for full details. 118 | -------------------------------------------------------------------------------- /src/stm32f103/target_stm32f103.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | /* Common STM32F103 target functions */ 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "dapboot.h" 29 | #include "target.h" 30 | #include "config.h" 31 | #include "backup.h" 32 | 33 | #ifndef USES_GPIOA 34 | #if (HAVE_USB_PULLUP_CONTROL == 0) 35 | #define USES_GPIOA 1 36 | #else 37 | #define USES_GPIOA 0 38 | #endif 39 | #endif 40 | 41 | #ifndef USES_GPIOB 42 | #define USES_GPIOB 0 43 | #endif 44 | 45 | #ifndef USES_GPIOC 46 | #define USES_GPIOC 0 47 | #endif 48 | 49 | #ifndef BUTTON_USES_PULL 50 | #define BUTTON_USES_PULL 1 51 | #endif 52 | 53 | #ifdef FLASH_SIZE_OVERRIDE 54 | _Static_assert((FLASH_BASE + FLASH_SIZE_OVERRIDE >= APP_BASE_ADDRESS), 55 | "Incompatible flash size"); 56 | #endif 57 | 58 | #ifndef REG_BOOT 59 | #define REG_BOOT BKP1 60 | #endif 61 | 62 | #ifndef CMD_BOOT 63 | #define CMD_BOOT 0x4F42UL 64 | #endif 65 | 66 | void target_clock_setup(void) { 67 | #ifdef USE_HSI 68 | /* Set the system clock to 48MHz from the internal RC oscillator. 69 | The clock tolerance doesn't meet the official USB spec, but 70 | it's better than nothing. */ 71 | rcc_clock_setup_in_hsi_out_48mhz(); 72 | #else 73 | /* Set system clock to 72 MHz from an external crystal */ 74 | rcc_clock_setup_in_hse_8mhz_out_72mhz(); 75 | #endif 76 | } 77 | 78 | void target_gpio_setup(void) { 79 | /* Enable GPIO clocks */ 80 | #if USES_GPIOA 81 | rcc_periph_clock_enable(RCC_GPIOA); 82 | #endif 83 | #if USES_GPIOB 84 | rcc_periph_clock_enable(RCC_GPIOB); 85 | #endif 86 | #if USES_GPIOC 87 | rcc_periph_clock_enable(RCC_GPIOC); 88 | #endif 89 | 90 | /* Disable SWD if PA13 and/or PA14 are used for another purpose */ 91 | #if ((HAVE_LED && LED_GPIO_PORT == GPIOA && (LED_GPIO_PORT == GPIO13 || LED_GPIO_PORT == GPIO14)) || \ 92 | (HAVE_BUTTON && BUTTON_GPIO_PORT == GPIOA && (BUTTON_GPIO_PIN == GPIO13 || BUTTON_GPIO_PIN == GPIO14)) || \ 93 | (HAVE_USB_PULLUP_CONTROL && USB_PULLUP_GPIO_PORT == GPIOA && \ 94 | (USB_PULLUP_GPIO_PIN == GPIO13 || USB_PULLUP_GPIO_PIN == GPIO14))) 95 | { 96 | rcc_periph_clock_enable(RCC_AFIO); 97 | gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF, 0); 98 | } 99 | #endif 100 | 101 | /* Setup LEDs */ 102 | #if HAVE_LED 103 | { 104 | const uint8_t mode = GPIO_MODE_OUTPUT_10_MHZ; 105 | const uint8_t conf = (LED_OPEN_DRAIN ? GPIO_CNF_OUTPUT_OPENDRAIN 106 | : GPIO_CNF_OUTPUT_PUSHPULL); 107 | if (LED_OPEN_DRAIN) { 108 | gpio_set(LED_GPIO_PORT, LED_GPIO_PIN); 109 | } else { 110 | gpio_clear(LED_GPIO_PORT, LED_GPIO_PIN); 111 | } 112 | gpio_set_mode(LED_GPIO_PORT, mode, conf, LED_GPIO_PIN); 113 | } 114 | #endif 115 | 116 | /* Setup the internal pull-up/pull-down for the button */ 117 | #if HAVE_BUTTON 118 | { 119 | const uint8_t mode = GPIO_MODE_INPUT; 120 | const uint8_t conf = (BUTTON_USES_PULL ? GPIO_CNF_INPUT_PULL_UPDOWN 121 | : GPIO_CNF_INPUT_FLOAT); 122 | gpio_set_mode(BUTTON_GPIO_PORT, mode, conf, BUTTON_GPIO_PIN); 123 | if (BUTTON_USES_PULL) { 124 | if (BUTTON_ACTIVE_HIGH) { 125 | gpio_clear(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN); 126 | } else { 127 | gpio_set(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN); 128 | } 129 | } 130 | } 131 | #endif 132 | 133 | #if HAVE_USB_PULLUP_CONTROL 134 | { 135 | const uint8_t mode = GPIO_MODE_OUTPUT_10_MHZ; 136 | const uint8_t conf = (USB_PULLUP_OPEN_DRAIN ? GPIO_CNF_OUTPUT_OPENDRAIN 137 | : GPIO_CNF_OUTPUT_PUSHPULL); 138 | /* Configure USB pullup transistor, initially disabled */ 139 | if (USB_PULLUP_ACTIVE_HIGH) { 140 | gpio_clear(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); 141 | } else { 142 | gpio_set(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); 143 | } 144 | gpio_set_mode(USB_PULLUP_GPIO_PORT, mode, conf, USB_PULLUP_GPIO_PIN); 145 | } 146 | #else 147 | { 148 | /* Drive the USB DP pin to override the pull-up */ 149 | gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_10_MHZ, 150 | GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); 151 | } 152 | #endif 153 | } 154 | 155 | const usbd_driver* target_usb_init(void) { 156 | rcc_periph_reset_pulse(RST_USB); 157 | 158 | #if HAVE_USB_PULLUP_CONTROL 159 | /* Enable USB pullup to connect */ 160 | if (USB_PULLUP_ACTIVE_HIGH) { 161 | gpio_set(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); 162 | } else { 163 | gpio_clear(USB_PULLUP_GPIO_PORT, USB_PULLUP_GPIO_PIN); 164 | } 165 | #else 166 | /* Override hard-wired USB pullup to disconnect and reconnect */ 167 | gpio_clear(GPIOA, GPIO12); 168 | int i; 169 | for (i = 0; i < 800000; i++) { 170 | __asm__("nop"); 171 | } 172 | #endif 173 | 174 | return &st_usbfs_v1_usb_driver; 175 | } 176 | 177 | bool target_get_force_bootloader(void) { 178 | bool force = false; 179 | /* Check the RTC backup register */ 180 | uint16_t cmd = backup_read(REG_BOOT); 181 | if (cmd == CMD_BOOT) { 182 | force = true; 183 | } 184 | 185 | /* Clear the RTC backup register */ 186 | backup_write(REG_BOOT, 0); 187 | 188 | #if HAVE_BUTTON 189 | /* Wait some time in case the button has some debounce capacitor */ 190 | int i; 191 | for (i = 0; i < BUTTON_SAMPLE_DELAY_CYCLES; i++) { 192 | __asm__("nop"); 193 | } 194 | /* Check if the user button is held down */ 195 | if (BUTTON_ACTIVE_HIGH) { 196 | if (gpio_get(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN)) { 197 | force = true; 198 | } 199 | } else { 200 | if (!gpio_get(BUTTON_GPIO_PORT, BUTTON_GPIO_PIN)) { 201 | force = true; 202 | } 203 | } 204 | #endif 205 | 206 | return force; 207 | } 208 | 209 | void target_get_serial_number(char* dest, size_t max_chars) { 210 | desig_get_unique_id_as_string(dest, max_chars+1); 211 | } 212 | 213 | static uint16_t* get_flash_end(void) { 214 | #ifdef FLASH_SIZE_OVERRIDE 215 | /* Allow access to the unofficial full 128KiB flash size */ 216 | return (uint16_t*)(FLASH_BASE + FLASH_SIZE_OVERRIDE); 217 | #else 218 | /* Only allow access to the chip's self-reported flash size */ 219 | return (uint16_t*)(FLASH_BASE + ((size_t)desig_get_flash_size())*1024); 220 | #endif 221 | } 222 | 223 | size_t target_get_max_firmware_size(void) { 224 | uint8_t* flash_end = (uint8_t*)get_flash_end(); 225 | uint8_t* flash_start = (uint8_t*)(APP_BASE_ADDRESS); 226 | 227 | return (flash_end >= flash_start) ? (size_t)(flash_end - flash_start) : 0; 228 | } 229 | 230 | void target_relocate_vector_table(void) { 231 | SCB_VTOR = APP_BASE_ADDRESS & 0xFFFF; 232 | } 233 | 234 | void target_flash_unlock(void) { 235 | flash_unlock(); 236 | } 237 | 238 | void target_flash_lock(void) { 239 | flash_lock(); 240 | } 241 | 242 | static inline uint16_t* get_flash_page_address(uint16_t* dest) { 243 | return (uint16_t*)(((uint32_t)dest / FLASH_PAGE_SIZE) * FLASH_PAGE_SIZE); 244 | } 245 | 246 | bool target_flash_program_array(uint16_t* dest, const uint16_t* data, size_t half_word_count) { 247 | bool verified = true; 248 | 249 | /* Remember the bounds of erased data in the current page */ 250 | static uint16_t* erase_start; 251 | static uint16_t* erase_end; 252 | 253 | const uint16_t* flash_end = get_flash_end(); 254 | while (half_word_count > 0) { 255 | /* Avoid writing past the end of flash */ 256 | if (dest >= flash_end) { 257 | verified = false; 258 | break; 259 | } 260 | 261 | if (dest >= erase_end || dest < erase_start) { 262 | erase_start = get_flash_page_address(dest); 263 | erase_end = erase_start + (FLASH_PAGE_SIZE)/sizeof(uint16_t); 264 | flash_erase_page((uint32_t)erase_start); 265 | } 266 | flash_program_half_word((uint32_t)dest, *data); 267 | erase_start = dest + 1; 268 | if (*dest != *data) { 269 | verified = false; 270 | break; 271 | } 272 | dest++; 273 | data++; 274 | half_word_count--; 275 | } 276 | 277 | return verified; 278 | } 279 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | With the exception of files that contain licensing information 2 | stating the contrary, files within the dapboot project are licensed 3 | under the ISC license as follows: 4 | 5 | Copyright (c) 2016, Devan Lai 6 | 7 | Permission to use, copy, modify, and/or distribute this software 8 | for any purpose with or without fee is hereby granted, provided 9 | that the above copyright notice and this permission notice 10 | appear in all copies. 11 | 12 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 13 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 14 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 15 | AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 16 | CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 17 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 18 | NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 19 | CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 | 21 | The following files in the dapboot project pertaining to the base 22 | Makefile and linker script are derived from the libopencm3 examples 23 | template and are licensed under the GNU Lesser General Public 24 | License version 3: 25 | * libopencm3.rules.mk 26 | * src/libopencm3.target.mk 27 | * src/stm32f042/stm32f042x6.ld 28 | * src/stm32f103/stm32f103x8.ld 29 | 30 | libopencm3, included as a submodule and statically linked as part 31 | of the build process, is separately licensed under the LGPLv3. 32 | 33 | The following is for informative purposes only: all LICENSE files 34 | contained within the project should be consulted for precise 35 | specifications. 36 | 37 | The LGLPv3 is the most restrictive license applying to any subset 38 | of the dapboot project; all other licensed material is strictly less 39 | restrictive than the LGPLv3. Accordingly, you may distribute the 40 | dapboot project in source or object code form under the terms of 41 | the LGPLv3 without needing to meet additional requirements for 42 | the less restrictively licensed portions of the dapboot project. 43 | 44 | Otherwise, the combined work consisting of the dapboot object code 45 | linked with the libopencm3 object code may be distributed without 46 | distributing a copy of the dapboot source code or any modifications 47 | to it. 48 | 49 | However, if the source code is not distributed, you must provide a 50 | means for the user to "re-link" the libopencm3 object code to 51 | produce a new combined work containing updated libopencm3 object 52 | code along-side any dapboot object code. 53 | 54 | The text of the GNU Lesser General Public License version 3 is 55 | reproduced below for use with the limited portions of the dapboot 56 | project licensed under the LGPLv3: 57 | 58 | GNU LESSER GENERAL PUBLIC LICENSE 59 | Version 3, 29 June 2007 60 | 61 | Copyright (C) 2007 Free Software Foundation, Inc. 62 | Everyone is permitted to copy and distribute verbatim copies 63 | of this license document, but changing it is not allowed. 64 | 65 | 66 | This version of the GNU Lesser General Public License incorporates 67 | the terms and conditions of version 3 of the GNU General Public 68 | License, supplemented by the additional permissions listed below. 69 | 70 | 0. Additional Definitions. 71 | 72 | As used herein, "this License" refers to version 3 of the GNU Lesser 73 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 74 | General Public License. 75 | 76 | "The Library" refers to a covered work governed by this License, 77 | other than an Application or a Combined Work as defined below. 78 | 79 | An "Application" is any work that makes use of an interface provided 80 | by the Library, but which is not otherwise based on the Library. 81 | Defining a subclass of a class defined by the Library is deemed a mode 82 | of using an interface provided by the Library. 83 | 84 | A "Combined Work" is a work produced by combining or linking an 85 | Application with the Library. The particular version of the Library 86 | with which the Combined Work was made is also called the "Linked 87 | Version". 88 | 89 | The "Minimal Corresponding Source" for a Combined Work means the 90 | Corresponding Source for the Combined Work, excluding any source code 91 | for portions of the Combined Work that, considered in isolation, are 92 | based on the Application, and not on the Linked Version. 93 | 94 | The "Corresponding Application Code" for a Combined Work means the 95 | object code and/or source code for the Application, including any data 96 | and utility programs needed for reproducing the Combined Work from the 97 | Application, but excluding the System Libraries of the Combined Work. 98 | 99 | 1. Exception to Section 3 of the GNU GPL. 100 | 101 | You may convey a covered work under sections 3 and 4 of this License 102 | without being bound by section 3 of the GNU GPL. 103 | 104 | 2. Conveying Modified Versions. 105 | 106 | If you modify a copy of the Library, and, in your modifications, a 107 | facility refers to a function or data to be supplied by an Application 108 | that uses the facility (other than as an argument passed when the 109 | facility is invoked), then you may convey a copy of the modified 110 | version: 111 | 112 | a) under this License, provided that you make a good faith effort to 113 | ensure that, in the event an Application does not supply the 114 | function or data, the facility still operates, and performs 115 | whatever part of its purpose remains meaningful, or 116 | 117 | b) under the GNU GPL, with none of the additional permissions of 118 | this License applicable to that copy. 119 | 120 | 3. Object Code Incorporating Material from Library Header Files. 121 | 122 | The object code form of an Application may incorporate material from 123 | a header file that is part of the Library. You may convey such object 124 | code under terms of your choice, provided that, if the incorporated 125 | material is not limited to numerical parameters, data structure 126 | layouts and accessors, or small macros, inline functions and templates 127 | (ten or fewer lines in length), you do both of the following: 128 | 129 | a) Give prominent notice with each copy of the object code that the 130 | Library is used in it and that the Library and its use are 131 | covered by this License. 132 | 133 | b) Accompany the object code with a copy of the GNU GPL and this license 134 | document. 135 | 136 | 4. Combined Works. 137 | 138 | You may convey a Combined Work under terms of your choice that, 139 | taken together, effectively do not restrict modification of the 140 | portions of the Library contained in the Combined Work and reverse 141 | engineering for debugging such modifications, if you also do each of 142 | the following: 143 | 144 | a) Give prominent notice with each copy of the Combined Work that 145 | the Library is used in it and that the Library and its use are 146 | covered by this License. 147 | 148 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 149 | document. 150 | 151 | c) For a Combined Work that displays copyright notices during 152 | execution, include the copyright notice for the Library among 153 | these notices, as well as a reference directing the user to the 154 | copies of the GNU GPL and this license document. 155 | 156 | d) Do one of the following: 157 | 158 | 0) Convey the Minimal Corresponding Source under the terms of this 159 | License, and the Corresponding Application Code in a form 160 | suitable for, and under terms that permit, the user to 161 | recombine or relink the Application with a modified version of 162 | the Linked Version to produce a modified Combined Work, in the 163 | manner specified by section 6 of the GNU GPL for conveying 164 | Corresponding Source. 165 | 166 | 1) Use a suitable shared library mechanism for linking with the 167 | Library. A suitable mechanism is one that (a) uses at run time 168 | a copy of the Library already present on the user's computer 169 | system, and (b) will operate properly with a modified version 170 | of the Library that is interface-compatible with the Linked 171 | Version. 172 | 173 | e) Provide Installation Information, but only if you would otherwise 174 | be required to provide such information under section 6 of the 175 | GNU GPL, and only to the extent that such information is 176 | necessary to install and execute a modified version of the 177 | Combined Work produced by recombining or relinking the 178 | Application with a modified version of the Linked Version. (If 179 | you use option 4d0, the Installation Information must accompany 180 | the Minimal Corresponding Source and Corresponding Application 181 | Code. If you use option 4d1, you must provide the Installation 182 | Information in the manner specified by section 6 of the GNU GPL 183 | for conveying Corresponding Source.) 184 | 185 | 5. Combined Libraries. 186 | 187 | You may place library facilities that are a work based on the 188 | Library side by side in a single library together with other library 189 | facilities that are not Applications and are not covered by this 190 | License, and convey such a combined library under terms of your 191 | choice, if you do both of the following: 192 | 193 | a) Accompany the combined library with a copy of the same work based 194 | on the Library, uncombined with any other library facilities, 195 | conveyed under the terms of this License. 196 | 197 | b) Give prominent notice with the combined library that part of it 198 | is a work based on the Library, and explaining where to find the 199 | accompanying uncombined form of the same work. 200 | 201 | 6. Revised Versions of the GNU Lesser General Public License. 202 | 203 | The Free Software Foundation may publish revised and/or new versions 204 | of the GNU Lesser General Public License from time to time. Such new 205 | versions will be similar in spirit to the present version, but may 206 | differ in detail to address new problems or concerns. 207 | 208 | Each version is given a distinguishing version number. If the 209 | Library as you received it specifies that a certain numbered version 210 | of the GNU Lesser General Public License "or any later version" 211 | applies to it, you have the option of following the terms and 212 | conditions either of that published version or of any later version 213 | published by the Free Software Foundation. If the Library as you 214 | received it does not specify a version number of the GNU Lesser 215 | General Public License, you may choose any version of the GNU Lesser 216 | General Public License ever published by the Free Software Foundation. 217 | 218 | If the Library as you received it specifies that a proxy can decide 219 | whether future versions of the GNU Lesser General Public License shall 220 | apply, that proxy's public statement of acceptance of any version is 221 | permanent authorization for you to choose that version for the 222 | Library. -------------------------------------------------------------------------------- /src/dfu.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016, Devan Lai 3 | * 4 | * Permission to use, copy, modify, and/or distribute this software 5 | * for any purpose with or without fee is hereby granted, provided 6 | * that the above copyright notice and this permission notice 7 | * appear in all copies. 8 | * 9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 10 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 11 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 12 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR 13 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 14 | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 15 | * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 16 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "config.h" 28 | #include "usb_conf.h" 29 | #include "dfu.h" 30 | #include "dfu_defs.h" 31 | #include "target.h" 32 | #include "dapboot.h" 33 | 34 | #ifndef TARGET_DFU_WTRANSFERSIZE 35 | #define TARGET_DFU_WTRANSFERSIZE USB_CONTROL_BUF_SIZE 36 | #endif 37 | 38 | const struct usb_dfu_descriptor dfu_function = { 39 | .bLength = sizeof(struct usb_dfu_descriptor), 40 | .bDescriptorType = DFU_FUNCTIONAL, 41 | .bmAttributes = ((DFU_DOWNLOAD_AVAILABLE ? USB_DFU_CAN_DOWNLOAD : 0) | 42 | (DFU_UPLOAD_AVAILABLE ? USB_DFU_CAN_UPLOAD : 0) | 43 | (DFU_WILL_DETACH ? 0 : USB_DFU_MANIFEST_TOLERANT) | 44 | (DFU_WILL_DETACH ? USB_DFU_WILL_DETACH : 0)), 45 | .wDetachTimeout = 255, 46 | .wTransferSize = TARGET_DFU_WTRANSFERSIZE, 47 | .bcdDFUVersion = 0x0110, 48 | }; 49 | 50 | static enum dfu_state current_dfu_state; 51 | static enum dfu_status current_dfu_status; 52 | static size_t current_dfu_offset; 53 | 54 | static bool manifestation_complete = false; 55 | 56 | static uint8_t dfu_download_buffer[USB_CONTROL_BUF_SIZE]; 57 | static size_t dfu_download_size; 58 | 59 | /* User callbacks */ 60 | static ManifestationCallback dfu_manifest_request_callback = NULL; 61 | static StateChangeCallback dfu_state_change_callback = NULL; 62 | static StatusChangeCallback dfu_status_change_callback = NULL; 63 | 64 | static inline void dfu_set_state(enum dfu_state state) { 65 | if (state != current_dfu_state) { 66 | if (dfu_state_change_callback) { 67 | dfu_state_change_callback(state); 68 | } 69 | } 70 | current_dfu_state = state; 71 | } 72 | 73 | static inline enum dfu_status dfu_get_status(void) { 74 | return current_dfu_status; 75 | } 76 | 77 | static inline void dfu_set_status(enum dfu_status status) { 78 | if (status != current_dfu_status) { 79 | if (dfu_status_change_callback) { 80 | dfu_status_change_callback(status); 81 | } 82 | } 83 | if (status == DFU_STATUS_OK) { 84 | if (current_dfu_state == STATE_DFU_ERROR) { 85 | dfu_set_state(STATE_DFU_IDLE); 86 | } 87 | } else { 88 | dfu_set_state(STATE_DFU_ERROR); 89 | } 90 | current_dfu_status = status; 91 | } 92 | 93 | static void dfu_on_download_complete(usbd_device* usbd_dev, struct usb_setup_data* req) { 94 | (void)usbd_dev; 95 | (void)req; 96 | 97 | dfu_set_state(STATE_DFU_MANIFEST_SYNC); 98 | } 99 | 100 | static void dfu_on_detach_complete(usbd_device* usbd_dev, struct usb_setup_data* req) { 101 | (void)usbd_dev; 102 | (void)req; 103 | 104 | /* Run the target-specific pre-detach hook before resetting */ 105 | target_pre_detach(manifestation_complete); 106 | 107 | /* Reset and maybe launch the application */ 108 | scb_reset_system(); 109 | } 110 | 111 | static void dfu_on_download_request(usbd_device* usbd_dev, struct usb_setup_data* req) { 112 | (void)usbd_dev; 113 | (void)req; 114 | 115 | if (DFU_PATCH_VECTORS && current_dfu_offset == 0) { 116 | if (dfu_download_size < offsetof(vector_table_t, reserved_x001c[1])) { 117 | /* Can't handle splitting the vector table right now */ 118 | dfu_set_status(DFU_STATUS_ERR_VENDOR); 119 | } else { 120 | vector_table_t* app_vector_table = (vector_table_t*)dfu_download_buffer; 121 | /* Stash the application's initial stack value and reset 122 | pointer in unused vector table entries */ 123 | app_vector_table->reserved_x001c[0] = (vector_table_entry_t)(app_vector_table->initial_sp_value); 124 | app_vector_table->reserved_x001c[1] = app_vector_table->reset; 125 | /* Overwrite the stack and reset pointer to run the 126 | bootloader instead */ 127 | app_vector_table->initial_sp_value = &_stack; 128 | app_vector_table->reset = reset_handler; 129 | } 130 | } 131 | 132 | const uint16_t* data = (uint16_t*)dfu_download_buffer; 133 | uint16_t* dest = (uint16_t*)(APP_BASE_ADDRESS + current_dfu_offset); 134 | 135 | target_flash_unlock(); 136 | bool ok = target_flash_program_array(dest, data, dfu_download_size/2); 137 | target_flash_lock(); 138 | 139 | if (ok) { 140 | current_dfu_offset += dfu_download_size; 141 | /* We could go back to STATE_DFU_DNLOAD_SYNC, but then 142 | we would have to remember that we already programmed this block */ 143 | dfu_set_state(STATE_DFU_DNLOAD_IDLE); 144 | } else { 145 | dfu_set_status(DFU_STATUS_ERR_VERIFY); 146 | } 147 | } 148 | 149 | static void dfu_on_manifest_request(usbd_device* usbd_dev, struct usb_setup_data* req) { 150 | (void)usbd_dev; 151 | (void)req; 152 | 153 | if (dfu_manifest_request_callback) { 154 | /* The manifestation callback returns a boolean indicating if it succeeded */ 155 | manifestation_complete = dfu_manifest_request_callback(); 156 | } else { 157 | /* Assume manifestation success */ 158 | manifestation_complete = true; 159 | } 160 | 161 | if (manifestation_complete) { 162 | dfu_set_state(STATE_DFU_MANIFEST_SYNC); 163 | } else { 164 | dfu_set_status(DFU_STATUS_ERR_FIRMWARE); 165 | return; /* Avoid resetting on error */ 166 | } 167 | 168 | #if DFU_WILL_DETACH 169 | /* DFU_WILL_DETACH being enabled equates to transitioning to the dfuMANIFEST-WAIT-RESET state, 170 | * which combined with bitWillDetach being set with DFU_WILL_DETACH means that the device should 171 | * generate a detach-attach sequence and enter the application, i.e. reset itself, here */ 172 | dfu_on_detach_complete(NULL, NULL); 173 | #endif 174 | } 175 | 176 | static enum usbd_request_return_codes 177 | dfu_control_class_request(usbd_device *usbd_dev, 178 | struct usb_setup_data *req, 179 | uint8_t **buf, uint16_t *len, 180 | usbd_control_complete_callback* complete) { 181 | if (req->wIndex != INTF_DFU) { 182 | return USBD_REQ_NEXT_CALLBACK; 183 | } 184 | 185 | enum usbd_request_return_codes status = USBD_REQ_HANDLED; 186 | switch (req->bRequest) { 187 | case DFU_GETSTATE: { 188 | struct dfu_getstate_response* resp; 189 | resp = (struct dfu_getstate_response*)(*buf); 190 | resp->bState = (uint8_t)current_dfu_state; 191 | *len = sizeof(*resp); 192 | break; 193 | } 194 | case DFU_GETSTATUS: { 195 | struct dfu_getstatus_response* resp; 196 | resp = (struct dfu_getstatus_response*)(*buf); 197 | uint32_t bwPollTimeout = 0; 198 | switch (current_dfu_state) { 199 | #if DFU_DOWNLOAD_AVAILABLE 200 | case STATE_DFU_DNLOAD_SYNC: { 201 | dfu_set_state(STATE_DFU_DNBUSY); 202 | bwPollTimeout = target_get_timeout(); 203 | *complete = &dfu_on_download_request; 204 | break; 205 | } 206 | case STATE_DFU_MANIFEST_SYNC: { 207 | /* According to the DFU spec the dfuMANIFEST-SYNC state is entered twice, 208 | * once after the download completes, and again after manifestation if 209 | * the device is manifestation tolerant (DFU_WILL_DETACH == 0) */ 210 | if (manifestation_complete) { 211 | /* Only enter idle state after manifestation has completed successfully */ 212 | dfu_set_state(STATE_DFU_IDLE); 213 | } else { 214 | /* Perform manifestation after download as described in the 215 | * spec regardless of if DFU_WILL_DETACH is enabled or not */ 216 | dfu_set_state(STATE_DFU_MANIFEST); 217 | *complete = &dfu_on_manifest_request; 218 | } 219 | break; 220 | } 221 | #endif 222 | default: { 223 | break; 224 | } 225 | } 226 | resp->bStatus = dfu_get_status(); 227 | resp->bwPollTimeout[0] = (uint8_t)(bwPollTimeout & 0xFF); 228 | resp->bwPollTimeout[1] = (uint8_t)((bwPollTimeout >> 8) & 0xFF); 229 | resp->bwPollTimeout[2] = (uint8_t)((bwPollTimeout >> 16) & 0xFF); 230 | resp->bState = (uint8_t)current_dfu_state; 231 | resp->iString = 0; 232 | *len = sizeof(*resp); 233 | break; 234 | } 235 | case DFU_CLRSTATUS: { 236 | dfu_set_status(DFU_STATUS_OK); 237 | break; 238 | } 239 | #if DFU_DOWNLOAD_AVAILABLE 240 | case DFU_DNLOAD: { 241 | switch (current_dfu_state) { 242 | case STATE_DFU_IDLE: { 243 | if (req->wLength > 0) { 244 | current_dfu_offset = 0; 245 | dfu_download_size = req->wLength; 246 | memcpy(dfu_download_buffer, *buf, dfu_download_size); 247 | dfu_set_state(STATE_DFU_DNLOAD_SYNC); 248 | /* Reset manifestation progress on new download */ 249 | manifestation_complete = false; 250 | } else { 251 | dfu_set_status(DFU_STATUS_ERR_STALLEDPKT); 252 | usbd_ep_stall_set(usbd_dev, 0x00, 1); 253 | } 254 | break; 255 | } 256 | case STATE_DFU_DNLOAD_IDLE: { 257 | if (req->wLength > 0) { 258 | dfu_download_size = req->wLength; 259 | memcpy(dfu_download_buffer, *buf, dfu_download_size); 260 | dfu_set_state(STATE_DFU_DNLOAD_SYNC); 261 | } else { 262 | *complete = &dfu_on_download_complete; 263 | } 264 | break; 265 | } 266 | default: { 267 | break; 268 | } 269 | } 270 | break; 271 | } 272 | #endif 273 | case DFU_ABORT: { 274 | switch (current_dfu_state) { 275 | case STATE_DFU_IDLE: 276 | case STATE_DFU_DNLOAD_SYNC: 277 | case STATE_DFU_DNLOAD_IDLE: 278 | case STATE_DFU_MANIFEST_SYNC: 279 | case STATE_DFU_UPLOAD_IDLE: { 280 | dfu_set_state(STATE_DFU_IDLE); 281 | break; 282 | } 283 | default: { 284 | break; 285 | } 286 | } 287 | break; 288 | } 289 | #if DFU_UPLOAD_AVAILABLE 290 | case DFU_UPLOAD: { 291 | switch (current_dfu_state) { 292 | case STATE_DFU_IDLE: { 293 | current_dfu_offset = 0; 294 | /* Fall through */ 295 | __attribute__ ((fallthrough)); 296 | } 297 | case STATE_DFU_UPLOAD_IDLE: { 298 | uint16_t len_to_copy = req->wLength; 299 | size_t max_firmware_size = target_get_max_firmware_size(); 300 | if (current_dfu_offset + req->wLength > max_firmware_size) { 301 | len_to_copy = max_firmware_size - current_dfu_offset; 302 | dfu_set_state(STATE_DFU_IDLE); 303 | } else { 304 | dfu_set_state(STATE_DFU_UPLOAD_IDLE); 305 | } 306 | *len = len_to_copy; 307 | if (DFU_PATCH_VECTORS && current_dfu_offset < sizeof(vector_table_t)) { 308 | /* Copy the flash memory to the download buffer, to 309 | undo the vector modifications. */ 310 | memcpy(dfu_download_buffer, (const void*)(APP_BASE_ADDRESS), 311 | sizeof(dfu_download_buffer)); 312 | vector_table_t* app_vector_table = (vector_table_t*)dfu_download_buffer; 313 | /* Put the original stack pointer and reset vectors 314 | back */ 315 | app_vector_table->initial_sp_value = (unsigned int*)(app_vector_table->reserved_x001c[0]); 316 | app_vector_table->reset = app_vector_table->reserved_x001c[1]; 317 | app_vector_table->reserved_x001c[0] = 0; 318 | app_vector_table->reserved_x001c[1] = 0; 319 | /* Return the correct pointer */ 320 | *buf = dfu_download_buffer + current_dfu_offset; 321 | } else { 322 | *buf = (uint8_t*)(APP_BASE_ADDRESS + current_dfu_offset); 323 | } 324 | current_dfu_offset += len_to_copy; 325 | break; 326 | } 327 | default: { 328 | break; 329 | } 330 | } 331 | break; 332 | } 333 | #endif 334 | 335 | case DFU_DETACH: { 336 | *complete = &dfu_on_detach_complete; 337 | status = USBD_REQ_HANDLED; 338 | break; 339 | } 340 | 341 | default: { 342 | /* Stall the control pipe */ 343 | dfu_set_status(DFU_STATUS_ERR_STALLEDPKT); 344 | usbd_ep_stall_set(usbd_dev, 0x00, 1); 345 | status = USBD_REQ_NOTSUPP; 346 | break; 347 | } 348 | } 349 | 350 | return status; 351 | } 352 | 353 | /* Track dfu enumeration status to distinguish between the first USB 354 | reset after bootup versus a subsequent USB reset and re-enumeration */ 355 | static bool dfu_enumerated = false; 356 | 357 | static void dfu_set_config(usbd_device* usbd_dev, uint16_t wValue) { 358 | (void)wValue; 359 | 360 | usbd_register_control_callback( 361 | usbd_dev, 362 | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, 363 | USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, 364 | dfu_control_class_request); 365 | 366 | dfu_enumerated = true; 367 | } 368 | 369 | static void dfu_on_usb_reset(void) { 370 | /* Ignore all USB resets until the DFU control callback has been registered, since 371 | * reset callback will fire once as the USB connection is established. Without this 372 | * the target enters a reset loop when trying to enter the bootloader. */ 373 | if (!dfu_enumerated) { 374 | return; 375 | } 376 | 377 | /* Perform a DFU detach (which resets the target), this enables issuing a USB bus 378 | * reset as an alternative means to submitting a DFU_DETACH command post-download. */ 379 | dfu_on_detach_complete(NULL, NULL); 380 | } 381 | 382 | void dfu_setup(usbd_device* usbd_dev, 383 | ManifestationCallback on_manifest_request, 384 | StateChangeCallback on_state_change, 385 | StatusChangeCallback on_status_change) { 386 | dfu_manifest_request_callback = on_manifest_request; 387 | dfu_state_change_callback = on_state_change; 388 | dfu_status_change_callback = on_status_change; 389 | 390 | usbd_register_reset_callback(usbd_dev, dfu_on_usb_reset); 391 | usbd_register_set_config_callback(usbd_dev, dfu_set_config); 392 | current_dfu_state = STATE_DFU_IDLE; 393 | current_dfu_status = DFU_STATUS_OK; 394 | if (on_state_change) { 395 | on_state_change(current_dfu_state); 396 | } 397 | } 398 | --------------------------------------------------------------------------------