1063 lines
31 KiB
C
1063 lines
31 KiB
C
// Copyright 2020-2021 Beken
|
|
//
|
|
// 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 <common/bk_include.h>
|
|
#include <components/ate.h>
|
|
#include <os/mem.h>
|
|
#include <driver/flash.h>
|
|
#include <os/os.h>
|
|
#include "flash_driver.h"
|
|
#include "flash_hal.h"
|
|
#include "sys_driver.h"
|
|
#include "driver/flash_partition.h"
|
|
#include <modules/chip_support.h>
|
|
#include "flash_bypass.h"
|
|
|
|
#if (CONFIG_SOC_BK7236XX) || (CONFIG_SOC_BK7239XX)
|
|
#include "partitions_gen.h"
|
|
#endif
|
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
#include "spinlock.h"
|
|
static SPINLOCK_SECTION volatile spinlock_t flash_spin_lock = SPIN_LOCK_INIT;
|
|
#endif // CONFIG_FREERTOS_SMP
|
|
|
|
typedef struct {
|
|
flash_hal_t hal;
|
|
uint32_t flash_id;
|
|
uint32_t flash_status_reg_val;
|
|
uint32_t flash_line_mode;
|
|
const flash_config_t * flash_cfg;
|
|
} flash_driver_t;
|
|
|
|
typedef struct {
|
|
uint32_t reg16;
|
|
uint32_t reg17;
|
|
} flash_ctrl_context_t;
|
|
|
|
#define FLASH_GET_PROTECT_CFG(cfg) ((cfg) & FLASH_STATUS_REG_PROTECT_MASK)
|
|
#define FLASH_GET_CMP_CFG(cfg) (((cfg) >> FLASH_STATUS_REG_PROTECT_OFFSET) & FLASH_STATUS_REG_PROTECT_MASK)
|
|
|
|
#define FLASH_RETURN_ON_DRIVER_NOT_INIT() do {\
|
|
if (!s_flash_is_init) {\
|
|
return BK_ERR_FLASH_NOT_INIT;\
|
|
}\
|
|
} while(0)
|
|
|
|
#define FLASH_RETURN_ON_WRITE_ADDR_OUT_OF_RANGE(addr, len) do {\
|
|
if ((addr >= s_flash.flash_cfg->flash_size) ||\
|
|
(len > s_flash.flash_cfg->flash_size) ||\
|
|
((addr + len) > s_flash.flash_cfg->flash_size)) {\
|
|
FLASH_LOGW("write error[addr:0x%x len:0x%x]\r\n", addr, len);\
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;\
|
|
}\
|
|
} while(0)
|
|
|
|
static const flash_config_t flash_config[] = {
|
|
/* flash_id, flash_size, status_reg_size, line_mode, cmp_post, protect_post, protect_mask, protect_all, protect_none, unprotect_last_block. quad_en_post, quad_en_val, coutinuous_read_mode_bits_val */
|
|
{0x1C7016, FLASH_SIZE_4M, 1, FLASH_LINE_MODE_FOUR, 0, 2, 0x1F, 0x1F, 0x00, 0x01B, 9, 1, 0xA5, }, //en_25qh32b
|
|
{0x1C7015, FLASH_SIZE_2M, 1, FLASH_LINE_MODE_FOUR, 0, 2, 0x1F, 0x1F, 0x00, 0x0d, 9, 1, 0xA5, }, //en_25qh16b
|
|
{0x0B4014, FLASH_SIZE_1M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //xtx_25f08b
|
|
{0x0B4015, FLASH_SIZE_2M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //xtx_25f16b
|
|
{0x0B4016, FLASH_SIZE_4M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //xtx_25f32b
|
|
{0x0B4017, FLASH_SIZE_8M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x05, 0x00, 0x109, 9, 1, 0xA0, }, //xtx_25f64b
|
|
{0x0B6017, FLASH_SIZE_8M, 2, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 9, 1, 0xA0, }, //xt_25q64d
|
|
{0x0B6018, FLASH_SIZE_16M, 2, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 9, 1, 0xA0, }, //xt_25q128d
|
|
{0x0B4018, FLASH_SIZE_16M, 2, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 9, 1, 0xA0, }, //xt_25F128F-W
|
|
{0x0E4016, FLASH_SIZE_4M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //xtx_FT25H32
|
|
{0x1C4116, FLASH_SIZE_4M, 1, FLASH_LINE_MODE_FOUR, 0, 2, 0x1F, 0x1F, 0x00, 0x00E, 9, 1, 0xA0, }, //en_25qe32a(not support 4 line)
|
|
{0x5E5018, FLASH_SIZE_16M, 1, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 9, 1, 0xA0, }, //zb_25lq128c
|
|
{0xC84015, FLASH_SIZE_2M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //gd_25q16c
|
|
{0xC84017, FLASH_SIZE_8M, 1, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //gd_25q16c
|
|
{0xC84016, FLASH_SIZE_4M, 3, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x00E, 9, 1, 0xA0, }, //gd_25q32c
|
|
{0xC86018, FLASH_SIZE_16M, 2, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 9, 1, 0xA0, }, //gd_25lq128e
|
|
{0xC86515, FLASH_SIZE_2M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //gd_25w16e
|
|
{0xC86516, FLASH_SIZE_4M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x00E, 9, 1, 0xA0, }, //gd_25wq32e
|
|
{0xEF4016, FLASH_SIZE_4M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //w_25q32(bfj)
|
|
{0x204118, FLASH_SIZE_16M, 2, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 9, 1, 0xA0, }, //xm_25qu128c
|
|
{0x204016, FLASH_SIZE_4M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //xmc_25qh32b
|
|
{0xC22315, FLASH_SIZE_2M, 1, FLASH_LINE_MODE_FOUR, 0, 2, 0x0F, 0x0F, 0x00, 0x00E, 6, 1, 0xA5, }, //mx_25v16b
|
|
{0xEB6015, FLASH_SIZE_2M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x101, 9, 1, 0xA0, }, //zg_th25q16b
|
|
{0xC86517, FLASH_SIZE_8M, 2, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x00E, 9, 1, 0xA0, }, //gd_25Q32E
|
|
{0xCD6017, FLASH_SIZE_8M, 3, FLASH_LINE_MODE_FOUR, 14, 2, 0x1F, 0x1F, 0x00, 0x00E, 9, 1, 0xA0, }, //th_25q64ha
|
|
{0x000000, FLASH_SIZE_4M, 2, FLASH_LINE_MODE_TWO, 0, 2, 0x1F, 0x00, 0x00, 0x000, 0, 0, 0x00, }, //default
|
|
};
|
|
|
|
static flash_driver_t s_flash = {0};
|
|
static bool s_flash_is_init = false;
|
|
|
|
// static flash_ctrl_context_t flash_ctrl_context;
|
|
|
|
#if (CONFIG_SOC_BK7256XX)
|
|
static uint32_t s_hold_low_speed_status = 0;
|
|
#endif
|
|
|
|
extern bk_err_t mb_flash_ipc_init(void);
|
|
extern bk_err_t mb_flash_op_prepare(void);
|
|
extern bk_err_t mb_flash_op_finish(void);
|
|
|
|
extern bk_err_t bk_flash_partition_write_perm_check_by_addr(uint32_t addr, uint32_t size, uint32_t magic_code);
|
|
|
|
extern int xTaskResumeAll( void );
|
|
extern void vTaskSuspendAll( void );
|
|
|
|
static inline uint32_t flash_enter_critical()
|
|
{
|
|
uint32_t flags = rtos_disable_int();
|
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
spin_lock(&flash_spin_lock);
|
|
#endif // CONFIG_FREERTOS_SMP
|
|
|
|
return flags;
|
|
}
|
|
|
|
static inline void flash_exit_critical(uint32_t flags)
|
|
{
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
spin_unlock(&flash_spin_lock);
|
|
#endif // CONFIG_FREERTOS_SMP
|
|
|
|
rtos_enable_int(flags);
|
|
}
|
|
|
|
#if 1
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
static beken_mutex_t s_flash_mutex = NULL;
|
|
#endif
|
|
|
|
static void flash_lock_init(void)
|
|
{
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
int ret = rtos_init_mutex(&s_flash_mutex);
|
|
BK_ASSERT(kNoErr == ret); /* ASSERT VERIFIED */
|
|
#endif
|
|
}
|
|
|
|
#if 0
|
|
static void flash_lock_deinit(void)
|
|
{
|
|
int ret = rtos_deinit_mutex(&s_flash_mutex);
|
|
BK_ASSERT(kNoErr == ret); /* ASSERT VERIFIED */
|
|
}
|
|
#endif
|
|
|
|
static void flash_lock(void)
|
|
{
|
|
if(rtos_is_in_interrupt_context() || rtos_local_irq_disabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
rtos_lock_mutex(&s_flash_mutex);
|
|
#endif
|
|
vTaskSuspendAll();
|
|
|
|
mb_flash_op_prepare();
|
|
}
|
|
|
|
static void flash_unlock(void)
|
|
{
|
|
if(rtos_is_in_interrupt_context() || rtos_local_irq_disabled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
mb_flash_op_finish();
|
|
|
|
xTaskResumeAll();
|
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
rtos_unlock_mutex(&s_flash_mutex);
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
|
|
static void flash_get_current_config(void)
|
|
{
|
|
bool cfg_success = false;
|
|
|
|
for (uint32_t i = 0; i < (ARRAY_SIZE(flash_config) - 1); i++) {
|
|
if (s_flash.flash_id == flash_config[i].flash_id) {
|
|
s_flash.flash_cfg = &flash_config[i];
|
|
cfg_success = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!cfg_success) {
|
|
s_flash.flash_cfg = &flash_config[ARRAY_SIZE(flash_config) - 1];
|
|
for(int i = 0; i < 10; i++) {
|
|
FLASH_LOGE("This flash is not identified, choose default config\r\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
static uint32_t flash_read_status_reg(void)
|
|
{
|
|
uint32_t status_reg;;
|
|
|
|
uint32_t int_level = flash_enter_critical();
|
|
status_reg = flash_hal_read_status_reg(&s_flash.hal, s_flash.flash_cfg->status_reg_size);
|
|
flash_exit_critical(int_level);
|
|
|
|
return status_reg;
|
|
}
|
|
|
|
static void flash_write_status_reg(uint32_t status_reg_val)
|
|
{
|
|
uint32_t int_level = flash_enter_critical();
|
|
s_flash.flash_status_reg_val = status_reg_val;
|
|
|
|
flash_hal_write_status_reg(&s_flash.hal, s_flash.flash_cfg->status_reg_size, status_reg_val);
|
|
flash_exit_critical(int_level);
|
|
}
|
|
|
|
static uint32_t flash_get_id(void)
|
|
{
|
|
uint32_t flash_id;;
|
|
|
|
uint32_t int_level = flash_enter_critical();
|
|
flash_id = flash_hal_get_id(&s_flash.hal);
|
|
flash_exit_critical(int_level);
|
|
|
|
return flash_id;
|
|
}
|
|
|
|
static uint32_t flash_get_protect_cfg(flash_protect_type_t type)
|
|
{
|
|
switch (type) {
|
|
case FLASH_PROTECT_NONE:
|
|
return FLASH_GET_PROTECT_CFG(s_flash.flash_cfg->protect_none);
|
|
case FLASH_PROTECT_ALL:
|
|
return FLASH_GET_PROTECT_CFG(s_flash.flash_cfg->protect_all);
|
|
case FLASH_UNPROTECT_LAST_BLOCK:
|
|
return FLASH_GET_PROTECT_CFG(s_flash.flash_cfg->unprotect_last_block);
|
|
default:
|
|
return FLASH_GET_PROTECT_CFG(s_flash.flash_cfg->protect_all);
|
|
}
|
|
}
|
|
|
|
static void flash_set_protect_cfg(uint32_t *status_reg_val, uint32_t new_protect_cfg)
|
|
{
|
|
*status_reg_val &= ~(s_flash.flash_cfg->protect_mask << s_flash.flash_cfg->protect_post);
|
|
*status_reg_val |= ((new_protect_cfg & s_flash.flash_cfg->protect_mask) << s_flash.flash_cfg->protect_post);
|
|
}
|
|
|
|
static uint32_t flash_get_cmp_cfg(flash_protect_type_t type)
|
|
{
|
|
switch (type) {
|
|
case FLASH_PROTECT_NONE:
|
|
return FLASH_GET_CMP_CFG(s_flash.flash_cfg->protect_none);
|
|
case FLASH_PROTECT_ALL:
|
|
return FLASH_GET_CMP_CFG(s_flash.flash_cfg->protect_all);
|
|
case FLASH_UNPROTECT_LAST_BLOCK:
|
|
return FLASH_GET_CMP_CFG(s_flash.flash_cfg->unprotect_last_block);
|
|
default:
|
|
return FLASH_GET_CMP_CFG(s_flash.flash_cfg->protect_all);
|
|
}
|
|
}
|
|
|
|
static void flash_set_cmp_cfg(uint32_t *status_reg_val, uint32_t new_cmp_cfg)
|
|
{
|
|
*status_reg_val &= ~(FLASH_CMP_MASK << s_flash.flash_cfg->cmp_post);
|
|
*status_reg_val |= ((new_cmp_cfg & FLASH_CMP_MASK) << s_flash.flash_cfg->cmp_post);
|
|
}
|
|
|
|
static bool flash_is_need_update_status_reg(uint32_t protect_cfg, uint32_t cmp_cfg, uint32_t status_reg_val)
|
|
{
|
|
uint32_t cur_protect_val_in_status_reg = (status_reg_val >> s_flash.flash_cfg->protect_post) & s_flash.flash_cfg->protect_mask;
|
|
uint32_t cur_cmp_val_in_status_reg = (status_reg_val >> s_flash.flash_cfg->cmp_post) & FLASH_CMP_MASK;
|
|
|
|
if (cur_protect_val_in_status_reg != protect_cfg ||
|
|
cur_cmp_val_in_status_reg != cmp_cfg) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static flash_protect_type_t flash_get_protect_type(uint32_t sr_value)
|
|
{
|
|
uint32_t type = 0;
|
|
uint16_t protect_value = 0;
|
|
uint16_t cmp;
|
|
|
|
protect_value = sr_value >> s_flash.flash_cfg->protect_post;
|
|
protect_value = protect_value & s_flash.flash_cfg->protect_mask;
|
|
|
|
cmp = (sr_value >> s_flash.flash_cfg->cmp_post) & FLASH_CMP_MASK;
|
|
protect_value |= cmp << FLASH_STATUS_REG_PROTECT_OFFSET;
|
|
|
|
if (protect_value == s_flash.flash_cfg->protect_all)
|
|
type = FLASH_PROTECT_ALL;
|
|
else if (protect_value == s_flash.flash_cfg->protect_none)
|
|
type = FLASH_PROTECT_NONE;
|
|
else if (protect_value == s_flash.flash_cfg->unprotect_last_block)
|
|
type = FLASH_UNPROTECT_LAST_BLOCK;
|
|
else
|
|
type = FLASH_PROTECT_ALL; // FLASH_UNPROTECT_LAST_BLOCK ???
|
|
|
|
return type;
|
|
}
|
|
|
|
static void flash_set_protect_type(flash_protect_type_t type)
|
|
{
|
|
uint32_t protect_cfg;
|
|
uint32_t cmp_cfg;
|
|
uint32_t status_reg = s_flash.flash_status_reg_val;
|
|
|
|
protect_cfg = flash_get_protect_cfg(type);
|
|
cmp_cfg = flash_get_cmp_cfg(type);
|
|
|
|
#if CONFIG_FLASH_SUPPORT_MULTI_PE /* multiple process element. (multi-cores or SPE/NSPE) */
|
|
status_reg = flash_read_status_reg();
|
|
#endif
|
|
|
|
#if CONFIG_FLASH_WRITE_STATUS_VOLATILE
|
|
flash_hal_set_volatile_status_write(&s_flash.hal);
|
|
#endif
|
|
|
|
if (flash_is_need_update_status_reg(protect_cfg, cmp_cfg, status_reg)) {
|
|
flash_set_protect_cfg(&status_reg, protect_cfg);
|
|
flash_set_cmp_cfg(&status_reg, cmp_cfg);
|
|
|
|
//FLASH_LOGD("write status reg:%x, status_reg_size:%d\r\n", status_reg, s_flash.flash_cfg->status_reg_size);
|
|
flash_write_status_reg(status_reg);
|
|
}
|
|
}
|
|
|
|
static void flash_set_qe(void)
|
|
{
|
|
uint32_t status_reg = s_flash.flash_status_reg_val;
|
|
|
|
#if CONFIG_FLASH_SUPPORT_MULTI_PE
|
|
status_reg = flash_read_status_reg();
|
|
#endif
|
|
if (((status_reg >> s_flash.flash_cfg->quad_en_post) & 0x01) == s_flash.flash_cfg->quad_en_val) {
|
|
return;
|
|
}
|
|
|
|
if (1 == s_flash.flash_cfg->quad_en_val)
|
|
status_reg |= (1 << s_flash.flash_cfg->quad_en_post);
|
|
else
|
|
status_reg &= ~(1 << s_flash.flash_cfg->quad_en_post);
|
|
|
|
flash_write_status_reg(status_reg);
|
|
}
|
|
|
|
static void flash_read_common(uint8_t *buffer, uint32_t address, uint32_t len)
|
|
{
|
|
uint32_t addr = address & (~FLASH_ADDRESS_MASK);
|
|
uint32_t buf[FLASH_BUFFER_LEN] = {0};
|
|
uint8_t *pb = (uint8_t *)&buf[0];
|
|
|
|
if (len == 0) {
|
|
return;
|
|
}
|
|
|
|
while (len) {
|
|
uint32_t int_level = flash_enter_critical();
|
|
|
|
flash_hal_set_op_cmd_read(&s_flash.hal, addr);
|
|
addr += FLASH_BYTES_CNT;
|
|
for (uint32_t i = 0; i < FLASH_BUFFER_LEN; i++) {
|
|
buf[i] = flash_hal_read_data(&s_flash.hal);
|
|
}
|
|
flash_exit_critical(int_level);
|
|
|
|
for (uint32_t i = address % FLASH_BYTES_CNT; i < FLASH_BYTES_CNT; i++) {
|
|
*buffer++ = pb[i];
|
|
address++;
|
|
len--;
|
|
if (len == 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void flash_read_word_common(uint32_t *buffer, uint32_t address, uint32_t len)
|
|
{
|
|
uint32_t addr = address & (~FLASH_ADDRESS_MASK);
|
|
uint32_t buf[FLASH_BUFFER_LEN] = {0};
|
|
//nt8_t *pb = (uint8_t *)&buf[0];
|
|
uint32_t *pb = (uint32_t *)&buf[0];
|
|
|
|
if (len == 0) {
|
|
return;
|
|
}
|
|
|
|
while (len) {
|
|
uint32_t int_level = flash_enter_critical();
|
|
|
|
flash_hal_set_op_cmd_read(&s_flash.hal, addr);
|
|
addr += FLASH_BYTES_CNT;
|
|
for (uint32_t i = 0; i < FLASH_BUFFER_LEN; i++) {
|
|
buf[i] = flash_hal_read_data(&s_flash.hal);
|
|
}
|
|
|
|
flash_exit_critical(int_level);
|
|
|
|
for (uint32_t i = address % (FLASH_BYTES_CNT/4); i < (FLASH_BYTES_CNT/4); i++) {
|
|
*buffer++ = pb[i];
|
|
address++;
|
|
len--;
|
|
if (len == 0) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static bk_err_t flash_write_common(const uint8_t *buffer, uint32_t address, uint32_t len)
|
|
{
|
|
uint32_t buf[FLASH_BUFFER_LEN];
|
|
uint8_t *pb = (uint8_t *)&buf[0];
|
|
uint32_t addr = address & (~FLASH_ADDRESS_MASK);
|
|
|
|
FLASH_RETURN_ON_WRITE_ADDR_OUT_OF_RANGE(addr, len);
|
|
|
|
while (len) {
|
|
os_memset(pb, 0xFF, FLASH_BYTES_CNT);
|
|
for (uint32_t i = address % FLASH_BYTES_CNT; i < FLASH_BYTES_CNT; i++) {
|
|
pb[i] = *buffer++;
|
|
address++;
|
|
len--;
|
|
if (len == 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint32_t int_level = flash_enter_critical();
|
|
flash_hal_wait_op_done(&s_flash.hal);
|
|
|
|
for (uint32_t i = 0; i < FLASH_BUFFER_LEN; i++) {
|
|
flash_hal_write_data(&s_flash.hal, buf[i]);
|
|
}
|
|
flash_hal_set_op_cmd_write(&s_flash.hal, addr);
|
|
flash_exit_critical(int_level);
|
|
|
|
addr += FLASH_BYTES_CNT;
|
|
}
|
|
return BK_OK;
|
|
}
|
|
|
|
static bk_err_t flash_erase_block(uint32_t address, int type)
|
|
{
|
|
uint32_t int_level = flash_enter_critical();
|
|
|
|
flash_hal_erase_block(&s_flash.hal, address, type);
|
|
|
|
flash_exit_critical(int_level);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
static flash_line_mode_t flash_set_line_mode(flash_line_mode_t line_mode)
|
|
{
|
|
uint32_t int_level = flash_enter_critical();
|
|
|
|
flash_line_mode_t new_line_mode;
|
|
flash_line_mode_t old_line_mode = s_flash.flash_line_mode;
|
|
|
|
#if CONFIG_FLASH_QUAD_ENABLE
|
|
if ( (FLASH_LINE_MODE_FOUR == line_mode)
|
|
&& (FLASH_LINE_MODE_FOUR == s_flash.flash_cfg->line_mode) )
|
|
{
|
|
new_line_mode = FLASH_LINE_MODE_FOUR;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
new_line_mode = FLASH_LINE_MODE_TWO;
|
|
}
|
|
|
|
if(new_line_mode == old_line_mode)
|
|
{
|
|
flash_exit_critical(int_level);
|
|
return old_line_mode;
|
|
}
|
|
|
|
flash_hal_clear_qwfr(&s_flash.hal); // cmd CRMR (coutinuous_read_mode reset), quit QPI mode.
|
|
|
|
#if CONFIG_SOC_BK7236XX
|
|
sys_drv_set_sys2flsh_2wire(0);
|
|
#endif
|
|
|
|
if (FLASH_LINE_MODE_FOUR == new_line_mode)
|
|
{
|
|
flash_hal_set_quad_m_value(&s_flash.hal, s_flash.flash_cfg->coutinuous_read_mode_bits_val);
|
|
flash_set_qe();
|
|
flash_hal_set_mode(&s_flash.hal, FLASH_MODE_QUAD); // enter QPI mode.
|
|
}
|
|
else
|
|
{
|
|
flash_hal_set_mode(&s_flash.hal, FLASH_MODE_DUAL);
|
|
}
|
|
|
|
s_flash.flash_line_mode = new_line_mode;
|
|
|
|
#if CONFIG_SOC_BK7236XX
|
|
sys_drv_set_sys2flsh_2wire(1);
|
|
#endif
|
|
|
|
flash_exit_critical(int_level);
|
|
|
|
return old_line_mode;
|
|
|
|
}
|
|
|
|
flash_line_mode_t bk_flash_get_line_mode(void)
|
|
{
|
|
return s_flash.flash_cfg->line_mode;
|
|
}
|
|
|
|
bk_err_t bk_flash_set_line_mode(flash_line_mode_t line_mode)
|
|
{
|
|
return BK_OK;
|
|
|
|
(void)line_mode;
|
|
}
|
|
|
|
bk_err_t bk_flash_driver_init(void)
|
|
{
|
|
if (s_flash_is_init) {
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t ret_code = mb_flash_ipc_init(); /* used for projects with LCD. */
|
|
if(ret_code != BK_OK)
|
|
return ret_code;
|
|
|
|
#if (CONFIG_CPU_CNT > 1)
|
|
extern bk_err_t bk_flash_svr_init(void);
|
|
ret_code = bk_flash_svr_init();
|
|
if(ret_code != BK_OK)
|
|
{
|
|
BK_LOGE("Flash", "flash svr create failed %d.\r\n", ret_code);
|
|
}
|
|
#endif
|
|
|
|
os_memset(&s_flash, 0, sizeof(s_flash));
|
|
|
|
flash_hal_init(&s_flash.hal);
|
|
|
|
#if (0 == CONFIG_JTAG)
|
|
flash_hal_disable_cpu_data_wr(&s_flash.hal);
|
|
#endif
|
|
|
|
// s_flash.flash_line_mode = 0;
|
|
|
|
flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
|
|
s_flash.flash_id = flash_get_id();
|
|
|
|
FLASH_LOGI("id=0x%x\r\n", s_flash.flash_id);
|
|
|
|
flash_get_current_config();
|
|
|
|
flash_hal_set_quad_m_value(&s_flash.hal, s_flash.flash_cfg->coutinuous_read_mode_bits_val);
|
|
|
|
s_flash.flash_status_reg_val = flash_read_status_reg();
|
|
|
|
flash_set_protect_type(FLASH_UNPROTECT_LAST_BLOCK);
|
|
|
|
flash_set_line_mode(s_flash.flash_cfg->line_mode);
|
|
|
|
flash_hal_set_default_clk(&s_flash.hal);
|
|
#if (CONFIG_SOC_BK7256XX)
|
|
#if CONFIG_ATE_TEST
|
|
bk_flash_clk_switch(FLASH_SPEED_LOW, 0);
|
|
#else
|
|
bk_flash_clk_switch(FLASH_SPEED_HIGH, 0);
|
|
#endif
|
|
#endif
|
|
|
|
#if (CONFIG_SOC_BK7236XX) || (CONFIG_SOC_BK7239XX)
|
|
#if (CONFIG_SOC_BK7236N) || (CONFIG_SOC_BK7239XX)
|
|
if((s_flash.flash_id >> FLASH_ManuFacID_POSI) == FLASH_ManuFacID_GD || (s_flash.flash_id >> FLASH_ManuFacID_POSI) == FLASH_ManuFacID_TH) {
|
|
if((2 != sys_drv_flash_get_clk_sel()) || (0 != sys_drv_flash_get_clk_div())) {
|
|
sys_drv_flash_set_clk_div(0); // 80M div 1 = 80M
|
|
sys_drv_flash_cksel(2);
|
|
}
|
|
} else {
|
|
if((0 != sys_drv_flash_get_clk_sel()) || (0 != sys_drv_flash_get_clk_div())) {
|
|
sys_drv_flash_set_clk_div(0); // XTAL= 40M
|
|
sys_drv_flash_cksel(0);
|
|
}
|
|
}
|
|
#else
|
|
if((s_flash.flash_id >> FLASH_ManuFacID_POSI) == FLASH_ManuFacID_GD || (s_flash.flash_id >> FLASH_ManuFacID_POSI) == FLASH_ManuFacID_TH) {
|
|
if((1 != sys_drv_flash_get_clk_sel()) || (1 != sys_drv_flash_get_clk_div())) {
|
|
#if (CONFIG_FLASH_CLK_120M)
|
|
sys_drv_flash_set_clk_div(0); // dpll div 4 = 120M
|
|
#else
|
|
sys_drv_flash_set_clk_div(1); // dpll div 6 = 80M
|
|
#endif
|
|
sys_drv_flash_cksel(1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if((1 != sys_drv_flash_get_clk_sel()) || (3 != sys_drv_flash_get_clk_div())) {
|
|
sys_drv_flash_set_clk_div(3); // dpll div 10 = 48M
|
|
sys_drv_flash_cksel(1);
|
|
}
|
|
}
|
|
#endif
|
|
sys_drv_set_sys2flsh_2wire(1);
|
|
|
|
#endif
|
|
|
|
flash_lock_init();
|
|
|
|
s_flash_is_init = true;
|
|
|
|
#if CONFIG_FLASH_TEST
|
|
// int bk_flash_register_cli_test_feature(void);
|
|
// int bk_flash_wr_register_cli_test_feature(void);
|
|
// bk_flash_register_cli_test_feature();
|
|
// bk_flash_wr_register_cli_test_feature();
|
|
#endif
|
|
|
|
#if CONFIG_FLASH_API_TEST
|
|
int bk_flash_api_register_cli_test_feature(void);
|
|
bk_flash_api_register_cli_test_feature();
|
|
#endif
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_driver_deinit(void)
|
|
{
|
|
if (!s_flash_is_init) {
|
|
return BK_OK;
|
|
}
|
|
|
|
s_flash_is_init = false;
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
static bk_err_t flash_erase_no_lock(uint32_t address, int cmd)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("erase error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
|
|
uint32_t erase_size = 0;
|
|
|
|
if(cmd == FLASH_OP_CMD_SE)
|
|
erase_size = FLASH_SECTOR_SIZE;
|
|
else if(cmd == FLASH_OP_CMD_BE1)
|
|
erase_size = FLASH_BLOCK32_SIZE;
|
|
else if(cmd == FLASH_OP_CMD_BE2)
|
|
erase_size = FLASH_BLOCK_SIZE;
|
|
else
|
|
return BK_FAIL;
|
|
|
|
uint32_t erase_addr = address & (~(erase_size - 1));
|
|
|
|
bk_err_t ret_val = BK_FAIL;
|
|
|
|
flash_line_mode_t old_line_mode = flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
|
|
uint32_t status_reg = s_flash.flash_status_reg_val;
|
|
#if CONFIG_FLASH_SUPPORT_MULTI_PE
|
|
status_reg = flash_read_status_reg();
|
|
#endif
|
|
|
|
flash_protect_type_t partition_type = flash_get_protect_type(status_reg);
|
|
|
|
if(bk_flash_partition_write_perm_check_by_addr(erase_addr, erase_size, FLASH_API_MAGIC_CODE) == BK_OK)
|
|
{
|
|
flash_set_protect_type(FLASH_PROTECT_NONE);
|
|
|
|
if(bk_flash_partition_write_perm_check_by_addr(erase_addr, erase_size, FLASH_API_MAGIC_CODE) == BK_OK)
|
|
ret_val = flash_erase_block(address, cmd);
|
|
}
|
|
|
|
flash_set_protect_type(partition_type);
|
|
flash_set_line_mode(old_line_mode);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
bk_err_t bk_flash_erase_sector(uint32_t address)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("erase error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
|
|
flash_lock();
|
|
|
|
bk_err_t ret_val = flash_erase_no_lock(address, FLASH_OP_CMD_SE);
|
|
|
|
flash_unlock();
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
bk_err_t bk_flash_erase_32k(uint32_t address)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("erase error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
|
|
flash_lock();
|
|
|
|
bk_err_t ret_val = flash_erase_no_lock(address, FLASH_OP_CMD_BE1);
|
|
|
|
flash_unlock();
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
bk_err_t bk_flash_erase_block(uint32_t address)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("erase error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
|
|
flash_lock();
|
|
|
|
bk_err_t ret_val = flash_erase_no_lock(address, FLASH_OP_CMD_BE2);
|
|
|
|
flash_unlock();
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
bk_err_t bk_flash_read_bytes(uint32_t address, uint8_t *user_buf, uint32_t size)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("read error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
flash_read_common(user_buf, address, size);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_read_word(uint32_t address, uint32_t *user_buf, uint32_t size)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("read error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
flash_read_word_common(user_buf, address, size);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
static bk_err_t flash_write_no_lock(uint32_t address, const uint8_t *user_buf, uint32_t size)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("write error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
|
|
bk_err_t ret_val = BK_FAIL;
|
|
|
|
flash_line_mode_t old_line_mode = flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
|
|
uint32_t status_reg = s_flash.flash_status_reg_val;
|
|
#if CONFIG_FLASH_SUPPORT_MULTI_PE
|
|
status_reg = flash_read_status_reg();
|
|
#endif
|
|
|
|
flash_protect_type_t partition_type = flash_get_protect_type(status_reg);
|
|
|
|
if(bk_flash_partition_write_perm_check_by_addr(address, size, FLASH_API_MAGIC_CODE) == BK_OK)
|
|
{
|
|
flash_set_protect_type(FLASH_PROTECT_NONE);
|
|
|
|
if(bk_flash_partition_write_perm_check_by_addr(address, size, FLASH_API_MAGIC_CODE) == BK_OK)
|
|
ret_val = flash_write_common(user_buf, address, size);
|
|
}
|
|
|
|
flash_set_protect_type(partition_type);
|
|
flash_set_line_mode(old_line_mode);
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
bk_err_t bk_flash_write_bytes(uint32_t address, const uint8_t *user_buf, uint32_t size)
|
|
{
|
|
if (address >= s_flash.flash_cfg->flash_size) {
|
|
FLASH_LOGW("write error:invalid address 0x%x\r\n", address);
|
|
return BK_ERR_FLASH_ADDR_OUT_OF_RANGE;
|
|
}
|
|
|
|
flash_lock();
|
|
|
|
bk_err_t ret_val = flash_write_no_lock(address, user_buf, size);
|
|
|
|
flash_unlock();
|
|
|
|
return ret_val;
|
|
}
|
|
|
|
uint32_t bk_flash_get_id(void)
|
|
{
|
|
return s_flash.flash_id;
|
|
}
|
|
|
|
bk_err_t bk_flash_set_clk_dpll(void)
|
|
{
|
|
sys_drv_flash_set_dpll();
|
|
flash_hal_set_clk_dpll(&s_flash.hal);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_set_clk_dco(void)
|
|
{
|
|
sys_drv_flash_set_dco();
|
|
bool ate_enabled = ate_is_enabled();
|
|
flash_hal_set_clk_dco(&s_flash.hal, ate_enabled);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
#if (CONFIG_SOC_BK7256XX)
|
|
bk_err_t bk_flash_set_clk(flash_clk_src_t flash_src_clk, uint8_t flash_dpll_div)
|
|
{
|
|
if ((FLASH_CLK_DPLL == flash_src_clk) && (flash_dpll_div == 0)) {
|
|
FLASH_LOGE("flash 120M clock not support.\r\n");
|
|
return BK_FAIL;
|
|
}
|
|
if (FLASH_CLK_APLL == flash_src_clk) {
|
|
FLASH_LOGE("flash apll clock not support.\r\n");
|
|
return BK_FAIL;
|
|
}
|
|
|
|
uint32_t int_level = flash_enter_critical();
|
|
if((sys_drv_flash_get_clk_sel() == flash_src_clk) && (sys_drv_flash_get_clk_div() == flash_dpll_div)) {
|
|
flash_exit_critical(int_level);
|
|
return BK_OK;
|
|
}
|
|
if (FLASH_CLK_DPLL == flash_src_clk) {
|
|
sys_drv_flash_set_clk_div(flash_dpll_div);
|
|
}
|
|
sys_drv_flash_cksel(flash_src_clk);
|
|
flash_exit_critical(int_level);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_clk_switch(uint32_t flash_speed_type, uint32_t modules)
|
|
{
|
|
uint32_t int_level = flash_enter_critical();
|
|
int chip_id = 0;
|
|
|
|
switch (flash_speed_type) {
|
|
case FLASH_SPEED_LOW:
|
|
s_hold_low_speed_status |= modules;
|
|
FLASH_LOGD("%s: set low, 0x%x 0x%x\r\n", __func__, s_hold_low_speed_status, modules);
|
|
if (s_hold_low_speed_status) {
|
|
bk_flash_set_clk(FLASH_CLK_XTAL, FLASH_DPLL_DIV_VALUE_TEN);
|
|
}
|
|
break;
|
|
|
|
case FLASH_SPEED_HIGH:
|
|
s_hold_low_speed_status &= ~(modules);
|
|
FLASH_LOGD("%s: clear low bit, 0x%x 0x%x\r\n", __func__, s_hold_low_speed_status, modules);
|
|
if (0 == s_hold_low_speed_status) {
|
|
chip_id = bk_get_hardware_chip_id_version();
|
|
//chipC version with GD flash switch to 80M for peformance
|
|
if ((chip_id == CHIP_VERSION_C) && ((s_flash.flash_id >> FLASH_ManuFacID_POSI) == FLASH_ManuFacID_GD)) {
|
|
bk_flash_set_clk(FLASH_CLK_DPLL, FLASH_DPLL_DIV_VALUE_SIX);
|
|
} else {
|
|
bk_flash_set_clk(FLASH_CLK_DPLL, FLASH_DPLL_DIV_VALUE_TEN);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
flash_exit_critical(int_level);
|
|
|
|
return BK_OK;
|
|
}
|
|
#endif
|
|
|
|
#if CONFIG_FLASH_TEST
|
|
bk_err_t bk_flash_write_enable(void)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_write_disable(void)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
|
|
uint16_t bk_flash_read_status_reg(void)
|
|
{
|
|
#if CONFIG_FLASH_SUPPORT_MULTI_PE
|
|
flash_line_mode_t old_line_mode = flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
uint16_t sr_data = flash_read_status_reg();
|
|
flash_set_line_mode(old_line_mode);
|
|
return sr_data;
|
|
#else
|
|
return s_flash.flash_status_reg_val;
|
|
#endif
|
|
}
|
|
|
|
bk_err_t bk_flash_write_status_reg(uint16_t status_reg_data)
|
|
{
|
|
#if 0
|
|
flash_line_mode_t old_line_mode = flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
flash_write_status_reg(status_reg_data);
|
|
flash_set_line_mode(old_line_mode);
|
|
#endif
|
|
return BK_OK;
|
|
}
|
|
|
|
uint32_t bk_flash_get_crc_err_num(void)
|
|
{
|
|
return flash_hal_get_crc_err_num(&s_flash.hal);
|
|
}
|
|
#endif
|
|
|
|
flash_protect_type_t bk_flash_get_protect_type(void)
|
|
{
|
|
|
|
return FLASH_PROTECT_ALL;
|
|
}
|
|
|
|
bk_err_t bk_flash_set_protect_type(flash_protect_type_t type)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
|
|
bool bk_flash_is_driver_inited()
|
|
{
|
|
return s_flash_is_init;
|
|
}
|
|
|
|
uint32_t bk_flash_get_current_total_size(void)
|
|
{
|
|
return s_flash.flash_cfg->flash_size;
|
|
}
|
|
|
|
bk_err_t bk_flash_register_ps_suspend_callback(flash_ps_callback_t ps_suspend_cb)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_register_ps_resume_callback(flash_ps_callback_t ps_resume_cb)
|
|
{
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_power_saving_enter(void)
|
|
{
|
|
// save flash ctrl setting to flash_ctrl_context;
|
|
flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
bk_err_t bk_flash_power_saving_exit(void)
|
|
{
|
|
// restore flash ctrl setting from flash_ctrl_context;
|
|
// the restore API must run in SRAM/ITCM.
|
|
// don't access flash before restoring setting, especially for A/B image project.
|
|
|
|
s_flash.flash_line_mode = 0;
|
|
flash_set_line_mode(s_flash.flash_cfg->line_mode);
|
|
|
|
return BK_OK;
|
|
}
|
|
|
|
__attribute__((section(".iram"))) bk_err_t bk_flash_enter_deep_sleep(void)
|
|
{
|
|
#if CONFIG_SOC_BK7236XX
|
|
int ret = 0;
|
|
uint8_t op_code = FLASH_CMD_ENTER_DEEP_PWR_DW;
|
|
|
|
// flash need to change 2 line when do flash operate except read
|
|
// need to recover 4 line, please do it manually
|
|
//if (FLASH_LINE_MODE_FOUR == bk_flash_get_line_mode())
|
|
// bk_flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
|
|
ret = flash_bypass_op_write(&op_code, NULL, 0);
|
|
if(ret == 0)// success
|
|
{
|
|
// delay T_dp: 3us
|
|
//for(volatile int j=0; j<500; j++);
|
|
return BK_OK;
|
|
}
|
|
#endif
|
|
return BK_FAIL;
|
|
}
|
|
|
|
__attribute__((section(".iram"))) bk_err_t bk_flash_exit_deep_sleep(void)
|
|
{
|
|
#if CONFIG_SOC_BK7236XX
|
|
int ret = 0;
|
|
uint8_t op_code = FLASH_CMD_EXIT_DEEP_PWR_DW;
|
|
|
|
// flash need to change 2 line when do flash operate except read
|
|
// need to recover 4 line, please do it manually
|
|
//if (FLASH_LINE_MODE_FOUR == bk_flash_get_line_mode())
|
|
// bk_flash_set_line_mode(FLASH_LINE_MODE_TWO);
|
|
|
|
ret = flash_bypass_op_write(&op_code, NULL, 0);
|
|
if(ret == 0)// success
|
|
{
|
|
// delay T_res1: 20us
|
|
//for(volatile int j=0; j<500; j++);
|
|
return BK_OK;
|
|
}
|
|
#endif
|
|
return BK_FAIL;
|
|
}
|
|
|
|
#if CONFIG_SECURITY_OTA
|
|
uint32_t flash_get_excute_enable()
|
|
{
|
|
return flash_hal_read_offset_enable(&s_flash.hal);
|
|
}
|
|
|
|
void bk_flash_enable_cpu_data_wr(void)
|
|
{
|
|
flash_hal_enable_cpu_data_wr(&s_flash.hal);
|
|
}
|
|
|
|
void bk_flash_disable_cpu_data_wr(void)
|
|
{
|
|
flash_hal_disable_cpu_data_wr(&s_flash.hal);
|
|
}
|
|
#endif
|
|
|
|
/* flash dump APIs are called in context of interrupt disabled. */
|
|
bk_err_t bk_flash_dump_erase_sector(uint32_t address)
|
|
{
|
|
return flash_erase_no_lock(address, FLASH_OP_CMD_SE);
|
|
}
|
|
|
|
bk_err_t bk_flash_dump_write(uint32_t address, const uint8_t *user_buf, uint32_t size)
|
|
{
|
|
return flash_write_no_lock(address, user_buf, size);
|
|
}
|
|
|