Skip to content

Commit

Permalink
Merge pull request #754 from xmos-jmccarthy/master
Browse files Browse the repository at this point in the history
Add DFU Class per Version 1.1 Spec
  • Loading branch information
hathach authored May 26, 2021
2 parents 220f441 + f9c542a commit 85186ab
Show file tree
Hide file tree
Showing 27 changed files with 1,416 additions and 72 deletions.
Empty file.
37 changes: 37 additions & 0 deletions examples/device/dfu/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# use directory name for project id
get_filename_component(PROJECT ${CMAKE_CURRENT_SOURCE_DIR} NAME)
set(PROJECT ${BOARD}-${PROJECT})

# TOP is absolute path to root directory of TinyUSB git repo
set(TOP "../../..")
get_filename_component(TOP "${TOP}" REALPATH)

# Check for -DFAMILY=
if(FAMILY STREQUAL "rp2040")
cmake_minimum_required(VERSION 3.12)

include(${TOP}/hw/bsp/${FAMILY}/pico_sdk_import.cmake)
project(${PROJECT})
add_executable(${PROJECT})

include(${TOP}/hw/bsp/${FAMILY}/family.cmake)

# Example source
target_sources(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)

# Example include
target_include_directories(${PROJECT} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)

# Example defines
target_compile_definitions(${PROJECT} PUBLIC
CFG_TUSB_OS=OPT_OS_PICO
)

else()
message(FATAL_ERROR "Invalid FAMILY specified: ${FAMILY}")
endif()
12 changes: 12 additions & 0 deletions examples/device/dfu/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
include ../../../tools/top.mk
include ../../make.mk

INC += \
src \
$(TOP)/hw \

# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))

include ../../rules.mk
187 changes: 187 additions & 0 deletions examples/device/dfu/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

/*
* After device is enumerated in dfu mode run the following commands
*
* To transfer firmware from host to device:
*
* $ dfu-util -D [filename]
*
* To transfer firmware from device to host:
*
* $ dfu-util -U [filename]
*
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "bsp/board.h"
#include "tusb.h"


//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF PROTYPES
//--------------------------------------------------------------------+
#ifndef DFU_VERBOSE
#define DFU_VERBOSE 0
#endif

/* Blink pattern
* - 1000 ms : device should reboot
* - 250 ms : device not mounted
* - 1000 ms : device mounted
* - 2500 ms : device is suspended
*/
enum {
BLINK_DFU_MODE = 100,
BLINK_NOT_MOUNTED = 250,
BLINK_MOUNTED = 1000,
BLINK_SUSPENDED = 2500,
};

static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;

void led_blinking_task(void);

/*------------- MAIN -------------*/
int main(void)
{
board_init();

tusb_init();

while (1)
{
tud_task(); // tinyusb device task
led_blinking_task();
}

return 0;
}

//--------------------------------------------------------------------+
// Device callbacks
//--------------------------------------------------------------------+

// Invoked when device is mounted
void tud_mount_cb(void)
{
blink_interval_ms = BLINK_MOUNTED;
}

// Invoked when device is unmounted
void tud_umount_cb(void)
{
blink_interval_ms = BLINK_NOT_MOUNTED;
}

// Invoked when usb bus is suspended
// remote_wakeup_en : if host allow us to perform remote wakeup
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
void tud_suspend_cb(bool remote_wakeup_en)
{
(void) remote_wakeup_en;
blink_interval_ms = BLINK_SUSPENDED;
}

// Invoked when usb bus is resumed
void tud_resume_cb(void)
{
blink_interval_ms = BLINK_MOUNTED;
}

// Invoked on DFU_DETACH request to reboot to the bootloader
void tud_dfu_runtime_reboot_to_dfu_cb(void)
{
blink_interval_ms = BLINK_DFU_MODE;
}

//--------------------------------------------------------------------+
// Class callbacks
//--------------------------------------------------------------------+
bool tud_dfu_firmware_valid_check_cb(void)
{
printf(" Firmware check\r\n");
return true;
}

