This commit is contained in:
刘可亮
2025-07-22 11:15:46 +08:00
parent d164b333ed
commit 11c97ef399
2870 changed files with 951307 additions and 26675 deletions

View File

@@ -25,10 +25,6 @@ static int g_sample_num = AIC_GPAI_DEFAULT_SAMPLES_NUM;
static int g_inited = 1;
static aicos_sem_t g_gpai_sem = NULL;
#ifdef AIC_GPAI_DRV_DMA
static struct aic_dma_transfer_info g_dma_info;
static u32 g_adc_buf[CACHE_LINE_SIZE / 4] __attribute__((aligned(CACHE_LINE_SIZE)));
#endif
static void cmd_gpai_usage(void)
{
@@ -144,54 +140,6 @@ int adc_check_gpai_by_cpu_mode(int ch, u32 cal_param)
return -1;
}
#ifdef AIC_GPAI_DRV_DMA
static int gpai_dma_get_data(int ch)
{
int i;
int *dma_data = (int *)g_dma_info.buf;
drv_gpai_get_dma_data(ch);
aicos_dcache_invalid_range(g_adc_buf, g_dma_info.buf_size);
for(i = 0; i < g_dma_info.buf_size / sizeof(g_adc_buf[0]); i++) {
printf("[%d] %d\n",i, dma_data[i]);
}
return 0;
}
static void gpai_dma_callback(void *arg)
{
int ch = (int)arg;
printf("dma callback happened\n");
gpai_dma_get_data(ch);
}
static int gpai_get_adc_by_dma(int ch)
{
int ret;
drv_gpai_enabled(ch, true);
g_dma_info.chan_id = ch;
g_dma_info.buf = g_adc_buf;
g_dma_info.buf_size = sizeof(g_adc_buf);
g_dma_info.callback = gpai_dma_callback;
g_dma_info.callback_param = (void *)ch;
ret = drv_gpai_config_dma(&g_dma_info);
if (ret) {
printf("Failed to config DMA\n");
return -1;
}
gpai_dma_get_data(ch);
//drv_gpai_stop_dma(ch);// Use this interface at the point where you want to stop DMA
return 0;
}
#endif
static int gpai_get_adc_by_poll(int ch, u32 cal_param)
{
@@ -252,11 +200,6 @@ static int cmd_gpai_read(int argc, char **argv)
case AIC_GPAI_OBTAIN_DATA_BY_CPU:
adc_check_gpai_by_cpu_mode(ch, cal_param);
break;
#ifdef AIC_GPAI_DRV_DMA
case AIC_GPAI_OBTAIN_DATA_BY_DMA:
gpai_get_adc_by_dma(ch);
break;
#endif
case AIC_GPAI_OBTAIN_DATA_BY_POLL:
gpai_get_adc_by_poll(ch, cal_param);
break;

View File

@@ -41,7 +41,7 @@ static void cmd_gpio_usage(void)
static void cmd_gpio_irq_callback(void *args)
{
u32 value;
u32 pin = (u32)args;
u32 pin = (u32)(uintptr_t)args;
u32 g, p;
g = GPIO_GROUP(pin);
@@ -160,7 +160,7 @@ static int cmd_gpio_input_pin_cfg(int argc, char **argv)
hal_gpio_set_irq_mode(g, p, PIN_IRQ_MODE_EDGE_BOTH);
gpio_irq = AIC_GPIO_TO_IRQ(g * GPIO_GROUP_SIZE + p);
drv_irq_register(gpio_irq, cmd_gpio_irq_callback, (void *)pin);
drv_irq_register(gpio_irq, cmd_gpio_irq_callback, (void *)(uintptr_t)pin);
hal_gpio_enable_irq(g, p);
cmd_gpio_get_pin_cfg_status(argc, argv);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
* Copyright (c) 2022-2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -153,6 +153,89 @@ static int do_mmc_write(int argc, char **argv)
return 0;
}
static int do_mmc_scan(int argc, char **argv)
{
unsigned long id, blkoffset;
struct aic_sdmc *host;
char *pe;
int ret;
u8 w_buf[512] = {0}, r_buf[512] = {0};
u8 scan_res[4][32] = {0};
int i, j, k;
if (argc < 3)
return -1;
id = strtoul(argv[1], &pe, 0);
blkoffset = strtoul(argv[2], &pe, 0);
ret = mmc_init(id);
if (ret) {
printf("sdmc %ld init failed.\n", id);
return ret;
}
host = find_mmc_dev_by_index(id);
if (host== NULL) {
printf("can't find mmc device!");
return -1;
}
/* set the write buf and write to the block */
srand(aic_get_ticks());
for (k = 0; k < 512; k++)
w_buf[k] = rand() & 0xff;
ret = mmc_bwrite(host, blkoffset, 1, w_buf);
if (ret == 0) {
printf("mmc_bwrite error!\n");
return -1;
}
memset(scan_res, 1, sizeof(scan_res));
/* scan the sample phase and chain */
for (i = 0; i < 4; i++) {
mmc_set_rx_phase(host, i);
for (j = 0; j < 32; j++) {
mmc_set_rx_delay(host, j);
memset(r_buf, 0, sizeof(r_buf));
ret = mmc_bread(host, blkoffset, 1, r_buf);
if (ret == 0) {
printf("mmc_bread error!\n");
scan_res[i][j] = 0;
continue;
}
for (k = 0; k < 512; k++) {
if (w_buf[k] != r_buf[k]) {
printf("r_buf[%d]:expect 0x%02x, actual:0x%02x\n", k, w_buf[k], r_buf[k]);
scan_res[i][j] = 0;
break;
}
}
}
}
/* print the result */
printf(" ");
for (i = 0; i < 32; i++) {
printf("%-3d", i);
}
printf("\n ----------------------------------------------------------------"
"--------------------------------\n");
for (i = 0; i < 4; i++) {
printf("%-2d | ", i);
for (j = 0; j < 32; j++) {
printf("%02x ", scan_res[i][j]);
}
printf("\n");
}
return 0;
}
static int confirm_key_prog(void)
{
puts("Warning: Programming authentication key can be done only once !\n"
@@ -393,6 +476,7 @@ static void do_mmc_help(void)
printf("mmc erase <id> <blkoffset> <blkcnt> : Erase data in mmc <id>\n");
printf("mmc read <id> <blkoffset> <blkcnt> <addr> : Read data in mmc <id> to RAM address\n");
printf("mmc write <id> <blkoffset> <blkcnt> <addr> : Write data to mmc <id> from RAM address\n");
printf("mmc scan <id> <blkoffset> : scan the mmc phase and delay chain \n");
printf("mmc rpmb dump <id> <blkoffset> <blkcnt> [addr of auth-key]\n");
printf("mmc rpmb read <id> <blkoffset> <blkcnt> <addr> [addr of auth-key]\n");
printf("mmc rpmb write <id> <blkoffset> <blkcnt> <addr> <addr of auth-key>\n");
@@ -450,6 +534,9 @@ static int cmd_mmc_do(int argc, char **argv)
} else if (!strcmp(argv[1], "rpmb")) {
do_mmc_rpmb(argc - 1, &argv[1]);
return 0;
} else if (!strcmp(argv[1], "scan")) {
do_mmc_scan(argc - 1, &argv[1]);
return 0;
}
help:

View File

@@ -4,10 +4,12 @@ from building import *
cwd = GetCurrentDir()
CPPPATH = []
src = []
if GetDepend('KERNEL_BAREMETAL') and GetDepend('AIC_SPINAND_DRV_TEST'):
src += Glob('spinand.c')
src += Glob('spinand_benchmark.c')
src += Glob('spinand_bbt_cmd.c')
group = DefineGroup('test-spinand', src, depend = [''], CPPPATH = CPPPATH)

View File

@@ -0,0 +1,361 @@
/*
* Copyright (c) 2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Jiji.Chen <jiji.chenen@artinchip.com>
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <console.h>
#include <aic_common.h>
#include <aic_errno.h>
#include <aic_utils.h>
#include <spinand_port.h>
#include <spinand_bbt.h>
#define SPINAND_BBT_HELP \
"As spinand will generate bad blocks randomly, erase/read/write need to avoid bad blocks\n"\
"or the data will be unstable. Spinand_bbt maintain a bad block table, it can translate \n"\
"logic_addr to physic_addr and avoid bad blocks by itself.\n" \
"In this way, users can erase/read/write logic_addr without considering bad blocks.\n" \
"\n" \
"spinand_bbt command:\n" \
" spinand_bbt init <spi_bus> <offset> <size>\n" \
" init a bbt control, manage the address of spinand[spi_bus] with bad block management"\
" the truth size subcommands can use is (size - block_size * bad_block_reserved(default 8))"\
" spinand_bbt dump <offset size>\n" \
" dump the data of spinand_bbt in logic_addr (offset, offset + size)"\
" spinand_bbt write <addr offset size>\n" \
" write data to spinand_bbt in logic_addr (offset, offset + size)"\
" spinand_bbt erase <offset size>\n" \
" erase spinand_bbt in logic_addr (offset, offset + size)\n"\
" spinand_bbt deinit\n"\
" terminate the instance and reclaim its resources\n"\
"example:\n" \
" spinand_bbt init 0 0x4800000 0x800000\n" \
" spinand_bbt erase 0x5000000 0x100000\n" \
" spinand_bbt write 0x40400000 0x5000800 0x80000\n" \
" spinand_bbt dump 0x5000800 0x80000\n" \
struct aic_spinand_bbt *g_spinand_bbt_t = NULL;
static void spinand_bbt_help(void)
{
puts(SPINAND_BBT_HELP);
}
static int do_spinand_init(int argc, char *argv[])
{
unsigned long spi_bus;
u32 offset, size;
if (argc < 4) {
spinand_bbt_help();
return -1;
}
spi_bus = strtol(argv[1], NULL, 0);
offset = strtol(argv[2], NULL, 0);
size = strtol(argv[3], NULL, 0);
g_spinand_bbt_t = malloc(sizeof(struct aic_spinand_bbt));
if (!g_spinand_bbt_t) {
printf("malloc failed\n");
return -1;
}
g_spinand_bbt_t->spinand_flash = spinand_probe(spi_bus);
return spinand_bbt_init(g_spinand_bbt_t, 0, offset, size);
}
static int do_spinand_deinit(int argc, char *argv[])
{
if (g_spinand_bbt_t == NULL)
return 0;
spinand_bbt_deinit(g_spinand_bbt_t);
free(g_spinand_bbt_t);
g_spinand_bbt_t = NULL;
return 0;
}
static int do_spinand_dump(int argc, char *argv[])
{
unsigned long offset, size;
uint8_t *data;
int ret = 0;
if (argc < 3) {
spinand_bbt_help();
return 0;
}
if (!g_spinand_bbt_t->spinand_flash) {
printf("Error, please init before.\n");
return -1;
}
offset = strtol(argv[1], NULL, 0);
size = strtol(argv[2], NULL, 0);
data = malloc(size);
if (data == NULL) {
printf("Out of memory.\n");
return -1;
}
memset(data, 0, size);
ret = spinand_bbt_read(g_spinand_bbt_t, data, offset, size);
if (!ret)
hexdump((void *)data, size, 1);
free(data);
return 0;
}
static int do_spinand_write(int argc, char *argv[])
{
unsigned long addr;
unsigned long offset, size;
if (argc < 4) {
spinand_bbt_help();
return 0;
}
if (!g_spinand_bbt_t->spinand_flash) {
printf("Error, please init before.\n");
return -1;
}
addr = strtol(argv[1], NULL, 0);
offset = strtol(argv[2], NULL, 0);
size = strtol(argv[3], NULL, 0);
spinand_bbt_write(g_spinand_bbt_t, (u8 *)addr, offset, size);
return 0;
}
static int do_spinand_erase(int argc, char *argv[])
{
unsigned long offset, size;
u32 block_size = 0;
if (argc < 3) {
spinand_bbt_help();
return 0;
}
if (!g_spinand_bbt_t->spinand_flash) {
printf("Error, please init before.\n");
return -1;
}
block_size = g_spinand_bbt_t->spinand_flash->info->page_size * g_spinand_bbt_t->spinand_flash->info->pages_per_eraseblock;
offset = strtol(argv[1], NULL, 0);
size = strtol(argv[2], NULL, 0);
if (offset % block_size || size % block_size) {
printf("offset: %lu or size: %lu, not align with block_size(%u)", offset, size, block_size);
return -1;
}
spinand_bbt_erase(g_spinand_bbt_t, offset, size);
return 0;
}
static int verify_mem(u8 *src1, u8 *src2, u32 cnt) {
int i = 0;
for (i = 0; i < cnt; i++) {
if (src1[i] != src2[i]) {
printf("varify fail! i = %d, 0x%02x != 0x%02x\n", i, src1[i], src2[i]);
return i;
}
}
return 0;
}
#define BBT_REGION_START 0x04800000
#define BBT_REGION_SIZE 0x600000
#define BBT_BUFFER_SIZE 0x100000
/* make a env */
static int spinand_bbt_make_env(u32 spi_bus, u32 offset, u32 size)
{
struct aic_spinand *s_spinand_flash;
s_spinand_flash = spinand_probe(spi_bus);
if (s_spinand_flash == NULL) {
printf("Failed to probe spinand flash.\n");
return -1;
}
spinand_erase(s_spinand_flash, offset, size);
int block_num = rand() % 5;
for (int i = 0; i < block_num; i++) {
int bad_block = rand() % (size / 0x20000); // block_size == 0x20000
u32 bad_block_t = bad_block + offset / 0x20000;
printf("mark bad block: %u.\n", bad_block_t);
spinand_block_markbad(s_spinand_flash, bad_block_t);
}
return 0;
}
#define BBT_ROUND_UP(a,b) ((a + b - 1) / b * b)
#define TEST_ADD_NEW_BAD_BLOCK 0
static int do_spinand_bbt_benchmark(int argc, char *argv[])
{
int ret = 0;
ret = spinand_bbt_make_env(0, BBT_REGION_START, BBT_REGION_SIZE);
if (ret)
return -1;
u8 *s_read_buf = NULL, *s_write_buf = NULL;
s_read_buf = aicos_malloc_align(0, BBT_BUFFER_SIZE, CACHE_LINE_SIZE);
if (!s_read_buf) {
printf("malloc failed\n");
return -1;
}
s_write_buf = aicos_malloc_align(0, BBT_BUFFER_SIZE, CACHE_LINE_SIZE);
if (!s_write_buf) {
printf("malloc failed\n");
goto exit_free;
}
for (int index = 0; index < BBT_BUFFER_SIZE; index++) {
s_write_buf[index] = rand() % 0xff;
}
struct aic_spinand_bbt *s_spinand_bbt_t = malloc(sizeof(struct aic_spinand_bbt));
if (!s_spinand_bbt_t) {
printf("malloc failed\n");
goto exit_free;
}
memset(s_spinand_bbt_t, 0, sizeof(struct aic_spinand_bbt));
s_spinand_bbt_t->spinand_flash = spinand_probe(0);
ret = spinand_bbt_init(s_spinand_bbt_t, 0, BBT_REGION_START, BBT_REGION_SIZE);
if (ret) {
goto exit_spinand_bbt_benchmark;
}
if (NULL == s_spinand_bbt_t->spinand_flash) {
printf("Error, please init before.\n");
goto exit_spinand_bbt_benchmark;
}
u32 block_size = s_spinand_bbt_t->spinand_flash->info->page_size * s_spinand_bbt_t->spinand_flash->info->pages_per_eraseblock;
u32 page_size = s_spinand_bbt_t->spinand_flash->info->page_size;
for (int i = 0; i < 16; i++) {
/* delay */
aicos_mdelay(rand() % 1000);
memset(s_read_buf, 0, BBT_BUFFER_SIZE);
u32 start_offset = (rand() % (s_spinand_bbt_t->use_block_num - 1)) * block_size;
printf(" ==== start block(%u) ==== \n", start_offset/block_size);
u32 test_size = (rand() % (BBT_BUFFER_SIZE - page_size + 1)) + page_size;
test_size = BBT_ROUND_UP(test_size, block_size);
if ((test_size + start_offset) / block_size > s_spinand_bbt_t->use_block_num)
test_size = (s_spinand_bbt_t->use_block_num * block_size) - start_offset;
start_offset += BBT_REGION_START;
if ((start_offset + test_size) / block_size >= (s_spinand_bbt_t->use_block_num + s_spinand_bbt_t->start_block)) {
printf(" start block(%u) out of range\n", start_offset/block_size);
continue;
}
/* erase */
printf(" == erase start block :%u size block :%u\n", start_offset / block_size, test_size / block_size);
if (spinand_bbt_erase(s_spinand_bbt_t, start_offset, test_size)) {
printf(" erase start:%u size:%u\n", (start_offset - BBT_REGION_START)/block_size, test_size/page_size);
continue;
}
/* make a new bad block */
#if TEST_ADD_NEW_BAD_BLOCK
static int do_flag = 0;
int to_do_flag = 3;
if (rand() % to_do_flag == 0) {
if (do_flag == 0) {
u32 new_bad = rand() % (test_size / block_size) + start_offset / block_size;
printf(" mark a new bad block:%u.\n", new_bad);
spinand_block_markbad(s_spinand_bbt_t->spinand_flash, new_bad);
do_flag++;
}
}
#endif
u32 temp_offset = (rand() % s_spinand_bbt_t->spinand_flash->info->pages_per_eraseblock) * page_size;
start_offset += temp_offset;
test_size -= temp_offset;
printf(" == write/read/verify start page :%u size:%u\n", (start_offset % block_size) / page_size, test_size / page_size);
if (spinand_bbt_write(s_spinand_bbt_t, (u8 *)s_write_buf, start_offset, test_size))
continue;
if (spinand_bbt_read(s_spinand_bbt_t, (u8 *)s_read_buf, start_offset, test_size))
continue;
int tt = verify_mem(s_write_buf, s_read_buf, test_size);
if (tt) {
u32 err_p = tt / page_size;
u32 err_b = (tt / block_size) + start_offset / block_size + 1;
printf("error_block:%u:%u, error_page:%u\n", err_b, start_offset / block_size, err_p);
goto exit_spinand_bbt_benchmark;
}
}
exit_spinand_bbt_benchmark:
if (s_spinand_bbt_t) {
spinand_bbt_deinit(s_spinand_bbt_t);
free(s_spinand_bbt_t);
s_spinand_bbt_t = NULL;
}
exit_free:
if (s_read_buf)
aicos_free_align(1, s_read_buf);
if (s_write_buf)
aicos_free_align(1, s_write_buf);
return 0;
}
CONSOLE_CMD(spinand_bbt_benchmark, do_spinand_bbt_benchmark, "SPI NAND flash benchmark.");
static int do_spinand_bbt(int argc, char *argv[])
{
if (argc < 2) {
spinand_bbt_help();
return 0;
}
if (!strncmp(argv[1], "init", 4))
return do_spinand_init(argc - 1, &argv[1]);
else if (!strncmp(argv[1], "dump", 4))
return do_spinand_dump(argc - 1, &argv[1]);
else if (!strncmp(argv[1], "write", 5))
return do_spinand_write(argc - 1, &argv[1]);
else if (!strncmp(argv[1], "erase", 5))
return do_spinand_erase(argc - 1, &argv[1]);
spinand_bbt_help();
if (!strncmp(argv[1], "deinit", 6))
return do_spinand_deinit(argc - 1, &argv[1]);
return 0;
}
CONSOLE_CMD(spinand_bbt, do_spinand_bbt, "SPI NAND flash R/W command.");

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022-2024, ArtInChip Technology Co., Ltd
* Copyright (c) 2022-2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -27,6 +27,7 @@
" spinor regwrite reg val\n" \
" spinor statuswrite [reg] [val] <volatile>\n" \
" spinor regread reg\n" \
" spinor uidread\n" \
"e.g.: \n" \
" spinor read 0x40000000 0 256\n" \
" spinor statuswrite 0x05 0x60 non-volatile\n" \
@@ -71,6 +72,8 @@ static int do_spinor_init(int argc, char *argv[])
printf("probe spinor flash success.\n");
printf("Flash ID: 0x%02x%02x%02x\n", flash->chip.mf_id, flash->chip.type_id, flash->chip.capacity_id);
g_spinor_flash = flash;
return 0;
}
@@ -283,6 +286,30 @@ static int do_spinor_reg_read(int argc, char *argv[])
return err;
}
static int do_spinor_uid_read(int argc, char *argv[])
{
sfud_err len;
sfud_flash *flash;
uint8_t data[64];
flash = g_spinor_flash;
if (flash == NULL) {
printf("spinor init first.\n");
return 0;
}
get_uid_func get_uid = flash->get_uid;
len = get_uid(flash, data);
if (!len)
printf("Read unique ID failure.\n");
hexdump((void *)data, len, 1);
return len;
}
#ifdef SFUD_USING_SECURITY_REGISTER
static int do_spinor_secureg_read(int argc, char *argv[])
{
@@ -447,7 +474,7 @@ static int do_spinor_se(int argc, char *argv[])
*/
static int do_spinor(int argc, char *argv[])
{
if (argc < 3) {
if (argc < 2) {
spinor_help();
return 0;
}
@@ -474,6 +501,8 @@ static int do_spinor(int argc, char *argv[])
else if (!strncmp(argv[1], "se", 2))
return do_spinor_se(argc - 1, &argv[1]);
#endif
else if (!strncmp(argv[1], "uidread", 7))
return do_spinor_uid_read(argc - 1, &argv[1]);
spinor_help();
return 0;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Artinchip Technology Co., Ltd
* Copyright (c) 2024-2025, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
@@ -17,7 +17,7 @@ struct aic_tsen_ch aic_tsen_chs[] = {
.hta_enable = 0,
.lta_enable = 0,
.otp_enable = 0,
#ifndef CONFIG_FPGA_BOARD_ARTINCHIP
#ifndef FPGA_BOARD_ARTINCHIP
.slope = -1134,
.offset = 2439001,
#endif
@@ -33,7 +33,7 @@ struct aic_tsen_ch aic_tsen_chs[] = {
.hta_enable = 0,
.lta_enable = 0,
.otp_enable = 0,
#ifndef CONFIG_FPGA_BOARD_ARTINCHIP
#ifndef FPGA_BOARD_ARTINCHIP
.slope = -1139,
.offset = 2450566,
#endif