This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Background DFU postvalidation

Hello all,

We are trying to use Background DFU.

We are able to trigger using "background_dfu_validate_trigger" and "background_dfu_process_trigger". Process the init packet block. Receive all the firmware blocks.

After calling "background_dfu_process_block" on all the firmware blocks, we call "app_sched_execute" and

"err_code = background_dfu_handle_event(&dfu.bg_dfu_ctx, BACKGROUND_DFU_EVENT_TRANSFER_COMPLETE);"

But when we reset into the bootloader we get the message "<info> app: No firmware to activate.". "nrf_dfu_validation_post_data_execute" is never called.

How do we trigger the postvalidation process after the last block is processed?

The Background DFU ctx:

bg_dfu_ctx  
dfu_state 0x04
dfu_mode 0x00
reset_suppress 0x00
dfu_diag  
init_cmd_size 140
init_cmd_crc 0xc0bfbc63
firmware_size 0x00002024
firmware_crc 0xc0bfbc63
max_obj_size 4096
remaining_size 0
block_num 2
p_resource_size  
block_manager  
image_size 8228
image_type 2
last_block_stored 1
current_block 2
data  
bitmap  
[0] 128
result_handler 0x00039fb9
p_context 0x2000a538
currently_stored_block 2
retry_count

3

RTT log file:

