Compare commits

..

16 Commits

Author SHA1 Message Date
Eric Wild 3761545fcf usb serial number descriptor
Change-Id: I4a23682cee0849c788e5f6c611df4ed1f1cac3da
2021-06-30 08:16:43 +00:00
Harald Welte b932c514f3 contrib/jenkins.sh: Switch from rita -> ftp.osmocom.org
We should use service-aliases and not the primary host name, as
that makes migration between machines hard.

Change-Id: I1ba0a5e6185af1fba5e7cccb7966fda2fa50bf24
2021-04-22 11:21:56 +02:00
Harald Welte b90f7068da update iManufacturer strings (full sysmocom company name, ...)
this ensures the iManufacturer string is identical across different
products.

Change-Id: I45ce8b6d182d6e2d9f1fefa4928f85860b68d2fb
2019-12-06 22:34:13 +01:00
Harald Welte dc5bdcf7db jenkins.sh: Introduce 'make clean' between different board builds
Change-Id: I907c9d7ec805ee7f1d7383a23941d338bcd89dfd
2019-11-30 22:00:57 +01:00
Harald Welte 53feef0f69 contrib/jenkins.sh: move to /bin/bash
We need this in order to support constructs like foobar.{bin,elf} to
expand properly.

Change-Id: I3d12795da7ab29d1bd0f7371c3365c54c79ae09a
2019-11-30 22:00:57 +01:00
Harald Welte ed363a4a0e jenkins.sh: Add --publish to publish binaries, similar to simtrace2.git
Binaries will be on https://ftp.osmocom.org/binaries/osmo-asf4-dfu/

Change-Id: Idc27a3d7d2bd7cbee1061ce778ace280eff17bf4
2019-11-30 16:18:22 +01:00
Harald Welte aec6b1ee85 create bootloader-$(BOARD).{elf,bin} symlinks
Change-Id: I3a1eb038e51f4b38ae2e2154bd53c615d98db517
2019-11-11 19:18:40 +01:00
Harald Welte 397966fa3c include board (target) in filename, files are now called like
bootloader-sysmooctsim-0.1.1-5554-dirty.elf

Change-Id: Ibdde1c02d5dd3bcd714bae1d374397d9596fede0
2019-11-11 19:14:51 +01:00
Harald Welte 5554133528 name binaries including their git version number
Change-Id: I90fb8e6effd05c3e472492aced7c07a2ce837e5e
Related: OS#3452
2019-06-20 18:39:55 +02:00
Kevin Redon 5538ea8530 minox: use RAM address define instead of hardcoded value
Change-Id: I81a42637194cbf0b5152fe38c691522021ab7582
2019-02-15 10:10:38 +01:00
Kevin Redon 6794b97e21 fix DFU magic address and linker script
using the address specified in the linker script leads to a large
output binary (as large as the address specified.
instead the address is now specified in the source file.

Change-Id: I69ad101593e903b74084f179cfc97fccccdfa5a3
2019-02-15 10:08:39 +01:00
Kevin Redon b842918d16 set initial DFU state to ERROR if application is corrupt
as specified in DFU standard

Change-Id: Icd503a2d19f829eb43a83c28b526b73d595640f0
2019-02-14 18:59:39 +01:00
Kevin Redon 45554d71f9 add force DFU using magic value
if the string "DFU!" is found at the beginning of the RAM (e.g. as
written by the main application during USB detach), the DFU
bootloader will be started.

Change-Id: I298e3697c06d352a6e0f47266097844c490e1722
2019-02-14 18:45:20 +01:00
Kevin Redon 9336494491 minor: rename output binary to bootloader
Change-Id: I4dfa761c482d6d061eddf3ff8ee91ec049955f53
2019-02-14 18:45:17 +01:00
Kevin Redon 5fcc4ac54a add specific board support, including sysmoOCTSIM
the board specific definitions should be coded when particular
environment variable/marco is defined.
this macro name is provided by the makefile in the BOARD variable.
this allows to compile the bootloader for specific devices.
see README for more information.
the board definition for the sysmoOCTSIM is also added.

Change-Id: Ie51a3af7c77ba76ac40570b871f31fd527fb255b
2019-02-14 17:21:14 +01:00
Benjamin Freeman f278032e9f fix USB transfer
this ASFv4 USB library change fixes USB transfer.
two transfer-size issues existed:
- on multi-packet transfer if the last packet was less than the
USB transfer packet size, the packet would be received but not
acknowledged
- during normal transfer the packet size of a previous packet set
the size of the current packet, ignoring the actual transfer size

transfer with a combination of partial or full USB single packet,
USB multi-packet, max transfer, and control endpoint sizes was
successfully tested (in bytes): 4, 32, 64, 128, 129, 512, 516,
544, 576, 640, 641, 1024, 1028

Change-Id: Ic4e64168e865362e12e0b76386f964895b8b6c20
2019-02-14 12:48:56 +01:00
13 changed files with 468 additions and 37 deletions

View File

@ -1,10 +1,22 @@
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.
This branch is specific to the proprietary sysmocom sysmoOCTSIM hardware.
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).
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
=======
@ -16,22 +28,29 @@ 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-cimpilig toolchain:
Use the 'Makefile' script to compile the source code using the ARM none EABI GCC cross-compiling toolchain:
```
cd gcc
make
```
The resulting firmware binary is `AtmelStart.bin`.
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`.
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.
@ -39,14 +58,29 @@ 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.
ST-LINK/V2
----------
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:
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
`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"`
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"`

