This commit is contained in:
刘可亮
2024-06-04 19:00:30 +08:00
parent 990c72f5be
commit 0a13af6a1d
1668 changed files with 342810 additions and 37726 deletions

View File

@@ -9,7 +9,7 @@ if GetDepend('AIC_QSPI_DRV_TEST') and GetDepend('RT_USING_FINSH'):
src = Glob('test_qspidev.c')
src += Glob('test_spibit.c')
src += Glob('test_spi_async.c')
if GetDepend('AIC_QSPI_DRV_V11'):
if GetDepend('AIC_QSPI_DRV_V11') and GetDepend('AIC_CHIP_D13X'):
src += Glob('test_spislave*.c')
group = DefineGroup('test-qspi', src, depend = [''], CPPPATH = CPPPATH)

View File

@@ -85,6 +85,18 @@ static void show_speed(char *msg, u32 len, u32 us)
printf("%s: %d byte, %d us -> %d KB/s\n", msg, len, us, speed);
}
static void hex_dump(uint8_t *data, unsigned long len)
{
unsigned long i = 0;
printf("\n");
for (i = 0; i < len; i++) {
if (i && (i % 16) == 0)
printf("\n");
printf("%02x ", data[i]);
}
printf("\n");
}
static int test_qspi_attach(int argc, char **argv)
{
char *bus_name, *dev_name;
@@ -265,12 +277,18 @@ static void test_qspi_sendlen(int argc, char **argv)
data_len = 0;
data_len = strtoul(argv[2], NULL, 0);
data = RT_NULL;
printf("data len %ld\n", data_len);
if (data_len) {
align_len = roundup(data_len, CACHE_LINE_SIZE);
align_len = 64;
data = aicos_malloc_align(0, align_len, CACHE_LINE_SIZE);
}
rt_memset(&msg, 0, sizeof(msg));
if (data == NULL) {
printf("Low memory!\n");
return;
} else {
printf("data len %ld\n", data_len);
rt_memset(&msg, 0, sizeof(msg));
}
msg.instruction.content = cmd;
msg.instruction.qspi_lines = 0;
@@ -286,7 +304,7 @@ static void test_qspi_sendlen(int argc, char **argv)
start_us = aic_get_time_us();
ret = rt_qspi_transfer_message(g_qspi, &msg);
show_speed("mtd_read speed", data_len, aic_get_time_us() - start_us);
show_speed("qspi send speed", data_len, aic_get_time_us() - start_us);
if (ret != data_len) {
printf("Send data failed. ret 0x%x\n", (int)ret);
}
@@ -299,14 +317,12 @@ static void test_qspi_recvhex(int argc, char **argv)
{
char *pl;
uint32_t line = 0, addrsiz = 0, addr = 0, dmycyc = 0;
unsigned long i, data_len, align_len;
unsigned long data_len, align_len;
uint8_t *data, cmd;
struct rt_qspi_message msg;
if (!g_qspi) {
printf("QSPI device is not init yet.\n");
return;
}
RT_ASSERT(g_qspi);
if (argc < 3) {
printf("Argument is not correct, please see help for more information.\n");
return;
@@ -318,27 +334,20 @@ static void test_qspi_recvhex(int argc, char **argv)
return;
}
cmd = (uint8_t)strtoul(argv[2], NULL, 16);
addrsiz = 0;
if (argc >= 4) {
if (rt_memcmp(argv[3], "-", 1)) {
addrsiz = (strlen(argv[3]) + 1) >> 1;
addr = strtoul(argv[3], NULL, 16);
} else {
addrsiz = 0;
addr = 0;
}
if (argc >= 4 && rt_memcmp(argv[3], "-", 1)) {
addrsiz = (strlen(argv[3]) + 1) >> 1;
addr = strtoul(argv[3], NULL, 16);
}
dmycyc = 0;
if (argc >= 5) {
if (rt_memcmp(argv[4], "-", 1))
dmycyc = strtoul(argv[4], NULL, 16);
if (argc >= 5 && rt_memcmp(argv[4], "-", 1)) {
dmycyc = strtoul(argv[4], NULL, 16);
}
data_len = 0;
if (argc >= 6) {
data_len = strtoul(argv[5], NULL, 16);
}
data = RT_NULL;
if (data_len > 0) {
if (argc >= 6 && strtoul(argv[5], NULL, 0) > 0) {
data_len = strtoul(argv[5], NULL, 0);
align_len = roundup(data_len, CACHE_LINE_SIZE);
data = aicos_malloc_align(0, align_len, CACHE_LINE_SIZE);
if (data == NULL) {
@@ -366,13 +375,7 @@ static void test_qspi_recvhex(int argc, char **argv)
rt_spi_release_bus((struct rt_spi_device *)g_qspi);
if (data) {
printf("\n");
for (i = 0; i < data_len; i++) {
if (i && (i % 16) == 0)
printf("\n");
printf("%02x ", data[i]);
}
printf("\n");
hex_dump(data, data_len);
aicos_free_align(0, data);
}
}
@@ -560,7 +563,7 @@ static void cmd_test_qspi(int argc, char **argv)
test_qspi_recv(argc - 1, &argv[1]);
return;
} else if (!rt_strcmp(argv[1], "slaverw")) {
#ifdef AIC_QSPI_DRV_V11
#ifdef AIC_CHIP_D13X
if (!g_qspi) {
printf("QSPI device is not init yet.\n");
return;
@@ -569,7 +572,7 @@ static void cmd_test_qspi(int argc, char **argv)
return;
#endif
} else if (!rt_strcmp(argv[1], "send2slave")) {
#ifdef AIC_QSPI_DRV_V11
#ifdef AIC_CHIP_D13X
if (!g_qspi) {
printf("QSPI device is not init yet.\n");
return;

View File

@@ -1,42 +0,0 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Xuan.Wen <xuan.wen@artinchip.com>
*/
#ifndef _AIC_QSPI_SLAVE_
#define _AIC_QSPI_SLAVE_
/* Write flow:
* 1BYTE 3BYTE 512
* 1. WRITE ADDRESS DATA
*
* Read flow:
* 1. LOAD ADDRESS
* 2. GET_STATUS (Slave preparing data, should read N times)
* 3. Read DATA ()
*/
#define MEM_CMD_WRITE 0x10
#define MEM_CMD_LOAD 0x20
#define MEM_CMD_STATUS 0x21
#define MEM_CMD_READ 0x22
#define WRITE_STATUS_VAL 0xF0F0F0F0
#define LOAD_STATUS_VAL 0xF1F1F1F1
#define TEST_BUF_SIZE (512 * 1024)
/* All data should be 4 bytes aligned. */
#define CMD_SIZE 4
#define STATUS_SIZE 4
#define PKT_SIZE TEST_BUF_SIZE
// #define PKT_SIZE 256
int test_qspi_slave_controller_init(u32 id, u32 bus_width,
qspi_slave_async_cb cb, void *priv,
qspi_slave_handle *h);
void test_qspi_slave_controller_deinit(qspi_slave_handle *h);
#endif

View File

@@ -1,287 +0,0 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Xuan.Wen <xuan.wen@artinchip.com>
*/
#include <string.h>
#include <finsh.h>
#include <rtconfig.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <aic_hal.h>
#include <hal_qspi.h>
#include <rtthread.h>
#include "test_spislave.h"
#define RUN_STATE_IN 0
#define RUN_STATE_OUT 1
#define MEM_STATE_IDLE 0
#define MEM_STATE_CMD 1
#define MEM_STATE_DATA 2
struct fakemem_state {
int run_state;
int mem_state;
u32 qspi_id;
u32 bus_width;
qspi_slave_handle handle;
u8 *data_buf;
u8 *work_buf;
};
static struct fakemem_state g_state;
#define USAGE \
"fakemem help : Get this information.\n" \
"fakemem start <spi id> <bus width>: Start fake slave device(mem) on SPI bus.\n" \
"fakemem stop : Stop fake slave device.\n" \
"example: standard spi by using QSPI1\n" \
" fakemem start 1 1\n" \
" fakemem stop\n" \
" \n" \
"example: dual spi by using QSPI1\n" \
" fakemem start 1 2\n" \
" fakemem stop\n"
static void qspi_usage(void)
{
printf("%s", USAGE);
}
void slave_dump_data(char *msg, u8 *buf, u32 len)
{
printf("%s:\n", msg);
for (u32 i = 0; i < len; i++) {
if (i != 0 && (i % 16 == 0))
printf("\n");
printf("%02x ", buf[i]);
}
printf("\n");
}
static int read_cmd_start(struct fakemem_state *state, u8 *buf, u32 len)
{
struct qspi_transfer t;
int ret;
memset(&t, 0, sizeof(t));
buf[0] = 0;
t.rx_data = buf;
t.data_len = len;
printf("%s, reset rx fifo\n", __func__);
hal_qspi_slave_fifo_reset(&state->handle, HAL_QSPI_RX_FIFO);
ret = hal_qspi_slave_transfer_async(&state->handle, &t);
if (ret < 0)
return -1;
return 0;
}
static int send_data_start(struct fakemem_state *state, u32 start_addr, u8 *buf)
{
struct qspi_transfer t;
u32 offset, ready_to_read_flag;
u8 *p, *status_data;
status_data = state->work_buf;
memset(&t, 0, sizeof(t));
offset = start_addr;
printf("Send load status + data\n");
/* Read/Write data length required 4 bytes aligned */
ready_to_read_flag = LOAD_STATUS_VAL;
memcpy(&status_data[0], &ready_to_read_flag, 4);
/* Data need to following status flag, and required to send togather,
* otherwise master won't know the start of data
*/
p = buf + (offset % TEST_BUF_SIZE);
// printf("offset %d\n", offset);
memcpy(&status_data[4], p, PKT_SIZE);
t.tx_data = status_data;
t.data_len = STATUS_SIZE + PKT_SIZE;
/* Clear TX FIFO before write new data */
hal_qspi_slave_fifo_reset(&state->handle, HAL_QSPI_TX_FIFO);
/* Set data to slave qspi, it will wait master's clock to send data out */
hal_qspi_slave_transfer_async(&state->handle, &t);
return 0;
}
static int send_write_ok(struct fakemem_state *state)
{
struct qspi_transfer t;
u32 write_ok_flag;
u8 *status;
status = state->work_buf;
memset(&t, 0, sizeof(t));
printf("Send write status\n");
/* Read/Write data length required 4 bytes aligned */
write_ok_flag = WRITE_STATUS_VAL;
memcpy(&status[0], &write_ok_flag, 4);
t.tx_data = status;
t.data_len = STATUS_SIZE;
hal_qspi_slave_fifo_reset(&state->handle, HAL_QSPI_TX_FIFO);
hal_qspi_slave_transfer_async(&state->handle, &t);
return 0;
}
void qspi_slave_fakemem_async_callback(qspi_slave_handle *h, void *priv)
{
struct fakemem_state *state = priv;
int status, cnt;
u32 addr = 0;
u8 cmd = 0;
u8 *p;
status = hal_qspi_slave_get_status(&state->handle);
cnt = 0;
if (status == HAL_QSPI_STATUS_OK) {
printf("%s, status %d\n", __func__, status);
/*
* status OK:
* TRANSFER DONE or CS INVALID
*/
p = state->work_buf;
if (state->run_state == RUN_STATE_IN) {
if (state->mem_state == MEM_STATE_IDLE) {
cnt = hal_qspi_slave_transfer_count(&state->handle);
if (cnt < CMD_SIZE)
return;
printf("Got new command\n");
slave_dump_data("Command", p, cnt);
state->mem_state = MEM_STATE_CMD;
}
if (state->mem_state == MEM_STATE_CMD) {
cmd = p[0];
// addr = (p[1] << 16) | (p[2] << 8) | p[3];
addr = 0;
memcpy(&addr, &p[1], 3);
state->mem_state = MEM_STATE_DATA;
}
if (state->mem_state == MEM_STATE_DATA) {
if (cmd == MEM_CMD_WRITE) {
if (cnt > CMD_SIZE) {
p += CMD_SIZE;
memcpy(state->data_buf + addr , p, cnt - CMD_SIZE);
}
/* Stop to receive data now, switch to send out: write
* status flag
*/
hal_qspi_slave_transfer_abort(&state->handle);
send_write_ok(state);
state->mem_state = MEM_STATE_IDLE;
state->run_state = RUN_STATE_OUT;
}
if (cmd == MEM_CMD_LOAD) {
/* Prepare data and ready to send out, next wait the host
* to read all data
*/
hal_qspi_slave_transfer_abort(&state->handle);
send_data_start(state, addr, state->data_buf);
state->run_state = RUN_STATE_OUT;
}
}
} else { /* (state->run_state == RUN_STATE_OUT) */
/* Get the send-out data count */
cnt = hal_qspi_slave_transfer_count(&state->handle);
if ((cnt == STATUS_SIZE) || (cnt == (STATUS_SIZE + PKT_SIZE))) {
state->mem_state = MEM_STATE_IDLE;
state->run_state = RUN_STATE_IN;
/* Send data is finished, prepare to wait new command */
read_cmd_start(state, state->work_buf, TEST_BUF_SIZE);
}
}
} else {
/* Error process */
printf("%s, status %d\n", __func__, status);
}
}
static int test_fakemem_start(int argc, char **argv)
{
unsigned long val;
int ret;
if (argc < 2) {
qspi_usage();
return -1;
}
val = strtol(argv[1], NULL, 10);
g_state.qspi_id = val;
g_state.mem_state = MEM_STATE_IDLE;
g_state.bus_width = 1; // Default is 1
if (g_state.data_buf == NULL)
g_state.data_buf =
aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
memset(g_state.data_buf, 0, TEST_BUF_SIZE);
if (g_state.work_buf == NULL)
g_state.work_buf =
aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
if (argc >= 3) {
val = strtol(argv[2], NULL, 10);
g_state.bus_width = val;
}
ret = test_qspi_slave_controller_init(g_state.qspi_id, g_state.bus_width,
qspi_slave_fakemem_async_callback, &g_state,
&g_state.handle);
if (ret) {
printf("QSPI Slave init failure.\n");
return -1;
}
/* Start with waiting command */
read_cmd_start(&g_state, g_state.work_buf, TEST_BUF_SIZE);
g_state.run_state = RUN_STATE_IN;
return 0;
}
static int test_fakemem_stop(int argc, char **argv)
{
test_qspi_slave_controller_deinit(&g_state.handle);
g_state.run_state = RUN_STATE_IN;
if (g_state.data_buf) {
aicos_free_align(0, g_state.data_buf);
g_state.data_buf = NULL;
}
if (g_state.work_buf) {
aicos_free_align(0, g_state.work_buf);
g_state.work_buf = NULL;
}
return 0;
}
extern void test_qspi_slave_set_pinmux(void);
static void cmd_test_qspislave_pinmux(int argc, char **argv)
{
test_qspi_slave_set_pinmux();
}
static void cmd_test_qspislave(int argc, char **argv)
{
if (argc < 2)
goto help;
if (!rt_strcmp(argv[1], "help")) {
goto help;
} else if (!rt_strcmp(argv[1], "start")) {
test_fakemem_start(argc - 1, &argv[1]);
return;
} else if (!rt_strcmp(argv[1], "stop")) {
test_fakemem_stop(argc - 1, &argv[1]);
return;
}
help:
qspi_usage();
}
MSH_CMD_EXPORT_ALIAS(cmd_test_qspislave, fakemem, Test QSPI Slave);
MSH_CMD_EXPORT_ALIAS(cmd_test_qspislave_pinmux, qpinmux, Test QSPI Slave);

View File

@@ -1,145 +0,0 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Xuan.Wen <xuan.wen@artinchip.com>
*/
#include <string.h>
#include <finsh.h>
#include <rtconfig.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <aic_hal.h>
#include <hal_qspi.h>
#include <rtthread.h>
struct spi_pinmux {
unsigned char func;
unsigned char bias;
unsigned char drive;
char *name;
};
/* Please change your pinmux setting according your board */
static struct spi_pinmux spi_pinmux_config[] = {
/* qspi1 */
{ 3, PIN_PULL_UP, 3, "PD.4" }, // CS, default set to high
{ 3, PIN_PULL_UP, 3, "PD.5" },
{ 3, PIN_PULL_UP, 3, "PD.6" }, // SI
{ 3, PIN_PULL_UP, 7, "PD.7" }, // CLK
{ 3, PIN_PULL_UP, 3, "PD.8" },
{ 3, PIN_PULL_UP, 3, "PD.9" },
/* qspi2 */
{ 3, PIN_PULL_UP, 3, "PB.6" },
{ 3, PIN_PULL_UP, 3, "PB.7" },
{ 3, PIN_PULL_UP, 3, "PB.8" },
{ 3, PIN_PULL_UP, 3, "PB.9" },
{ 3, PIN_PULL_UP, 3, "PB.10" },
{ 3, PIN_PULL_UP, 3, "PB.11" },
/* qspi3 */
{ 3, PIN_PULL_UP, 3, "PD.0" },
{ 3, PIN_PULL_UP, 3, "PD.1" }, //CS, default set to high
{ 3, PIN_PULL_UP, 3, "PD.2" },
{ 3, PIN_PULL_UP, 3, "PD.3" },
};
static u32 qspi_clk_ids[4] = {CLK_QSPI0, CLK_QSPI1, CLK_QSPI2, CLK_QSPI3};
static u32 qspi_irq_num[] = {QSPI0_IRQn, QSPI1_IRQn, QSPI2_IRQn, QSPI3_IRQn};
static u32 qspi_input_clk[4] = {
#ifdef AIC_USING_QSPI0
[0] = AIC_DEV_QSPI0_MAX_SRC_FREQ_HZ,
#endif
#ifdef AIC_USING_QSPI1
[1] = AIC_DEV_QSPI1_MAX_SRC_FREQ_HZ,
#endif
#ifdef AIC_USING_QSPI2
[2] = AIC_DEV_QSPI2_MAX_SRC_FREQ_HZ,
#endif
#ifdef AIC_USING_QSPI3
[3] = AIC_DEV_QSPI3_MAX_SRC_FREQ_HZ,
#endif
};
void test_qspi_slave_set_pinmux(void)
{
uint32_t i = 0;
long pin = 0;
unsigned int g;
unsigned int p;
for (i=0; i<ARRAY_SIZE(spi_pinmux_config); i++) {
pin = hal_gpio_name2pin(spi_pinmux_config[i].name);
if (pin < 0)
continue;
g = GPIO_GROUP(pin);
p = GPIO_GROUP_PIN(pin);
hal_gpio_set_func(g, p, spi_pinmux_config[i].func);
hal_gpio_set_bias_pull(g, p, spi_pinmux_config[i].bias);
hal_gpio_set_drive_strength(g, p, spi_pinmux_config[i].drive);
}
}
static irqreturn_t qspi_slave_irq_handler(int irq_num, void *arg)
{
qspi_slave_handle *h = arg;
rt_interrupt_enter();
hal_qspi_slave_irq_handler(h);
rt_interrupt_leave();
return IRQ_HANDLED;
}
int test_qspi_slave_controller_init(u32 id, u32 bus_width,
qspi_slave_async_cb cb, void *priv,
qspi_slave_handle *h)
{
struct qspi_slave_config cfg;
int ret;
u32 clk_id, irq_num, clk_in;
clk_id = qspi_clk_ids[id];
irq_num = qspi_irq_num[id];
clk_in = qspi_input_clk[id];
memset(&cfg, 0, sizeof(cfg));
cfg.idx = id;
cfg.clk_in_hz = clk_in;
cfg.clk_id = clk_id;
/* Default is Mode0 */
cfg.cpol = HAL_QSPI_CPOL_ACTIVE_HIGH;
cfg.cpha = HAL_QSPI_CPHA_FIRST_EDGE;
cfg.cs_polarity = HAL_QSPI_CS_POL_VALID_LOW;
ret = hal_qspi_slave_init(h, &cfg);
if (ret) {
pr_err("hal_qspi_slave_init failed. ret %d\n", ret);
return -1;
}
hal_qspi_slave_set_bus_width(h, bus_width);
ret = hal_qspi_slave_register_cb(h, cb, priv);
if (ret) {
pr_err("qspi register async callback failed.\n");
return ret;
}
aicos_request_irq(irq_num, qspi_slave_irq_handler, 0, NULL, (void *)h);
aicos_irq_enable(irq_num);
return 0;
}
void test_qspi_slave_controller_deinit(qspi_slave_handle *h)
{
hal_qspi_slave_deinit(h);
}

View File

@@ -1,151 +0,0 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Xuan.Wen <xuan.wen@artinchip.com>
*/
#include <string.h>
#include <finsh.h>
#include <rtconfig.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <aic_hal.h>
#include <hal_qspi.h>
#include <rtthread.h>
#include "test_spislave.h"
#define RUN_STATE_IN 0
#define RUN_STATE_OUT 1
#define MEM_STATE_IDLE 0
#define MEM_STATE_CMD 1
#define MEM_STATE_DATA 2
struct qspirecv_state {
u32 qspi_id;
u32 bus_width;
qspi_slave_handle handle;
u8 *work_buf;
};
static struct qspirecv_state g_state;
extern void slave_dump_data(char *msg, u8 *buf, u32 len);
static void qspi_usage(void)
{
}
static int recv_new_data(struct qspirecv_state *state, u8 *buf, u32 len)
{
struct qspi_transfer t;
int ret;
memset(&t, 0, sizeof(t));
t.rx_data = buf;
t.data_len = len;
// memset(buf, 0, len);
// printf("%s, reset rx fifo\n", __func__);
hal_qspi_slave_fifo_reset(&state->handle, HAL_QSPI_RX_FIFO);
ret = hal_qspi_slave_transfer_async(&state->handle, &t);
if (ret < 0)
return -1;
return 0;
}
static void qspirecv_slave_async_callback(qspi_slave_handle *h, void *priv)
{
struct qspirecv_state *state = priv;
int status, cnt;
u32 *p32, cksum;
status = hal_qspi_slave_get_status(&state->handle);
cnt = 0;
if (status == HAL_QSPI_STATUS_OK) {
/*
* status OK:
* TRANSFER DONE or CS INVALID
*/
// p = state->work_buf;
cnt = hal_qspi_slave_transfer_count(&state->handle);
printf("%s, status %d, cnt %d\n", __func__, status, cnt);
p32 = (void *)state->work_buf;
cksum = 0;
for (int i = 0; i<PKT_SIZE/4; i++) {
cksum += *p32;
p32++;
}
printf("cksum 0x%x\n", cksum);
recv_new_data(state, state->work_buf, PKT_SIZE);
// slave_dump_data("Data", p, cnt);
} else {
/* Error process */
printf("%s, status %d\n", __func__, status);
}
}
static int test_qspirecv_start(int argc, char **argv)
{
unsigned long val;
int ret;
if (argc < 2) {
qspi_usage();
return -1;
}
val = strtol(argv[1], NULL, 10);
g_state.qspi_id = val;
g_state.bus_width = 1; // Default is 1
if (g_state.work_buf == NULL)
g_state.work_buf =
aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
if (argc >= 3) {
val = strtol(argv[2], NULL, 10);
g_state.bus_width = val;
}
ret = test_qspi_slave_controller_init(g_state.qspi_id, g_state.bus_width,
qspirecv_slave_async_callback, &g_state,
&g_state.handle);
if (ret) {
printf("QSPI Slave init failure.\n");
return -1;
}
/* Start with waiting command */
recv_new_data(&g_state, g_state.work_buf, PKT_SIZE);
return 0;
}
static int test_qspirecv_stop(int argc, char **argv)
{
test_qspi_slave_controller_deinit(&g_state.handle);
if (g_state.work_buf) {
aicos_free_align(0, g_state.work_buf);
g_state.work_buf = NULL;
}
return 0;
}
static void cmd_test_qspislave_receiver(int argc, char **argv)
{
if (argc < 2)
goto help;
if (!rt_strcmp(argv[1], "help")) {
goto help;
} else if (!rt_strcmp(argv[1], "start")) {
test_qspirecv_start(argc - 1, &argv[1]);
return;
} else if (!rt_strcmp(argv[1], "stop")) {
test_qspirecv_stop(argc - 1, &argv[1]);
return;
}
help:
qspi_usage();
}
MSH_CMD_EXPORT_ALIAS(cmd_test_qspislave_receiver, spirecv, Test QSPI Slave);

View File

@@ -1,238 +0,0 @@
/*
* Copyright (c) 2024, ArtInChip Technology Co., Ltd
*
* SPDX-License-Identifier: Apache-2.0
*
* Authors: Xuan.Wen <xuan.wen@artinchip.com>
*/
#include <string.h>
#include <finsh.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <drv_qspi.h>
#include "test_spislave.h"
struct bus_cfg {
u8 cmd; /* CMD bus width */
u8 addr; /* Address bus width */
u8 dmycyc; /* Dummy clock cycle */
u8 data; /* Data bus width */
};
extern void slave_dump_data(char *msg, u8 *buf, u32 len);
void master_tx(struct rt_qspi_device *qspi, u8 bus_width, u8 *buf, u32 datalen)
{
struct rt_qspi_message msg;
struct bus_cfg cfg;
rt_size_t ret;
cfg.cmd = 0;
cfg.addr = 0;
cfg.dmycyc = 0;
cfg.data = bus_width;
rt_memset(&msg, 0, sizeof(msg));
msg.qspi_data_lines = cfg.data;
msg.parent.recv_buf = NULL;
msg.parent.send_buf = buf;
msg.parent.length = datalen;
msg.parent.cs_take = 1;
msg.parent.cs_release = 1;
rt_spi_take_bus((struct rt_spi_device *)qspi);
ret = rt_qspi_transfer_message(qspi, &msg);
if (ret != datalen) {
printf("master tx failed. ret 0x%x\n", ret);
}
rt_spi_release_bus((struct rt_spi_device *)qspi);
}
void master_rx(struct rt_qspi_device *qspi, u8 bus_width, u8 *buf, u32 datalen)
{
struct rt_qspi_message msg;
struct bus_cfg cfg;
rt_size_t ret;
cfg.cmd = 0;
cfg.addr = 0;
cfg.dmycyc = 0;
cfg.data = bus_width;
rt_memset(&msg, 0, sizeof(msg));
msg.qspi_data_lines = cfg.data;
msg.parent.recv_buf = buf;
msg.parent.send_buf = NULL;
msg.parent.length = datalen;
msg.parent.cs_take = 1;
msg.parent.cs_release = 1;
rt_spi_take_bus((struct rt_spi_device *)qspi);
ret = rt_qspi_transfer_message(qspi, &msg);
if (ret != datalen) {
printf("master tx failed. ret 0x%x\n", ret);
}
rt_spi_release_bus((struct rt_spi_device *)qspi);
}
static void slave_get_status(struct rt_qspi_device *qspi, u8 bus_width, u8 *buf,
u32 datalen)
{
master_rx(qspi, bus_width, buf, datalen);
}
void slave_write(struct rt_qspi_device *qspi, u8 bus_width, u8 *buf, u32 datalen, u32 addr)
{
u8 *work_buf;
u32 status;
work_buf = aicos_malloc_align(0, datalen + 4, CACHE_LINE_SIZE);
work_buf[0] = MEM_CMD_WRITE;
memcpy(&work_buf[1], &addr, 3);
memcpy(&work_buf[4], buf, datalen);
master_tx(qspi, bus_width, work_buf, datalen + 4);
rt_thread_mdelay(10);
do {
status = 0;
slave_get_status(qspi, bus_width, (void *)&status, 4);
printf("write status 0x%x\n", status);
rt_thread_mdelay(1000);
} while (status != WRITE_STATUS_VAL);
aicos_free_align(0, work_buf);
}
static void slave_load_data(struct rt_qspi_device *qspi, u8 bus_width, u32 addr)
{
u8 work_buf[4];
work_buf[0] = MEM_CMD_LOAD;
memcpy(&work_buf[1], &addr, 3);
master_tx(qspi, bus_width, work_buf, 4);
}
static void slave_read_data(struct rt_qspi_device *qspi, u8 bus_width,
u8 *buf, u32 datalen)
{
master_rx(qspi, bus_width, buf, datalen);
}
void slave_read(struct rt_qspi_device *qspi, u8 bus_width, u8 *buf, u32 datalen,
u32 addr)
{
u32 status;
slave_load_data(qspi, bus_width, addr);
rt_thread_mdelay(100);
do {
status = 0;
slave_get_status(qspi, bus_width, (void *)&status, 4);
printf("load status 0x%x\n", status);
rt_thread_mdelay(1000);
} while (status != LOAD_STATUS_VAL);
slave_read_data(qspi, bus_width, buf, datalen);
}
void test_qspi_slaverw(struct rt_qspi_device *qspi, int argc, char **argv)
{
u8 *tx_buf, *rx_buf;
u8 bus_width;
unsigned long val;
bus_width = 1;
if (argc >= 2) {
val = strtol(argv[1], NULL, 10);
bus_width = (u8)val;
}
tx_buf = aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
rx_buf = aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
for (int i = 0; i < TEST_BUF_SIZE; i++) {
tx_buf[i] = i % 256;
}
printf("\nHOST: Write data to address 0\n");
slave_write(qspi, bus_width, tx_buf, PKT_SIZE, 0);
rt_thread_mdelay(100);
printf("\nHOST: Write data to address 0\n");
slave_write(qspi, bus_width, tx_buf, PKT_SIZE, 0);
rt_thread_mdelay(100);
printf("\nHOST: Write data to address 0\n");
slave_write(qspi, bus_width, tx_buf, PKT_SIZE, 0);
rt_thread_mdelay(100);
printf("\nHOST: Read data from address 0\n");
memset(rx_buf, 0, PKT_SIZE);
slave_read(qspi, bus_width, rx_buf, PKT_SIZE, 0);
slave_dump_data("Read", rx_buf, PKT_SIZE);
rt_thread_mdelay(100);
printf("\nHOST: Write data to address 0x%x\n", PKT_SIZE);
slave_write(qspi, bus_width, tx_buf + PKT_SIZE, PKT_SIZE, PKT_SIZE);
rt_thread_mdelay(100);
printf("\nHOST: Read data from address 0x10\n");
memset(rx_buf, 0, PKT_SIZE);
slave_read(qspi, bus_width, rx_buf, PKT_SIZE, 0x10);
slave_dump_data("Read", rx_buf, PKT_SIZE);
printf("\nHOST: Read data from address 0x01\n");
memset(rx_buf, 0, PKT_SIZE);
slave_read(qspi, bus_width, rx_buf, PKT_SIZE, 0x01);
slave_dump_data("Read", rx_buf, PKT_SIZE);
printf("\nHOST: Read data from address 0x02\n");
memset(rx_buf, 0, PKT_SIZE);
slave_read(qspi, bus_width, rx_buf, PKT_SIZE, 0x02);
slave_dump_data("Read", rx_buf, PKT_SIZE);
aicos_free_align(0, tx_buf);
aicos_free_align(0, rx_buf);
}
void test_qspi_send2slave(struct rt_qspi_device *qspi, int argc, char **argv)
{
u8 *tx_buf, *rx_buf;
u8 bus_width;
unsigned long val;
u32 cksum, *p;
bus_width = 1;
if (argc >= 2) {
val = strtol(argv[1], NULL, 10);
bus_width = (u8)val;
}
tx_buf = aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
rx_buf = aicos_malloc_align(0, TEST_BUF_SIZE, CACHE_LINE_SIZE);
for (int i = 0; i < 100; i++) {
printf("\nHOST: Write data to address 0, round %d\n", i);
p = (void *)tx_buf;
for (int j = 0; j < TEST_BUF_SIZE; j++) {
//tx_buf[i] = 0xA << 4 | (i % 16);
// tx_buf[i] = 0xA5;
tx_buf[i] = (j + i) % 256;
}
tx_buf[0] = i;
cksum = 0;
for (int i = 0; i < TEST_BUF_SIZE / 4; i++) {
cksum += *p;
p++;
}
printf("ckxsum 0x%x\n", cksum);
master_tx(qspi, bus_width, tx_buf, PKT_SIZE);
rt_thread_mdelay(1000);
}
aicos_free_align(0, tx_buf);
aicos_free_align(0, rx_buf);
}