Compare commits
3 Commits
master
...
sysmoOCTSI
Author | SHA1 | Date |
---|---|---|
Kevin Redon | 5078232cce | |
Kevin Redon | 3a64538b32 | |
Kevin Redon | da201623c1 |
54
README.md
54
README.md
|
@ -1,22 +1,10 @@
|
|||
This is an implementation of the DFU mode of the [USB DFU Device Class Specification](https://usb.org/document-library/device-firmware-upgrade-11-new-version-31-aug-2004) for the Microchip SAM D5x/E5x micro-controller.
|
||||
It is meant to be used as bootloader to allow flashing the main application over USB.
|
||||
|
||||
The code has been developed using a [SAM E54](https://www.microchip.com/wwwproducts/en/ATSAME54P20A) micro-controller.
|
||||
It should work on any chip of the SAM D5x/E5x device family by replacing the corresponding device-specific definitions (usually including the chip name in the file name).
|
||||
This branch is specific to the proprietary sysmocom sysmoOCTSIM hardware.
|
||||
|
||||
The code uses the [Atmel START](https://start.atmel.com/) ASFv4 library.
|
||||
|
||||
Board
|
||||
=====
|
||||
|
||||
The code can be compiled for specific boards:
|
||||
|
||||
- Microchip [SAM E54 Xplained Pro](https://www.microchip.com/DevelopmentTools/ProductDetails/PartNo/ATSAME54-XPRO) development board, named *SAME54_XPLAINED_PRO*
|
||||
- sysmocom sysmoOCTSIM, name *SYSMOOCTSIM*
|
||||
|
||||
The board name can be set in 'gcc/Makefile' *BOARD* variable, or provided while compiling (e.g. `make BOARD=SAME54_XPLAINED_PRO`).
|
||||
*SAME54_XPLAINED_PRO* is the default value.
|
||||
|
||||
USB DFU
|
||||
=======
|
||||
|
||||
|
@ -28,29 +16,22 @@ This implementation support the following USB DFU capabilities:
|
|||
|
||||
Set the corresponding attributes in the 'DFUD_IFACE_DESCB' macro definition in the 'usb/class/dfu/device/dfudf_desc.h' file.
|
||||
|
||||
To force the DFU bootloader to start there are several possibilities:
|
||||
|
||||
* if the application following the bootloader is invalid (e.g. MSP is not in RAM)
|
||||
* if a button is pressed (the button defined in *BUTTON_FORCE_DFU*)
|
||||
* if the magic value "DFU!" (e.g. 0x44465521) is set at the start of the RAM (e.g. by the main application when performing a USB detach)
|
||||
|
||||
Compiling
|
||||
=========
|
||||
|
||||
Use the 'Makefile' script to compile the source code using the ARM none EABI GCC cross-compiling toolchain:
|
||||
Use the 'Makefile' script to compile the source code using the ARM none EABI GCC cross-cimpilig toolchain:
|
||||
```
|
||||
cd gcc
|
||||
make
|
||||
```
|
||||
|
||||
The board name can be set in 'gcc/Makefile' *BOARD* variable, or provided while compiling (e.g. `make BOARD=SAME54_XPLAINED_PRO`).
|
||||
*SAME54_XPLAINED_PRO* is the default value.
|
||||
|
||||
The resulting firmware binary is `bootloader-$(BOARD)-$(GIT_VERSION).bin`.
|
||||
The resulting firmware binary is `AtmelStart.bin`.
|
||||
|
||||
Flashing
|
||||
========
|
||||
|
||||
To flash the bootloader you can use OpenOCD with any SWJ adapter.
|
||||
|
||||
The USB DFU bootloader should be flashed in a protected area of the flash memory to prevent for erasing it, as specified in data sheet section 25.6.2 Memory Organization.
|
||||
The bootloader size is configured in the NVM user configuration BOOTPROT field, as specified in data sheet section 25.6.9 NVM User Configuration.
|
||||
The bit position of the BOOTPROT field is documented in data sheet section 9.4 NVM User Page Mapping.
|
||||
|
@ -58,29 +39,14 @@ We need to reserve as least 2 pages of 8192 bytes for the bootloader since it is
|
|||
This setting will also tell the bootloader where to flash the application firmware to (e.g. after the bootloader reserved space).
|
||||
The LED will blink once per second if this size is not set.
|
||||
|
||||
EDBG
|
||||
----
|
||||
|
||||
To flash the bootloader using the [edbg tool](https://github.com/ataradov/edbg) over the EDBG interface of the SAM E54 Xplained Pro development board.
|
||||
|
||||
To flash the USB DFU bootloader, perform the following actions:
|
||||
* remove reserved bootloader space so we can erase it: `edbg --target atmel_cm4v2 --fuse wv,29:26,15`
|
||||
* erase the whole flash: `edbg --target atmel_cm4v2 --fuse v,29:26,15 --erase`
|
||||
* program the bootloader: `edbg --target atmel_cm4v2 --fuse v,29:26,15 --program --verify --file bootloader-BOARD-XXXX.bin`
|
||||
* reserve bootloader space: `edbg --target atmel_cm4v2 --fuse wv,29:26,13`
|
||||
|
||||
SWJ
|
||||
---
|
||||
|
||||
The bootloader can also be flashed over SWJ (e.g. JTAG or SWD).
|
||||
You need to perform the following actions:
|
||||
ST-LINK/V2
|
||||
----------
|
||||
|
||||
To flash the USB DFU bootloader, we will use OpenOCD (with the [SAM E54 patch](http://openocd.zylin.com/#/c/4272/) and a ST-LINK/V2 SWD adapter.
|
||||
The command will perform the following actions:
|
||||
* remove reserved bootloader space so we can erase it (and reset MCU for change to be effective)
|
||||
* erase the whole flash
|
||||
* program the bootloader
|
||||
* reserve bootloader space
|
||||
|
||||
Using OpenOCD (with the [SAM E54 patch](http://openocd.zylin.com/#/c/4272/)) and a ST-LINK/V2 SWD adapter, run the following command:
|
||||
|
||||
`openocd --file interface/stlink.cfg --command "transport select hla_swd" --command "set CHIPNAME same54" --command "set CPUTAPID 0x2ba01477" --file target/atsame5x.cfg --command "init" --command "reset halt" --command "atsame5 bootloader 0" --command "flash erase_sector 0 0 last" --command "reset halt" --command "program ./bootloader.bin" --command "atsame5 bootloader 16384" --command "reset run" --command "shutdown"`
|
||||
|
||||
`openocd --file interface/stlink.cfg --command "transport select hla_swd" --command "set CHIPNAME same54" --command "set CPUTAPID 0x2ba01477" --file target/atsame5x.cfg --command "init" --command "reset halt" --command "atsame5 bootloader 0" --command "flash erase_sector 0 0 last" --command "reset halt" --command "program ./AtmelStart.bin" --command "atsame5 bootloader 16384" --command "reset run" --command "shutdown"`
|
||||
|
|
|
@ -27,19 +27,11 @@
|
|||
#define GPIO_PIN_FUNCTION_M 12
|
||||
#define GPIO_PIN_FUNCTION_N 13
|
||||
|
||||
/** LED pin to indicate system state */
|
||||
#if defined(SAME54_XPLAINED_PRO)
|
||||
#define LED_SYSTEM GPIO(GPIO_PORTC, 18)
|
||||
#elif defined(SYSMOOCTSIM)
|
||||
/** LED pin to indicate system state (pull high to switch on) */
|
||||
#define LED_SYSTEM GPIO(GPIO_PORTC, 26)
|
||||
#endif
|
||||
|
||||
/** User button to force DFU bootloader (connected to ground when pressed) */
|
||||
#if defined(SAME54_XPLAINED_PRO)
|
||||
#define BUTTON_FORCE_DFU GPIO(GPIO_PORTB, 31)
|
||||
#elif defined(SYSMOOCTSIM)
|
||||
/** User button to force DFu bootloader (connected to ground when pressed) */
|
||||
#define BUTTON_FORCE_DFU GPIO(GPIO_PORTC, 14)
|
||||
#endif
|
||||
|
||||
/** USB D+/D- pins */
|
||||
#define PA24 GPIO(GPIO_PORTA, 24)
|
||||
|
|
|
@ -85,11 +85,7 @@
|
|||
// <0x6140=> osmo-ASF4-DFU
|
||||
// <id> usb_dfud_idproduct
|
||||
#ifndef CONF_USB_OSMOASF4DFU_IDPRODUCT
|
||||
#if defined(SYSMOOCTSIM)
|
||||
#define CONF_USB_OSMOASF4DFU_IDPRODUCT 0x6141
|
||||
#else
|
||||
#define CONF_USB_OSMOASF4DFU_IDPRODUCT 0x6140
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// <o> bcdDevice <0x0000-0xFFFF>
|
||||
|
@ -111,20 +107,11 @@
|
|||
// <s> Unicode string of iManufact
|
||||
// <id> usb_dfud_imanufact_str
|
||||
#ifndef CONF_USB_DFUD_IMANUFACT_STR
|
||||
#if defined(SYSMOOCTSIM)
|
||||
#define CONF_USB_DFUD_IMANUFACT_STR "sysmocom - s.f.m.c. GmbH"
|
||||
#else
|
||||
#define CONF_USB_DFUD_IMANUFACT_STR "Osmocom"
|
||||
#endif
|
||||
#define CONF_USB_DFUD_IMANUFACT_STR "sysmocom"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_USB_DFUD_IMANUFACT_STR_DESC
|
||||
#if defined(SYSMOOCTSIM)
|
||||
#define CONF_USB_DFUD_IMANUFACT_STR_DESC 50, 0x03, 's',0, 'y',0, 's',0, 'm',0, 'o',0, 'c',0, 'o',0, 'm',0, ' ',0, '-',0, ' ',0, \
|
||||
's',0, '.',0, 'f',0, '.',0, 'm',0, '.',0, 'c',0, '.',0, ' ',0, 'G',0, 'm',0, 'b',0, 'H',0,
|
||||
#else
|
||||
#define CONF_USB_DFUD_IMANUFACT_STR_DESC 16, 0x03, 'O', 0x00, 's', 0x00, 'm', 0x00, 'o', 0x00, 'c', 0x00, 'o', 0x00, 'm', 0x00,
|
||||
#endif
|
||||
#define CONF_USB_DFUD_IMANUFACT_STR_DESC 18, 0x03, 's', 0x00, 'y', 0x00, 's', 0x00, 'm', 0x00, 'o', 0x00, 'c', 0x00, 'o', 0x00, 'm', 0x00,
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
@ -143,19 +130,11 @@
|
|||
// <s> Unicode string of iProduct
|
||||
// <id> usb_dfud_iproduct_str
|
||||
#ifndef CONF_USB_DFUD_IPRODUCT_STR
|
||||
#if defined(SYSMOOCTSIM)
|
||||
#define CONF_USB_DFUD_IPRODUCT_STR "sysmoOCTSIM (osmo-ASF4-DFU)"
|
||||
#else
|
||||
#define CONF_USB_DFUD_IPRODUCT_STR "osmo-ASF4-DFU"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CONF_USB_DFUD_IPRODUCT_STR_DESC
|
||||
#if defined(SYSMOOCTSIM)
|
||||
#define CONF_USB_DFUD_IPRODUCT_STR_DESC 56, 0x03, 's', 0x00, 'y', 0x00, 's', 0x00, 'm', 0x00, 'o', 0x00, 'O', 0x00, 'C', 0x00, 'T', 0x00, 'S', 0x00, 'I', 0x00, 'M', 0x00, ' ', 0x00, '(', 0x00, 'o', 0x00, 's', 0x00, 'm', 0x00, 'o', 0x00, '-', 0x00, 'A', 0x00, 'S', 0x00, 'F', 0x00, '4', 0x00, '-', 0x00, 'D', 0x00, 'F', 0x00, 'U', 0x00, ')', 0x00,
|
||||
#else
|
||||
#define CONF_USB_DFUD_IPRODUCT_STR_DESC 28, 0x03, 'o', 0x00, 's', 0x00, 'm', 0x00, 'o', 0x00, '-', 0x00, 'A', 0x00, 'S', 0x00, 'F', 0x00, '4', 0x00, '-', 0x00, 'D', 0x00, 'F', 0x00, 'U', 0x00,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
@ -163,7 +142,7 @@
|
|||
// <e> Enable string descriptor of iSerialNum
|
||||
// <id> usb_dfud_iserialnum_en
|
||||
#ifndef CONF_USB_DFUD_ISERIALNUM_EN
|
||||
#define CONF_USB_DFUD_ISERIALNUM_EN 1
|
||||
#define CONF_USB_DFUD_ISERIALNUM_EN 0
|
||||
#endif
|
||||
|
||||
#ifndef CONF_USB_DFUD_ISERIALNUM
|
||||
|
@ -175,11 +154,11 @@
|
|||
// <s> Unicode string of iSerialNum
|
||||
// <id> usb_dfud_iserialnum_str
|
||||
#ifndef CONF_USB_DFUD_ISERIALNUM_STR
|
||||
#define CONF_USB_DFUD_ISERIALNUM_STR "dummy"
|
||||
#define CONF_USB_DFUD_ISERIALNUM_STR "123456789ABCDEF"
|
||||
#endif
|
||||
|
||||
#ifndef CONF_USB_DFUD_ISERIALNUM_STR_DESC
|
||||
#define CONF_USB_DFUD_ISERIALNUM_STR_DESC 12, 0x03, 'd', 0x00, 'u', 0x00, 'm', 0x00, 'm', 0x00, 'y', 0x00,
|
||||
#define CONF_USB_DFUD_ISERIALNUM_STR_DESC
|
||||
#endif
|
||||
|
||||
// </e>
|
||||
|
|
|
@ -1,9 +1,4 @@
|
|||
#!/bin/bash
|
||||
|
||||
if ! [ -x "$(command -v osmo-deps.sh)" ]; then
|
||||
echo "Error: We need to have scripts/osmo-deps.sh from http://git.osmocom.org/osmo-ci/ in PATH !"
|
||||
exit 2
|
||||
fi
|
||||
#!/bin/sh
|
||||
|
||||
set -ex
|
||||
|
||||
|
@ -13,40 +8,10 @@ if [ -z "$MAKE" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
TOPDIR=`pwd`
|
||||
|
||||
publish="$1"
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
|
||||
verify_value_string_arrays_are_terminated.py $(find . -name "*.[hc]")
|
||||
|
||||
cd gcc
|
||||
$MAKE mrproper
|
||||
# build for EVK
|
||||
$MAKE $PARALLEL_MAKE
|
||||
$MAKE clean
|
||||
# build for sysmoOCTSIM
|
||||
$MAKE $PARALLEL_MAKE BOARD=SYSMOOCTSIM
|
||||
|
||||
if [ "x$publish" = "x--publish" ]; then
|
||||
echo
|
||||
echo "=============== UPLOAD BUILD =============="
|
||||
|
||||
cat > "/build/known_hosts" <<EOF
|
||||
[ftp.osmocom.org]:48 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDgQ9HntlpWNmh953a2Gc8NysKE4orOatVT1wQkyzhARnfYUerRuwyNr1GqMyBKdSI9amYVBXJIOUFcpV81niA7zQRUs66bpIMkE9/rHxBd81SkorEPOIS84W4vm3SZtuNqa+fADcqe88Hcb0ZdTzjKILuwi19gzrQyME2knHY71EOETe9Yow5RD2hTIpB5ecNxI0LUKDq+Ii8HfBvndPBIr0BWYDugckQ3Bocf+yn/tn2/GZieFEyFpBGF/MnLbAAfUKIdeyFRX7ufaiWWz5yKAfEhtziqdAGZaXNaLG6gkpy3EixOAy6ZXuTAk3b3Y0FUmDjhOHllbPmTOcKMry9
|
||||
[ftp.osmocom.org]:48 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPdWn1kEousXuKsZ+qJEZTt/NSeASxCrUfNDW3LWtH+d8Ust7ZuKp/vuyG+5pe5pwpPOgFu7TjN+0lVjYJVXH54=
|
||||
[ftp.osmocom.org]:48 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK8iivY70EiR5NiGChV39gRLjNpC8lvu1ZdHtdMw2zuX
|
||||
EOF
|
||||
SSH_COMMAND="ssh -o 'UserKnownHostsFile=/build/known_hosts' -p 48"
|
||||
rsync --archive --copy-links --verbose --compress --delete --rsh "$SSH_COMMAND" \
|
||||
$TOPDIR/gcc/bootloader-sysmooctsim.{bin,elf} \
|
||||
binaries@ftp.osmocom.org:web-files/osmo-asf4-dfu/latest/
|
||||
rsync --archive --verbose --compress --rsh "$SSH_COMMAND" \
|
||||
$TOPDIR/gcc/bootloader-*-*.{bin,elf} \
|
||||
binaries@ftp.osmocom.org:web-files/osmo-asf4-dfu/all/
|
||||
fi
|
||||
#--exclude $TOPDIR/sysmoOCTSIM/gcc/bootloader-sysmooctsim.bin \
|
||||
#--exclude $TOPDIR/sysmoOCTSIM/gcc/bootloader-sysmooctsim.elf \
|
||||
cd gcc && $MAKE $PARALLEL_MAKE
|
||||
|
||||
osmo-clean-workspace.sh
|
||||
|
|
|
@ -139,38 +139,17 @@ void FLASH_0_init(void)
|
|||
flash_init(&FLASH_0, NVMCTRL);
|
||||
}
|
||||
|
||||
void LED_SYSTEM_on(void)
|
||||
{
|
||||
#if defined(SYSMOOCTSIM)
|
||||
gpio_set_pin_level(LED_SYSTEM, true);
|
||||
#else
|
||||
gpio_set_pin_level(LED_SYSTEM, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void LED_SYSTEM_off(void)
|
||||
{
|
||||
#if defined(SYSMOOCTSIM)
|
||||
gpio_set_pin_level(LED_SYSTEM, false);
|
||||
#else
|
||||
gpio_set_pin_level(LED_SYSTEM, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void system_init(void)
|
||||
{
|
||||
init_mcu();
|
||||
|
||||
// configure system LED
|
||||
LED_SYSTEM_off();
|
||||
gpio_set_pin_level(LED_SYSTEM, false); // switch off LED
|
||||
gpio_set_pin_direction(LED_SYSTEM, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_function(LED_SYSTEM, GPIO_PIN_FUNCTION_OFF);
|
||||
|
||||
// configure force DFU user button
|
||||
gpio_set_pin_direction(BUTTON_FORCE_DFU, GPIO_DIRECTION_IN);
|
||||
#if !defined(SYSMOOCTSIM)
|
||||
gpio_set_pin_pull_mode(BUTTON_FORCE_DFU, GPIO_PULL_UP); // use internal pull-up resistor
|
||||
#endif
|
||||
gpio_set_pin_function(BUTTON_FORCE_DFU, GPIO_PIN_FUNCTION_OFF);
|
||||
|
||||
USB_DEVICE_INSTANCE_init();
|
||||
|
|
|
@ -33,15 +33,6 @@ extern struct flash_descriptor FLASH_0;
|
|||
void FLASH_0_init(void);
|
||||
void FLASH_0_CLOCK_init(void);
|
||||
|
||||
/**
|
||||
* \brief Switch system LED on
|
||||
*/
|
||||
void LED_SYSTEM_on(void);
|
||||
/**
|
||||
* \brief Switch system LED off
|
||||
*/
|
||||
void LED_SYSTEM_off(void);
|
||||
|
||||
/**
|
||||
* \brief Perform system initialization, initialize pins and clocks for
|
||||
* peripherals
|
||||
|
|
32
gcc/Makefile
32
gcc/Makefile
|
@ -1,14 +1,3 @@
|
|||
################################################################################
|
||||
# User configuration. Can be edited
|
||||
################################################################################
|
||||
|
||||
# Set for which board the bootloader should be compiled
|
||||
# run `make clean` for the change to be effective
|
||||
# possible values: SAME54_XPLAINED_PRO, SYSMOOCTSIM
|
||||
BOARD ?= SAME54_XPLAINED_PRO
|
||||
|
||||
GIT_VERSION=$(shell ../git-version-gen $(TOP)/.tarvers)
|
||||
|
||||
################################################################################
|
||||
# Automatically-generated file. Do not edit!
|
||||
################################################################################
|
||||
|
@ -169,8 +158,7 @@ DEPS_AS_ARGS += \
|
|||
"gcc/system_same54.d" \
|
||||
"atmel_start.d"
|
||||
|
||||
BOARD_LC := $(shell echo $(BOARD) | tr A-Z a-z)
|
||||
OUTPUT_FILE_NAME := bootloader-$(BOARD_LC)-$(GIT_VERSION)
|
||||
OUTPUT_FILE_NAME :=AtmelStart
|
||||
QUOTE := "
|
||||
OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf
|
||||
OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf
|
||||
|
@ -180,7 +168,7 @@ vpath %.s ../
|
|||
vpath %.S ../
|
||||
|
||||
# All Target
|
||||
all: $(SUB_DIRS) $(OUTPUT_FILE_PATH) symlink
|
||||
all: $(SUB_DIRS) $(OUTPUT_FILE_PATH)
|
||||
|
||||
# Linker target
|
||||
|
||||
|
@ -203,10 +191,7 @@ $(OUTPUT_FILE_PATH): $(OBJS)
|
|||
"arm-none-eabi-objdump" -h -S "$(OUTPUT_FILE_NAME).elf" > "$(OUTPUT_FILE_NAME).lss"
|
||||
"arm-none-eabi-size" "$(OUTPUT_FILE_NAME).elf"
|
||||
|
||||
.PHONY: symlink
|
||||
symlink: $(OUTPUT_FILE_PATH)
|
||||
ln -sf $(OUTPUT_FILE_NAME).bin bootloader-$(BOARD_LC).bin
|
||||
ln -sf $(OUTPUT_FILE_NAME).elf bootloader-$(BOARD_LC).elf
|
||||
|
||||
|
||||
# Compiler targets
|
||||
|
||||
|
@ -217,7 +202,7 @@ symlink: $(OUTPUT_FILE_PATH)
|
|||
@echo Building file: $<
|
||||
@echo ARM/GNU C Compiler
|
||||
$(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \
|
||||
-D__SAME54P20A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
|
||||
-D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
|
||||
-I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include" \
|
||||
-MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<"
|
||||
@echo Finished building: $<
|
||||
|
@ -226,7 +211,7 @@ symlink: $(OUTPUT_FILE_PATH)
|
|||
@echo Building file: $<
|
||||
@echo ARM/GNU Assembler
|
||||
$(QUOTE)arm-none-eabi-as$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \
|
||||
-D__SAME54P20A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
|
||||
-D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
|
||||
-I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include" \
|
||||
-MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<"
|
||||
@echo Finished building: $<
|
||||
|
@ -235,7 +220,7 @@ symlink: $(OUTPUT_FILE_PATH)
|
|||
@echo Building file: $<
|
||||
@echo ARM/GNU Preprocessing Assembler
|
||||
$(QUOTE)arm-none-eabi-gcc$(QUOTE) -x c -mthumb -DDEBUG -Os -ffunction-sections -mlong-calls -g3 -Wall -c -std=gnu99 \
|
||||
-D__SAME54P20A__ -D$(BOARD) -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
|
||||
-D__SAME54P20A__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
|
||||
-I"../" -I"../config" -I"../hal/include" -I"../hal/utils/include" -I"../hpl/cmcc" -I"../hpl/core" -I"../hpl/dmac" -I"../hpl/gclk" -I"../hpl/mclk" -I"../hpl/nvmctrl" -I"../hpl/osc32kctrl" -I"../hpl/oscctrl" -I"../hpl/pm" -I"../hpl/port" -I"../hpl/ramecc" -I"../hpl/usb" -I"../hri" -I"../" -I"../config" -I"../usb" -I"../usb/class/dfu" -I"../usb/class/dfu/device" -I"../usb/device" -I"../" -I"../CMSIS/Include" -I"../include" \
|
||||
-MD -MP -MF "$(@:%.o=%.d)" -MT"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -o "$@" "$<"
|
||||
@echo Finished building: $<
|
||||
|
@ -256,7 +241,4 @@ clean:
|
|||
rm -f $(DEPS_AS_ARGS)
|
||||
rm -f $(OUTPUT_FILE_NAME).a $(OUTPUT_FILE_NAME).hex $(OUTPUT_FILE_NAME).bin \
|
||||
$(OUTPUT_FILE_NAME).lss $(OUTPUT_FILE_NAME).eep $(OUTPUT_FILE_NAME).map \
|
||||
$(OUTPUT_FILE_NAME).srec bootloader-$(BOARD_LC).bin bootloader-$(BOARD_LC).elf
|
||||
|
||||
mrproper: clean
|
||||
rm -f *.o *.d *.a *.elf *.bin *.ihex *.eep *.lss *.map *.srec
|
||||
$(OUTPUT_FILE_NAME).srec
|
||||
|
|
|
@ -36,8 +36,7 @@ SEARCH_DIR(.)
|
|||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
|
||||
/* The first word of the RAM is used for the DFU magic */
|
||||
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 0x00040000 - 4
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
|
||||
bkupram (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000
|
||||
qspi (rwx) : ORIGIN = 0x04000000, LENGTH = 0x01000000
|
||||
}
|
||||
|
|
151
git-version-gen
151
git-version-gen
|
@ -1,151 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2010-01-28.01
|
||||
|
||||
# Copyright (C) 2007-2010 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# This script is derived from GIT-VERSION-GEN from GIT: http://git.or.cz/.
|
||||
# It may be run two ways:
|
||||
# - from a git repository in which the "git describe" command below
|
||||
# produces useful output (thus requiring at least one signed tag)
|
||||
# - from a non-git-repo directory containing a .tarball-version file, which
|
||||
# presumes this script is invoked like "./git-version-gen .tarball-version".
|
||||
|
||||
# In order to use intra-version strings in your project, you will need two
|
||||
# separate generated version string files:
|
||||
#
|
||||
# .tarball-version - present only in a distribution tarball, and not in
|
||||
# a checked-out repository. Created with contents that were learned at
|
||||
# the last time autoconf was run, and used by git-version-gen. Must not
|
||||
# be present in either $(srcdir) or $(builddir) for git-version-gen to
|
||||
# give accurate answers during normal development with a checked out tree,
|
||||
# but must be present in a tarball when there is no version control system.
|
||||
# Therefore, it cannot be used in any dependencies. GNUmakefile has
|
||||
# hooks to force a reconfigure at distribution time to get the value
|
||||
# correct, without penalizing normal development with extra reconfigures.
|
||||
#
|
||||
# .version - present in a checked-out repository and in a distribution
|
||||
# tarball. Usable in dependencies, particularly for files that don't
|
||||
# want to depend on config.h but do want to track version changes.
|
||||
# Delete this file prior to any autoconf run where you want to rebuild
|
||||
# files to pick up a version string change; and leave it stale to
|
||||
# minimize rebuild time after unrelated changes to configure sources.
|
||||
#
|
||||
# It is probably wise to add these two files to .gitignore, so that you
|
||||
# don't accidentally commit either generated file.
|
||||
#
|
||||
# Use the following line in your configure.ac, so that $(VERSION) will
|
||||
# automatically be up-to-date each time configure is run (and note that
|
||||
# since configure.ac no longer includes a version string, Makefile rules
|
||||
# should not depend on configure.ac for version updates).
|
||||
#
|
||||
# AC_INIT([GNU project],
|
||||
# m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||
# [bug-project@example])
|
||||
#
|
||||
# Then use the following lines in your Makefile.am, so that .version
|
||||
# will be present for dependencies, and so that .tarball-version will
|
||||
# exist in distribution tarballs.
|
||||
#
|
||||
# BUILT_SOURCES = $(top_srcdir)/.version
|
||||
# $(top_srcdir)/.version:
|
||||
# echo $(VERSION) > $@-t && mv $@-t $@
|
||||
# dist-hook:
|
||||
# echo $(VERSION) > $(distdir)/.tarball-version
|
||||
|
||||
case $# in
|
||||
1) ;;
|
||||
*) echo 1>&2 "Usage: $0 \$srcdir/.tarball-version"; exit 1;;
|
||||
esac
|
||||
|
||||
tarball_version_file=$1
|
||||
nl='
|
||||
'
|
||||
|
||||
# First see if there is a tarball-only version file.
|
||||
# then try "git describe", then default.
|
||||
if test -f $tarball_version_file
|
||||
then
|
||||
v=`cat $tarball_version_file` || exit 1
|
||||
case $v in
|
||||
*$nl*) v= ;; # reject multi-line output
|
||||
[0-9]*) ;;
|
||||
*) v= ;;
|
||||
esac
|
||||
test -z "$v" \
|
||||
&& echo "$0: WARNING: $tarball_version_file seems to be damaged" 1>&2
|
||||
fi
|
||||
|
||||
if test -n "$v"
|
||||
then
|
||||
: # use $v
|
||||
elif
|
||||
v=`git describe --abbrev=4 --match='v*' HEAD 2>/dev/null \
|
||||
|| git describe --abbrev=4 HEAD 2>/dev/null` \
|
||||
&& case $v in
|
||||
[0-9]*) ;;
|
||||
v[0-9]*) ;;
|
||||
*) (exit 1) ;;
|
||||
esac
|
||||
then
|
||||
# Is this a new git that lists number of commits since the last
|
||||
# tag or the previous older version that did not?
|
||||
# Newer: v6.10-77-g0f8faeb
|
||||
# Older: v6.10-g0f8faeb
|
||||
case $v in
|
||||
*-*-*) : git describe is okay three part flavor ;;
|
||||
*-*)
|
||||
: git describe is older two part flavor
|
||||
# Recreate the number of commits and rewrite such that the
|
||||
# result is the same as if we were using the newer version
|
||||
# of git describe.
|
||||
vtag=`echo "$v" | sed 's/-.*//'`
|
||||
numcommits=`git rev-list "$vtag"..HEAD | wc -l`
|
||||
v=`echo "$v" | sed "s/\(.*\)-\(.*\)/\1-$numcommits-\2/"`;
|
||||
;;
|
||||
esac
|
||||
|
||||
# Change the first '-' to a '.', so version-comparing tools work properly.
|
||||
# Remove the "g" in git describe's output string, to save a byte.
|
||||
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
|
||||
else
|
||||
v=UNKNOWN
|
||||
fi
|
||||
|
||||
v=`echo "$v" |sed 's/^v//'`
|
||||
|
||||
# Don't declare a version "dirty" merely because a time stamp has changed.
|
||||
git status > /dev/null 2>&1
|
||||
|
||||
dirty=`sh -c 'git diff-index --name-only HEAD' 2>/dev/null` || dirty=
|
||||
case "$dirty" in
|
||||
'') ;;
|
||||
*) # Append the suffix only if there isn't one already.
|
||||
case $v in
|
||||
*-dirty) ;;
|
||||
*) v="$v-dirty" ;;
|
||||
esac ;;
|
||||
esac
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
echo "$v" | tr -d '\012'
|
||||
|
||||
# Local variables:
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-end: "$"
|
||||
# End:
|
|
@ -1135,7 +1135,6 @@ static void _usb_d_dev_out_next(struct _usb_d_dev_ep *ept, bool isr)
|
|||
/* Short packet. */
|
||||
ept->flags.bits.need_zlp = 0;
|
||||
ept->trans_count += last_trans;
|
||||
_usbd_ep_set_out_trans(epn, 0, ept->size, 0);
|
||||
} else {
|
||||
/* Full packets. */
|
||||
ept->trans_count += trans_size;
|
||||
|
@ -1155,6 +1154,9 @@ static void _usb_d_dev_out_next(struct _usb_d_dev_ep *ept, bool isr)
|
|||
if (trans_next > ept->size) {
|
||||
if (trans_next > USB_D_DEV_TRANS_MAX) {
|
||||
trans_next = USB_D_DEV_TRANS_MAX;
|
||||
} else {
|
||||
/* Must expect multiple of ep size. */
|
||||
trans_next -= trans_next & size_mask;
|
||||
}
|
||||
} else if (trans_next < ept->size) {
|
||||
/* Last un-aligned packet should be cached. */
|
||||
|
|
|
@ -306,6 +306,7 @@ int32_t dfudf_init(void)
|
|||
usbdc_register_function(&_dfudf);
|
||||
usbdc_register_handler(USBDC_HDL_REQ, &dfudf_req_h);
|
||||
|
||||
// TODO check if firmware is corrupted and set dfuERROR state if it is
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include "atmel_start.h"
|
||||
#include "atmel_start_pins.h"
|
||||
|
||||
|
@ -28,9 +27,6 @@
|
|||
*/
|
||||
static uint32_t* application_start_address;
|
||||
|
||||
/** Location of the DFU magic value to force starting DFU */
|
||||
static volatile uint32_t* dfu_magic = (uint32_t*)HSRAM_ADDR; // magic value should be written at start of RAM
|
||||
|
||||
/** Check if the bootloader is valid
|
||||
* \return true if the bootloader is valid and can be run
|
||||
* \remark initializes application_start_address
|
||||
|
@ -52,14 +48,7 @@ static bool check_bootloader(void)
|
|||
*/
|
||||
static bool check_force_dfu(void)
|
||||
{
|
||||
if (0x44465521 == *dfu_magic) { // check for the magic value which can be set by the main application
|
||||
*dfu_magic = 0; // erase value so we don't stay in the DFU bootloader upon reset
|
||||
return true;
|
||||
}
|
||||
if (0 == gpio_get_pin_level(BUTTON_FORCE_DFU)) { // signal is low when button is pressed
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return (0 == gpio_get_pin_level(BUTTON_FORCE_DFU)); // signal is low when button is pressed (pulled high externally)
|
||||
}
|
||||
|
||||
/** Check if the application is valid
|
||||
|
@ -74,7 +63,7 @@ static bool check_application(void)
|
|||
* if the SP is not in this range (e.g. flash has been erased) there is no valid application
|
||||
* the second entry in the vector table is the reset address, corresponding to the application start
|
||||
*/
|
||||
return (HSRAM_ADDR == ((*application_start_address) & 0xFFF80000));
|
||||
return (0x20000000 == ((*application_start_address) & 0xFFF80000));
|
||||
}
|
||||
|
||||
/** Start the application
|
||||
|
@ -86,63 +75,10 @@ static void start_application(void)
|
|||
SCB->VTOR = ((uint32_t) application_start_address & SCB_VTOR_TBLOFF_Msk); // re-base the vector table base address
|
||||
asm("bx %0"::"r"(*(application_start_address + 1))); // jump to application Reset Handler in the application */
|
||||
}
|
||||
#if defined(SYSMOOCTSIM)
|
||||
/* Section 9.6 of SAMD5x/E5x Family Data Sheet */
|
||||
static int get_chip_unique_serial(uint8_t *out, size_t len)
|
||||
{
|
||||
uint32_t *out32 = (uint32_t *)out;
|
||||
if (len < 16)
|
||||
return -EINVAL;
|
||||
|
||||
out32[0] = *(uint32_t *)0x008061fc;
|
||||
out32[1] = *(uint32_t *)0x00806010;
|
||||
out32[2] = *(uint32_t *)0x00806014;
|
||||
out32[3] = *(uint32_t *)0x00806018;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* same as get_chip_unique_serial but in hex-string format */
|
||||
static int get_chip_unique_serial_str(char *out, size_t len)
|
||||
{
|
||||
uint8_t buf[16];
|
||||
int rc;
|
||||
|
||||
if (len < 16*2 + 1)
|
||||
return -EINVAL;
|
||||
|
||||
rc = get_chip_unique_serial(buf, sizeof(buf));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
for (int i = 0; i < sizeof(buf); i++)
|
||||
sprintf(&out[i*2], "%02x", buf[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int str_to_usb_desc(char* in, uint8_t in_sz, uint8_t* out, uint8_t out_sz){
|
||||
if (2+in_sz*2 < out_sz)
|
||||
return -1;
|
||||
|
||||
memset(out, 0, out_sz);
|
||||
out[0] = out_sz;
|
||||
out[1] = 0x3;
|
||||
for (int i= 2; i < out_sz; i+=2)
|
||||
out[i] = in[(i >> 1) - 1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
char sernr_buf[16*2+1];
|
||||
//unicode for descriptor
|
||||
uint8_t sernr_buf_descr[1+1+16*2*2];
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
atmel_start_init(); // initialise system
|
||||
#if defined(SYSMOOCTSIM)
|
||||
get_chip_unique_serial_str(sernr_buf, sizeof(sernr_buf));
|
||||
str_to_usb_desc(sernr_buf, sizeof(sernr_buf), sernr_buf_descr, sizeof(sernr_buf_descr));
|
||||
#endif
|
||||
if (!check_bootloader()) { // check bootloader
|
||||
// blink the LED to tell the user we don't know where the application starts
|
||||
while (true) {
|
||||
|
@ -155,9 +91,6 @@ int main(void)
|
|||
if (!check_force_dfu() && check_application()) { // application is valid
|
||||
start_application(); // start application
|
||||
} else {
|
||||
if (!check_application()) { // if the application is corrupted the start DFU start should be dfuERROR
|
||||
dfu_state = USB_DFU_STATE_DFU_ERROR;
|
||||
}
|
||||
usb_dfu(); // start DFU bootloader
|
||||
}
|
||||
}
|
||||
|
|
75
usb_start.c
75
usb_start.c
|
@ -17,7 +17,6 @@
|
|||
*/
|
||||
#include "atmel_start.h"
|
||||
#include "usb_start.h"
|
||||
#include "config/usbd_config.h"
|
||||
|
||||
#if CONF_USBD_HS_SP
|
||||
static uint8_t single_desc_bytes[] = {
|
||||
|
@ -46,71 +45,6 @@ static const usb_dfu_func_desc_t* usb_dfu_func_desc = (usb_dfu_func_desc_t*)&usb
|
|||
/** Ctrl endpoint buffer */
|
||||
static uint8_t ctrl_buffer[64];
|
||||
|
||||
|
||||
|
||||
/* transmit given string descriptor */
|
||||
static bool send_str_desc(uint8_t ep, const struct usb_req *req, enum usb_ctrl_stage stage,
|
||||
const uint8_t *desc)
|
||||
{
|
||||
uint16_t len_req = LE16(req->wLength);
|
||||
uint16_t len_desc = desc[0];
|
||||
uint16_t len_tx;
|
||||
bool need_zlp = !(len_req & (CONF_USB_DFUD_BMAXPKSZ0 - 1));
|
||||
|
||||
if (len_req <= len_desc) {
|
||||
need_zlp = false;
|
||||
len_tx = len_req;
|
||||
} else {
|
||||
len_tx = len_desc;
|
||||
}
|
||||
|
||||
if (ERR_NONE != usbdc_xfer(ep, (uint8_t *)desc, len_tx, need_zlp)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
extern uint8_t sernr_buf_descr[];
|
||||
/* call-back for every control EP request */
|
||||
static int32_t string_req_cb(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
|
||||
{
|
||||
uint8_t index, type;
|
||||
|
||||
if (stage != USB_SETUP_STAGE)
|
||||
return ERR_NOT_FOUND;
|
||||
|
||||
if ((req->bmRequestType & (USB_REQT_TYPE_MASK | USB_REQT_DIR_IN)) !=
|
||||
(USB_REQT_TYPE_STANDARD | USB_REQT_DIR_IN))
|
||||
return ERR_NOT_FOUND;
|
||||
|
||||
/* abort if it's not a GET DESCRIPTOR request */
|
||||
if (req->bRequest != USB_REQ_GET_DESC)
|
||||
return ERR_NOT_FOUND;
|
||||
|
||||
/* abort if it's not about a string descriptor */
|
||||
type = req->wValue >> 8;
|
||||
if (type != USB_DT_STRING)
|
||||
return ERR_NOT_FOUND;
|
||||
#if 0
|
||||
printf("ep=%02x, bmReqT=%04x, bReq=%02x, wValue=%04x, stage=%d\r\n",
|
||||
ep, req->bmRequestType, req->bRequest, req->wValue, stage);
|
||||
#endif
|
||||
/* abort if it's not a standard GET request */
|
||||
index = req->wValue & 0x00FF;
|
||||
switch (index) {
|
||||
case CONF_USB_DFUD_ISERIALNUM:
|
||||
return send_str_desc(ep, req, stage, sernr_buf_descr);
|
||||
default:
|
||||
return ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct usbdc_handler string_req_h = {NULL, (FUNC_PTR)string_req_cb};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief USB DFU Init
|
||||
*/
|
||||
|
@ -118,9 +52,6 @@ void usb_dfu_init(void)
|
|||
{
|
||||
usbdc_init(ctrl_buffer);
|
||||
dfudf_init();
|
||||
#if defined(SYSMOOCTSIM)
|
||||
usbdc_register_handler(USBDC_HDL_REQ, &string_req_h);
|
||||
#endif
|
||||
|
||||
usbdc_start(single_desc);
|
||||
usbdc_attach();
|
||||
|
@ -149,7 +80,7 @@ static void usb_dfu_reset(const enum usb_event ev, const uint32_t param)
|
|||
void usb_dfu(void)
|
||||
{
|
||||
while (!dfudf_is_enabled()); // wait for DFU to be installed
|
||||
LED_SYSTEM_on(); // switch LED on to indicate USB DFU stack is ready
|
||||
gpio_set_pin_level(LED_SYSTEM, true); // switch LED on to indicate USB DFU stack is ready
|
||||
|
||||
ASSERT(hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw) <= 15);
|
||||
uint32_t application_start_address = (15 - hri_nvmctrl_read_STATUS_BOOTPROT_bf(FLASH_0.dev.hw)) * 8192; // calculate bootloader size to know where we should write the application firmware
|
||||
|
@ -158,7 +89,7 @@ void usb_dfu(void)
|
|||
while (true) { // main DFU infinite loop
|
||||
// run the second part of the USB DFU state machine handling non-USB aspects
|
||||
if (USB_DFU_STATE_DFU_DNLOAD_SYNC == dfu_state || USB_DFU_STATE_DFU_DNBUSY == dfu_state) { // there is some data to be flashed
|
||||
LED_SYSTEM_off(); // switch LED off to indicate we are flashing
|
||||
gpio_set_pin_level(LED_SYSTEM, false); // switch LED off to indicate we are flashing
|
||||
if (dfu_download_length > 0) { // there is some data to be flashed
|
||||
int32_t rc = flash_write(&FLASH_0, application_start_address + dfu_download_offset, dfu_download_data, dfu_download_length); // write downloaded data chunk to flash
|
||||
if (ERR_NONE == rc) {
|
||||
|
@ -177,7 +108,7 @@ void usb_dfu(void)
|
|||
// this case should not happen, but it's not a critical error
|
||||
dfu_state = USB_DFU_STATE_DFU_DNLOAD_IDLE; // indicate flashing can continue
|
||||
}
|
||||
LED_SYSTEM_on(); // switch LED on to indicate USB DFU can resume
|
||||
gpio_set_pin_level(LED_SYSTEM, true); // switch LED on to indicate USB DFU can resume
|
||||
}
|
||||
if (USB_DFU_STATE_DFU_MANIFEST == dfu_state) { // we can start manifestation (finish flashing)
|
||||
// in theory every DFU files should have a suffix to with a CRC to check the data
|
||||
|
|
Loading…
Reference in New Issue