View File

@ -27,11 +27,19 @@
#define GPIO_PIN_FUNCTION_M 12
#define GPIO_PIN_FUNCTION_N 13
/** LED pin to indicate system state (pull high to switch on) */
/** LED pin to indicate system state */
#if defined(SAME54_XPLAINED_PRO)
#define LED_SYSTEM GPIO(GPIO_PORTC, 18)
#elif defined(SYSMOOCTSIM)
#define LED_SYSTEM GPIO(GPIO_PORTC, 26)
#endif
/** User button to force DFu bootloader (connected to ground when pressed) */
/** 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)
#define BUTTON_FORCE_DFU GPIO(GPIO_PORTC, 14)
#endif
/** USB D+/D- pins */
#define PA24 GPIO(GPIO_PORTA, 24)

View File

@ -85,7 +85,11 @@
// <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>
@ -107,11 +111,20 @@
// <s> Unicode string of iManufact
// <id> usb_dfud_imanufact_str
#ifndef CONF_USB_DFUD_IMANUFACT_STR
#define CONF_USB_DFUD_IMANUFACT_STR "sysmocom"
#if defined(SYSMOOCTSIM)
#define CONF_USB_DFUD_IMANUFACT_STR "sysmocom - s.f.m.c. GmbH"
#else
#define CONF_USB_DFUD_IMANUFACT_STR "Osmocom"
#endif
#endif
#ifndef CONF_USB_DFUD_IMANUFACT_STR_DESC
#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,
#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
#endif
// </e>
@ -130,11 +143,19 @@
// <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>
@ -142,7 +163,7 @@
// <e> Enable string descriptor of iSerialNum
// <id> usb_dfud_iserialnum_en
#ifndef CONF_USB_DFUD_ISERIALNUM_EN
#define CONF_USB_DFUD_ISERIALNUM_EN 0
#define CONF_USB_DFUD_ISERIALNUM_EN 1
#endif
#ifndef CONF_USB_DFUD_ISERIALNUM
@ -154,11 +175,11 @@
// <s> Unicode string of iSerialNum
// <id> usb_dfud_iserialnum_str
#ifndef CONF_USB_DFUD_ISERIALNUM_STR
#define CONF_USB_DFUD_ISERIALNUM_STR "123456789ABCDEF"
#define CONF_USB_DFUD_ISERIALNUM_STR "dummy"
#endif
#ifndef CONF_USB_DFUD_ISERIALNUM_STR_DESC
#define 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,
#endif
// </e>

View File

@ -1,4 +1,9 @@
#!/bin/sh
#!/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
set -ex
@ -8,10 +13,40 @@ 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 $PARALLEL_MAKE
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 \
osmo-clean-workspace.sh

