From ac53612291b4409271f2316c5d0453477a461bf2 Mon Sep 17 00:00:00 2001 From: Ein Terakawa Date: Sat, 5 Jun 2021 18:06:40 +0900 Subject: [PATCH 1/2] UF2 Format Support --- source/daplink/drag-n-drop/file_stream.c | 78 ++++++++++++++++++++++++ source/daplink/drag-n-drop/file_stream.h | 1 + source/daplink/drag-n-drop/vfs_manager.c | 8 ++- source/daplink/validation.c | 24 ++++++++ source/daplink/validation.h | 1 + source/target/target_board.h | 2 +- 6 files changed, 112 insertions(+), 2 deletions(-) diff --git a/source/daplink/drag-n-drop/file_stream.c b/source/daplink/drag-n-drop/file_stream.c index 284ccc9f8..255abf228 100644 --- a/source/daplink/drag-n-drop/file_stream.c +++ b/source/daplink/drag-n-drop/file_stream.c @@ -60,9 +60,14 @@ typedef struct { uint8_t bin_buffer[256]; } hex_state_t; +typedef struct { + // bool parsing_complete; +} uf2_state_t; + typedef union { bin_state_t bin; hex_state_t hex; + uf2_state_t uf2; } shared_state_t; static bool detect_bin(const uint8_t *data, uint32_t size); @@ -75,9 +80,15 @@ static error_t open_hex(void *state); static error_t write_hex(void *state, const uint8_t *data, uint32_t size); static error_t close_hex(void *state); +static bool detect_uf2(const uint8_t *data, uint32_t size); +static error_t open_uf2(void *state); +static error_t write_uf2(void *state, const uint8_t *data, uint32_t size); +static error_t close_uf2(void *state); + stream_t stream[] = { {detect_bin, open_bin, write_bin, close_bin}, // STREAM_TYPE_BIN {detect_hex, open_hex, write_hex, close_hex}, // STREAM_TYPE_HEX + {detect_uf2, open_uf2, write_uf2, close_uf2}, // STREAM_TYPE_UF2 }; COMPILER_ASSERT(ARRAY_SIZE(stream) == STREAM_TYPE_COUNT); // STREAM_TYPE_NONE must not be included in count @@ -119,6 +130,8 @@ stream_type_t stream_type_from_name(const vfs_filename_t filename) return STREAM_TYPE_BIN; } else if (0 == strncmp("HEX", &filename[8], 3)) { return STREAM_TYPE_HEX; + } else if (0 == strncmp("UF2", &filename[8], 3)) { + return STREAM_TYPE_UF2; } else { return STREAM_TYPE_NONE; } @@ -364,3 +377,68 @@ static error_t close_hex(void *state) status = flash_decoder_close(); return status; } + +/* UF2 file processing */ + +static bool detect_uf2(const uint8_t *data, uint32_t size) +{ + return 0 != validate_uf2file(data); +} + +static error_t open_uf2(void *state) +{ + error_t status; + // uf2_state_t *uf2_state = (uf2_state_t *)state; + // memset(uf2_state, 0, sizeof(*uf2_state)); + // uf2_state->parsing_complete = false; + status = flash_decoder_open(); + return status; +} + +static error_t write_uf2(void *state, const uint8_t *data, uint32_t size) +{ + error_t status = ERROR_SUCCESS; + // uf2_state_t *uf2_state = (uf2_state_t *)state; + uint32_t bin_start_address = 0; // Decoded from the uf2 file, the binary buffer data starts at this address + uint32_t bin_buf_written = 0; // The amount of data in the binary buffer starting at address above + + // TODO deal with endianness + + while (1) { + util_assert(size >= 512); + if (validate_uf2file(data) == 0) { + status = ERROR_HEX_PARSER; // UF2 validation error + break; + } + + bin_start_address = *(uint32_t *)(data + 12); + bin_buf_written = *(uint32_t *)(data + 16); + + status = flash_decoder_write(bin_start_address, data + 32, bin_buf_written); + if (status != ERROR_SUCCESS) { + break; + } + + if (*(uint32_t *)(data + 20) + 1 == *(uint32_t *)(data + 24)) { + // uf2_state->parsing_complete = true; + status = ERROR_SUCCESS_DONE; + break; + } + + size -= 512; + data += 512; + + if (size == 0) { + break; // status == ERROR_SUCCESS + } + } + + return status; +} + +static error_t close_uf2(void *state) +{ + error_t status; + status = flash_decoder_close(); + return status; +} diff --git a/source/daplink/drag-n-drop/file_stream.h b/source/daplink/drag-n-drop/file_stream.h index 50bf38e08..2e9cdca83 100644 --- a/source/daplink/drag-n-drop/file_stream.h +++ b/source/daplink/drag-n-drop/file_stream.h @@ -36,6 +36,7 @@ typedef enum { STREAM_TYPE_BIN = STREAM_TYPE_START, STREAM_TYPE_HEX, + STREAM_TYPE_UF2, // Add new stream types here diff --git a/source/daplink/drag-n-drop/vfs_manager.c b/source/daplink/drag-n-drop/vfs_manager.c index d50ae01bc..bd4de0535 100644 --- a/source/daplink/drag-n-drop/vfs_manager.c +++ b/source/daplink/drag-n-drop/vfs_manager.c @@ -138,6 +138,7 @@ static uint32_t time_usb_idle; static osMutexId_t sync_mutex; static osThreadId_t sync_thread = 0; +static bool sync_at_first_call = false; // Synchronization functions static void sync_init(void); @@ -352,12 +353,17 @@ void usbd_msc_write_sect(uint32_t sector, uint8_t *buf, uint32_t num_of_sectors) static void sync_init(void) { - sync_thread = osThreadGetId(); + sync_at_first_call = true; + sync_thread = 0; sync_mutex = osMutexNew(NULL); } static void sync_assert_usb_thread(void) { + if (sync_at_first_call) { + sync_at_first_call = false; + sync_thread = osThreadGetId(); + } util_assert(osThreadGetId() == sync_thread); } diff --git a/source/daplink/validation.c b/source/daplink/validation.c index 0a3134f89..f073dc16c 100644 --- a/source/daplink/validation.c +++ b/source/daplink/validation.c @@ -94,3 +94,27 @@ uint8_t validate_hexfile(const uint8_t *buf) return ((buf[0] == ':') && ((buf[8] == '0') || (buf[8] == '2') || (buf[8] == '3') || (buf[8] == '4') || (buf[8] == '5'))) ? 1 : 0; } } + +uint8_t validate_uf2file(const uint8_t *buf) +{ +#if 0 + if (g_target_family && g_target_family->validate_uf2file) { + return g_target_family->validate_uf2file(buf); + } +#endif + // look here for known uf2 record + // First magic number, UF2 signature + if ((buf[0] != 0x55) || (buf[1] != 0x46) || (buf[2] != 0x32) || (buf[3] != 0x0A)) { + return 0; + } + // Second magic number, 0x9E5D5157 + if ((buf[4] != 0x57) || (buf[5] != 0x51) || (buf[6] != 0x5D) || (buf[7] != 0x9E)) { + return 0; + } + // Final magic number, 0x0AB16F30 + if ((buf[508] != 0x30) || (buf[509] != 0x6F) || (buf[510] != 0xB1) || (buf[511] != 0x0A)) { + return 0; + } + // TODO validate check sum , assuming 512-byte granularity . + return 1; +} diff --git a/source/daplink/validation.h b/source/daplink/validation.h index 929d827fb..a8a773406 100644 --- a/source/daplink/validation.h +++ b/source/daplink/validation.h @@ -30,6 +30,7 @@ extern "C" { uint8_t validate_bin_nvic(const uint8_t *buf); uint8_t validate_hexfile(const uint8_t *buf); +uint8_t validate_uf2file(const uint8_t *buf); /*! * @brief Baseline implementation of NVIC validator. diff --git a/source/target/target_board.h b/source/target/target_board.h index 6b4476aa4..0c227164d 100644 --- a/source/target/target_board.h +++ b/source/target/target_board.h @@ -60,7 +60,7 @@ typedef struct board_info { char board_id[5]; /*!< 4-char board ID plus null terminator */ uint8_t _padding[3]; uint32_t flags; /*!< Flags from #_board_info_flags */ - target_cfg_t *target_cfg; /*!< Specific chip configuration for the target and enables MSD when non-NULL */ + const target_cfg_t *target_cfg; /*!< Specific chip configuration for the target and enables MSD when non-NULL */ //! @name MSD customization //@{ From 7fbb95df3d53b058d34951a23b053a51d4549510 Mon Sep 17 00:00:00 2001 From: Ein Terakawa Date: Sun, 6 Jun 2021 14:19:37 +0900 Subject: [PATCH 2/2] UF2 & LPC11U35/LPC55S69 Testing --- projects.yaml | 9 ++++ records/board/generic_nrf52840.yaml | 7 +++ records/hic_hal/lpc55s69.yaml | 1 + source/board/generic_nrf52840.c | 59 +++++++++++++++++++++ source/daplink/drag-n-drop/flash_decoder.c | 4 +- source/daplink/interface/target_flash.c | 8 +-- source/daplink/validation.c | 4 +- source/hic_hal/nxp/lpc11u35/gcc/lpc11u35.ld | 4 +- 8 files changed, 86 insertions(+), 10 deletions(-) create mode 100644 records/board/generic_nrf52840.yaml create mode 100644 source/board/generic_nrf52840.c diff --git a/projects.yaml b/projects.yaml index 019b317a7..750985cf1 100644 --- a/projects.yaml +++ b/projects.yaml @@ -598,3 +598,12 @@ projects: - *module_hic_lpc55s69 - records/board/lpc55s69_nrf52840dk.yaml - records/board/mcu_link.yaml + lpc55s69_nrf52840_if: + - *module_if + - *module_hic_lpc55s69 + - records/board/lpc55s69_if.yaml # Sets the USB product string. + - records/board/generic_nrf52840.yaml + lpc11u35_nrf52840_if: + - *module_if + - *module_hic_lpc11u35_bulk + - records/board/generic_nrf52840.yaml diff --git a/records/board/generic_nrf52840.yaml b/records/board/generic_nrf52840.yaml new file mode 100644 index 000000000..3c662bf85 --- /dev/null +++ b/records/board/generic_nrf52840.yaml @@ -0,0 +1,7 @@ +common: + sources: + board: + - source/board/generic_nrf52840.c + family: + - source/family/nordic/nrf52/target.c + - source/family/nordic/target_reset_nrf52.c diff --git a/records/hic_hal/lpc55s69.yaml b/records/hic_hal/lpc55s69.yaml index 14b2aafb5..c4257c6ec 100644 --- a/records/hic_hal/lpc55s69.yaml +++ b/records/hic_hal/lpc55s69.yaml @@ -8,6 +8,7 @@ common: - CPU_LPC55S69JBD64_cm33_core0 - DAPLINK_HIC_ID=0x4C504355 # DAPLINK_HIC_ID_LPC55XX - OS_CLOCK=96000000 + - DELAY_FAST_CYCLES=2 includes: - source/hic_hal/nxp/lpc55xx - source/hic_hal/nxp/lpc55xx/LPC55S69 diff --git a/source/board/generic_nrf52840.c b/source/board/generic_nrf52840.c new file mode 100644 index 000000000..2b71c7441 --- /dev/null +++ b/source/board/generic_nrf52840.c @@ -0,0 +1,59 @@ +/** + * @file generic_nrf52840.c + * @brief board ID not assigned + * + * DAPLink Interface Firmware + * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "target_board.h" +#include "target_family.h" + +extern target_cfg_t target_device_nrf52840; + +#if 0 +// To put this target_device struct on RAM , +// target_device_nrf52840 must be declared const so that it gets stored in FLASH region. +target_cfg_t target_device = { // invalid by default + .version = kTargetConfigVersion, + .rt_family_id = kStub_SWSysReset_FamilyID, + .rt_board_id = "0000", +}; +#endif + +static void nrf_prerun_board_config(void) +{ +#if 0 + target_device = target_device_nrf52840; + target_device.rt_family_id = kNordic_Nrf52_FamilyID; + target_device.rt_board_id = "0000"; +#endif + // Forcibly overwrite target_device_nrf52840 sturct in place. + target_device_nrf52840.rt_family_id = kNordic_Nrf52_FamilyID; + target_device_nrf52840.rt_board_id = "0000"; +} + +const board_info_t g_board_info = { + .info_version = kBoardInfoVersion, + .flags = kEnablePageErase, + // .prerun_board_config = nrf_prerun_board_config, + .family_id = kNordic_Nrf52_FamilyID, + .board_id = "0000", + .target_cfg = &target_device_nrf52840, + .board_vendor = "N/A", + .board_name = "Generic nRF52840", + .daplink_target_url = "https://github.com/ARMmbed/DAPLink/", +}; diff --git a/source/daplink/drag-n-drop/flash_decoder.c b/source/daplink/drag-n-drop/flash_decoder.c index 46b4bc7ae..dafb75abc 100644 --- a/source/daplink/drag-n-drop/flash_decoder.c +++ b/source/daplink/drag-n-drop/flash_decoder.c @@ -153,7 +153,7 @@ error_t flash_decoder_get_flash(flash_decoder_type_t type, uint32_t addr, bool a } } else if (FLASH_DECODER_TYPE_TARGET == type) { if (g_board_info.target_cfg) { - region_info_t * region = g_board_info.target_cfg->flash_regions; + const region_info_t * region = g_board_info.target_cfg->flash_regions; for (; region->start != 0 || region->end != 0; ++region) { if (kRegionIsDefault == region->flags) { flash_start_local = region->start; @@ -396,7 +396,7 @@ static bool flash_decoder_is_at_end(uint32_t addr, const uint8_t *data, uint32_t case FLASH_DECODER_TYPE_TARGET: //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) { - region_info_t * region = g_board_info.target_cfg->flash_regions; + const region_info_t * region = g_board_info.target_cfg->flash_regions; for (; region->start != 0 || region->end != 0; ++region) { if (addr >= region->start && addr<=region->end) { end_addr = region->end; diff --git a/source/daplink/interface/target_flash.c b/source/daplink/interface/target_flash.c index 77489dac7..4ab86304d 100644 --- a/source/daplink/interface/target_flash.c +++ b/source/daplink/interface/target_flash.c @@ -74,14 +74,14 @@ static flash_func_t last_flash_func = FLASH_FUNC_NOP; static program_target_t * current_flash_algo = NULL; //saved default region for default flash algo -static region_info_t * default_region = NULL; +static const region_info_t * default_region = NULL; //saved flash start from flash algo static uint32_t flash_start = 0; static program_target_t * get_flash_algo(uint32_t addr) { - region_info_t * flash_region = g_board_info.target_cfg->flash_regions; + const region_info_t * flash_region = g_board_info.target_cfg->flash_regions; for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) { if (addr >= flash_region->start && addr <= flash_region->end) { @@ -164,7 +164,7 @@ static error_t target_flash_init() } //get default region - region_info_t * flash_region = g_board_info.target_cfg->flash_regions; + const region_info_t * flash_region = g_board_info.target_cfg->flash_regions; for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) { if (flash_region->flags & kRegionIsDefault) { default_region = flash_region; @@ -336,7 +336,7 @@ static error_t target_flash_erase_chip(void) { if (g_board_info.target_cfg){ error_t status = ERROR_SUCCESS; - region_info_t * flash_region = g_board_info.target_cfg->flash_regions; + const region_info_t * flash_region = g_board_info.target_cfg->flash_regions; for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) { program_target_t *new_flash_algo = get_flash_algo(flash_region->start); diff --git a/source/daplink/validation.c b/source/daplink/validation.c index f073dc16c..94258ae54 100644 --- a/source/daplink/validation.c +++ b/source/daplink/validation.c @@ -47,7 +47,7 @@ uint8_t validate_bin_nvic_base(const uint8_t *buf) // test the initial SP value memcpy(&nvic_val, buf + 0, sizeof(nvic_val)); - region_info_t * region = g_board_info.target_cfg->ram_regions; + const region_info_t * region = g_board_info.target_cfg->ram_regions; for (; region->start != 0 || region->end != 0; ++region) { if (1 == test_range(nvic_val, region->start, region->end)) { in_range = 1; @@ -65,7 +65,7 @@ uint8_t validate_bin_nvic_base(const uint8_t *buf) for (; i <= 12; i += 4) { in_range = 0; memcpy(&nvic_val, buf + i, sizeof(nvic_val)); - region_info_t * region = g_board_info.target_cfg->flash_regions; + const region_info_t * region = g_board_info.target_cfg->flash_regions; for (; region->start != 0 || region->end != 0; ++region) { if (1 == test_range(nvic_val, region->start, region->end)) { in_range = 1; diff --git a/source/hic_hal/nxp/lpc11u35/gcc/lpc11u35.ld b/source/hic_hal/nxp/lpc11u35/gcc/lpc11u35.ld index 7f9699607..54aeb01e1 100644 --- a/source/hic_hal/nxp/lpc11u35/gcc/lpc11u35.ld +++ b/source/hic_hal/nxp/lpc11u35/gcc/lpc11u35.ld @@ -33,8 +33,8 @@ STACK_SIZE = DEFINED(__stack_size__) ? __stack_size__ : DAPLINK_STACK_SIZE; /* Specify the memory areas */ MEMORY { - m_interrupts (RX) : ORIGIN = DAPLINK_ROM_APP_START, LENGTH = 0x400 - m_text (RX) : ORIGIN = DAPLINK_ROM_APP_START + 0x400, LENGTH = DAPLINK_ROM_APP_SIZE - 0x400 + m_interrupts (RX) : ORIGIN = DAPLINK_ROM_APP_START, LENGTH = 0x300 + m_text (RX) : ORIGIN = DAPLINK_ROM_APP_START + 0x300, LENGTH = DAPLINK_ROM_APP_SIZE - 0x300 m_cfgrom (RW) : ORIGIN = DAPLINK_ROM_CONFIG_USER_START, LENGTH = DAPLINK_ROM_CONFIG_USER_SIZE m_data (RW) : ORIGIN = DAPLINK_RAM_APP_START, LENGTH = DAPLINK_RAM_APP_SIZE m_cfgram (RW) : ORIGIN = DAPLINK_RAM_SHARED_START, LENGTH = DAPLINK_RAM_SHARED_SIZE