/*************************************************************************** * * Copyright 2015-2019 BES. * All rights reserved. All unpublished rights reserved. * * No part of this work may be used or reproduced in any form or by any * means, or stored in a database or retrieval system, without prior written * permission of BES. * * Use of this work is governed by a license granted by BES. * This work contains confidential and proprietary information of * BES. which is protected by copyright, trade secret, * trademark and other intellectual property rights. * ****************************************************************************/ #include #include #include "cmsis.h" #include "coredump_section.h" #include "hal_timer.h" #include "hal_trace.h" #include "hal_norflash.h" #include "norflash_api.h" /* Usage: arm-none-eabi-gdb elf_file -ex "target remote | ./tools/bins/lin64/CrashDebug --elf elf_file --dump coredump.dat" */ extern uint32_t __coredump_section_start; extern uint32_t __coredump_section_end; static const uint32_t coredump_flash_start_addr = (uint32_t)&__coredump_section_start; static const uint32_t coredump_flash_end_addr = (uint32_t)&__coredump_section_end; static uint32_t coredump_flash_addr_offset = (uint32_t)&__coredump_section_start; void coredump_to_flash_init() { uint32_t block_size = 0; uint32_t sector_size = 0; uint32_t page_size = 0; uint32_t buffer_len = 0; enum NORFLASH_API_RET_T result; hal_norflash_get_size(HAL_NORFLASH_ID_0,NULL, &block_size, §or_size, &page_size); buffer_len = COREDUMP_SECTOR_SIZE; TRACE(4,"%s: coredump_flash_start_addr = 0x%x, coredump_flash_end_addr = 0x%x, buff_len = 0x%x.", __func__, coredump_flash_start_addr, coredump_flash_end_addr, buffer_len); result = norflash_api_register( NORFLASH_API_MODULE_ID_COREDUMP, HAL_NORFLASH_ID_0, coredump_flash_start_addr, coredump_flash_end_addr - coredump_flash_start_addr, block_size, sector_size, page_size, buffer_len, NULL ); if(result == NORFLASH_API_OK) { TRACE(0,"coredump_to_flash_init ok."); } else { TRACE(1,"coredump_to_flash_init failed,result = %d.",result); } } void core_dump_erase_section() { //erase whole core dump section enum NORFLASH_API_RET_T ret = 0; uint32_t lock; do { lock = int_lock_global(); ret = norflash_api_erase(NORFLASH_API_MODULE_ID_COREDUMP, coredump_flash_addr_offset, COREDUMP_SECTOR_SIZE, false); int_unlock_global(lock); if(ret != NORFLASH_API_OK) { TRACE(3,"%s:offset = 0x%x,ret = %d.", __func__,coredump_flash_addr_offset,ret); } coredump_flash_addr_offset += COREDUMP_SECTOR_SIZE; if (coredump_flash_addr_offset == coredump_flash_end_addr) { coredump_flash_addr_offset = coredump_flash_start_addr; break; } } while (1); } int32_t core_dump_write_large(const uint8_t* ptr,uint32_t len) { enum NORFLASH_API_RET_T ret; uint32_t write_len; uint32_t remain_len = len; uint32_t lock; //TRACE(4,"%s offset = 0x%x ptr = 0x%x len=0x%x",__func__, coredump_flash_addr_offset, ptr, len); do { if (coredump_flash_addr_offset % COREDUMP_SECTOR_SIZE != 0) { write_len = COREDUMP_SECTOR_SIZE - (coredump_flash_addr_offset - (coredump_flash_addr_offset & ~COREDUMP_SECTOR_SIZE_MASK)); lock = int_lock_global(); ret = norflash_api_write(NORFLASH_API_MODULE_ID_COREDUMP, coredump_flash_addr_offset, ptr, write_len, false); int_unlock_global(lock); if(ret != NORFLASH_API_OK) { TRACE(4,"%s: addr = 0x%x,write_len = 0x%x,ret = %d.", __func__,coredump_flash_addr_offset,write_len,ret); return (int32_t)ret; } coredump_flash_addr_offset += write_len; ptr += write_len; remain_len -= write_len; } if (remain_len < COREDUMP_SECTOR_SIZE) { lock = int_lock_global(); ret = norflash_api_write(NORFLASH_API_MODULE_ID_COREDUMP, coredump_flash_addr_offset, ptr, remain_len, false); int_unlock_global(lock); if(ret != NORFLASH_API_OK) { TRACE(4,"%s: addr = 0x%x,remain_len = 0x%x,ret = %d.", __func__,coredump_flash_addr_offset,remain_len,ret); return (int32_t)ret; } coredump_flash_addr_offset += remain_len; ptr += remain_len; remain_len = 0; } else { lock = int_lock_global(); ret = norflash_api_write(NORFLASH_API_MODULE_ID_COREDUMP, coredump_flash_addr_offset, ptr, COREDUMP_SECTOR_SIZE, false); int_unlock_global(lock); if(ret != NORFLASH_API_OK) { TRACE(3,"%s: addr = 0x%x,ret = %d.", __func__,coredump_flash_addr_offset,ret); return (int32_t)ret; } coredump_flash_addr_offset += COREDUMP_SECTOR_SIZE; ptr += COREDUMP_SECTOR_SIZE; remain_len -= COREDUMP_SECTOR_SIZE; } } while (remain_len > 0); //TRACE(3,"%s offset = 0x%x ptr = 0x%x",__func__, coredump_flash_addr_offset, ptr); return 0; } int32_t core_dump_write(const uint8_t* ptr,uint32_t len) { enum NORFLASH_API_RET_T ret; uint32_t i; uint32_t lock; //TRACE(2,"%s: len = 0x%x", __func__,len); //write by byte to avoid cross flash sector boundary for (i = 0; i < len; i++) { lock = int_lock_global(); ret = norflash_api_write(NORFLASH_API_MODULE_ID_COREDUMP, coredump_flash_addr_offset++, ptr++, 1, false); int_unlock_global(lock); if(ret != NORFLASH_API_OK) { TRACE(4,"%s: offset = 0x%x ret = %d ch =%02x", __func__,coredump_flash_addr_offset,ret,*(ptr-1)); } } return 0; }