diff --git a/source/daplink/drag-n-drop/flash_decoder.c b/source/daplink/drag-n-drop/flash_decoder.c index fbf97d2b8..50b4d79f7 100644 --- a/source/daplink/drag-n-drop/flash_decoder.c +++ b/source/daplink/drag-n-drop/flash_decoder.c @@ -56,6 +56,7 @@ static uint32_t initial_addr; static uint32_t current_addr; static bool flash_initialized; static bool initial_addr_set; +static bool flash_type_target_bin; static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t size); @@ -65,7 +66,9 @@ flash_decoder_type_t flash_decoder_detect_type(const uint8_t *data, uint32_t siz util_assert(size >= FLASH_DECODER_MIN_SIZE); // Check if this is a daplink image memcpy(&info, data + DAPLINK_INFO_OFFSET, sizeof(info)); - + if(!addr_valid){ //reset until we know the binary type + flash_type_target_bin = false; + } if (DAPLINK_HIC_ID == info.hic_id) { if (DAPLINK_BUILD_KEY_IF == info.build_key) { // Interface update @@ -80,6 +83,9 @@ flash_decoder_type_t flash_decoder_detect_type(const uint8_t *data, uint32_t siz // Check if a valid vector table for the target can be found if (validate_bin_nvic(data)) { + if(!addr_valid){ //binary is a bin type + flash_type_target_bin = true; + } return FLASH_DECODER_TYPE_TARGET; } @@ -341,9 +347,10 @@ static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t case FLASH_DECODER_TYPE_INTERFACE: end_addr = DAPLINK_ROM_IF_START + DAPLINK_ROM_IF_SIZE; break; - + case FLASH_DECODER_TYPE_TARGET: - if (g_board_info.target_cfg) { + //only if we are sure it is a bin for the target; without check unordered hex files will cause to terminate flashing + if (flash_type_target_bin && g_board_info.target_cfg) { end_addr = g_board_info.target_cfg->flash_end; } else { diff --git a/source/daplink/drag-n-drop/flash_manager.c b/source/daplink/drag-n-drop/flash_manager.c index 06f01a8a9..8ff256084 100755 --- a/source/daplink/drag-n-drop/flash_manager.c +++ b/source/daplink/drag-n-drop/flash_manager.c @@ -59,6 +59,7 @@ static const flash_intf_t *intf; static state_t state = STATE_CLOSED; static bool flash_intf_valid(const flash_intf_t *flash_intf); +static error_t flush_current_block(uint32_t addr); static error_t setup_next_sector(uint32_t addr); error_t flash_manager_init(const flash_intf_t *flash_intf) @@ -124,15 +125,6 @@ error_t flash_manager_data(uint32_t addr, const uint8_t *data, uint32_t size) return ERROR_INTERNAL; } - // Enforce that addresses are sequential. Currently flash manager - // only supports sequential addresses. In the future flash manager - // could be updated to support this. - if (addr < last_addr) { - util_assert(0); - state = STATE_ERROR; - return ERROR_INTERNAL; - } - // Setup the current sector if it is not setup already if (!current_sector_valid) { status = setup_next_sector(addr); @@ -142,27 +134,34 @@ error_t flash_manager_data(uint32_t addr, const uint8_t *data, uint32_t size) return status; } current_sector_valid = true; + last_addr = addr; + } + + //non-increasing address support + if (ROUND_DOWN(addr, current_write_block_size) != ROUND_DOWN(last_addr, current_write_block_size)) { + status = flush_current_block(addr); + if (ERROR_SUCCESS != status) { + state = STATE_ERROR; + return status; + } + } + + if (ROUND_DOWN(addr, current_sector_size) != ROUND_DOWN(last_addr, current_sector_size)) { + status = setup_next_sector(addr); + if (ERROR_SUCCESS != status) { + state = STATE_ERROR; + return status; + } } while (true) { // flush if necessary if (addr >= current_write_block_addr + current_write_block_size) { - - // Write out current buffer if there is data in it - if (!buf_empty) { - status = intf->program_page(current_write_block_addr, buf, current_write_block_size); - flash_manager_printf(" intf->program_page(addr=0x%x, size=0x%x) ret=%i\r\n", current_write_block_addr, current_write_block_size, status); - - if (ERROR_SUCCESS != status) { - state = STATE_ERROR; - return status; - } - buf_empty = true; + status = flush_current_block(addr); + if (ERROR_SUCCESS != status) { + state = STATE_ERROR; + return status; } - - // Setup for next page - memset(buf, 0xFF, current_write_block_size); - current_write_block_addr = ROUND_DOWN(addr,current_write_block_size); } // Check for end @@ -207,13 +206,11 @@ error_t flash_manager_uninit(void) return ERROR_INTERNAL; } - // Write out current page - if ((STATE_OPEN == state) && (!buf_empty)) { - flash_write_error = intf->program_page(current_write_block_addr, buf, current_write_block_size); - flash_manager_printf(" intf->program_page(addr=0x%x, size=0x%x) ret=%i\r\n", - current_write_block_addr, current_write_block_size, flash_write_error); + // Flush last buffer if its not empty + if (STATE_OPEN == state) { + flash_write_error = flush_current_block(0); + flash_manager_printf(" last flush_current_block ret=%i\r\n",flash_write_error); } - // Close flash interface (even if there was an error during program_page) flash_uninit_error = intf->uninit(); flash_manager_printf(" intf->uninit() ret=%i\r\n", flash_uninit_error); @@ -284,6 +281,21 @@ static bool flash_intf_valid(const flash_intf_t *flash_intf) return true; } +static error_t flush_current_block(uint32_t addr){ + // Write out current buffer if there is data in it + error_t status = ERROR_SUCCESS; + if (!buf_empty) { + status = intf->program_page(current_write_block_addr, buf, current_write_block_size); + flash_manager_printf(" intf->program_page(addr=0x%x, size=0x%x) ret=%i\r\n", current_write_block_addr, current_write_block_size, status); + buf_empty = true; + } + + // Setup for next block + memset(buf, 0xFF, current_write_block_size); + current_write_block_addr = ROUND_DOWN(addr,current_write_block_size); + return status; +} + static error_t setup_next_sector(uint32_t addr) { uint32_t min_prog_size; diff --git a/source/daplink/drag-n-drop/intelhex.c b/source/daplink/drag-n-drop/intelhex.c index 6923d210a..56f8c7ae6 100644 --- a/source/daplink/drag-n-drop/intelhex.c +++ b/source/daplink/drag-n-drop/intelhex.c @@ -121,75 +121,7 @@ hexfile_parse_status_t parse_hex_blob(const uint8_t *hex_blob, const uint32_t he // junk we dont care about could also just run the validate_checksum on &line case '\r': case '\n': - if (0 == validate_checksum(&line)) { - status = HEX_PARSE_CKSUM_FAIL; - goto hex_parser_exit; - } else { - if (!record_processed) { - record_processed = 1; - // address byteswap... - line.address = swap16(line.address); - - switch (line.record_type) { - case DATA_RECORD: - // keeping a record of the last hex record - memcpy(shadow_line.buf, line.buf, sizeof(hex_line_t)); - - // verify this is a continous block of memory or need to exit and dump - if (((next_address_to_write & 0xffff0000) | line.address) != next_address_to_write) { - load_unaligned_record = 1; - status = HEX_PARSE_UNALIGNED; - goto hex_parser_exit; - } - - // move from line buffer back to input buffer - memcpy(bin_buf, line.data, line.byte_count); - bin_buf += line.byte_count; - *bin_buf_cnt = (uint32_t)(*bin_buf_cnt) + line.byte_count; - // Save next address to write - next_address_to_write = ((next_address_to_write & 0xffff0000) | line.address) + line.byte_count; - break; - - case EOF_RECORD: - // pad rest of the buffer with 0xff - //memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt))); - //*bin_buf_cnt = bin_buf_size; - status = HEX_PARSE_EOF; - goto hex_parser_exit; - - case EXT_SEG_ADDR_RECORD: - // Could have had data in the buffer so must exit and try to program - // before updating bin_buf_address with next_address_to_write - memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt))); - // figure the start address for the buffer before returning - *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt); - *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob)); - // update the address msb's - next_address_to_write = (next_address_to_write & 0x00000000) | ((line.data[0] << 12) | (line.data[1] << 4)); - // Need to exit and program if buffer has been filled - status = HEX_PARSE_UNALIGNED; - return status; - - case EXT_LINEAR_ADDR_RECORD: - // Could have had data in the buffer so must exit and try to program - // before updating bin_buf_address with next_address_to_write - // Good catch Gaute!! - memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt))); - // figure the start address for the buffer before returning - *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt); - *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob)); - // update the address msb's - next_address_to_write = (next_address_to_write & 0x00000000) | ((line.data[0] << 24) | (line.data[1] << 16)); - // Need to exit and program if buffer has been filled - status = HEX_PARSE_UNALIGNED; - return status; - - default: - break; - } - } - } - + //ignore new lines break; // found start of a new record. reset state variables @@ -204,7 +136,73 @@ hexfile_parse_status_t parse_hex_blob(const uint8_t *hex_blob, const uint32_t he default: if (low_nibble) { line.buf[idx] |= ctoh((uint8_t)(*hex_blob)) & 0xf; - idx++; + if (++idx >= (line.byte_count + 5)) { //all data in + if (0 == validate_checksum(&line)) { + status = HEX_PARSE_CKSUM_FAIL; + goto hex_parser_exit; + } else { + if (!record_processed) { + record_processed = 1; + // address byteswap... + line.address = swap16(line.address); + + switch (line.record_type) { + case DATA_RECORD: + // keeping a record of the last hex record + memcpy(shadow_line.buf, line.buf, sizeof(hex_line_t)); + + // verify this is a continous block of memory or need to exit and dump + if (((next_address_to_write & 0xffff0000) | line.address) != next_address_to_write) { + load_unaligned_record = 1; + status = HEX_PARSE_UNALIGNED; + goto hex_parser_exit; + } + + // move from line buffer back to input buffer + memcpy(bin_buf, line.data, line.byte_count); + bin_buf += line.byte_count; + *bin_buf_cnt = (uint32_t)(*bin_buf_cnt) + line.byte_count; + // Save next address to write + next_address_to_write = ((next_address_to_write & 0xffff0000) | line.address) + line.byte_count; + break; + + case EOF_RECORD: + status = HEX_PARSE_EOF; + goto hex_parser_exit; + + case EXT_SEG_ADDR_RECORD: + // Could have had data in the buffer so must exit and try to program + // before updating bin_buf_address with next_address_to_write + memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt))); + // figure the start address for the buffer before returning + *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt); + *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob)); + // update the address msb's + next_address_to_write = (next_address_to_write & 0x00000000) | ((line.data[0] << 12) | (line.data[1] << 4)); + // Need to exit and program if buffer has been filled + status = HEX_PARSE_UNALIGNED; + return status; + + case EXT_LINEAR_ADDR_RECORD: + // Could have had data in the buffer so must exit and try to program + // before updating bin_buf_address with next_address_to_write + // Good catch Gaute!! + memset(bin_buf, 0xff, (bin_buf_size - (uint32_t)(*bin_buf_cnt))); + // figure the start address for the buffer before returning + *bin_buf_address = next_address_to_write - (uint32_t)(*bin_buf_cnt); + *hex_parse_cnt = (uint32_t)(hex_blob_size - (end - hex_blob)); + // update the address msb's + next_address_to_write = (next_address_to_write & 0x00000000) | ((line.data[0] << 24) | (line.data[1] << 16)); + // Need to exit and program if buffer has been filled + status = HEX_PARSE_UNALIGNED; + return status; + + default: + break; + } + } + } + } } else { if (idx < sizeof(hex_line_t)) { line.buf[idx] = ctoh((uint8_t)(*hex_blob)) << 4;