sdk-hwV1.3/lichee/xr806/appos/project/common/cmd/cmd_flash.c

1200 lines
28 KiB
C
Executable File

/*
* Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
* 3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "image/flash.h"
#include "driver/chip/hal_timer.h"
#include "driver/chip/hal_xip.h"
#include "cmd_debug.h"
#include "cmd_timer.h"
#include "cmd_util.h"
#include "cmd_flash.h"
#include "driver/chip/hal_flash.h"
#include "driver/hal_dev.h"
#include "driver/chip/hal_sysctl.h"
#include "../board/board_common.h"
#define MFLASH 0
static enum cmd_status cmd_flash_start_exec(char *cmd)
{
if (HAL_Flash_Open(MFLASH, 5000) != HAL_OK) {
CMD_ERR("flash driver open failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_flash_stop_exec(char *cmd)
{
/* deinie driver */
if (HAL_Flash_Close(MFLASH) != HAL_OK) {
CMD_ERR("flash driver close failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
#define FLASH_TEST_BUF_SIZE (0x100)
/* drv flash erase s=4kb a=0x110000
*/
static enum cmd_status cmd_flash_erase_exec(char *cmd)
{
int32_t cnt;
char size_str[8];
uint32_t addr;
FlashEraseMode size_type;
int32_t size;
uint8_t buf[FLASH_TEST_BUF_SIZE];
/* get param */
cnt = cmd_sscanf(cmd, "s=%7s a=0x%x", size_str, &addr);
/* check param */
if (cnt != 2) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (cmd_strcmp(size_str, "chip") == 0) {
size_type = FLASH_ERASE_CHIP;
size = 0;
} else if (cmd_strcmp(size_str, "64kb") == 0) {
size = 0x10000;
size_type = FLASH_ERASE_64KB;
} else if (cmd_strcmp(size_str, "32kb") == 0) {
size_type = FLASH_ERASE_32KB;
size = 0x8000;
} else if (cmd_strcmp(size_str, "4kb") == 0) {
size = 0x1000;
size_type = FLASH_ERASE_4KB;
} else {
CMD_ERR("invalid size %s\n", size_str);
return CMD_STATUS_INVALID_ARG;
}
/* erase */
//HAL_Flash_MemoryOf(MFLASH, size_type, addr, &addr);
if (HAL_Flash_Erase(MFLASH, size_type, addr, 1) != HAL_OK) {
CMD_ERR("flash erase failed\n");
return CMD_STATUS_FAIL;
}
while (size > 0) {
int32_t tmp_size =
(size < FLASH_TEST_BUF_SIZE) ? size : FLASH_TEST_BUF_SIZE;
//CMD_DBG("tmp_size: %d\n", tmp_size);
if (HAL_Flash_Read(MFLASH, addr, buf, tmp_size) != HAL_OK) {
CMD_ERR("flash read failed\n");
return CMD_STATUS_FAIL;
}
size -= tmp_size;
addr += tmp_size;
while (--tmp_size >= 0) {
if ((uint8_t)(~(buf[tmp_size])) != 0) {
CMD_ERR("flash erase failed: read data from flash != 0xFF,"
" ~data = 0x%x, tmp_size = %d\n",
(uint8_t)(~(buf[tmp_size])), tmp_size);
return CMD_STATUS_FAIL;
}
}
}
return CMD_STATUS_OK;
}
/* drv flash write a=0x110000 s=32
* or drv flash write a=0x110000 s=32 sa=0x120000
* or drv flash write a=0x110000 s=32 sa=0x1400000
*/
static enum cmd_status cmd_flash_write_exec(char *cmd)
{
uint32_t cnt;
uint32_t waddr, raddr = -1;
int32_t size;
uint8_t *wbuf, *wbuf_bk;
uint8_t *rbuf;
/* get param */
cnt = cmd_sscanf(cmd, "a=0x%x s=%d sa=0x%x", &waddr, &size, &raddr);
/* check param */
if (cnt != 3) {
cnt = cmd_sscanf(cmd, "a=0x%x s=%d", &waddr, &size);
if (cnt != 2) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
}
cmd_write_respond(CMD_STATUS_OK, "OK");
if (size == 0) {
// special handle
wbuf = cmd_malloc(size+5);
if (wbuf == NULL) {
CMD_ERR("no memory\n");
return CMD_STATUS_FAIL;
}
memset(wbuf, 0, (size+5));
wbuf[0] = 0x1;
if (HAL_Flash_Write(MFLASH, waddr, wbuf, size) != HAL_OK) {
CMD_ERR("flash write failed\n");
}
cmd_free(wbuf);
return CMD_STATUS_ACKED;
}
wbuf = cmd_malloc(size);
if (wbuf == NULL) {
CMD_ERR("no memory\n");
return CMD_STATUS_FAIL;
}
wbuf_bk = wbuf;
rbuf = cmd_malloc(size);
if (rbuf == NULL) {
CMD_ERR("no memory\n");
cmd_free(wbuf);
return CMD_STATUS_FAIL;
}
if (raddr == -1) {
cmd_raw_mode_enable();
cmd_raw_mode_read(wbuf, size, 30000);
} else if ((raddr >= PSRAM_START_ADDR) && (raddr < PSRAM_END_ADDR)) {
#ifndef CONFIG_PSRAM
CMD_ERR("open psram when write source data from psram!\n");
cmd_free(wbuf);
cmd_free(rbuf);
return CMD_STATUS_FAIL;
#endif
wbuf = (uint8_t *)raddr;
} else {
#ifndef CONFIG_XIP
CMD_ERR("open xip when write source data from xip!\n");
cmd_free(wbuf);
cmd_free(rbuf);
return CMD_STATUS_FAIL;
#endif
wbuf = (uint8_t *)raddr;
}
/* write */
if (HAL_Flash_Write(MFLASH, waddr, wbuf, size) != HAL_OK) {
CMD_ERR("flash write failed\n");
}
if (HAL_Flash_Read(MFLASH, waddr, rbuf, size) != HAL_OK) {
CMD_ERR("flash read failed\n");
}
if (raddr == -1) {
cmd_raw_mode_write(rbuf, size);
cmd_raw_mode_disable();
} else {
print_hex_dump_bytes(rbuf, size);
}
cmd_free(wbuf_bk);
cmd_free(rbuf);
return CMD_STATUS_ACKED;
}
/* drv flash read a=0x10000 s=32
*/
static enum cmd_status cmd_flash_read_exec(char *cmd)
{
int32_t cnt;
uint8_t *buf;
uint32_t addr;
uint32_t size;
char *pre_str = "read buf:";
/* get param */
cnt = cmd_sscanf(cmd, "a=0x%x s=%u", &addr, &size);
/* check param */
if (cnt != 2) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
cmd_write_respond(CMD_STATUS_OK, "OK");
if (size == 0) {
// special handle
buf = cmd_malloc(size+5);
if (buf == NULL) {
CMD_ERR("no memory\n");
cmd_free(buf);
return CMD_STATUS_FAIL;
}
if (HAL_Flash_Read(MFLASH, addr, buf, size) != HAL_OK) {
CMD_ERR("spi driver read failed\n");
}
cmd_free(buf);
return CMD_STATUS_ACKED;
}
/* read */
buf = cmd_malloc(size);
if (buf == NULL) {
CMD_ERR("no memory\n");
cmd_free(buf);
return CMD_STATUS_FAIL;
}
if (HAL_Flash_Read(MFLASH, addr, buf, size) != HAL_OK) {
CMD_ERR("spi driver read failed\n");
cmd_free(buf);
return CMD_STATUS_FAIL;
}
cmd_print_uint8_array(buf, size);
cmd_raw_mode_write((uint8_t *)pre_str, strlen(pre_str));
cmd_raw_mode_write(buf, size);
cmd_free(buf);
return CMD_STATUS_ACKED;
}
/* drv flash overwrite a=0x110000 s=32
*/
static enum cmd_status cmd_flash_overwrite_exec(char *cmd)
{
uint32_t cnt;
uint32_t addr;
int32_t size;
uint8_t *wbuf;
int ret;
/* get param */
cnt = cmd_sscanf(cmd, "a=0x%x s=%d", &addr, &size);
/* check param */
if (cnt != 2) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
wbuf = cmd_malloc(size);
if (wbuf == NULL) {
CMD_ERR("no memory\n");
return CMD_STATUS_FAIL;
}
cmd_write_respond(CMD_STATUS_OK, "OK");
cmd_raw_mode_enable();
cmd_raw_mode_read(wbuf, size, 30000);
/* write */
if ((ret = HAL_Flash_Overwrite(MFLASH, addr, wbuf, size)) != HAL_OK) {
CMD_ERR("flash write failed: %d\n", ret);
}
if ((ret = HAL_Flash_Check(MFLASH, addr, wbuf, size)) != 0) {
CMD_ERR("flash write not success %d\n", ret);
}
cmd_raw_mode_disable();
cmd_free(wbuf);
return CMD_STATUS_ACKED;
}
int8_t flash_test_rdwr(uint32_t flash, uint32_t addr, uint32_t max_size, uint8_t *buf)
{
uint32_t len = max_size;
uint8_t *tmp1, *tmp2;
static uint8_t tmpdata = 0x5a;
tmp1 = buf;
tmp2 = buf + len;
cmd_memset(tmp1, tmpdata, len);
cmd_memset(tmp2, 0, len);
if (flash_erase(flash, addr, max_size) != 0) {
printf("Flash Erase failure!(addr: 0x%08x)\r\n", addr);
return -1;
}
if (flash_write(flash, addr, tmp1, len) != len) {
printf("Flash Write failure!(addr: 0x%08x)\r\n", addr);
return -1;
}
if (flash_read(flash, addr, tmp2, len) != len) {
printf("Flash Read failure!(addr: 0x%08x)\r\n", addr);
return -1;
}
if (cmd_memcmp(tmp2, tmp1, len) == 0) {
tmpdata = ~tmpdata;
return 0;
} else {
printf("Flash w&r check res failure!(addr: 0x%08x)\r\n", addr);
#if 0
for (uint32_t i = 0x0; i < 4096; i++) {
if ((i%16) == 0 && (i != 0))
printf("\n");
if (tmp1[i] != tmp2[i])
printf("\n*****error data pos:%d,tmp1:0x%02x,tmp2:0x%02x*****\n",
i, tmp1[i], tmp2[i]);
else
printf("%02x ", tmp2[i]);
}
#endif
return -1;
}
}
int8_t flash_test_read(uint32_t flash, uint32_t addr, uint32_t len, uint8_t *buf)
{
cmd_memset(buf, 0, len);
if (flash_read(flash, addr, buf, len) != len)
return -1;
return 0;
}
#if (defined FLASH_XIP_OPT_WRITE) && (defined FLASH_XIP_OPT_ERASR)
#define USER_PRIO 4
#define USER_STACKSIZE 2048
static OS_Thread_t g_user_thread;
void timer0_callback(void *arg)
{
static uint32_t ti0 = 0;
if (++ti0 >= 1000) {
ti0 = 0;
printf("%s,%d fn:%p\n", __func__, __LINE__, timer0_callback);
}
}
void timer1_callback(void *arg)
{
static uint32_t ti1 = 0;
if (++ti1 >= 1000) {
ti1 = 0;
printf("%s,%d fn:%p\n", __func__, __LINE__, timer1_callback);
}
}
static HAL_Status timer_inital(TIMER_ID id)
{
TIMER_InitParam param;
param.cfg = HAL_TIMER_MakeInitCfg(TIMER_MODE_REPEAT, TIMER_CLK_SRC_HFCLK,
TIMER_CLK_PRESCALER_4); /* 10M */
param.period = 10000;
param.isEnableIRQ = 1;
if (id == TIMER0_ID)
param.callback = timer0_callback;
else
param.callback = timer1_callback;
param.arg = (void *)id;
if (HAL_TIMER_Init((TIMER_ID)id, &param) != HAL_OK) {
return HAL_ERROR;
}
HAL_TIMER_Start((TIMER_ID)id);
return HAL_OK;
}
#define FLASH_TEST_START_ADD 0x180000 /* 1.5M */
#define FLASH_TEST_END_ADD 0x200000 /* 2M */
#define FLASH_TEST_ADD_STEP 0x1000 /* 4K */
#define FLASH_TEST_LOOP_CNT 1000
void optimize_press_task(void *arg)
{
uint32_t erase_cnt = 0;
uint32_t write_add = FLASH_TEST_START_ADD, read_add = 0;
int status = 0;
uint32_t cnt = 0, read_len = 1;
uint8_t *buf = cmd_malloc(FLASH_TEST_ADD_STEP * 2 + 16);
printf("run user task per 100ms...%d\n", erase_cnt);
while (1) {
status = flash_test_rdwr(0, write_add, FLASH_TEST_ADD_STEP, buf);
if (status < 0) {
printf("\nstop..addr: 0x%08x, earse_cnt: %d\n",
write_add, erase_cnt);
break;
}
if (read_len > FLASH_TEST_ADD_STEP)
read_len = 1;
status = flash_test_read(0, read_add, read_len, buf);
if (status < 0) {
printf("\nstop..addr: 0x%08x, earse_cnt: %d\n",
read_add, erase_cnt);
break;
}
if (read_add < FLASH_TEST_END_ADD) {
read_add += read_len;
} else {
printf("addr: 0x%08x, read times reached max....\n",
read_add);
read_add = 0;
}
read_len++;
if (++erase_cnt >= FLASH_TEST_LOOP_CNT) {
erase_cnt = 0;
if (write_add < FLASH_TEST_END_ADD) {
write_add += FLASH_TEST_ADD_STEP;
} else {
printf("addr: 0x%08x, Erase times reached max....\n",
write_add);
write_add = FLASH_TEST_START_ADD;
}
}
OS_MSleep(50);
++cnt;
if ((cnt % 200) == 1)
printf("%s cnt:%d radd:%x wadd:%x\n",
__func__, cnt, read_add, write_add);
}
printf("%s exit\n", __func__);
cmd_free(buf);
HAL_TIMER_Stop(TIMER0_ID);
OS_ThreadDelete(NULL);
}
static enum cmd_status cmd_flash_optimize_exec(char *cmd)
{
uint32_t cnt, tn;
printf("%s\n", __func__);
cnt = cmd_sscanf(cmd, "%d", &tn);
/* check param */
if (cnt != 1) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (tn > 0) {
timer_inital(TIMER0_ID);
if (tn >= 2)
timer_inital(TIMER1_ID);
}
if (OS_ThreadCreate(&g_user_thread,
"flash_optm",
optimize_press_task,
NULL,
USER_PRIO,
USER_STACKSIZE) != OS_OK) {
printf("create user task failed!\r\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
#endif
/*
*FLASH_READ_NORMAL_MODE = 1 << 0, ->1
*FLASH_READ_FAST_MODE = 1 << 1, ->2
*FLASH_READ_DUAL_O_MODE = 1 << 2, ->4
*FLASH_READ_DUAL_IO_MODE = 1 << 3, ->8
*FLASH_READ_QUAD_O_MODE = 1 << 4, ->16
*FLASH_READ_QUAD_IO_MODE = 1 << 5, ->32
*FLASH_READ_QPI_MODE = 1 << 6, ->64
*/
static enum cmd_status cmd_flash_set_rmode_exec(char *cmd)
{
uint32_t cnt;
uint32_t rmod;
char rmod_str[10];
/* get param */
cnt = cmd_sscanf(cmd, "rmod=%9s", rmod_str);
/* check param */
if (cnt != 1) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (cmd_strcmp(rmod_str, "normal") == 0) {
rmod = 0x1;
} else if (cmd_strcmp(rmod_str, "fast") == 0) {
rmod = 0x2;
} else if (cmd_strcmp(rmod_str, "dual_o") == 0) {
rmod = 0x4;
} else if (cmd_strcmp(rmod_str, "dual_io") == 0) {
rmod = 0x8;
} else if (cmd_strcmp(rmod_str, "quad_o") == 0) {
rmod = 0x10;//16
} else if (cmd_strcmp(rmod_str, "quad_io") == 0) {
rmod = 0x20;//32
} else if (cmd_strcmp(rmod_str, "qpi") == 0) {
rmod = 0x40;//64
} else {
CMD_ERR("invalid rmod %s\n", rmod_str);
return CMD_STATUS_INVALID_ARG;
}
if (HAL_Flash_Ioctl(MFLASH, FLASH_SET_READ_MODE, rmod) != HAL_OK) {
CMD_ERR("set flash read mode failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
/*
*FLASH_PAGEPROGRAM = 1 << 0, ->1
*FLASH_QUAD_PAGEPROGRAM = 1 << 1, ->2
*/
static enum cmd_status cmd_flash_set_program_mode_exec(char *cmd)
{
/* deinie driver */
uint32_t cnt;
uint32_t wmod;
char wmod_str[10];
/* get param */
cnt = cmd_sscanf(cmd, "wmod=%9s", wmod_str);
/* check param */
if (cnt != 1) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
if (cmd_strcmp(wmod_str, "page") == 0) {
wmod = 0x1;
} else if (cmd_strcmp(wmod_str, "quad_page") == 0) {
wmod = 0x2;
} else {
CMD_ERR("invalid wmod %s\n", wmod_str);
return CMD_STATUS_INVALID_ARG;
}
if (HAL_Flash_Ioctl(MFLASH, FLASH_SET_PAGEPROGRAM_MODE, wmod) != HAL_OK) {
CMD_ERR("set flash pageprogram mode failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
/*
* flash press s=0x100000 e=0x1FF000 b=8192 l=50
*
* at least run one time when close xip for this test
*/
#define FLAH_WR_PRESS_DEBUG_ON 1
#define FLAH_WR_PRESS_TEST_DEBUG_SIZE (500 * 1024)
static void cmd_flash_press_test_task(void *arg)
{
uint32_t ret;
uint32_t addr, size, len, pos, write_pos;
uint32_t test_cnt;
uint8_t *wbuf, *rbuf;
uint32_t cnt, saddr, eaddr, bs, loop;
/* get param */
cnt = cmd_sscanf((char *)arg, "s=0x%x e=0x%x b=%d l=%d",
&saddr, &eaddr, &bs, &loop);
/* check param */
if (cnt != 4) {
CMD_ERR("invalid param number %d\n", cnt);
goto fail;
}
if ((eaddr - saddr) < bs) {
CMD_ERR("(end addr - start addr) must > buf size !\n");
goto fail;
}
#if FLAH_WR_PRESS_DEBUG_ON
uint32_t debug_size, debug_size_unit;
debug_size = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
debug_size_unit = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
#endif
len = bs;
addr = saddr;
size = eaddr - addr;
test_cnt = 0;
pos = len;
write_pos = 0;
wbuf = cmd_malloc(len);
if (wbuf == NULL) {
CMD_ERR("no memory, malloc size %d fail\n", len);
goto fail;
}
memset(wbuf, 0, len);
rbuf = cmd_malloc(len);
if (rbuf == NULL) {
CMD_ERR("no memory, malloc size %d fail\n", len);
cmd_free(wbuf);
goto fail;
}
memset(rbuf, 0, len);
for (int i = 0; i < len; ++i) {
wbuf[i] = ((i) & 0xff);
}
CMD_DBG("flash erase start\n");
if (flash_erase(MFLASH, addr, size)) {
CMD_ERR("flash erase err, add: 0x%x, size: 0x%x\n", addr, size);
goto out;
}
CMD_DBG("flash erase ok, add: 0x%x, size: 0x%x\n", addr, size);
while (1) {
ret = flash_write(MFLASH, addr + write_pos, wbuf, pos);
if (ret != pos) {
CMD_ERR("flash write err len:%d pos:%d\n", len, pos);
break;
}
ret = flash_read(MFLASH, addr + write_pos, rbuf, pos);
if (ret != pos) {
CMD_ERR("flash read err len:%d pos:%d\n", len, pos);
break;
}
for (int j = 0; j < pos; ++j) {
if (rbuf[j] != ((j) & 0xff)) {
CMD_ERR("flash read check err len:%d pos:%d + %d\n",
len, write_pos, j);
CMD_ERR("j:%d, now pos:%d\n", j, pos);
if (j < 32)
j = 0;
else
j -= 32;
print_hex_dump(NULL, DUMP_PREFIX_ADDRESS, 32, 1,
&rbuf[j], 64, 0);
ret = -1;
break;
}
}
if (ret != pos)
break;
memset(rbuf, 0, len);
write_pos += pos;
#if FLAH_WR_PRESS_DEBUG_ON
if (write_pos >= debug_size) {
CMD_DBG("write data:%dKB\n", write_pos / 1024);
debug_size += debug_size_unit;
}
#endif
if ((size - write_pos) > len)
pos = len;
else
pos = size - write_pos;
if (pos == 0) {
CMD_DBG("flash write & read over, addr:0x%x ~ 0x%x, len:%dKB\n",
addr, addr + write_pos, size / 1024);
if (++test_cnt >= loop) {
break;
} else {
CMD_DBG("flash test end, run test count:%d, should run:%d\n",
test_cnt, loop);
CMD_DBG("flash erase start\n");
if (flash_erase(MFLASH, addr, size)) {
CMD_ERR("flash erase err, add: 0x%x, size: 0x%x\n", addr,
size);
//break;
} else {
CMD_DBG("flash erase ok, add: 0x%x, size: 0x%x\n", addr,
size);
}
pos = len;
write_pos = 0;
#if FLAH_WR_PRESS_DEBUG_ON
debug_size = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
#endif
}
}
}
CMD_DBG("flash test end, run test count:%d, should run:%d\n", test_cnt,
loop);
out:
cmd_free(wbuf);
cmd_free(rbuf);
fail:
OS_ThreadDelete(NULL);
}
static void cmd_flash_bench_task(void *arg)
{
int32_t err = 0;
char *cmd = (char *)arg;
uint32_t mode, start_addr, loop;
uint32_t cnt, erase_kb = 4;
float throuth_mb;
float time_use;
FlashEraseMode size_type = FLASH_ERASE_4KB;
cnt = cmd_sscanf(cmd, "m=0x%x a=0x%x n=%d", &mode, &start_addr, &loop);
if (cnt != 3 || loop < 1) {
CMD_ERR("invalid argument %s\n", cmd);
goto out;
}
time_perf_init();
printf("\n");
for (int _l = 0; _l < loop; _l++) {
for (int i = 0; i < 20; i++) {
int j;
uint32_t bench_size = 1024 * (1 << i);
uint32_t *buf = cmd_malloc(bench_size);
if (!buf) {
CMD_DBG("%s test end for malloc buff failed.\n", __func__);
break;
}
for (j = 0; j < bench_size / 4; j++)
buf[j] = j;
if (mode & 0x1) {
cnt = 1;
if (bench_size <= 4*1024) {
size_type = FLASH_ERASE_4KB;
erase_kb = 4;
} else if (bench_size <= 32*1024) {
size_type = FLASH_ERASE_32KB;
erase_kb = 32;
} else {
size_type = FLASH_ERASE_64KB;
cnt = DIV_ROUND_UP(bench_size, 64*1024);
erase_kb = 64 * cnt;
}
time_perf_tag();
err = HAL_Flash_Erase(MFLASH, size_type, start_addr, cnt);
time_use = (float)time_perf_tag() / 1000.0;
if (time_use < 0.001)
time_use = 0.001;
if (err) {
CMD_ERR("erase err!\n");
goto next;
} else {
throuth_mb = erase_kb * 1024 / time_use / 1000;
printf("%s erase ok, %3d", __func__, erase_kb);
printf(" KB use:%3.3f ms, throughput:%2.3f MB/S\n",
time_use, throuth_mb);
}
}
if (mode & 0x2) {
time_perf_tag();
err = HAL_Flash_Write(MFLASH, start_addr,
(const unsigned char *)buf, bench_size);
time_use = (float)time_perf_tag() / 1000.0;
if (time_use < 0.001)
time_use = 0.001;
if (err) {
CMD_ERR("write err!\n");
goto next;
} else {
throuth_mb = bench_size * 1000 / 1024 / time_use / 1000;
printf("%s write ok, %3d", __func__, bench_size / 1024);
printf(" KB use:%3.3f ms, throughput:%2.3f MB/S\n",
time_use, throuth_mb);
}
}
if (mode & 0x4) {
for (j = 0; j < bench_size / 4; j++)
buf[j] = 0;
time_perf_tag();
err = HAL_Flash_Read(MFLASH, start_addr, (uint8_t *)buf,
bench_size);
time_use = (float)time_perf_tag() / 1000.0;
if (time_use < 0.001)
time_use = 0.001;
if (err) {
CMD_ERR("read err!\n");
goto next;
} else {
throuth_mb = bench_size * 1000 / 1024 / time_use / 1000;
}
err = 0;
for (j = 0; j < bench_size / 4; j++) {
if (buf[j] != j) {
err = -1;
break;
}
}
if (err) {
CMD_ERR("bench_size:%d write data err:0x%x should:0x%x,"
" idx:%d!\n", bench_size, buf[j], j, j);
j = j > 16 ? j - 16 : 0;
print_hex_dump_bytes((const void *)&buf[j], 256);
goto next;
}
printf("%s read ok, %3d", __func__, bench_size / 1024);
printf(" KB use:%3.3f ms, throughput:%2.3f MB/S\n",
time_use, throuth_mb);
}
next:
cmd_free(buf);
if (err)
break;
}
}
out:
CMD_DBG("%s test end\n", __func__);
time_perf_deinit();
cmd_free(arg);
OS_ThreadDelete(NULL);
}
#define CMD_ARG_LEN 64
/* flash bench m=<mode> <a=0xaddr> n=<loop_num>
* <mode>: 1: erase, 2: write, 4: read, other is add
* flash bench m=0x7 a=0x100000 n=1
*/
static enum cmd_status cmd_flash_bench_exec(char *cmd)
{
OS_Thread_t thread;
char *param;
uint32_t len;
len = strlen(cmd);
if (len >= CMD_ARG_LEN - 1) {
CMD_ERR("should adjust CMD_ARG_LEN to %d\n", len);
return CMD_STATUS_FAIL;
}
param = cmd_malloc(CMD_ARG_LEN);
if (!param)
return CMD_STATUS_FAIL;
memcpy(param, cmd, len);
param[len + 1] = 0;
OS_ThreadSetInvalid(&thread);
if (OS_ThreadCreate(&thread,
"",
cmd_flash_bench_task,
param,
OS_THREAD_PRIO_APP,
2 * 1024) != OS_OK) {
CMD_ERR("create flash bench test task failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
/*
* flash press s=0x100000 e=0x1FF000 b=8192 l=50
*/
static enum cmd_status cmd_flash_press_exec(char *cmd)
{
uint32_t cnt, saddr, eaddr, bs, loop;
/* get param */
cnt = cmd_sscanf(cmd, "s=0x%x e=0x%x b=%d l=%d", &saddr, &eaddr, &bs,
&loop);
/* check param */
if (cnt != 4) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
OS_Thread_t thread;
OS_ThreadSetInvalid(&thread);
if (OS_ThreadCreate(&thread,
"",
cmd_flash_press_test_task,
cmd,
OS_THREAD_PRIO_APP,
2 * 1024) != OS_OK) {
CMD_ERR("create flash press test task failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static void cmd_flash_press_r_test_task(void *arg)
{
uint32_t ret;
uint32_t addr, size, len, pos, write_pos;
uint32_t test_cnt;
uint8_t *wbuf, *rbuf;
uint32_t cnt, saddr, eaddr, bs, loop;
/* get param */
cnt = cmd_sscanf((char *)arg, "s=0x%x e=0x%x b=%d l=%d", &saddr, &eaddr,
&bs, &loop);
/* check param */
if (cnt != 4) {
CMD_ERR("invalid param number %d\n", cnt);
goto fail;
}
if ((eaddr - saddr) < bs) {
CMD_ERR("(end addr - start addr) must > buf size !\n");
goto fail;
}
#if FLAH_WR_PRESS_DEBUG_ON
uint32_t debug_size, debug_size_unit;
debug_size = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
debug_size_unit = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
#endif
len = bs;
addr = saddr;
size = eaddr - addr;
test_cnt = 0;
pos = len;
write_pos = 0;
wbuf = cmd_malloc(len);
if (wbuf == NULL) {
CMD_ERR("no memory, malloc size %d fail\n", len);
goto fail;
}
memset(wbuf, 0, len);
rbuf = cmd_malloc(len);
if (rbuf == NULL) {
CMD_ERR("no memory, malloc size %d fail\n", len);
cmd_free(wbuf);
goto fail;
}
memset(rbuf, 0, len);
for (int i = 0; i < len; ++i) {
wbuf[i] = ((i) & 0xff);
}
CMD_DBG("flash erase start\n");
if (flash_erase(MFLASH, addr, size)) {
CMD_ERR("flash erase err, add: 0x%x, size: 0x%x\n", addr, size);
goto out;
}
CMD_DBG("flash erase ok, add: 0x%x, size: 0x%x\n", addr, size);
while (1) {
ret = flash_write(MFLASH, addr + write_pos, wbuf, pos);
if (ret != pos) {
CMD_ERR("flash write err len:%d pos:%d\n", len, pos);
goto out;
}
CMD_DBG("write data:%dKB\n", write_pos / 1024);
write_pos += pos;
if ((size - write_pos) > len)
pos = len;
else
pos = size - write_pos;
if (pos == 0) {
CMD_DBG("flash write over, addr:0x%x ~ 0x%x, len:%dKB\n",
addr, addr + write_pos, size / 1024);
break;
}
}
pos = len;
write_pos = 0;
#if FLAH_WR_PRESS_DEBUG_ON
debug_size = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
#endif
while (1) {
ret = flash_read(MFLASH, addr + write_pos, rbuf, pos);
if (ret != pos) {
CMD_ERR("flash read err:%d len pos:%d\n", len, pos);
goto out;
}
for (int j = 0; j < pos; ++j) {
if (rbuf[j] != ((j) & 0xff)) {
CMD_ERR("flash read check err len:%d pos:%d + %d\n", len, write_pos, j);
CMD_ERR("j:%d, now pos:%d\n", j, pos);
#if 1
for (int dm = ((j > 0) ? (j - 1) : j); dm < pos; ++dm) {
if ((dm > 0) && (dm % 16) == 0) {
printf("\n");
}
printf(" %02X", rbuf[dm]);
}
printf("\n");
#endif
goto out;
}
}
memset(rbuf, 0, len);
write_pos += pos;
#if FLAH_WR_PRESS_DEBUG_ON
if (write_pos >= debug_size) {
CMD_DBG("read data:%dKB\n", write_pos / 1024);
debug_size += debug_size_unit;
}
#endif
if ((size - write_pos) > len)
pos = len;
else
pos = size - write_pos;
if (pos == 0) {
CMD_DBG("flash read over, addr:0x%x ~ 0x%x, len:%dKB\n",
addr, addr + write_pos, size / 1024);
if (++test_cnt >= loop) {
break;
} else {
pos = len;
write_pos = 0;
#if FLAH_WR_PRESS_DEBUG_ON
debug_size = FLAH_WR_PRESS_TEST_DEBUG_SIZE;
#endif
}
}
}
CMD_DBG("flash read test end, run test count:%d, should run:%d\n",
test_cnt, loop);
out:
cmd_free(wbuf);
cmd_free(rbuf);
fail:
OS_ThreadDelete(NULL);
}
/*
* flash press_r s=0x100000 e=0x1FF000 b=8192 l=50
*/
static enum cmd_status cmd_flash_press_r_exec(char *cmd)
{
uint32_t cnt, saddr, eaddr, bs, loop;
/* get param */
cnt = cmd_sscanf(cmd, "s=0x%x e=0x%x b=%d l=%d", &saddr, &eaddr, &bs,
&loop);
/* check param */
if (cnt != 4) {
CMD_ERR("invalid param number %d\n", cnt);
return CMD_STATUS_INVALID_ARG;
}
OS_Thread_t thread;
OS_ThreadSetInvalid(&thread);
if (OS_ThreadCreate(&thread,
"",
cmd_flash_press_r_test_task,
cmd,
OS_THREAD_PRIO_APP,
2 * 1024) != OS_OK) {
CMD_ERR("create flash read press test task failed\n");
return CMD_STATUS_FAIL;
}
return CMD_STATUS_OK;
}
static enum cmd_status cmd_flash_enter_sip_exec(char *cmd)
{
//writel(0x429D0001, 0x4000A044);
HAL_SYSCTL_SetSipFlashTestMapMode();
HAL_BoardIoctl(HAL_BIR_PINMUX_INIT, HAL_MKDEV(HAL_DEV_MAJOR_FLASHC, NOT_SIP_FLASH), 0);
HAL_BoardIoctl(HAL_BIR_PINMUX_INIT, HAL_MKDEV(HAL_DEV_MAJOR_FLASHC, SIP_FLASH), 0);
return CMD_STATUS_OK;
}
/*
* brief Flash Auto Test Command
* command start {spiNum} {csNum} {freq} {mode}
* stop
* config {ioMode}// -----need to be supported by Flash chip
* erase {size} {addr}
* write {addr} "{str}"
* read {str/hex} {addr} {size} // recommanded that size should not too large
*/
static const struct cmd_data g_flash_cmds[] = {
{ "start", cmd_flash_start_exec },
{ "stop", cmd_flash_stop_exec },
{ "erase", cmd_flash_erase_exec },
{ "write", cmd_flash_write_exec },
{ "read", cmd_flash_read_exec },
{ "overwrite", cmd_flash_overwrite_exec },
#if (defined FLASH_XIP_OPT_WRITE) && (defined FLASH_XIP_OPT_ERASR)
{ "optimize", cmd_flash_optimize_exec },
#endif
{ "set_rmod", cmd_flash_set_rmode_exec },
{ "set_wmod", cmd_flash_set_program_mode_exec },
{ "bench", cmd_flash_bench_exec },
{ "press", cmd_flash_press_exec },
{ "press_r", cmd_flash_press_r_exec },
{ "enter_sip", cmd_flash_enter_sip_exec },
};
enum cmd_status cmd_flash_exec(char *cmd)
{
return cmd_exec(cmd, g_flash_cmds, cmd_nitems(g_flash_cmds));
}