diff --git a/.gitmodules b/.gitmodules index 74acdd6..8acbe85 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,6 @@ [submodule "tinyusb"] path = lib/tinyusb url = https://github.com/hathach/tinyusb.git - branch = develop [submodule "lib/nrfx"] path = lib/nrfx url = https://github.com/NordicSemiconductor/nrfx.git diff --git a/Makefile b/Makefile index eeec375..ddcc508 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,6 @@ SD_HEX = $(SD_PATH)/$(SD_FILENAME)_softdevice.hex LD_FILE = $(SRC_PATH)/linker/$(SD_NAME)_v$(SD_VER1).ld MERGED_FNAME = $(OUTPUT_FILENAME)_$(SD_NAME)_$(SD_VERSION) -RELEASE_DIR = bin/$(BOARD) MK_DIS_FIRMWARE = "$(SD_NAME) $(SD_VERSION)" @@ -86,7 +85,7 @@ BOARD_LIST = $(sort $(subst .h,,$(subst src/boards/,,$(wildcard src/boards/*.h)) NRF52832_BOARDLIST = feather_nrf52832 IS_52832 = $(filter $(BOARD),$(NRF52832_BOARDLIST)) -ifeq ($(filter $(MAKECMDGOALS),all-board all-release help),) +ifeq ($(filter $(MAKECMDGOALS),all-board help),) ifeq ($(BOARD),) $(info You must provide a BOARD parameter with 'BOARD=') $(info Supported boards are: $(BOARD_LIST)) @@ -360,20 +359,11 @@ _make_all_board = $(foreach b,$(BOARD_LIST), $(call _make_board,$b,$1)) all-board: $(call _make_all_board,clean all) -all-release: - $(call _make_all_board,clean all release) - help: - @echo To flash (with jlink) a pre-built binary with a specific version to a board - @echo $$ make BOARD=feather_nrf52840_express VERSION=6.1.1r0 flash - @echo - @echo To flash (with dfu) a pre-built binary with a specific version to a board - @echo $$ make BOARD=feather_nrf52840_express VERSION=6.1.1r0 SERIAL=/dev/ttyACM0 dfu0-flash - @echo @echo To compile and build the current code for a board @echo $$ make BOARD=feather_nrf52840_express all @echo - @echo To flash current code using jlink + @echo To flash current code using Jlink @echo $$ make BOARD=feather_nrf52840_express flash @echo @echo To flash current code using existing bootloader dfu @@ -388,8 +378,6 @@ __check_defined = \ $(if $(value $1),, \ $(error Undefined make flag: $1$(if $2, ($2)))) -ifeq ($(VERSION),) - # Flash the compiled flash: $(BUILD)/$(OUTPUT_FILENAME)-nosd.hex @echo Flashing: $< @@ -397,26 +385,7 @@ flash: $(BUILD)/$(OUTPUT_FILENAME)-nosd.hex dfu-flash: $(BUILD)/$(MERGED_FNAME).zip @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) - $(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank - -else - -ifeq ($(VERSION),latest) -VERSION_FPATH = $(RELEASE_DIR)/$(MERGED_FNAME) -else -VERSION_FPATH = bin/$(BOARD)/$(VERSION)/$(OUTPUT_FILENAME)_$(SD_NAME)_$(VERSION) -endif - -# Flash specific version in binary release folder -flash: - @echo Flashing: $(VERSION_FPATH).hex - $(NRFJPROG) --program $(VERSION_FPATH).hex --chiperase -f nrf52 --reset - -dfu-flash: - @:$(call check_defined, SERIAL, example: SERIAL=/dev/ttyACM0) - $(NRFUTIL) --verbose dfu serial --package $(VERSION_FPATH).zip -p $(SERIAL) -b 115200 --singlebank - -endif + $(NRFUTIL) --verbose dfu serial --package $< -p $(SERIAL) -b 115200 --singlebank --touch 1200 sd: @echo Flashing: $(SD_HEX) @@ -457,7 +426,7 @@ size: $(BUILD)/$(OUTPUT_FILENAME)-nosd.out #******************* Binary generator ******************* -.phony: genhex genpkg release +.phony: genhex genpkg ## Create binary .hex file from the .out file genhex: $(BUILD)/$(OUTPUT_FILENAME)-nosd.hex @@ -478,11 +447,3 @@ genpkg: $(BUILD)/$(MERGED_FNAME).zip $(BUILD)/$(MERGED_FNAME).zip: $(BUILD)/$(OUTPUT_FILENAME)-nosd.hex @$(NRFUTIL) dfu genpkg --dev-type 0x0052 --dev-revision $(DFU_DEV_REV) --bootloader $< --softdevice $(SD_HEX) $@ - -# Create SD+bootloader combo with hex & dfu package at release folder -release: combinehex genpkg - @echo CR $(RELEASE_DIR)/$(MERGED_FNAME).hex - @echo CR $(RELEASE_DIR)/$(MERGED_FNAME).zip - @mkdir -p $(RELEASE_DIR) - @cp $(BUILD)/$(MERGED_FNAME).hex $(RELEASE_DIR)/$(MERGED_FNAME).hex - @cp $(BUILD)/$(MERGED_FNAME).zip $(RELEASE_DIR)/$(MERGED_FNAME).zip diff --git a/README.md b/README.md index 8a6ddd0..ebe16ad 100644 --- a/README.md +++ b/README.md @@ -97,12 +97,18 @@ To build: make BOARD=feather_nrf52840_express all combinehex ``` -To flash the bootloader: +To flash the bootloader with JLink: ``` make BOARD=feather_nrf52840_express flash ``` +To upgrade the bootloader using DFU Serial via port /dev/ttyACM0 + +``` +make BOARD=feather_nrf52840_express SERIAL=/dev/ttyACM0 dfu-flash +``` + To flash SoftDevice (and chip erase): ``` diff --git a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c index cf9072e..c3342b8 100644 --- a/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c +++ b/lib/sdk11/components/libraries/bootloader_dfu/bootloader.c @@ -130,9 +130,9 @@ static void wait_for_events(void) #ifdef NRF52840_XXAA // skip if usb is not inited ( e.g OTA / finializing sd/bootloader ) extern bool usb_inited(void); - if ( usb_inited() ) + if ( tusb_inited() ) { - tusb_task(); + tud_task(); tud_cdc_write_flush(); } #endif diff --git a/lib/tinyusb b/lib/tinyusb index a1c5964..5587481 160000 --- a/lib/tinyusb +++ b/lib/tinyusb @@ -1 +1 @@ -Subproject commit a1c596490aa40863cd5f1e36a821157ffeab2af6 +Subproject commit 55874813f82157b7509729b1a0c66e68f86e2d07 diff --git a/src/flash_nrf5x.c b/src/flash_nrf5x.c index bc13aa2..9145a31 100644 --- a/src/flash_nrf5x.c +++ b/src/flash_nrf5x.c @@ -53,8 +53,9 @@ void flash_nrf5x_flush (bool need_erase) { // - nRF52832 dfu via uart can miss incoming byte when erasing because cpu is blocked for > 2ms. // Since dfu_prepare_func_app_erase() already erase the page for us, we can skip it here. - // - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems. Note MSC uf2 - // does not erase page in advance like dfu serial + // - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems. + // + // Note: MSC uf2 does not erase page in advance like dfu serial if ( need_erase ) nrf_nvmc_page_erase(_fl_addr); nrf_nvmc_write_words(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4); diff --git a/src/usb/msc_uf2.c b/src/usb/msc_uf2.c index a241055..4f9109a 100644 --- a/src/usb/msc_uf2.c +++ b/src/usb/msc_uf2.c @@ -39,6 +39,8 @@ #if CFG_TUD_MSC +#include "bootloader.h" + /*------------------------------------------------------------------*/ /* MACRO TYPEDEF CONSTANT ENUM *------------------------------------------------------------------*/ @@ -46,8 +48,10 @@ /*------------------------------------------------------------------*/ /* UF2 *------------------------------------------------------------------*/ +static WriteState _wr_state = { 0 }; + void read_block(uint32_t block_no, uint8_t *data); -int write_block(uint32_t block_no, uint8_t *data, bool quiet/*, WriteState *state*/); +int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state); //--------------------------------------------------------------------+ // tinyusb callbacks @@ -137,7 +141,7 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* uint32_t count = 0; int wr_ret; - while ( (count < bufsize) && ((wr_ret = write_block(lba, buffer, false)) > 0) ) + while ( (count < bufsize) && ((wr_ret = write_block(lba, buffer, false, &_wr_state)) > 0) ) { lba++; buffer += 512; @@ -148,6 +152,25 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* return (wr_ret < 0) ? bufsize : count; } +// Callback invoked when WRITE10 command is completed (status received and accepted by host). +void tud_msc_write10_complete_cb(uint8_t lun) +{ + // uf2 file writing is complete --> complete DFU process + if ( _wr_state.numBlocks && (_wr_state.numWritten >= _wr_state.numBlocks) ) + { + led_state(STATE_WRITING_FINISHED); + + dfu_update_status_t update_status; + + memset(&update_status, 0, sizeof(dfu_update_status_t )); + update_status.status_code = DFU_UPDATE_APP_COMPLETE; + update_status.app_crc = 0; // skip CRC checking with uf2 upgrade + update_status.app_size = _wr_state.numBlocks*256; + + bootloader_dfu_update_process(update_status); + } +} + void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { (void) lun; diff --git a/src/usb/uf2/ghostfat.c b/src/usb/uf2/ghostfat.c index f4311cf..1f41c10 100644 --- a/src/usb/uf2/ghostfat.c +++ b/src/usb/uf2/ghostfat.c @@ -119,8 +119,6 @@ static FAT_BootBlock const BootBlock = { #define NRF_LOG_DEBUG(...) #define NRF_LOG_WARNING(...) -static WriteState _wr_state = { 0 }; - // get current.uf2 flash size in bytes, round up to 256 bytes static uint32_t current_flash_size(void) { @@ -241,21 +239,6 @@ void read_block(uint32_t block_no, uint8_t *data) { /* Write UF2 *------------------------------------------------------------------*/ -/** uf2 upgrade complete -> inform bootloader to update setting and reset */ -static void uf2_write_complete(uint32_t numBlocks) -{ - led_state(STATE_WRITING_FINISHED); - - dfu_update_status_t update_status; - - memset(&update_status, 0, sizeof(dfu_update_status_t )); - update_status.status_code = DFU_UPDATE_APP_COMPLETE; - update_status.app_crc = 0; // skip CRC checking with uf2 upgrade - update_status.app_size = numBlocks*256; - - bootloader_dfu_update_process(update_status); -} - /** Write an block * * @return number of bytes processed, only 3 following values @@ -263,9 +246,8 @@ static void uf2_write_complete(uint32_t numBlocks) * 512 : write is successful * 0 : is busy with flashing, tinyusb stack will call write_block again with the same parameters later on */ -int write_block(uint32_t block_no, uint8_t *data, bool quiet/*, WriteState *state*/) { +int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state) { UF2_Block *bl = (void *)data; - WriteState* state = &_wr_state; NRF_LOG_DEBUG("Write magic: %x", bl->magicStart0); @@ -318,8 +300,6 @@ int write_block(uint32_t block_no, uint8_t *data, bool quiet/*, WriteState *stat if (state->numWritten >= state->numBlocks) { // flush last blocks flash_nrf5x_flush(true); - - uf2_write_complete(state->numBlocks); } } NRF_LOG_DEBUG("wr %d=%d (of %d)", state->numWritten, bl->blockNo, bl->numBlocks); diff --git a/src/usb/usb.c b/src/usb/usb.c index 2ba83e4..b5baee6 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -63,22 +63,9 @@ extern uint16_t usb_desc_str_serial[1+16]; * We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. */ extern void tusb_hal_nrf_power_event(uint32_t event); - //------------- IMPLEMENTATION -------------// -static bool _inited = false; - -bool usb_inited(void) -{ - return _inited; -} - void usb_init(bool cdc_only) { - // skipped if already inited - if ( _inited ) return; - - _inited = true; - NVIC_SetPriority(USBD_IRQn, 2); // USB power may already be ready at this time -> no event generated diff --git a/src/usb/usb_desc.c b/src/usb/usb_desc.c index 630a369..4e5f5a3 100644 --- a/src/usb/usb_desc.c +++ b/src/usb/usb_desc.c @@ -59,19 +59,21 @@ enum { }; /*------------- Endpoint Numbering & Size -------------*/ -#define _EP_IN(x) (0x80 | (x)) -#define _EP_OUT(x) (x) +#define _EP_IN(x) (0x80 | (x)) +#define _EP_OUT(x) (x) // CDC -#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 ) -#define EP_CDC_NOTIF_SIZE 8 +#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 ) +#define EP_CDC_NOTIF_SIZE 8 -#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 ) -#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 ) +#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 ) +#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 ) // Mass Storage -#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 ) -#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 ) +#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 ) +#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 ) + +#define EP_MSC_SIZE 64 //--------------------------------------------------------------------+ // STRING DESCRIPTORS @@ -280,7 +282,7 @@ usb_desc_cfg_t usb_desc_cfg = .bDescriptorType = TUSB_DESC_ENDPOINT, .bEndpointAddress = EP_MSC_OUT, .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE}, + .wMaxPacketSize = { .size = EP_MSC_SIZE}, .bInterval = 1 }, @@ -290,7 +292,7 @@ usb_desc_cfg_t usb_desc_cfg = .bDescriptorType = TUSB_DESC_ENDPOINT, .bEndpointAddress = EP_MSC_IN, .bmAttributes = { .xfer = TUSB_XFER_BULK }, - .wMaxPacketSize = { .size = CFG_TUD_MSC_EPSIZE}, + .wMaxPacketSize = { .size = EP_MSC_SIZE }, .bInterval = 1 } }