mirror of
https://gitee.com/Vancouver2017/luban-lite-t3e-pro.git
synced 2025-12-14 18:38:55 +00:00
463 lines
14 KiB
C
463 lines
14 KiB
C
#include <string.h>
|
|
#include <finsh.h>
|
|
#include <rtdevice.h>
|
|
#include <aic_core.h>
|
|
#include <drv_qspi.h>
|
|
|
|
#define USAGE \
|
|
"qspidev help : Get this information.\n" \
|
|
"qspidev attach <bus name> <dev name> : Attach device to QSPI bus.\n" \
|
|
"qspidev init <name> <mode> <freq> : Initialize QSPI for device.\n" \
|
|
"qspidev alloc <size> : Allocate buffer for test.\n" \
|
|
"qspidev free <addr> : Free buffer for test.\n" \
|
|
"qspidev send <lines> <cmd> <addr> <dummy_cnt> <data addr> <data len>: Send data.\n" \
|
|
" lines: 111, 112, 114, 122, 144 (lines for cmd,addr,data)\n" \
|
|
" cmd : hex string, e.g. 01\n" \
|
|
" addr : hex string, e.g. 000001\n" \
|
|
" If address is not present, use \"-\" intead\n" \
|
|
" dummy_cycles: hex string, e.g. 02, dummy clock cycles\n" \
|
|
" If dummy cycles is not present, use \"-\" intead\n" \
|
|
" data addr: hex string, e.g. 0x40000000\n" \
|
|
" data len : hex string, e.g. 0x800\n" \
|
|
"qspidev sendhex <lines> <cmd> <addr> <dummy_cnt> <data hex string>: Send data.\n" \
|
|
" lines: 111, 112, 114, 122, 144 (lines for cmd,addr,data)\n" \
|
|
" cmd : hex string, e.g. 01\n" \
|
|
" addr : hex string, e.g. 000001\n" \
|
|
" If address is not present, use \"-\" intead\n" \
|
|
" dummy_cycles: hex string, e.g. 02, dummy clock cycles\n" \
|
|
" If dummy cycles is not present, use \"-\" intead\n" \
|
|
" data hex string: hex string, e.g. 41 42 43 44 45\n" \
|
|
"qspidev recv <lines> <cmd> <addr> <dummy_cnt> <data addr> <data len>: Send cmd and recieve data\n" \
|
|
" lines: 111, 112, 114, 122, 144 (lines for cmd,addr,data)\n" \
|
|
" cmd : hex string, e.g. 01\n" \
|
|
" addr : hex string, e.g. 000001\n" \
|
|
" If address is not present, use \"-\" intead\n" \
|
|
" dummy_cycles: hex string, e.g. 02, dummy clock cycles\n" \
|
|
" If dummy cycles is not present, use \"-\" intead\n" \
|
|
" data addr: hex string, e.g. 0x40000000\n" \
|
|
" data len : hex string, e.g. 0x800\n" \
|
|
"qspidev recvhex <lines> <cmd> <addr> <dummy_cnt> <data length>: Send cmd and recieve data, then print\n" \
|
|
" lines: 111, 112, 114, 122, 144 (lines for cmd,addr,data)\n" \
|
|
" cmd : hex string, e.g. 01\n" \
|
|
" addr : hex string, e.g. 000001\n" \
|
|
" If address is not present, use \"-\" intead\n" \
|
|
" dummy_cycles: hex string, e.g. 02, dummy clock cycles\n" \
|
|
" If dummy cycles is not present, use \"-\" intead\n" \
|
|
" data len : hex string, e.g. 0x800\n" \
|
|
"example:\n" \
|
|
"qspidev attach qspi1 qtestdev\n" \
|
|
"qspidev init qtestdev 3 50000000\n" \
|
|
"qspidev recvhex 111 9f - 8 3\n" \
|
|
"qspidev sendhex 111 ff\n" \
|
|
"qspidev sendhex 111 13 000000\n" \
|
|
"qspidev recvhex 111 03 000000 0 0x800\n"
|
|
|
|
static void qspi_usage(void)
|
|
{
|
|
printf("%s", USAGE);
|
|
}
|
|
|
|
static struct rt_qspi_device *g_qspi;
|
|
|
|
static int test_qspi_attach(int argc, char **argv)
|
|
{
|
|
char *bus_name, *dev_name;
|
|
|
|
if (argc != 3) {
|
|
qspi_usage();
|
|
return -1;
|
|
}
|
|
bus_name = argv[1];
|
|
dev_name = argv[2];
|
|
|
|
/* Attach/Create dev to spi bus */
|
|
aic_qspi_bus_attach_device(bus_name, dev_name, 0, 4, RT_NULL, RT_NULL);
|
|
return 0;
|
|
}
|
|
|
|
static int test_qspi_init(int argc, char **argv)
|
|
{
|
|
struct rt_qspi_configuration qspi_cfg;
|
|
struct rt_device *dev;
|
|
char *name;
|
|
int ret = 0;
|
|
|
|
if (argc != 4) {
|
|
printf("Argument error, please see help information.\n");
|
|
return -1;
|
|
}
|
|
name = argv[1];
|
|
|
|
g_qspi = (struct rt_qspi_device *)rt_device_find(name);
|
|
if (!g_qspi) {
|
|
printf("Failed to get device in name %s\n", name);
|
|
return -1;
|
|
}
|
|
|
|
dev = (struct rt_device *)g_qspi;
|
|
if (dev->type != RT_Device_Class_SPIDevice) {
|
|
g_qspi = NULL;
|
|
printf("%s is not SPI device.\n", name);
|
|
return -1;
|
|
}
|
|
qspi_cfg.qspi_dl_width = 4;
|
|
qspi_cfg.parent.mode = atol(argv[2]);
|
|
qspi_cfg.parent.max_hz = atol(argv[3]);
|
|
ret = rt_qspi_configure(g_qspi, &qspi_cfg);
|
|
if (ret < 0) {
|
|
printf("qspi configure failure.\n");
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static bool qspi_lines_check(uint32_t line)
|
|
{
|
|
switch (line) {
|
|
case 111: /* cmd 1 line, addr 1 line, data 1 line */
|
|
case 112: /* cmd 1 line, addr 1 line, data 2 line */
|
|
case 122: /* cmd 1 line, addr 2 line, data 2 line */
|
|
case 114: /* cmd 1 line, addr 1 line, data 4 line */
|
|
case 144: /* cmd 1 line, addr 4 line, data 4 line */
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static void test_qspi_sendhex(int argc, char **argv)
|
|
{
|
|
char *pl;
|
|
uint32_t line = 0, addrsiz = 0, addr = 0, dmycyc = 0;
|
|
unsigned long i, data_len, align_len;
|
|
uint8_t cmd, *data;
|
|
struct rt_qspi_message msg;
|
|
rt_size_t ret;
|
|
|
|
if (!g_qspi) {
|
|
printf("QSPI device is not init yet.\n");
|
|
return;
|
|
}
|
|
if (argc < 3) {
|
|
printf("Argument is not correct, please see help for more information.\n");
|
|
return;
|
|
}
|
|
pl = argv[1];
|
|
line = strtol(pl, NULL, 10);
|
|
if (qspi_lines_check(line) == false) {
|
|
qspi_usage();
|
|
return;
|
|
}
|
|
cmd = (uint8_t)strtol(argv[2], NULL, 16);
|
|
addrsiz = 0;
|
|
addr = 0;
|
|
if (argc >= 4) {
|
|
if (rt_memcmp(argv[3], "-", 1)) {
|
|
addrsiz = (strlen(argv[3]) + 1) >> 1;
|
|
addr = strtol(argv[3], NULL, 16);
|
|
} else {
|
|
addrsiz = 0;
|
|
addr = 0;
|
|
}
|
|
}
|
|
dmycyc = 0;
|
|
data_len = 0;
|
|
if (argc >= 5) {
|
|
dmycyc = strtol(argv[4], NULL, 16);
|
|
data_len = argc - 5;
|
|
}
|
|
data = RT_NULL;
|
|
if (data_len) {
|
|
align_len = roundup(data_len, CACHE_LINE_SIZE);
|
|
data = aicos_malloc_align(0, align_len, CACHE_LINE_SIZE);
|
|
for (i = 5; i < argc; i++) {
|
|
data[i] = (uint8_t)strtol(argv[i], NULL, 16);
|
|
}
|
|
}
|
|
rt_memset(&msg, 0, sizeof(msg));
|
|
msg.instruction.content = cmd;
|
|
msg.instruction.qspi_lines = pl[0] - '0';
|
|
if (addrsiz) {
|
|
msg.address.content = addr;
|
|
msg.address.size = addrsiz;
|
|
msg.address.qspi_lines = pl[1] - '0';
|
|
}
|
|
msg.dummy_cycles = dmycyc;
|
|
if (data) {
|
|
msg.qspi_data_lines = pl[2] - '0';
|
|
msg.parent.send_buf = (void *)data;
|
|
msg.parent.length = data_len;
|
|
}
|
|
msg.parent.cs_take = 1;
|
|
msg.parent.cs_release = 1;
|
|
rt_spi_take_bus((struct rt_spi_device *)g_qspi);
|
|
ret = rt_qspi_transfer_message(g_qspi, &msg);
|
|
if (ret != data_len) {
|
|
printf("Send data failed. ret 0x%lx\n", ret);
|
|
}
|
|
rt_spi_release_bus((struct rt_spi_device *)g_qspi);
|
|
if (data)
|
|
aicos_free_align(0, data);
|
|
}
|
|
|
|
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;
|
|
uint8_t *data, cmd;
|
|
struct rt_qspi_message msg;
|
|
|
|
if (!g_qspi) {
|
|
printf("QSPI device is not init yet.\n");
|
|
return;
|
|
}
|
|
if (argc < 3) {
|
|
printf("Argument is not correct, please see help for more information.\n");
|
|
return;
|
|
}
|
|
pl = argv[1];
|
|
line = strtol(pl, NULL, 10);
|
|
if (qspi_lines_check(line) == false) {
|
|
qspi_usage();
|
|
return;
|
|
}
|
|
cmd = (uint8_t)strtol(argv[2], NULL, 16);
|
|
addrsiz = 0;
|
|
if (argc >= 4) {
|
|
if (rt_memcmp(argv[3], "-", 1)) {
|
|
addrsiz = (strlen(argv[3]) + 1) >> 1;
|
|
addr = strtol(argv[3], NULL, 16);
|
|
} else {
|
|
addrsiz = 0;
|
|
addr = 0;
|
|
}
|
|
}
|
|
dmycyc = 0;
|
|
if (argc >= 5) {
|
|
dmycyc = strtol(argv[4], NULL, 16);
|
|
}
|
|
data_len = 0;
|
|
if (argc >= 6) {
|
|
data_len = strtol(argv[5], NULL, 16);
|
|
}
|
|
data = RT_NULL;
|
|
if (data_len > 0) {
|
|
align_len = roundup(data_len, CACHE_LINE_SIZE);
|
|
data = aicos_malloc_align(0, align_len, CACHE_LINE_SIZE);
|
|
}
|
|
rt_memset(&msg, 0, sizeof(msg));
|
|
msg.instruction.content = cmd;
|
|
msg.instruction.qspi_lines = pl[0] - '0';
|
|
if (addrsiz) {
|
|
msg.address.content = addr;
|
|
msg.address.size = addrsiz;
|
|
msg.address.qspi_lines = pl[1] - '0';
|
|
}
|
|
msg.dummy_cycles = dmycyc;
|
|
msg.qspi_data_lines = pl[2] - '0';
|
|
msg.parent.recv_buf = (void *)data;
|
|
msg.parent.length = data_len;
|
|
msg.parent.cs_take = 1;
|
|
msg.parent.cs_release = 1;
|
|
rt_spi_take_bus((struct rt_spi_device *)g_qspi);
|
|
rt_qspi_transfer_message(g_qspi, &msg);
|
|
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");
|
|
aicos_free_align(0, data);
|
|
}
|
|
}
|
|
|
|
static void test_qspi_send(int argc, char **argv)
|
|
{
|
|
char *pl;
|
|
uint32_t line = 0, addrsiz = 0, addr = 0, dmycyc = 0;
|
|
unsigned long data, data_len;
|
|
uint8_t cmd;
|
|
rt_size_t ret;
|
|
struct rt_qspi_message msg;
|
|
|
|
if (!g_qspi) {
|
|
printf("QSPI device is not init yet.\n");
|
|
return;
|
|
}
|
|
if (argc < 3) {
|
|
printf("Argument is not correct, please see help for more information.\n");
|
|
return;
|
|
}
|
|
pl = argv[1];
|
|
line = strtol(pl, NULL, 10);
|
|
if (qspi_lines_check(line) == false) {
|
|
qspi_usage();
|
|
return;
|
|
}
|
|
cmd = (uint8_t)strtol(argv[2], NULL, 16);
|
|
addrsiz = 0;
|
|
addr = 0;
|
|
if (argc >= 4) {
|
|
if (rt_memcmp(argv[3], "-", 1)) {
|
|
addrsiz = (strlen(argv[3]) + 1) >> 1;
|
|
addr = strtol(argv[3], NULL, 16);
|
|
} else {
|
|
addrsiz = 0;
|
|
addr = 0;
|
|
}
|
|
}
|
|
dmycyc = 0;
|
|
if (argc >= 5) {
|
|
dmycyc = strtol(argv[4], NULL, 16);
|
|
}
|
|
data = 0;
|
|
if (argc >= 6) {
|
|
data = strtol(argv[5], NULL, 16);
|
|
}
|
|
data_len = 0;
|
|
if (argc >= 7) {
|
|
data_len = strtol(argv[6], NULL, 16);
|
|
}
|
|
rt_memset(&msg, 0, sizeof(msg));
|
|
msg.instruction.content = cmd;
|
|
msg.instruction.qspi_lines = pl[0] - '0';
|
|
if (addrsiz) {
|
|
msg.address.content = addr;
|
|
msg.address.size = addrsiz;
|
|
msg.address.qspi_lines = pl[1] - '0';
|
|
}
|
|
msg.dummy_cycles = dmycyc;
|
|
if (data) {
|
|
msg.qspi_data_lines = pl[2] - '0';
|
|
msg.parent.send_buf = (void *)data;
|
|
msg.parent.length = data_len;
|
|
}
|
|
msg.parent.cs_take = 1;
|
|
msg.parent.cs_release = 1;
|
|
rt_spi_take_bus((struct rt_spi_device *)g_qspi);
|
|
ret = rt_qspi_transfer_message(g_qspi, &msg);
|
|
if (ret != data_len) {
|
|
printf("Send data failed. ret 0x%lx\n", ret);
|
|
}
|
|
rt_spi_release_bus((struct rt_spi_device *)g_qspi);
|
|
}
|
|
|
|
static void test_qspi_recv(int argc, char **argv)
|
|
{
|
|
char *pl;
|
|
uint32_t line = 0, addrsiz = 0, addr = 0, dmycyc = 0;
|
|
unsigned long data, data_len;
|
|
uint8_t cmd;
|
|
rt_size_t ret;
|
|
struct rt_qspi_message msg;
|
|
|
|
if (!g_qspi) {
|
|
printf("QSPI device is not init yet.\n");
|
|
return;
|
|
}
|
|
if (argc < 3) {
|
|
printf("Argument is not correct, please see help for more information.\n");
|
|
return;
|
|
}
|
|
pl = argv[1];
|
|
line = strtol(pl, NULL, 10);
|
|
if (qspi_lines_check(line) == false) {
|
|
qspi_usage();
|
|
return;
|
|
}
|
|
cmd = (uint8_t)strtol(argv[2], NULL, 16);
|
|
addrsiz = 0;
|
|
if (argc >= 4) {
|
|
if (rt_memcmp(argv[3], "-", 1)) {
|
|
addrsiz = (strlen(argv[3]) + 1) >> 1;
|
|
addr = strtol(argv[3], NULL, 16);
|
|
} else {
|
|
addrsiz = 0;
|
|
addr = 0;
|
|
}
|
|
}
|
|
dmycyc = 0;
|
|
if (argc >= 5) {
|
|
dmycyc = strtol(argv[4], NULL, 16);
|
|
}
|
|
data = 0;
|
|
if (argc >= 6) {
|
|
data = strtol(argv[5], NULL, 16);
|
|
}
|
|
data_len = 0;
|
|
if (argc >= 7) {
|
|
data_len = strtol(argv[6], NULL, 16);
|
|
}
|
|
rt_memset(&msg, 0, sizeof(msg));
|
|
msg.instruction.content = cmd;
|
|
msg.instruction.qspi_lines = pl[0] - '0';
|
|
if (addrsiz) {
|
|
msg.address.content = addr;
|
|
msg.address.size = addrsiz;
|
|
msg.address.qspi_lines = pl[1] - '0';
|
|
}
|
|
msg.dummy_cycles = dmycyc;
|
|
msg.qspi_data_lines = pl[2] - '0';
|
|
msg.parent.recv_buf = (void *)data;
|
|
msg.parent.length = data_len;
|
|
msg.parent.cs_take = 1;
|
|
msg.parent.cs_release = 1;
|
|
rt_spi_take_bus((struct rt_spi_device *)g_qspi);
|
|
ret = rt_qspi_transfer_message(g_qspi, &msg);
|
|
if (ret != data_len) {
|
|
printf("Recv data failed. ret 0x%lx\n", ret);
|
|
}
|
|
rt_spi_release_bus((struct rt_spi_device *)g_qspi);
|
|
}
|
|
|
|
static void cmd_test_qspi(int argc, char **argv)
|
|
{
|
|
unsigned long size = 0, addr = 0, align_len;
|
|
|
|
if (argc < 2)
|
|
goto help;
|
|
|
|
if (!rt_strcmp(argv[1], "help")) {
|
|
goto help;
|
|
} else if (!rt_strcmp(argv[1], "attach")) {
|
|
test_qspi_attach(argc - 1, &argv[1]);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "init")) {
|
|
test_qspi_init(argc - 1, &argv[1]);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "alloc")) {
|
|
size = strtol(argv[2], NULL, 0);
|
|
align_len = roundup(size, CACHE_LINE_SIZE);
|
|
printf("0x%08lx\n", (unsigned long)aicos_malloc_align(0, align_len, CACHE_LINE_SIZE));
|
|
printf("size %lu\n", align_len);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "free")) {
|
|
addr = strtol(argv[2], NULL, 0);
|
|
aicos_free_align(0, (void *)addr);
|
|
printf("free 0x%lx\n", addr);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "sendhex")) {
|
|
test_qspi_sendhex(argc - 1, &argv[1]);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "recvhex")) {
|
|
test_qspi_recvhex(argc - 1, &argv[1]);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "send")) {
|
|
test_qspi_send(argc - 1, &argv[1]);
|
|
return;
|
|
} else if (!rt_strcmp(argv[1], "recv")) {
|
|
test_qspi_recv(argc - 1, &argv[1]);
|
|
return;
|
|
}
|
|
help:
|
|
qspi_usage();
|
|
}
|
|
|
|
MSH_CMD_EXPORT_ALIAS(cmd_test_qspi, qspidev, Test QSPI. "qspidev help" for more information);
|