View File

@ -139,17 +139,38 @@ 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
gpio_set_pin_level(LED_SYSTEM, false); // switch off LED
LED_SYSTEM_off();
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();

View File

@ -33,6 +33,15 @@ 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

View File

@ -1,3 +1,14 @@
################################################################################
# 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!
################################################################################
@ -158,7 +169,8 @@ DEPS_AS_ARGS += \
"gcc/system_same54.d" \
"atmel_start.d"
OUTPUT_FILE_NAME :=AtmelStart
BOARD_LC := $(shell echo $(BOARD) | tr A-Z a-z)
OUTPUT_FILE_NAME := bootloader-$(BOARD_LC)-$(GIT_VERSION)
QUOTE := "
OUTPUT_FILE_PATH +=$(OUTPUT_FILE_NAME).elf
OUTPUT_FILE_PATH_AS_ARGS +=$(OUTPUT_FILE_NAME).elf
@ -168,7 +180,7 @@ vpath %.s ../
vpath %.S ../
# All Target
all: $(SUB_DIRS) $(OUTPUT_FILE_PATH)
all: $(SUB_DIRS) $(OUTPUT_FILE_PATH) symlink
# Linker target
@ -191,7 +203,10 @@ $(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
@ -202,7 +217,7 @@ $(OUTPUT_FILE_PATH): $(OBJS)
@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__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
-D__SAME54P20A__ -D$(BOARD) -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: $<
@ -211,7 +226,7 @@ $(OUTPUT_FILE_PATH): $(OBJS)
@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__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
-D__SAME54P20A__ -D$(BOARD) -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: $<
@ -220,7 +235,7 @@ $(OUTPUT_FILE_PATH): $(OBJS)
@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__ -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 \
-D__SAME54P20A__ -D$(BOARD) -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: $<
@ -241,4 +256,7 @@ 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
$(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

View File

@ -36,7 +36,8 @@ SEARCH_DIR(.)
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = 0x00100000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00040000
/* The first word of the RAM is used for the DFU magic */
ram (rwx) : ORIGIN = 0x20000000 + 4, LENGTH = 0x00040000 - 4
bkupram (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000
qspi (rwx) : ORIGIN = 0x04000000, LENGTH = 0x01000000
}

151
git-version-gen Executable file
View File

@ -0,0 +1,151 @@
#!/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:

View File

@ -1135,6 +1135,7 @@ 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;
@ -1154,9 +1155,6 @@ 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. */

View File

@ -306,7 +306,6 @@ 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;
}

View File

@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include "atmel_start.h"
#include "atmel_start_pins.h"
@ -27,6 +28,9 @@
*/
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
@ -48,7 +52,14 @@ static bool check_bootloader(void)
*/
static bool check_force_dfu(void)
{
return (0 == gpio_get_pin_level(BUTTON_FORCE_DFU)); // signal is low when button is pressed (pulled high externally)
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;
}
/** Check if the application is valid
@ -63,7 +74,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 (0x20000000 == ((*application_start_address) & 0xFFF80000));
return (HSRAM_ADDR == ((*application_start_address) & 0xFFF80000));
}
/** Start the application
@ -75,10 +86,63 @@ 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) {
@ -91,6 +155,9 @@ 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
}
}

View File

@ -17,6 +17,7 @@
*/
#include "atmel_start.h"
#include "usb_start.h"
#include "config/usbd_config.h"
#if CONF_USBD_HS_SP
static uint8_t single_desc_bytes[] = {
@ -45,6 +46,71 @@ 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
*/
@ -52,6 +118,9 @@ 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();
@ -80,7 +149,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
gpio_set_pin_level(LED_SYSTEM, true); // switch LED on to indicate USB DFU stack is ready
LED_SYSTEM_on(); // 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
@ -89,7 +158,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
gpio_set_pin_level(LED_SYSTEM, false); // switch LED off to indicate we are flashing
LED_SYSTEM_off(); // 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) {
@ -108,7 +177,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
}
gpio_set_pin_level(LED_SYSTEM, true); // switch LED on to indicate USB DFU can resume
LED_SYSTEM_on(); // 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