Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DRAFT] UF2 format support #935

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
7 changes: 7 additions & 0 deletions records/board/generic_nrf52840.yaml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions records/hic_hal/lpc55s69.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
59 changes: 59 additions & 0 deletions source/board/generic_nrf52840.c
Original file line number Diff line number Diff line change
@@ -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/",
};
78 changes: 78 additions & 0 deletions source/daplink/drag-n-drop/file_stream.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions source/daplink/drag-n-drop/file_stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typedef enum {

STREAM_TYPE_BIN = STREAM_TYPE_START,
STREAM_TYPE_HEX,
STREAM_TYPE_UF2,

// Add new stream types here

Expand Down
4 changes: 2 additions & 2 deletions source/daplink/drag-n-drop/flash_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 7 additions & 1 deletion source/daplink/drag-n-drop/vfs_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down
8 changes: 4 additions & 4 deletions source/daplink/interface/target_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
28 changes: 26 additions & 2 deletions source/daplink/validation.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}
1 change: 1 addition & 0 deletions source/daplink/validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions source/hic_hal/nxp/lpc11u35/gcc/lpc11u35.ld
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion source/target/target_board.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
//@{
Expand Down