| | |
| | | /* |
| | | * Copyright (c) 2020-2021 Shanghai Panchip Microelectronics Co.,Ltd. |
| | | * Copyright (c) 2020-2025 Shanghai Panchip Microelectronics Co.,Ltd. |
| | | * |
| | | * SPDX-License-Identifier: Apache-2.0 |
| | | */ |
| | | |
| | | #include "soc_api.h" |
| | | #include "app_log.h" |
| | | #include "flash_manager.h" |
| | | |
| | | static uint32_t m_erased_area; |
| | | |
| | | void fm_status_refresh(void) |
| | | { |
| | | m_erased_area = FLASH_AREA_IMAGE_START; |
| | | m_erased_area = FLASH_AREA_IMAGE_START; |
| | | } |
| | | |
| | | void fm_write_flash(unsigned int addr, unsigned char *buf, unsigned int len) |
| | | { |
| | | if ((addr + len) <= m_erased_area) { /* means the specified flash has be erased before */ |
| | | FMC_WriteStream(FLCTL, addr, buf, len); /* todo chao*/ |
| | | } else { |
| | | if (FMC_EraseSector(FLCTL, m_erased_area) == 0) { |
| | | m_erased_area += SECTOR_SIZE; |
| | | FMC_WriteStream(FLCTL, addr, buf, len); |
| | | } else { |
| | | ASSERT; |
| | | } |
| | | } |
| | | { |
| | | if ((addr + len) <= m_erased_area) { /* means the specified flash has be erased before */ |
| | | FMC_WriteStream(FLCTL, addr, buf, len); /* todo chao*/ |
| | | } else { |
| | | if (FMC_EraseSector(FLCTL, m_erased_area) == 0) { |
| | | m_erased_area += SECTOR_SIZE; |
| | | FMC_WriteStream(FLCTL, addr, buf, len); |
| | | } else { |
| | | // Error occurs |
| | | while (1); |
| | | } |
| | | } |
| | | } |
| | | |
| | | int fm_read_flash(unsigned int addr, unsigned char *buf, unsigned int len) |
| | | { |
| | | return FMC_ReadStream(FLCTL, addr, CMD_FAST_READ, buf, len); |
| | | return FMC_ReadStream(FLCTL, addr, CMD_DREAD, buf, len); |
| | | } |
| | | |
| | | static void check_sum_add(uint32_t *init_val, uint8_t *val, uint16_t len) |
| | | { |
| | | for (uint16_t i =0 ; i < len; i++) { |
| | | *init_val += *(val + i); |
| | | } |
| | | for (uint16_t i =0 ; i < len; i++) { |
| | | *init_val += *(val + i); |
| | | } |
| | | } |
| | | |
| | | int fm_image_make_invalid(uint32_t im_addr) |
| | | { |
| | | return FMC_EraseSector(FLCTL, im_addr); |
| | | return FMC_EraseSector(FLCTL, im_addr); |
| | | } |
| | | |
| | | static uint8_t read_value[256]; |
| | | |
| | | void fm_image_move(uint32_t src_addr, uint32_t dst_addr) |
| | | { |
| | | uint32_t current_index = 0; |
| | | image_header_t header; |
| | | |
| | | /* fm write to image area, should handle one time fm_status_refresh */ |
| | | fm_status_refresh(); |
| | | |
| | | /* move header */ |
| | | fm_read_flash(src_addr, (unsigned char *)&header, sizeof(image_header_t)); |
| | | fm_write_flash(dst_addr, (unsigned char *)&header, sizeof(image_header_t)); |
| | | src_addr += sizeof(image_header_t); |
| | | dst_addr += sizeof(image_header_t); |
| | | |
| | | header.ih_img_size += 40; /*smp signed related*/ |
| | | /* move completed image*/ |
| | | while(current_index < header.ih_img_size) { |
| | | if (current_index + 256 <= header.ih_img_size){ /* remaining packets over than 256 bytes */ |
| | | fm_read_flash(src_addr + current_index, read_value, 256); |
| | | fm_write_flash(dst_addr+ current_index, read_value, 256); |
| | | current_index += 256; |
| | | } |
| | | else { |
| | | fm_read_flash(src_addr + current_index, read_value, header.ih_img_size - current_index); /* remaining packets less than 256 bytes */ |
| | | fm_write_flash(dst_addr+ current_index, read_value, header.ih_img_size - current_index); |
| | | current_index = header.ih_img_size; |
| | | } |
| | | } |
| | | /* escape move at next time, should be make it invalid */ |
| | | fm_image_make_invalid(src_addr); |
| | | uint32_t current_index = 0; |
| | | image_header_t header; |
| | | |
| | | /* fm write to image area, should handle one time fm_status_refresh */ |
| | | fm_status_refresh(); |
| | | |
| | | /* move header */ |
| | | fm_read_flash(src_addr, (unsigned char *)&header, sizeof(image_header_t)); |
| | | fm_write_flash(dst_addr, (unsigned char *)&header, sizeof(image_header_t)); |
| | | src_addr += sizeof(image_header_t); |
| | | dst_addr += sizeof(image_header_t); |
| | | |
| | | header.ih_img_size += 40; /*smp signed related*/ |
| | | /* move completed image*/ |
| | | while(current_index < header.ih_img_size) { |
| | | if (current_index + 256 <= header.ih_img_size){ /* remaining packets over than 256 bytes */ |
| | | fm_read_flash(src_addr + current_index, read_value, 256); |
| | | fm_write_flash(dst_addr+ current_index, read_value, 256); |
| | | current_index += 256; |
| | | } |
| | | else { |
| | | fm_read_flash(src_addr + current_index, read_value, header.ih_img_size - current_index); /* remaining packets less than 256 bytes */ |
| | | fm_write_flash(dst_addr+ current_index, read_value, header.ih_img_size - current_index); |
| | | current_index = header.ih_img_size; |
| | | } |
| | | } |
| | | /* escape move at next time, should be make it invalid */ |
| | | fm_image_make_invalid(src_addr); |
| | | } |
| | | |
| | | bool fm_image_completed_check(uint32_t im_addr) |
| | | { |
| | | |
| | | uint32_t check_sum = 0; |
| | | uint32_t current_index = 0; |
| | | image_header_t header; |
| | | |
| | | fm_read_flash(im_addr, (unsigned char *)&header, sizeof(image_header_t)); |
| | | |
| | | if (header.ih_img_size > FLASH_IMAGE_MAX_SIZE || header.ih_img_size <= 256) /* image size should be obtained a basic rules */ |
| | | return false; |
| | | |
| | | im_addr += sizeof(image_header_t); |
| | | |
| | | while(current_index < header.ih_img_size) { |
| | | if (current_index + 256 <= header.ih_img_size){ /* remaining packets over than 256 bytes */ |
| | | fm_read_flash(im_addr + current_index, read_value, 256); |
| | | current_index += 256; |
| | | check_sum_add(&check_sum, read_value, 256); |
| | | } |
| | | else { |
| | | fm_read_flash(im_addr + current_index, read_value, header.ih_img_size - current_index); /* remaining packets less than 256 bytes */ |
| | | check_sum_add(&check_sum, read_value, header.ih_img_size - current_index); |
| | | current_index = header.ih_img_size; |
| | | } |
| | | } |
| | | |
| | | if (header.checksum == check_sum) { |
| | | return true; |
| | | } else |
| | | return false; |
| | | |
| | | uint32_t check_sum = 0; |
| | | uint32_t current_index = 0; |
| | | image_header_t header; |
| | | |
| | | fm_read_flash(im_addr, (unsigned char *)&header, sizeof(image_header_t)); |
| | | |
| | | if (header.ih_img_size > FLASH_IMAGE_MAX_SIZE || header.ih_img_size <= 256) /* image size should be obtained a basic rules */ |
| | | return false; |
| | | |
| | | im_addr += sizeof(image_header_t); |
| | | |
| | | while(current_index < header.ih_img_size) { |
| | | if (current_index + 256 <= header.ih_img_size){ /* remaining packets over than 256 bytes */ |
| | | fm_read_flash(im_addr + current_index, read_value, 256); |
| | | current_index += 256; |
| | | check_sum_add(&check_sum, read_value, 256); |
| | | } |
| | | else { |
| | | fm_read_flash(im_addr + current_index, read_value, header.ih_img_size - current_index); /* remaining packets less than 256 bytes */ |
| | | check_sum_add(&check_sum, read_value, header.ih_img_size - current_index); |
| | | current_index = header.ih_img_size; |
| | | } |
| | | } |
| | | |
| | | if (header.checksum == check_sum) { |
| | | return true; |
| | | } else |
| | | return false; |
| | | } |
| | | |
| | | #if false |
| | | #if 0 |
| | | const uint8_t flash_image[] = { |
| | | 0x1, 0x2, 0x3, 0x4, |
| | | 0x1, 0x1, 0x0, 0x0, |
| | |
| | | 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, |
| | | 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, |
| | | 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, |
| | | 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 |
| | | 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 |
| | | }; |
| | | |
| | | void t_fm_image_completed_check_test(void) |
| | | { |
| | | bool ret; |
| | | |
| | | ret = fm_image_completed_check((uint32_t)flash_image); |
| | | if (ret) { |
| | | while(1); |
| | | } |
| | | bool ret; |
| | | |
| | | ret = fm_image_completed_check((uint32_t)flash_image); |
| | | if (ret) { |
| | | while(1); |
| | | } |
| | | } |
| | | #endif |
| | | |