void tud_dfu_req_dnload_data_cb(uint16_t wBlockNum, uint8_t* data, uint16_t length)
{
(void) data;
printf(" Received BlockNum %u of length %u\r\n", wBlockNum, length);

#if DFU_VERBOSE
for(uint16_t i=0; i<length; i++)
{
printf(" [%u][%u]: %x\r\n", wBlockNum, i, (uint8_t)data[i]);
}
#endif

tud_dfu_dnload_complete();
}

bool tud_dfu_device_data_done_check_cb(void)
{
printf(" Host said no more data... Returning true\r\n");
return true;
}

void tud_dfu_abort_cb(void)
{
printf(" Host aborted transfer\r\n");
}

#define UPLOAD_SIZE (29)
const uint8_t upload_test[UPLOAD_SIZE] = "Hello world from TinyUSB DFU!";

uint16_t tud_dfu_req_upload_data_cb(uint16_t block_num, uint8_t* data, uint16_t length)
{
(void) block_num;
(void) length;

memcpy(data, upload_test, UPLOAD_SIZE);

return UPLOAD_SIZE;
}

//--------------------------------------------------------------------+
// BLINKING TASK + Indicator pulse
//--------------------------------------------------------------------+

void led_blinking_task(void)
{
static uint32_t start_ms = 0;
static bool led_state = false;

// Blink every interval ms
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
start_ms += blink_interval_ms;

board_led_write(led_state);
led_state = 1 - led_state; // toggle
}
90 changes: 90 additions & 0 deletions examples/device/dfu/src/tusb_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* tusb_config.h
*
* Created on: May 5, 2021
* Author: Jeremiah McCarthy
*/

#ifndef TUSB_CONFIG_H_
#define TUSB_CONFIG_H_

#ifdef __cplusplus
extern "C" {
#endif

//--------------------------------------------------------------------
// COMMON CONFIGURATION
//--------------------------------------------------------------------

// defined by board.mk
#ifndef CFG_TUSB_MCU
#error CFG_TUSB_MCU must be defined
#endif

// RHPort number used for device can be defined by board.mk, default to port 0
#ifndef BOARD_DEVICE_RHPORT_NUM
#define BOARD_DEVICE_RHPORT_NUM 0
#endif

// RHPort max operational speed can defined by board.mk
// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
#ifndef BOARD_DEVICE_RHPORT_SPEED
#if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56)
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
#else
#define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
#endif
#endif

// Device mode with rhport and speed defined by board.mk
#if BOARD_DEVICE_RHPORT_NUM == 0
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#elif BOARD_DEVICE_RHPORT_NUM == 1
#define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
#else
#error "Incorrect RHPort configuration"
#endif

#ifndef CFG_TUSB_OS
#define CFG_TUSB_OS OPT_OS_NONE
#endif

// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
// #define CFG_TUSB_DEBUG 0

/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
* Tinyusb use follows macros to declare transferring memory so that they can be put
* into those specific section.
* e.g
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
*/
#ifndef CFG_TUSB_MEM_SECTION
#define CFG_TUSB_MEM_SECTION
#endif

#ifndef CFG_TUSB_MEM_ALIGN
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#endif

//--------------------------------------------------------------------
// DEVICE CONFIGURATION
//--------------------------------------------------------------------

#ifndef CFG_TUD_ENDPOINT0_SIZE
#define CFG_TUD_ENDPOINT0_SIZE 64
#endif

#define CFG_TUD_DFU_TRANSFER_BUFFER_SIZE 4096

//------------- CLASS -------------//

#define CFG_TUD_DFU_RUNTIME 0
#define CFG_TUD_DFU_MODE 1

#ifdef __cplusplus
}
#endif

#endif /* TUSB_CONFIG_H_ */
Loading

0 comments on commit 85186ab

Please sign in to comment.