mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
bootloaders: add riotboot_tinyusb_dfu bootloader
This commit is contained in:
parent
37b151111f
commit
a4f870f25b
19
bootloaders/riotboot_tinyusb_dfu/Makefile
Normal file
19
bootloaders/riotboot_tinyusb_dfu/Makefile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Default RIOT bootloader
|
||||||
|
APPLICATION = riotboot_tinyusb_dfu
|
||||||
|
|
||||||
|
# Add RIOTBOOT tinyUSB DFU integration
|
||||||
|
USEMODULE += riotboot_tinyusb_dfu
|
||||||
|
|
||||||
|
# Use xtimer for scheduled reboot
|
||||||
|
USEMODULE += ztimer
|
||||||
|
USEMODULE += ztimer_init
|
||||||
|
|
||||||
|
# USB device vendor and product ID
|
||||||
|
# pid.codes test VID/PID, not globally unique
|
||||||
|
|
||||||
|
# The VID/PID pair allocated for the RIOT bootloader
|
||||||
|
# as allocated on https://pid.codes/1209/7D02/
|
||||||
|
USB_VID ?= 1209
|
||||||
|
USB_PID ?= 7D02
|
||||||
|
|
||||||
|
include ../riotboot_common.mk
|
86
bootloaders/riotboot_tinyusb_dfu/doc.txt
Normal file
86
bootloaders/riotboot_tinyusb_dfu/doc.txt
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
@defgroup pkg_tinyusb_dfu riotboot tinyUSB DFU
|
||||||
|
@ingroup pkg_tinyusb
|
||||||
|
@ingroup bootloaders
|
||||||
|
|
||||||
|
# Overview
|
||||||
|
|
||||||
|
`riotboot_tinyusb_dfu` is a variation of @ref bootloader_riotboot that adds
|
||||||
|
USB device firmware upgrade (DFU) based on the tinyUSB device stack package.
|
||||||
|
It uses a board's USB interface to allow firmware upgrades from inside the
|
||||||
|
bootloader.
|
||||||
|
|
||||||
|
At startup, the DFU mode is entered when either
|
||||||
|
|
||||||
|
- none of the slots contains a valid firmware image, or
|
||||||
|
- the first button was pressed when the board started (configurable at board
|
||||||
|
level using @ref BTN_BOOTLOADER_PIN), or
|
||||||
|
- the last running firmware asked the bootloader to go to DFU mode by using a
|
||||||
|
magic number (see @ref RIOTBOOT_MAGIC_ADDR).
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
|
||||||
|
- The board must have functional USB support and has to support the
|
||||||
|
`tinyusb_device` feature.
|
||||||
|
- The board must have functional `riotboot` support, see
|
||||||
|
@ref bootloader_riotboot.
|
||||||
|
|
||||||
|
# Flashing riotboot_tinyusb_dfu
|
||||||
|
|
||||||
|
The `riotboot_tinyusb_dfu` bootloader can be flashed using a regular programmer
|
||||||
|
like any other application:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ make -C bootloaders/riotboot_tinyusb_dfu BOARD=... all flash
|
||||||
|
```
|
||||||
|
|
||||||
|
Depending on your setup, you may need to select the right `PROGRAMMER`
|
||||||
|
(and its details) in addition to your board.
|
||||||
|
|
||||||
|
# DFU mode
|
||||||
|
|
||||||
|
A device in riotboot DFU mode can be recognized in the USB device list by
|
||||||
|
its VID/PID pair 1209:7d02:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ lsusb
|
||||||
|
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
|
||||||
|
Bus 001 Device 005: ID 138a:003f [...]
|
||||||
|
Bus 001 Device 004: ID 8087:0a2b [...]
|
||||||
|
Bus 001 Device 045: ID 1209:7d02 Generic USB device
|
||||||
|
Bus 001 Device 001: ID 1d6b:0002 [...]
|
||||||
|
```
|
||||||
|
|
||||||
|
When running in DFU mode, the bootloader allows writing to either of the
|
||||||
|
two firmware slots.
|
||||||
|
|
||||||
|
When the device is attached and in DFU mode (or the current firmware uses the
|
||||||
|
`tinyusb_dfu` module), new firmware can be flashed to slot 0 using:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ FEATURES_REQUIRED+=riotboot USEMODULE+=tinyusb_dfu make -C examples/saul BOARD=particle-xenon \
|
||||||
|
PROGRAMMER=dfu-util USB_VID=1209 USB_PID=7d02 all riotboot/flash-slot0
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of setting `USB_VID` and `USB_PID`, the variable `DFU_USB_ID` could also
|
||||||
|
be used to specify the DFU device to be used.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ FEATURES_REQUIRED+=riotboot USEMODULE+=tinyusb_dfu make -C examples/saul BOARD=particle-xenon \
|
||||||
|
PROGRAMMER=dfu-util DFU_USB_ID=1209:7d02 all riotboot/flash-slot0
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that when building and flashing a different slot (e.g. `flash-slot1`),
|
||||||
|
not only is the image built for that slot, but also `dfu-util` gets passed
|
||||||
|
`--alt 1` (via the `DFU_ALT` build variable) to store it in the right place.
|
||||||
|
|
||||||
|
# Entering DFU mode
|
||||||
|
|
||||||
|
When RIOT applications are built with `USEMODULE=tinyusb_dfu`,
|
||||||
|
they implement what is called "runtime mode" in DFU.
|
||||||
|
|
||||||
|
In runtime mode, it is visible to the `dfu-util` that they are upgradable.
|
||||||
|
On firmware upgrades, the build system can send a command via USB to enter
|
||||||
|
DFU mode. This can also be done manually using `dfu-util -e`.
|
||||||
|
|
||||||
|
*/
|
86
bootloaders/riotboot_tinyusb_dfu/main.c
Normal file
86
bootloaders/riotboot_tinyusb_dfu/main.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
* Inria
|
||||||
|
* 2020 Mesotic SAS
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup bootloaders
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief RIOT-based bootloader with USB-DFU support
|
||||||
|
*
|
||||||
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||||
|
* @author Francisco Acosta <francisco.acosta@inria.fr>
|
||||||
|
* @author Dylan Laduranty <dylan.laduranty@mesotic.com>
|
||||||
|
*
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "cpu.h"
|
||||||
|
#include "panic.h"
|
||||||
|
#include "riotboot/slot.h"
|
||||||
|
#include "riotboot/usb_dfu.h"
|
||||||
|
#include "ztimer.h"
|
||||||
|
|
||||||
|
#include "riotboot/bootloader_selection.h"
|
||||||
|
|
||||||
|
#ifdef BTN_BOOTLOADER_PIN
|
||||||
|
#include "periph/gpio.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static bool _bootloader_alternative_mode(void)
|
||||||
|
{
|
||||||
|
#ifdef BTN_BOOTLOADER_PIN
|
||||||
|
gpio_init(BTN_BOOTLOADER_PIN, BTN_BOOTLOADER_MODE);
|
||||||
|
return (bool)gpio_read(BTN_BOOTLOADER_PIN) != BTN_BOOTLOADER_INVERTED;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void kernel_init(void)
|
||||||
|
{
|
||||||
|
uint32_t version = 0;
|
||||||
|
int slot = -1;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < riotboot_slot_numof; i++) {
|
||||||
|
const riotboot_hdr_t *riot_hdr = riotboot_slot_get_hdr(i);
|
||||||
|
if (riotboot_slot_validate(i)) {
|
||||||
|
/* skip slot if metadata broken */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (riot_hdr->start_addr != riotboot_slot_get_image_startaddr(i)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (slot == -1 || riot_hdr->version > version) {
|
||||||
|
version = riot_hdr->version;
|
||||||
|
slot = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init ztimer before starting DFU mode */
|
||||||
|
ztimer_init();
|
||||||
|
|
||||||
|
/* Flash the unused slot if magic word is set */
|
||||||
|
riotboot_usb_dfu_init(0);
|
||||||
|
|
||||||
|
if (slot != -1 && !_bootloader_alternative_mode()) {
|
||||||
|
riotboot_slot_jump(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Nothing to boot, stay in DFU mode to flash a slot */
|
||||||
|
riotboot_usb_dfu_init(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void core_panic(core_panic_t crash_code, const char *message)
|
||||||
|
{
|
||||||
|
(void)crash_code;
|
||||||
|
(void)message;
|
||||||
|
while (1) {}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user