<info> app: EVENT_ENCRYPT_NEGOTIATION_SUCCESS  ch: 1, state from 02
<info> app: new state: 3
<debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
<debug> nrf_dfu_flash: Initializing nrf_fstorage_sd backend.
<debug> nrf_dfu_settings: Using settings page.
<debug> nrf_dfu_settings: Copying forbidden parts from backup page.
<debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
<debug> nrf_dfu_flash: Initializing nrf_fstorage_sd backend.
<info> background_dfu: Current DFU Diag version: Sep 16 2019 17:50:47, 0x7C8D85A5
<info> background_dfu: state=DFU_IDLE event=DFU_EVENT_TRANSFER_COMPLETE
<info> app: state_update BACKGROUND_DFU_DOWNLOAD_TRIG
<info> app: send_request BACKGROUND_DFU_DOWNLOAD_TRIG
<info> background_dfu: DFU trigger: init (sz=140, crc=C0BFBC63) image (sz=8228, crc=C0BFBC63)
<info> background_dfu: state=DFU_DOWNLOAD_TRIG event=DFU_EVENT_TRANSFER_COMPLETE
<warning> background_dfu: Installed image CRC is different
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_SELECT (command)
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_EXECUTE (command)
<error> nrf_dfu_validation: Handler: Invalid init command.
<error> nrf_dfu_validation: Failed to decode init packet
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x5
<error> background_dfu: Init commad has changed
<info> app: state_update BACKGROUND_DFU_DOWNLOAD_INIT_CMD
<info> background_dfu: Init complete. Unicast Mode.
<info> background_dfu: state=DFU_DOWNLOAD_INIT_CMD event=DFU_EVENT_TRANSFER_CONTINUE
<info> app: Process block 0
<info> app: send_acknowledge_crc_to_beast block 0 CRC32 0xC0BFBC63
<info> background_dfu: Storing block (b:0 c:0).
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_CREATE (command)
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (command)
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_CRC_GET (command)
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_EXECUTE (command)
<debug> nrf_dfu_validation: PB: Init packet data len: 63
<info> nrf_dfu_validation: Signature required. Checking signature.
<info> nrf_dfu_validation: Calculating hash (len: 63)
<info> nrf_dfu_validation: Verify signature
<info> nrf_dfu_validation: Image verified
<debug> app: Enter nrf_dfu_cache_prepare()
<debug> app: required_size: 0x2024.
<debug> app: single_bank: false.
<debug> app: keep_app: true.
<debug> app: keep_softdevice: true.
<debug> app: SD_PRESENT: true.
<debug> app: Bank contents:
<debug> app: Bank 0 code: 0x01: Size: 0x20804
<debug> app: Bank 1 code: 0x00: Size: 0x0
<debug> app: pass: 0.
<debug> app: cache_address: 0x52000.
<debug> app: cache_too_small: false.
<debug> app: keep_firmware: true.
<debug> app: delete_more: false.
<debug> nrf_dfu_validation: Write address set to 0x00052000
<debug> nrf_dfu_settings: Writing settings...
<debug> nrf_dfu_settings: Erasing old settings at: 0x000FF000
<debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FF000, len=1 pages), queue usage: 0
<debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FF000, src=0x2000E004, len=896 bytes), queue usage: 1
<debug> nrf_dfu_req_handler: Writing valid init command to flash.
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> background_dfu: Is image complete (o:0 n:1).
<info> background_dfu: state=DFU_DOWNLOAD_INIT_CMD event=DFU_EVENT_TRANSFER_COMPLETE
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_SELECT (data)
<debug> nrf_dfu_req_handler: crc = 0x0, offset = 0x0, max_size = 0x1000
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<info> app: state_update BACKGROUND_DFU_DOWNLOAD_FIRMWARE
<info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_CONTINUE
<debug> nrf_dfu_flash: Flash erase success: addr=0x000FF000, pending 1
<debug> nrf_dfu_flash: Flash write success: addr=0x000FF000, pending 0
<info> app: EVENT_TRANSFER_TX_COMPLETED ch: 1
<warning> app: EVENT_TRANSFER_RX_FAILED ch: 1
<warning> app: EVENT_TRANSFER_RX_FAILED ch: 1
<warning> app: EVENT_RX_FAIL ch: 1
<warning> app: EVENT_RX_FAIL ch: 1
<warning> app: EVENT_TRANSFER_RX_FAILED ch: 1
<info> app: Block Remainder packet(7) coppied to buffer at 1000
<info> app: send_acknowledge_crc_to_beast block 0 CRC32 0x207223D
<info> app: Process block 0
<info> app: app_sched_execute 001000
<info> background_dfu: Storing block (b:0 c:0).
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_CREATE (data)
<debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00052000, len=1 pages), queue usage: 0
<debug> nrf_dfu_req_handler: Creating object with size: 4096. Offset: 0x00000000, CRC: 0x00000000
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
<debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00052000, src=0x2000A57C, len=4096 bytes), queue usage: 1
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_flash: Flash erase success: addr=0x00052000, pending 1
<debug> nrf_dfu_flash: Flash write success: addr=0x00052000, pending 0
<info> app: EVENT_TRANSFER_TX_COMPLETED ch: 1
<warning> app: EVENT_TRANSFER_RX_FAILED ch: 1
<warning> app: EVENT_TRANSFER_RX_FAILED ch: 1
<warning> app: EVENT_TRANSFER_RX_FAILED ch: 1
<warning> app: EVENT_RX_FAIL ch: 1
<info> app: Block Remainder packet(7) coppied to buffer at 1000
<info> app: send_acknowledge_crc_to_beast block 1 CRC32 0x6B820540
<info> app: Process block 1
<info> app: app_sched_execute 002000
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_CRC_GET (data)
<debug> nrf_dfu_req_handler: Offset:4096, CRC:0x0207223D
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_EXECUTE (data)
<debug> background_dfu: Is image complete (o:0 n:3).
<info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_CONTINUE
<info> background_dfu: Storing block (b:1 c:1).
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_CREATE (data)
<debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00053000, len=1 pages), queue usage: 0
<debug> nrf_dfu_req_handler: Creating object with size: 4096. Offset: 0x00001000, CRC: 0x0207223D
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
<debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00053000, src=0x2000B57C, len=4096 bytes), queue usage: 1
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_flash: Flash erase success: addr=0x00053000, pending 1
<debug> nrf_dfu_flash: Flash write success: addr=0x00053000, pending 0
<info> app: EVENT_TRANSFER_TX_COMPLETED ch: 1
<info> app: Last packet(7) coppied to buffer at 0024
<info> app: send_acknowledge_crc_to_beast block 2 CRC32 0x7531A6F4
<info> app: Process block 2
<info> app: app_sched_execute 002024
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_CRC_GET (data)
<debug> nrf_dfu_req_handler: Offset:8192, CRC:0x6B820540
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_EXECUTE (data)
<debug> background_dfu: Is image complete (o:1 n:3).
<info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_CONTINUE
<info> background_dfu: Storing block (b:2 c:2).
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_CREATE (data)
<debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x00054000, len=1 pages), queue usage: 0
<debug> nrf_dfu_req_handler: Creating object with size: 36. Offset: 0x00002000, CRC: 0x6B820540
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<debug> nrf_dfu_req_handler: Handle NRF_DFU_OP_OBJECT_WRITE (data)
<debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x00054000, src=0x2000A57C, len=36 bytes), queue usage: 1
<debug> nrf_dfu_req_handler: Request handling complete. Result: 0x1
<info> app: app_sched_execute dfu.index == dfu.firmware_size
<info> background_dfu: state=DFU_DOWNLOAD_FIRMWARE event=DFU_EVENT_TRANSFER_COMPLETE
<info> app: state_update BACKGROUND_DFU_WAIT_FOR_RESET or IDLE
<info> app: last app_sched_execute before reboot
<info> app: Inside main, BOOTLOADER_START_ADDR:000ED000
<debug> app: In nrf_bootloader_init
<debug> nrf_dfu_settings: Calling nrf_dfu_settings_init()...
<debug> nrf_dfu_flash: Initializing nrf_fstorage_nvmc backend.
<debug> nrf_dfu_settings: Using settings page.
<debug> nrf_dfu_settings: Copying forbidden parts from backup page.
<debug> nrf_dfu_settings: Destination settings are identical to source, write not needed. Skipping.
<info> nrf_dfu_settings: Backing up settings page to address 0xFE000.
<debug> nrf_dfu_settings: Writing settings...
<debug> nrf_dfu_settings: Erasing old settings at: 0x000FE000
<debug> nrf_dfu_flash: nrf_fstorage_erase(addr=0x0x000FE000, len=1 pages), queue usage: 0
<debug> nrf_dfu_flash: Flash erase success: addr=0x000FE000, pending 0
<debug> nrf_dfu_flash: nrf_fstorage_write(addr=0x000FE000, src=0x20007E50, len=896 bytes), queue usage: 1
<debug> nrf_dfu_flash: Flash write success: addr=0x000FE000, pending 0
<debug> app: Enter nrf_bootloader_fw_activate
<info> app: No firmware to activate.
<info> nrf_dfu_validation: Signature required. Checking signature.
<info> nrf_dfu_validation: Calculating hash (len: 133124)
<info> nrf_dfu_validation: Verify signature
<info> nrf_dfu_validation: Image verified
<debug> app: App is valid
<debug> app: DFU mode requested via GPREGRET.
<info> nrf_bootloader_wdt: WDT is not enabled
<debug> app: in weak nrf_dfu_init_user
<debug> app: timer_stop (0x20004000)
<debug> app: timer_activate (0x20004000)
<debug> app: in weak nrf_dfu_init
<debug> app: Enter main loop

