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