390 lines
11 KiB
C
390 lines
11 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 <driver/flash.h>
|
||
|
#include <driver/flash_partition.h>
|
||
|
#include "cli.h"
|
||
|
#include "flash_driver.h"
|
||
|
|
||
|
#if CONFIG_TFM_FLASH_NSC
|
||
|
#include "tfm_flash_nsc.h"
|
||
|
#endif
|
||
|
|
||
|
static void cli_flash_help(void)
|
||
|
{
|
||
|
CLI_LOGI("flash driver init\n");
|
||
|
CLI_LOGI("flash_driver deinit\n");
|
||
|
CLI_LOGI("flash {erase|write|read} [start_addr] [len]\n");
|
||
|
CLI_LOGI("flash_partition show\n");
|
||
|
CLI_LOGI("flash_erase_test ble\n");
|
||
|
}
|
||
|
|
||
|
static void cli_flash_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
||
|
{
|
||
|
char *msg = NULL;
|
||
|
if (argc < 2) {
|
||
|
cli_flash_help();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
uint32_t start_addr = os_strtoul(argv[2], NULL, 16);
|
||
|
uint32_t len = os_strtoul(argv[3], NULL, 16);
|
||
|
|
||
|
if (os_strcmp(argv[1], "erase") == 0) {
|
||
|
bk_flash_set_protect_type(FLASH_PROTECT_NONE);
|
||
|
for (uint32_t addr = start_addr; addr < (start_addr + len); addr += FLASH_SECTOR_SIZE) {
|
||
|
bk_flash_erase_sector(addr);
|
||
|
}
|
||
|
bk_flash_set_protect_type(FLASH_UNPROTECT_LAST_BLOCK);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "read") == 0) {
|
||
|
uint8_t buf[FLASH_PAGE_SIZE] = {0};
|
||
|
for (uint32_t addr = start_addr; addr < (start_addr + len); addr += FLASH_PAGE_SIZE) {
|
||
|
os_memset(buf, 0, FLASH_PAGE_SIZE);
|
||
|
bk_flash_read_bytes(addr, buf, FLASH_PAGE_SIZE);
|
||
|
CLI_LOGI("flash read addr:%x\r\n", addr);
|
||
|
|
||
|
CLI_LOGI("dump read flash data:\r\n");
|
||
|
for (uint32_t i = 0; i < 16; i++) {
|
||
|
for (uint32_t j = 0; j < 16; j++) {
|
||
|
os_printf("%02x ", buf[i * 16 + j]);
|
||
|
}
|
||
|
os_printf("\r\n");
|
||
|
}
|
||
|
}
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "write") == 0) {
|
||
|
uint8_t buf[FLASH_PAGE_SIZE] = {0};
|
||
|
for (uint32_t i = 0; i < FLASH_PAGE_SIZE; i++) {
|
||
|
buf[i] = i;
|
||
|
}
|
||
|
bk_flash_set_protect_type(FLASH_PROTECT_NONE);
|
||
|
for (uint32_t addr = start_addr; addr < (start_addr + len); addr += FLASH_PAGE_SIZE) {
|
||
|
bk_flash_write_bytes(addr, buf, FLASH_PAGE_SIZE);
|
||
|
}
|
||
|
bk_flash_set_protect_type(FLASH_UNPROTECT_LAST_BLOCK);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "get_id") == 0) {
|
||
|
uint32_t flash_id = bk_flash_get_id();
|
||
|
CLI_LOGI("flash_id:%x\r\n", flash_id);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "set_line") == 0) {
|
||
|
/*enable FLASH_QUAD_ENABLE first*/
|
||
|
uint16_t line_mode = os_strtoul(argv[2], NULL, 16);
|
||
|
bk_flash_set_line_mode(line_mode);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "mutex_test") == 0) {
|
||
|
extern void flash_svr_test_task(void * param);
|
||
|
int task_pri = os_strtoul(argv[2], NULL, 16);
|
||
|
rtos_create_thread(NULL, task_pri, "flash_test", flash_svr_test_task, 2048, NULL);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else {
|
||
|
cli_flash_help();
|
||
|
msg = CLI_CMD_RSP_ERROR;
|
||
|
}
|
||
|
|
||
|
os_memcpy(pcWriteBuffer, msg, os_strlen(msg));
|
||
|
}
|
||
|
|
||
|
#if CONFIG_TFM_FLASH_NSC
|
||
|
static void cli_flash_cmd_s(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
||
|
{
|
||
|
char *msg = NULL;
|
||
|
if (argc < 2) {
|
||
|
cli_flash_help();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
uint32_t start_addr = os_strtoul(argv[2], NULL, 16);
|
||
|
uint32_t len = os_strtoul(argv[3], NULL, 16);
|
||
|
|
||
|
if (os_strcmp(argv[1], "erase") == 0) {
|
||
|
psa_flash_set_protect_type(FLASH_PROTECT_NONE);
|
||
|
for (uint32_t addr = start_addr; addr < (start_addr + len); addr += FLASH_SECTOR_SIZE) {
|
||
|
psa_flash_erase_sector(addr);
|
||
|
}
|
||
|
psa_flash_set_protect_type(FLASH_UNPROTECT_LAST_BLOCK);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "read") == 0) {
|
||
|
uint8_t buf[FLASH_PAGE_SIZE] = {0};
|
||
|
for (uint32_t addr = start_addr; addr < (start_addr + len); addr += FLASH_PAGE_SIZE) {
|
||
|
os_memset(buf, 0, FLASH_PAGE_SIZE);
|
||
|
psa_flash_read_bytes(addr, buf, FLASH_PAGE_SIZE);
|
||
|
CLI_LOGI("flash read addr:%x\r\n", addr);
|
||
|
|
||
|
CLI_LOGI("dump read flash data:\r\n");
|
||
|
for (uint32_t i = 0; i < 16; i++) {
|
||
|
for (uint32_t j = 0; j < 16; j++) {
|
||
|
os_printf("%02x ", buf[i * 16 + j]);
|
||
|
}
|
||
|
os_printf("\r\n");
|
||
|
}
|
||
|
}
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else if (os_strcmp(argv[1], "write") == 0) {
|
||
|
uint8_t buf[FLASH_PAGE_SIZE] = {0};
|
||
|
for (uint32_t i = 0; i < FLASH_PAGE_SIZE; i++) {
|
||
|
buf[i] = i;
|
||
|
}
|
||
|
int level = rtos_enter_critical();
|
||
|
psa_flash_set_protect_type(FLASH_PROTECT_NONE);
|
||
|
for (uint32_t addr = start_addr; addr < (start_addr + len); addr += FLASH_PAGE_SIZE) {
|
||
|
psa_flash_write_bytes(addr, buf, FLASH_PAGE_SIZE);
|
||
|
}
|
||
|
psa_flash_set_protect_type(FLASH_UNPROTECT_LAST_BLOCK);
|
||
|
rtos_exit_critical(level);
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else {
|
||
|
cli_flash_help();
|
||
|
msg = CLI_CMD_RSP_ERROR;
|
||
|
}
|
||
|
|
||
|
os_memcpy(pcWriteBuffer, msg, os_strlen(msg));
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
static void cli_flash_partition_cmd(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
||
|
{
|
||
|
bk_logic_partition_t *partition;
|
||
|
|
||
|
if (os_strcmp(argv[1], "show") == 0) {
|
||
|
for (bk_partition_t par= BK_PARTITION_BOOTLOADER; par < BK_PARTITION_MAX; par++) {
|
||
|
partition = bk_flash_partition_get_info(par);
|
||
|
if (partition == NULL)
|
||
|
continue;
|
||
|
|
||
|
CLI_LOGI("%4d | %11s | Dev:%d | 0x%08lx | 0x%08lx |\r\n", par,
|
||
|
partition->partition_description, partition->partition_owner,
|
||
|
partition->partition_start_addr, partition->partition_length);
|
||
|
}
|
||
|
} else {
|
||
|
cli_flash_help();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* flash erase will affect ble connecting, unless flash erase while ble is sleeping
|
||
|
* This test case aims to do flash erasing with ble sleeping and connecting
|
||
|
*/
|
||
|
#define S_WAKE_UP (0)
|
||
|
#define S_SLEEP (1)
|
||
|
#define S_POWER_OFF (2)
|
||
|
#define S_NO_BT (3)
|
||
|
|
||
|
#define ERASE_TOUCH_TIMEOUT (3000)//ms
|
||
|
#define ERASE_FLASH_TIMEOUT (56)//ms
|
||
|
|
||
|
static u32 bt_sleepend_time = -1; //when cb return,bt is sleep ,recoeding the bt will sleep how long
|
||
|
static u32 bt_cb_anchor_time = 0; //when cb return ,record current time ;
|
||
|
static u8 bt_sleep_state = S_NO_BT; //record bt state;the default is 3(S_NO_BT);
|
||
|
|
||
|
static void flash_test_ble_sleep_cb(uint8_t is_sleeping, uint32_t slp_period);
|
||
|
typedef void (*ble_sleep_state_cb)(uint8_t is_sleeping, uint32_t slp_period);
|
||
|
extern void bk_ble_register_sleep_state_callback(ble_sleep_state_cb cb);
|
||
|
|
||
|
static void flash_test_ble_sleep_cb(uint8_t is_sleeping, uint32_t slp_period)
|
||
|
{
|
||
|
GLOBAL_INT_DECLARATION();
|
||
|
GLOBAL_INT_DISABLE();
|
||
|
|
||
|
bt_sleep_state = is_sleeping ;
|
||
|
bt_cb_anchor_time = rtos_get_time();
|
||
|
if (is_sleeping == S_SLEEP)
|
||
|
{
|
||
|
bt_sleepend_time = bt_cb_anchor_time + slp_period/32;
|
||
|
}
|
||
|
|
||
|
GLOBAL_INT_RESTORE();
|
||
|
}
|
||
|
|
||
|
static int ble_callback_deal_handler(uint32_t deal_flash_time)
|
||
|
{
|
||
|
uint32_t cur_time =0;
|
||
|
uint32_t temp_time = 0;
|
||
|
int ret_val = 0;
|
||
|
|
||
|
cur_time = rtos_get_time();
|
||
|
|
||
|
GLOBAL_INT_DECLARATION();
|
||
|
GLOBAL_INT_DISABLE();
|
||
|
|
||
|
do
|
||
|
{
|
||
|
if(bt_sleep_state == S_POWER_OFF) //poweroff
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
else if(bt_sleep_state == S_WAKE_UP) //wakeup
|
||
|
{
|
||
|
if(cur_time >= bt_cb_anchor_time)
|
||
|
{
|
||
|
temp_time = (cur_time - bt_cb_anchor_time);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp_time = 0xFFFFFFFF - bt_cb_anchor_time + cur_time;
|
||
|
}
|
||
|
|
||
|
if(temp_time >= ERASE_TOUCH_TIMEOUT)
|
||
|
{
|
||
|
bt_sleep_state = S_NO_BT;
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
ret_val = 0;
|
||
|
break;
|
||
|
}
|
||
|
else if(bt_sleep_state == S_SLEEP) //sleep
|
||
|
{
|
||
|
if(bt_sleepend_time > bt_cb_anchor_time)
|
||
|
{
|
||
|
if(bt_sleepend_time < cur_time)
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
else if(cur_time < bt_cb_anchor_time)
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
else if((bt_sleepend_time - cur_time) >= deal_flash_time)
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ret_val = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp_time = 0;
|
||
|
if((cur_time > bt_sleepend_time)&&(bt_cb_anchor_time > cur_time))
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
else if(bt_cb_anchor_time <= cur_time)
|
||
|
{
|
||
|
temp_time = 0xFFFFFFFF - cur_time + bt_sleepend_time;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp_time = bt_sleepend_time - cur_time;
|
||
|
}
|
||
|
|
||
|
if(temp_time >= deal_flash_time )
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ret_val = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ret_val = 1;
|
||
|
break;
|
||
|
}
|
||
|
}while(0);
|
||
|
|
||
|
GLOBAL_INT_RESTORE();
|
||
|
return ret_val;
|
||
|
}
|
||
|
|
||
|
void flash_erase_with_ble_sleep(uint32_t erase_addr)
|
||
|
{
|
||
|
uint32_t anchor_time = 0;
|
||
|
uint32_t temp_time = 0;
|
||
|
uint8_t flash_erase_ready = 0;
|
||
|
|
||
|
anchor_time = rtos_get_time();
|
||
|
while(1)
|
||
|
{
|
||
|
flash_erase_ready = ble_callback_deal_handler(ERASE_FLASH_TIMEOUT);
|
||
|
temp_time = rtos_get_time();
|
||
|
if(temp_time >= anchor_time)
|
||
|
{
|
||
|
temp_time -= anchor_time;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
temp_time += (0xFFFFFFFF - anchor_time);
|
||
|
}
|
||
|
if(temp_time >= ERASE_TOUCH_TIMEOUT)
|
||
|
flash_erase_ready = 1;
|
||
|
if(flash_erase_ready == 1)
|
||
|
{
|
||
|
bk_flash_erase_sector(erase_addr);
|
||
|
flash_erase_ready = 0;
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
rtos_delay_milliseconds(2);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void cli_flash_erase_test_with_ble(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv)
|
||
|
{
|
||
|
char *msg = NULL;
|
||
|
uint32_t start_addr = 0x260000;
|
||
|
uint32_t erase_len = 0x180000;
|
||
|
|
||
|
if (os_strcmp(argv[1], "ble") == 0) {
|
||
|
#if (CONFIG_BLUETOOTH)
|
||
|
bk_ble_register_sleep_state_callback(flash_test_ble_sleep_cb);
|
||
|
#endif
|
||
|
|
||
|
for (uint32_t erase_addr = start_addr; erase_addr <= (start_addr + erase_len);) {
|
||
|
flash_erase_with_ble_sleep(erase_addr);
|
||
|
erase_addr += FLASH_SECTOR_SIZE;
|
||
|
CLI_LOGI("erase_addr:%x\r\n", erase_addr);
|
||
|
}
|
||
|
CLI_LOGI("cli_flash_erase_test_with_ble finish.\r\n");
|
||
|
msg = CLI_CMD_RSP_SUCCEED;
|
||
|
} else {
|
||
|
cli_flash_help();
|
||
|
msg = CLI_CMD_RSP_ERROR;
|
||
|
}
|
||
|
os_memcpy(pcWriteBuffer, msg, os_strlen(msg));
|
||
|
}
|
||
|
|
||
|
#define FLASH_CMD_CNT (sizeof(s_flash_commands) / sizeof(struct cli_command))
|
||
|
static const struct cli_command s_flash_commands[] = {
|
||
|
{"flash", "flash {erase|read|write} [start_addr] [len]", cli_flash_cmd},
|
||
|
#if CONFIG_TFM_FLASH_NSC
|
||
|
{"flash_s", "flash {erase|read|write} [start_addr] [len]", cli_flash_cmd_s},
|
||
|
#endif
|
||
|
{"flash_partition", "flash_partition {show}", cli_flash_partition_cmd},
|
||
|
{"flash_erase_test", "cli_flash_erase_test with ble connecting", cli_flash_erase_test_with_ble},
|
||
|
};
|
||
|
|
||
|
int cli_flash_init(void)
|
||
|
{
|
||
|
BK_LOG_ON_ERR(bk_flash_driver_init());
|
||
|
return cli_register_commands(s_flash_commands, FLASH_CMD_CNT);
|
||
|
}
|
||
|
|