Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.
Upstream: https://github.com/ARMmbed/DAPLink
Diff: source/daplink/interface/target_flash.c
- Revision:
- 0:01f31e923fe2
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/source/daplink/interface/target_flash.c Tue Apr 07 12:55:42 2020 +0200 @@ -0,0 +1,406 @@ +/** + * @file target_flash.c + * @brief Implementation of target_flash.h + * + * DAPLink Interface Firmware + * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved + * Copyright 2019, Cypress Semiconductor Corporation + * or a subsidiary of Cypress Semiconductor Corporation. + * 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. + */ +#ifdef DRAG_N_DROP_SUPPORT +#include <string.h> + +#include "target_config.h" +#include "gpio.h" +#include "target_config.h" +#include "intelhex.h" +#include "swd_host.h" +#include "flash_intf.h" +#include "util.h" +#include "settings.h" +#include "target_family.h" +#include "target_board.h" + +#define DEFAULT_PROGRAM_PAGE_MIN_SIZE (256u) + +typedef enum { + STATE_CLOSED, + STATE_OPEN, + STATE_ERROR +} state_t; + +static error_t target_flash_init(void); +static error_t target_flash_uninit(void); +static error_t target_flash_program_page(uint32_t adr, const uint8_t *buf, uint32_t size); +static error_t target_flash_erase_sector(uint32_t addr); +static error_t target_flash_erase_chip(void); +static uint32_t target_flash_program_page_min_size(uint32_t addr); +static uint32_t target_flash_erase_sector_size(uint32_t addr); +static uint8_t target_flash_busy(void); +static error_t target_flash_set(uint32_t addr); + +static const flash_intf_t flash_intf = { + target_flash_init, + target_flash_uninit, + target_flash_program_page, + target_flash_erase_sector, + target_flash_erase_chip, + target_flash_program_page_min_size, + target_flash_erase_sector_size, + target_flash_busy, + target_flash_set, +}; + +static state_t state = STATE_CLOSED; + +const flash_intf_t *const flash_intf_target = &flash_intf; + +static flash_func_t last_flash_func = FLASH_FUNC_NOP; + +//saved flash algo +static program_target_t * current_flash_algo = NULL; + +//saved default region for default flash algo +static 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; + + for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) { + if (addr >= flash_region->start && addr <= flash_region->end) { + flash_start = flash_region->start; //save the flash start + if (flash_region->flash_algo) { + return flash_region->flash_algo; + }else{ + return NULL; + } + } + } + + //could not find a flash algo for the region; use default + if (default_region) { + flash_start = default_region->start; + return default_region->flash_algo; + } else { + return NULL; + } +} + +static error_t flash_func_start(flash_func_t func) +{ + program_target_t * flash = current_flash_algo; + + if (last_flash_func != func) + { + // Finish the currently active function. + if (FLASH_FUNC_NOP != last_flash_func && + ((flash->algo_flags & kAlgoSingleInitType) == 0 || FLASH_FUNC_NOP == func ) && + 0 == swd_flash_syscall_exec(&flash->sys_call_s, flash->uninit, last_flash_func, 0, 0, 0, FLASHALGO_RETURN_BOOL)) { + return ERROR_UNINIT; + } + + // Start a new function. + if (FLASH_FUNC_NOP != func && + ((flash->algo_flags & kAlgoSingleInitType) == 0 || FLASH_FUNC_NOP == last_flash_func ) && + 0 == swd_flash_syscall_exec(&flash->sys_call_s, flash->init, flash_start, 0, func, 0, FLASHALGO_RETURN_BOOL)) { + return ERROR_INIT; + } + + last_flash_func = func; + } + + return ERROR_SUCCESS; +} + +static error_t target_flash_set(uint32_t addr) +{ + program_target_t * new_flash_algo = get_flash_algo(addr); + if (new_flash_algo == NULL) { + return ERROR_ALGO_MISSING; + } + if(current_flash_algo != new_flash_algo){ + //run uninit to last func + error_t status = flash_func_start(FLASH_FUNC_NOP); + if (status != ERROR_SUCCESS) { + return status; + } + // Download flash programming algorithm to target + if (0 == swd_write_memory(new_flash_algo->algo_start, (uint8_t *)new_flash_algo->algo_blob, new_flash_algo->algo_size)) { + return ERROR_ALGO_DL; + } + + current_flash_algo = new_flash_algo; + + } + return ERROR_SUCCESS; +} + +static error_t target_flash_init() +{ + if (g_board_info.target_cfg) { + last_flash_func = FLASH_FUNC_NOP; + + current_flash_algo = NULL; + + if (0 == target_set_state(RESET_PROGRAM)) { + return ERROR_RESET; + } + + //get default region + 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; + break; + } + } + + state = STATE_OPEN; + return ERROR_SUCCESS; + } else { + return ERROR_FAILURE; + } + +} + +static error_t target_flash_uninit(void) +{ + if (g_board_info.target_cfg) { + error_t status = flash_func_start(FLASH_FUNC_NOP); + if (status != ERROR_SUCCESS) { + return status; + } + if (config_get_auto_rst()) { + // Resume the target if configured to do so + target_set_state(RESET_RUN); + } else { + // Leave the target halted until a reset occurs + target_set_state(RESET_PROGRAM); + } + // Check to see if anything needs to be done after programming. + // This is usually a no-op for most targets. + target_set_state(POST_FLASH_RESET); + + state = STATE_CLOSED; + swd_off(); + return ERROR_SUCCESS; + } else { + return ERROR_FAILURE; + } +} + +static error_t target_flash_program_page(uint32_t addr, const uint8_t *buf, uint32_t size) +{ + if (g_board_info.target_cfg) { + error_t status = ERROR_SUCCESS; + program_target_t * flash = current_flash_algo; + + if (!flash) { + return ERROR_INTERNAL; + } + + // check if security bits were set + if (g_target_family && g_target_family->security_bits_set){ + if (1 == g_target_family->security_bits_set(addr, (uint8_t *)buf, size)) { + return ERROR_SECURITY_BITS; + } + } + + status = flash_func_start(FLASH_FUNC_PROGRAM); + + if (status != ERROR_SUCCESS) { + return status; + } + + while (size > 0) { + uint32_t write_size = MIN(size, flash->program_buffer_size); + + // Write page to buffer + if (!swd_write_memory(flash->program_buffer, (uint8_t *)buf, write_size)) { + return ERROR_ALGO_DATA_SEQ; + } + + // Run flash programming + if (!swd_flash_syscall_exec(&flash->sys_call_s, + flash->program_page, + addr, + write_size, + flash->program_buffer, + 0, + FLASHALGO_RETURN_BOOL)) { + return ERROR_WRITE; + } + + if (config_get_automation_allowed()) { + // Verify data flashed if in automation mode + if (flash->verify != 0) { + status = flash_func_start(FLASH_FUNC_VERIFY); + if (status != ERROR_SUCCESS) { + return status; + } + flash_algo_return_t return_type; + if ((flash->algo_flags & kAlgoVerifyReturnsAddress) != 0) { + return_type = FLASHALGO_RETURN_POINTER; + } else { + return_type = FLASHALGO_RETURN_BOOL; + } + if (!swd_flash_syscall_exec(&flash->sys_call_s, + flash->verify, + addr, + write_size, + flash->program_buffer, + 0, + return_type)) { + return ERROR_WRITE_VERIFY; + } + } else { + while (write_size > 0) { + uint8_t rb_buf[16]; + uint32_t verify_size = MIN(write_size, sizeof(rb_buf)); + if (!swd_read_memory(addr, rb_buf, verify_size)) { + return ERROR_ALGO_DATA_SEQ; + } + if (memcmp(buf, rb_buf, verify_size) != 0) { + return ERROR_WRITE_VERIFY; + } + addr += verify_size; + buf += verify_size; + size -= verify_size; + write_size -= verify_size; + } + continue; + } + } + addr += write_size; + buf += write_size; + size -= write_size; + + } + + return ERROR_SUCCESS; + + } else { + return ERROR_FAILURE; + } +} + +static error_t target_flash_erase_sector(uint32_t addr) +{ + if (g_board_info.target_cfg) { + error_t status = ERROR_SUCCESS; + program_target_t * flash = current_flash_algo; + + if (!flash) { + return ERROR_INTERNAL; + } + + // Check to make sure the address is on a sector boundary + if ((addr % target_flash_erase_sector_size(addr)) != 0) { + return ERROR_ERASE_SECTOR; + } + + status = flash_func_start(FLASH_FUNC_ERASE); + + if (status != ERROR_SUCCESS) { + return status; + } + + if (0 == swd_flash_syscall_exec(&flash->sys_call_s, flash->erase_sector, addr, 0, 0, 0, FLASHALGO_RETURN_BOOL)) { + return ERROR_ERASE_SECTOR; + } + + return ERROR_SUCCESS; + } else { + return ERROR_FAILURE; + } +} + +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; + + for (; flash_region->start != 0 || flash_region->end != 0; ++flash_region) { + program_target_t *new_flash_algo = get_flash_algo(flash_region->start); + if ((new_flash_algo != NULL) && ((new_flash_algo->algo_flags & kAlgoSkipChipErase) != 0)) { + // skip flash region + continue; + } + status = target_flash_set(flash_region->start); + if (status != ERROR_SUCCESS) { + return status; + } + status = flash_func_start(FLASH_FUNC_ERASE); + if (status != ERROR_SUCCESS) { + return status; + } + if (0 == swd_flash_syscall_exec(¤t_flash_algo->sys_call_s, current_flash_algo->erase_chip, 0, 0, 0, 0, FLASHALGO_RETURN_BOOL)) { + return ERROR_ERASE_ALL; + } + } + + // Reset and re-initialize the target after the erase if required + if (g_board_info.target_cfg->erase_reset) { + status = target_flash_init(); + } + + return status; + } else { + return ERROR_FAILURE; + } +} + +static uint32_t target_flash_program_page_min_size(uint32_t addr) +{ + if (g_board_info.target_cfg){ + uint32_t size = DEFAULT_PROGRAM_PAGE_MIN_SIZE; + if (size > target_flash_erase_sector_size(addr)) { + size = target_flash_erase_sector_size(addr); + } + return size; + } else { + return 0; + } +} + +static uint32_t target_flash_erase_sector_size(uint32_t addr) +{ + if (g_board_info.target_cfg){ + if(g_board_info.target_cfg->sector_info_length > 0) { + int sector_index = g_board_info.target_cfg->sector_info_length - 1; + for (; sector_index >= 0; sector_index--) { + if (addr >= g_board_info.target_cfg->sectors_info[sector_index].start) { + return g_board_info.target_cfg->sectors_info[sector_index].size; + } + } + } + //sector information should be in sector_info + util_assert(0); + return 0; + } else { + return 0; + } +} + +static uint8_t target_flash_busy(void){ + return (state == STATE_OPEN); +} +#endif