Parents
  • Hi,

    "No firmware to activate" is printed from nrf_bootloader_fw_activate() when there is no firmware to activate in bank 1, according to the bootloader settings. So for some reason, the bootloader settings do not indicate a valid app.

    Can you elaborate more on how your application implements DFU and how the bootloader does it? Can you share details about SDK version, examples, your code etc to show what you are doing?

  • Yes, nrf_dfu_validation_post_data_execute is never called which is why there is no firmware to validate. I should be seeing rtt message "Whole firmware image received. Postvalidating." from function "on_data_obj_execute_request_sched" in nrf_dfu_req_handler

    SDK version 15.3.0

    This is how we use the Background DFU from the application.

    #include "string.h"
    
    #include "app_scheduler.h"
    #include "crc32.h"
    
    #include "background_dfu_transport.h"
    #include "background_dfu_block.h"
    #include "background_dfu_transport.h"
    
    #include "nrf_delay.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_dfu_settings.h"
    
    #include "DFU.h"
    #include "ANT.h"
    #include "ANT_message_response_types.h"
    
    #define DFU_BLOCK_SIZE 4096
    #define DFU_MAX_PACKET_SIZE 29
    #define DFU_BLOCK_REMAINDER (DFU_BLOCK_SIZE % DFU_MAX_PACKET_SIZE)
    #define SCHED_QUEUE_SIZE				(192)
    #define SCHED_MAX_EVENT_DATA_SIZE		(sizeof(nrf_dfu_request_t))                       /**< Maximum size of scheduler events. */
    
    typedef struct
    {
    	uint8_t *buffer;
    	uint16_t size;
    	uint32_t crc;
    	uint16_t index;
    } dfu_init_packet_t;
    
    typedef struct
    {
    	uint32_t firmware_size,  					// size in bytes
    		firmware_crc,
    		index,     								// bytes of update succesfully written to flash
    		packet_count,
    		block_number,
    		block_crc;
    	uint8_t *block;  			// malloced block, to be written to flash
    	background_dfu_trigger_t trigger;
    	background_dfu_context_t bg_dfu_ctx;  	// Background DFU context
    	dfu_init_packet_t init_packet;
    }background_device_firmware_update_t;
    
    static background_device_firmware_update_t dfu;
    
    extern response_t on_enter_bootloader(uint8_t* buffer, uint8_t len);
    
    static int dfu_start(uint8_t *buffer, uint8_t len)
    {
    	uint32_t dfu_packet_address = ((buffer[0] << 16) + (buffer[1] << 8) + buffer[2]),      // first 3 bytes contain address
    			init_packet_size = 0, 	// next two bytes (max 0x1000)
    			init_packet_crc = 0, 	// next 4 bytes	(crc32, 4 bytes)
    			firmware_size = 0, 		// next 3 bytes (firmware size max 0x100000)
    			firmware_crc = 0; 		// next 4 bytes	(crc32, 4 bytes)
    	
    	init_packet_size = (buffer[3] << 8) + buffer[4];
    	init_packet_crc = ((buffer[5] << 24) + (buffer[6] << 16) + (buffer[7] << 8) + buffer[8]);
    	firmware_size = ((buffer[9] << 16) + (buffer[10] << 8) + buffer[11]);
    	firmware_crc = ((buffer[12] << 24) + (buffer[13] << 16) + (buffer[14] << 8) + buffer[15]);
    	
    	// null check
    	if(init_packet_size == 0 || init_packet_crc == 0 || firmware_size == 0 || firmware_crc == 0)
    		return RESPONSE_ERROR;
    	
    	// initialize dfu struct to 0
    	memset(&dfu, 0, sizeof(dfu));
    	dfu.firmware_size = firmware_size;
    	dfu.firmware_crc = firmware_crc;
    	
    	// set init packet struct to 0
    	dfu.init_packet.size = init_packet_size;
    	dfu.init_packet.buffer = malloc(init_packet_size);
    	dfu.init_packet.crc = init_packet_crc;
    	
    	APP_SCHED_INIT(SCHED_MAX_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);
    	
    	return RESPONSE_SUCCESS;
    }
    
    static int dfu_init_packet(uint8_t *buffer, uint8_t len)
    {
    	uint16_t dfu_packet_address = ((buffer[1] << 8) + buffer[2]);      // first byte signals init packet, next 2 bytes contain address
    	
    	// if address + remainder is larger or equal to init packet size
    	if((dfu_packet_address + (dfu.init_packet.size % DFU_MAX_PACKET_SIZE)) >= (dfu.init_packet.size))
    	{
    		uint8_t last_packet_remainder = dfu.init_packet.size % DFU_MAX_PACKET_SIZE;
    		memcpy(dfu.init_packet.buffer + dfu.init_packet.index, buffer + 3, last_packet_remainder);
    		dfu.init_packet.index += last_packet_remainder;
    	}
    	else //if((dfu_packet_address / DFU_MAX_PACKET_SIZE) < (dfu.init_packet.size / DFU_MAX_PACKET_SIZE))
    	{
    		memcpy(dfu.init_packet.buffer + dfu.init_packet.index, buffer+3, DFU_MAX_PACKET_SIZE);
    		dfu.init_packet.index += DFU_MAX_PACKET_SIZE;
    	}
    	
    	// if init packet completed 
    	if (dfu.init_packet.index == dfu.init_packet.size)
    	{
    		dfu_init_packet_complete();
    	}
    }
    
    
    int dfu_packet(uint8_t* buffer, uint8_t len)
    {
    	uint32_t dfu_packet_address = ((buffer[0] << 16) + (buffer[1] << 8) + buffer[2]),     // first 3 bytes contain address
    		block_index = dfu_packet_address % DFU_BLOCK_SIZE;
    	uint8_t dfu_packet_length = len - 3;
    	uint32_t err_code = NRF_SUCCESS;
    	
    	dfu.packet_count++;     // just keeping count, may be removed
    	
    	// Handle init packets
    	if(dfu_packet_address == 0xffffff)
    	{
    		dfu_start(buffer, len);
    		return RESPONSE_SUCCESS;
    	}
    	else if(dfu_packet_address > 0xf00000 - 1)
    	{
    		dfu_init_packet(buffer, len);
    		return RESPONSE_SUCCESS;
    	}
    	
    	// if this is the block remainder
    	if((block_index / DFU_MAX_PACKET_SIZE) == (DFU_BLOCK_SIZE / DFU_MAX_PACKET_SIZE))
    	{
    		// dfu_packet_address should be the same as dfu_block + block_index
    		memcpy(dfu.block + block_index, buffer + 3, DFU_BLOCK_REMAINDER);
    		block_index += DFU_BLOCK_REMAINDER;
    		NRF_LOG_INFO("Block Remainder packet(%d) coppied to buffer at %04X", DFU_BLOCK_REMAINDER, block_index);
    	}
    	// Last packet of last block remainder Check
    	else if(((dfu.index + block_index) / DFU_MAX_PACKET_SIZE) == (dfu.firmware_size / DFU_MAX_PACKET_SIZE))
    	{
    		uint8_t last_packet_remainder = (dfu.firmware_size % DFU_BLOCK_SIZE) % DFU_MAX_PACKET_SIZE;
    		// dfu_packet_address should be the same as dfu_block + block_index
    		memcpy(dfu.block + block_index, buffer + 3, last_packet_remainder);
    		block_index += last_packet_remainder;
    		NRF_LOG_INFO("Last packet(%d) coppied to buffer at %04X", last_packet_remainder, block_index);
    	}
    	else
    	{
    		// dfu_packet_address should be the same as dfu_block + block_index
    		memcpy(dfu.block + block_index, buffer + 3, dfu_packet_length);
    		block_index += dfu_packet_length;
    	}
    	
    	// End of block check
    	if(block_index == DFU_BLOCK_SIZE || 
    		((dfu.index + block_index) == dfu.firmware_size))
    	{
    		// Calculate and send CRC32
    		dfu.block_crc = crc32_compute(dfu.block, block_index, &dfu.block_crc);
    		send_acknowledge_crc_to_beast(dfu.block_crc, (dfu_packet_address >> 12));
    		
    		// put block in scheduler to be written to flash
    		if((err_code = dfu_process_block(dfu.block)) != BACKGROUND_DFU_BLOCK_SUCCESS)
    		{
    			NRF_LOG_ERROR("dfu_process_block failed (0x%X)", err_code);
    			return RESPONSE_ERROR;
    		}
    		
    		// Add processed bytes to total index
    		dfu.index += block_index;
    		// Reset block index
    		block_index = 0;
    		
    		// Clear processed block
    		memset(dfu.block, 0, DFU_BLOCK_SIZE);
    		
    		NRF_LOG_INFO("app_sched_execute %06X", dfu.index);
    		// Process event 
    		app_sched_execute();
    		
    		// flush rtt log
    		NRF_LOG_FLUSH();
    		if (dfu.index == dfu.firmware_size)
    		{
    			NRF_LOG_INFO("app_sched_execute dfu.index == dfu.firmware_size");
    			// Process event 
    			app_sched_execute();
    			err_code = background_dfu_handle_event(&dfu.bg_dfu_ctx, BACKGROUND_DFU_EVENT_TRANSFER_COMPLETE);
    			if (err_code != NRF_SUCCESS)
    				return err_code;		
    			NRF_LOG_FLUSH();
    		}
    	}
    	
    	return RESPONSE_SUCCESS;
    }
    
    static int dfu_init_packet_complete()
    {
    	uint32_t err_code = NRF_SUCCESS;
    	
    	// Initialize and set trigger struct
    	uint32_t little = dfu.init_packet.size;
    	uint32_t big = uint32_big_decode((uint8_t*)&little);
    	dfu.trigger.init_length = big;       										// Initpacket size
    	
    	// calculate received crc32 init packet
    	little = crc32_compute(dfu.init_packet.buffer, dfu.init_packet.size, NULL);
    	// check calculated crc
    	if (little != dfu.init_packet.crc)
    	{
    		NRF_LOG_ERROR("Init Packet CRC(%08X) does not match calculated CRC(%08X)", dfu.init_packet.crc, little);
    		return NRF_ERROR_INVALID_DATA;
    	}
    	big = uint32_big_decode((uint8_t*)&little);
    	dfu.trigger.init_crc = big;     											// Initpacket crc
    	
    	little = dfu.firmware_size;
    	big = uint32_big_decode((uint8_t*)&little);
    	dfu.trigger.image_length = big;      										// Firmware size
    	
    	little = dfu.firmware_crc;     
    	big = uint32_big_decode((uint8_t*)&little);
    	dfu.trigger.image_crc = big;          										// Firmware crc
    	dfu.trigger.flags = 0;      												// Trigger version(1 or 0 lsh 4) and dfu flag(bit 3)
    	
    	// allocate block in memory
    	dfu.block = malloc(DFU_BLOCK_SIZE);
    	memset(dfu.block, 0, DFU_BLOCK_SIZE);
    	// NULL check on malloc
    	if (dfu.block == NULL)
    		return NRF_ERROR_NO_MEM;
    		
    	// Initialize dfu settings from flash if present
    	err_code = nrf_dfu_settings_init(true);
    	if (err_code != NRF_SUCCESS)
    		return err_code;
    	
    	// Initialize dfu request handler
    	err_code = nrf_dfu_req_handler_init(dfu_observer);
    	if (err_code != NRF_SUCCESS)
    		return err_code;
    	
    	// Init background dfu state machine
    	background_dfu_state_init(&dfu.bg_dfu_ctx);
    	if (dfu.bg_dfu_ctx.dfu_state != BACKGROUND_DFU_IDLE)
    	{
    		NRF_LOG_WARNING("Invalid state");
    		return NRF_ERROR_INVALID_STATE;
    	}
    	
    	// Transition from DFU_IDLE to DFU_DOWNLOAD_TRIG.
    	err_code = background_dfu_handle_event(&dfu.bg_dfu_ctx, BACKGROUND_DFU_EVENT_TRANSFER_COMPLETE);
    	if (err_code != NRF_SUCCESS)
    		return err_code;
    	
    	// Process events
    	app_sched_execute();
    				
    	// Process Trigger
    	if (background_dfu_validate_trigger(&dfu.bg_dfu_ctx, (uint8_t *)&dfu.trigger, sizeof(dfu.trigger)))
    	{
    		if (!background_dfu_process_trigger(&dfu.bg_dfu_ctx, (uint8_t *)&dfu.trigger, sizeof(dfu.trigger)))
    		{
    			NRF_LOG_ERROR("NRF_ERROR_INTERNAL");
    			return (err_code = NRF_ERROR_INTERNAL);
    		}
    	}
    	
    	// Process events
    	app_sched_execute();
    	
    	// Set init packet data
    	memcpy(dfu.block, dfu.init_packet.buffer, dfu.init_packet.size);
    	dfu_process_block(dfu.block);
    	
    	// reset block count for firmware
    	dfu.block_number = 0;
    	
    	// report back CRC32
    	send_acknowledge_crc_to_beast(dfu.init_packet.crc, 0);
    	
    	// Process events
    	app_sched_execute();
    	
    	return err_code;
    }
    
    /**
     * @brief Pass block of retrieved data to background DFU module.
     *
     * @param[in]  p_block  Pointer to block of retrieved data.
     */
    static int dfu_process_block(uint8_t *p_block)
    {
    	background_dfu_block_t block;
    	background_dfu_block_result_t result;
    
    	block.number = dfu.block_number;
    	block.size = DFU_BLOCK_SIZE;
    	block.p_payload = p_block;
    
    	NRF_LOG_INFO("Process block %d", block.number);
    	dfu.block_number++;
    
    	result = background_dfu_process_block(&dfu.bg_dfu_ctx, &block);
    	if (result != BACKGROUND_DFU_BLOCK_SUCCESS)
    	{
    		NRF_LOG_ERROR("Error in background_dfu_process_block (%d)", result);
    	}
    	return result;
    }
    
    // Background DFU required callbacks
    
    static void dfu_observer(nrf_dfu_evt_type_t evt_type)
    {
    	switch (evt_type)
    	{
    	case NRF_DFU_EVT_DFU_COMPLETED:
            NRF_LOG_INFO("NRF_DFU_EVT_DFU_COMPLETED");
    		break;
    
    	default:
    		break;
    	}
    }
    
    uint32_t background_dfu_random(void)
    {
    	// Intentionally empty: multicast DFU not implemented.
    	return 0;
    }
    
    void background_dfu_transport_block_request_send(background_dfu_context_t *p_dfu_ctx,
    	background_dfu_request_bitmap_t *p_req_bmp)
    {
    	// Intentionally empty: multicast DFU not implemented.
    }
    
    void background_dfu_handle_error(void)
    {
    	NRF_LOG_ERROR("background_dfu_handle_error");
    }
    
    void background_dfu_transport_state_update(background_dfu_context_t *p_dfu_ctx)
    {
    	switch (p_dfu_ctx->dfu_state)
    	{
    	case BACKGROUND_DFU_DOWNLOAD_TRIG:
    		NRF_LOG_INFO("state_update BACKGROUND_DFU_DOWNLOAD_TRIG");
    		break;
    
    	case BACKGROUND_DFU_DOWNLOAD_INIT_CMD:
    		NRF_LOG_INFO("state_update BACKGROUND_DFU_DOWNLOAD_INIT_CMD");
    		break;
    
    	case BACKGROUND_DFU_DOWNLOAD_FIRMWARE:
    		NRF_LOG_INFO("state_update BACKGROUND_DFU_DOWNLOAD_FIRMWARE");
    		break;
    
    	case BACKGROUND_DFU_WAIT_FOR_RESET:
    	case BACKGROUND_DFU_IDLE:
    		NRF_LOG_INFO("state_update BACKGROUND_DFU_WAIT_FOR_RESET or IDLE");
    		break;
    
    	default:
    		NRF_LOG_WARNING("Unhandled state in background_dfu_transport_state_update (s: %s).",
    			(uint32_t)background_dfu_state_to_string(p_dfu_ctx->dfu_state));
    	}
    }
    
    void background_dfu_transport_send_request(background_dfu_context_t *p_dfu_ctx)
    {
    	switch (dfu.bg_dfu_ctx.dfu_state)
    	{
    	case BACKGROUND_DFU_DOWNLOAD_TRIG:
    		NRF_LOG_INFO("send_request BACKGROUND_DFU_DOWNLOAD_TRIG");
    		break;
    
    	default:
    		// In other states download operation is triggered by state_update() notification.
    		break;
    	}
    }
    

    The bootloader has no transport and is very basic just like "nRF5_SDK_15.3.0_59ac345/examples/iot/bootloader/main.c"

  • Hi,

    I see. I need some time to look into this, but I will update you as soon as possible.

Reply Children
Related