2023-11-09 20:19:51 +08:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2022-2023, ArtInChip Technology Co., Ltd
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
*
|
|
|
|
|
* Authors: Siyao.Li <siyao.li@artinchip.com>
|
|
|
|
|
*/
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <getopt.h>
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
#include <rtthread.h>
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include "rtdevice.h"
|
|
|
|
|
#include "aic_core.h"
|
|
|
|
|
#include "aic_log.h"
|
|
|
|
|
#include "hal_adcim.h"
|
2023-11-30 19:48:02 +08:00
|
|
|
#include "hal_gpai.h"
|
2023-11-09 20:19:51 +08:00
|
|
|
|
|
|
|
|
#include "aic_core.h"
|
|
|
|
|
|
|
|
|
|
/* Global macro and variables */
|
|
|
|
|
#define AIC_ADCIM_NAME "adcim"
|
|
|
|
|
#define AIC_GPAI_NAME "gpai"
|
|
|
|
|
|
|
|
|
|
#ifdef AIC_ADCIM_DM_DRV
|
|
|
|
|
#define ADC_CHAN_GPAI11 11
|
|
|
|
|
#define ADC_CHAN_TSEN3 15
|
|
|
|
|
#endif
|
|
|
|
|
|
2023-11-30 19:48:02 +08:00
|
|
|
#define GPAI_AVG_SAMPLES_NUM 8
|
2023-11-09 20:19:51 +08:00
|
|
|
#define ADC_CHAN_NUM 16
|
|
|
|
|
#define ADC_DM_SRAM_SIZE 512
|
|
|
|
|
#define ADC_TEST_DATA_COUNT 64
|
|
|
|
|
|
|
|
|
|
static rt_adc_device_t gpai_dev;
|
2023-11-30 19:48:02 +08:00
|
|
|
static const char sopts[] = "c:mhv";
|
2023-11-09 20:19:51 +08:00
|
|
|
static const struct option lopts[] = {
|
|
|
|
|
{"channel", required_argument, NULL, 'c'},
|
2023-11-30 19:48:02 +08:00
|
|
|
{"mode", no_argument, NULL, 'm'},
|
2023-11-09 20:19:51 +08:00
|
|
|
{"usage", no_argument, NULL, 'h'},
|
2023-11-30 19:48:02 +08:00
|
|
|
{"verbose", no_argument, NULL, 'v'},
|
2023-11-09 20:19:51 +08:00
|
|
|
{0, 0, 0, 0}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static int g_verbose = 0;
|
2023-11-30 19:48:02 +08:00
|
|
|
static int g_dma_mode = 0;
|
|
|
|
|
static struct aic_dma_transfer_info dma_info;
|
|
|
|
|
static int g_cur_data[ADC_DM_SRAM_SIZE] = {0};
|
|
|
|
|
static int g_sram_data[ADC_DM_SRAM_SIZE] = {0};
|
|
|
|
|
static int g_expect_data[ADC_TEST_DATA_COUNT] = {0};
|
|
|
|
|
static rt_uint32_t g_adc_buf[ADC_TEST_DATA_COUNT] __attribute__((aligned(64)));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*dma_callback)(void *dma_param);
|
2023-11-09 20:19:51 +08:00
|
|
|
|
|
|
|
|
static void cmd_adcim_usage(char *program)
|
|
|
|
|
{
|
|
|
|
|
printf("Compile time: %s %s\n", __DATE__, __TIME__);
|
|
|
|
|
printf("Usage: %s [options]\n", program);
|
|
|
|
|
printf("\t -c, --channel\t\tSelect one channel in [0, 15]\n");
|
2023-11-30 19:48:02 +08:00
|
|
|
printf("\t -m, --dma_mode\t\tSelect the dma mode\n");
|
2023-11-09 20:19:51 +08:00
|
|
|
printf("\t -h, --usage \n");
|
|
|
|
|
printf("\n");
|
|
|
|
|
printf("Example: %s -c 0\n", program);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int abs(int val)
|
|
|
|
|
{
|
|
|
|
|
if (val < 0)
|
|
|
|
|
return -val;
|
|
|
|
|
else
|
|
|
|
|
return val;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gen_adc_data(u32 *size)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int *pdata = g_sram_data;
|
|
|
|
|
|
|
|
|
|
if (g_verbose)
|
|
|
|
|
pr_info("Generate %d data ...\n", ADC_DM_SRAM_SIZE);
|
|
|
|
|
for (i = 0; i < ADC_DM_SRAM_SIZE; i++)
|
|
|
|
|
*pdata++ = 1800 + abs(i % 256 - 128) - 64;
|
|
|
|
|
|
|
|
|
|
*size = ADC_DM_SRAM_SIZE;
|
|
|
|
|
if (g_verbose)
|
|
|
|
|
pr_info("The ADC data, size %d:\n", *size);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int average(int *data, u32 size, int trim)
|
|
|
|
|
{
|
|
|
|
|
int sum = 0, i, min = *data, max = 0;
|
|
|
|
|
|
|
|
|
|
if (!data || size < 3)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
|
if (data[i] < min)
|
|
|
|
|
min = data[i];
|
|
|
|
|
if (data[i] > max)
|
|
|
|
|
max = data[i];
|
|
|
|
|
sum += data[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (trim)
|
|
|
|
|
return (sum - min - max) / (size - 2);
|
|
|
|
|
else
|
|
|
|
|
return sum/size;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:48:02 +08:00
|
|
|
static void gpai_check_adc_by_cpu(void)
|
2023-11-09 20:19:51 +08:00
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
for(i = 0;i < ADC_TEST_DATA_COUNT;i++) {
|
|
|
|
|
if (g_cur_data[i] != g_expect_data[i])
|
|
|
|
|
printf("[%d] Failed%d/%d\n", i, g_cur_data[i], g_expect_data[i]);
|
|
|
|
|
else
|
|
|
|
|
printf("[%d] OK! %d/%d\n",i, g_cur_data[i], g_expect_data[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-11-30 19:48:02 +08:00
|
|
|
|
|
|
|
|
static int gpai_get_adc_by_cpu(int chan)
|
2023-11-09 20:19:51 +08:00
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
int i;
|
|
|
|
|
int current_irq_count;
|
|
|
|
|
int count = 0;
|
2023-11-30 19:48:02 +08:00
|
|
|
int cur_data_count = 1;
|
2023-11-09 20:19:51 +08:00
|
|
|
int cur;
|
|
|
|
|
|
|
|
|
|
gpai_dev = (rt_adc_device_t)rt_device_find(AIC_GPAI_NAME);
|
|
|
|
|
if (!gpai_dev) {
|
|
|
|
|
rt_kprintf("Failed to open %s device\n", AIC_GPAI_NAME);
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
ret = rt_adc_enable(gpai_dev, chan);
|
|
|
|
|
if (ret) {
|
|
|
|
|
rt_kprintf("Failed to enable %s device\n", AIC_GPAI_NAME);
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (count < ADC_TEST_DATA_COUNT) {
|
|
|
|
|
current_irq_count = rt_adc_control(gpai_dev, RT_ADC_CMD_IRQ_COUNT,
|
|
|
|
|
(void *)chan);
|
2023-11-30 19:48:02 +08:00
|
|
|
if (current_irq_count < 0) {
|
|
|
|
|
rt_kprintf("Failed to get irq count\n");
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
2023-11-09 20:19:51 +08:00
|
|
|
cur = rt_adc_read(gpai_dev, chan);
|
|
|
|
|
if (current_irq_count == cur_data_count) {
|
|
|
|
|
g_cur_data[count] = cur;
|
|
|
|
|
count++;
|
|
|
|
|
cur_data_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:48:02 +08:00
|
|
|
for (i = 0; i < ADC_DM_SRAM_SIZE / GPAI_AVG_SAMPLES_NUM; i++) {
|
|
|
|
|
g_expect_data[i] = average(&g_sram_data[i * GPAI_AVG_SAMPLES_NUM],
|
|
|
|
|
GPAI_AVG_SAMPLES_NUM, 0);
|
2023-11-09 20:19:51 +08:00
|
|
|
}
|
2023-11-30 19:48:02 +08:00
|
|
|
gpai_check_adc_by_cpu();
|
2023-11-09 20:19:51 +08:00
|
|
|
|
|
|
|
|
rt_adc_disable(gpai_dev, chan);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:48:02 +08:00
|
|
|
static void gpai_dma_callback(void *arg)
|
|
|
|
|
{
|
|
|
|
|
rt_kprintf("dma callback happened\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gpai_check_adc_by_dma(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int *dma_data = (int *)dma_info.buf;
|
|
|
|
|
|
|
|
|
|
for(i = 0; i < ADC_TEST_DATA_COUNT; i++) {
|
|
|
|
|
if (dma_data[i] != g_expect_data[i])
|
|
|
|
|
printf("[%d] Failed%d/%d\n", i, dma_data[i], g_expect_data[i]);
|
|
|
|
|
else
|
|
|
|
|
printf("[%d] OK! %d/%d\n",i, dma_data[i], g_expect_data[i]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int gpai_get_adc_by_dma(int chan)
|
|
|
|
|
{
|
|
|
|
|
int ret;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
gpai_dev = (rt_adc_device_t)rt_device_find(AIC_GPAI_NAME);
|
|
|
|
|
if (!gpai_dev) {
|
|
|
|
|
rt_kprintf("Failed to open %s device\n", AIC_GPAI_NAME);
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = rt_adc_enable(gpai_dev, chan);
|
|
|
|
|
if (ret) {
|
|
|
|
|
rt_kprintf("Failed to enable %s device\n", AIC_GPAI_NAME);
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dma_info.chan_id = chan;
|
|
|
|
|
dma_info.buf = g_adc_buf;
|
|
|
|
|
dma_info.buf_size = sizeof(g_adc_buf);
|
|
|
|
|
dma_info.callback = gpai_dma_callback;
|
|
|
|
|
|
|
|
|
|
ret = rt_adc_control(gpai_dev, RT_ADC_CMD_CONFIG_DMA, &dma_info);
|
|
|
|
|
if (ret) {
|
|
|
|
|
rt_kprintf("Failed to config dma\n");
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = rt_adc_control(gpai_dev, RT_ADC_CMD_GET_DMA_DATA, (void *)chan);
|
|
|
|
|
if (ret) {
|
|
|
|
|
rt_kprintf("Failed to get dma data\n");
|
|
|
|
|
return -RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ADC_DM_SRAM_SIZE / GPAI_AVG_SAMPLES_NUM; i++) {
|
|
|
|
|
g_expect_data[i] = average(&g_sram_data[i * GPAI_AVG_SAMPLES_NUM],
|
|
|
|
|
GPAI_AVG_SAMPLES_NUM, 0);
|
|
|
|
|
}
|
|
|
|
|
g_dma_mode = 0;
|
|
|
|
|
aicos_msleep(100);
|
|
|
|
|
gpai_check_adc_by_dma();
|
|
|
|
|
rt_adc_disable(gpai_dev, chan);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-09 20:19:51 +08:00
|
|
|
|
|
|
|
|
static void adc_dm_test(u32 chan)
|
|
|
|
|
{
|
|
|
|
|
u32 size = 0;
|
|
|
|
|
|
|
|
|
|
if (chan <= ADC_CHAN_GPAI11) {
|
|
|
|
|
gen_adc_data(&size);
|
|
|
|
|
hal_dm_chan_store(chan);
|
|
|
|
|
hal_adcdm_sram_write(g_sram_data, 0, ADC_DM_SRAM_SIZE);
|
2023-11-30 19:48:02 +08:00
|
|
|
|
|
|
|
|
if (g_dma_mode) {
|
|
|
|
|
rt_kprintf("Starting dma mode\n");
|
|
|
|
|
gpai_get_adc_by_dma(chan);
|
|
|
|
|
} else {
|
|
|
|
|
rt_kprintf("Starting cpu interrupt mode\n");
|
|
|
|
|
gpai_get_adc_by_cpu(chan);
|
|
|
|
|
}
|
2023-11-09 20:19:51 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-30 19:48:02 +08:00
|
|
|
static void cmd_test_adc(int argc, char **argv)
|
2023-11-09 20:19:51 +08:00
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
u32 ch = 0;
|
|
|
|
|
|
|
|
|
|
if (argc < 2) {
|
|
|
|
|
cmd_adcim_usage(argv[0]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
optind = 0;
|
|
|
|
|
while ((c = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
|
|
|
|
|
switch (c) {
|
|
|
|
|
case 'c':
|
|
|
|
|
ch = atoi(optarg);
|
|
|
|
|
if ((ch < 0) || (ch >= AIC_GPAI_CH_NUM))
|
|
|
|
|
pr_err("Invalid channel No.%s\n", optarg);
|
|
|
|
|
adc_dm_test(ch);
|
2023-11-30 19:48:02 +08:00
|
|
|
continue;
|
|
|
|
|
case 'm':
|
|
|
|
|
g_dma_mode = 1;
|
|
|
|
|
continue;
|
|
|
|
|
case 'v':
|
|
|
|
|
g_verbose = 1;
|
|
|
|
|
continue;
|
2023-11-09 20:19:51 +08:00
|
|
|
case 'h':
|
|
|
|
|
default:
|
|
|
|
|
cmd_adcim_usage(argv[0]);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MSH_CMD_EXPORT_ALIAS(cmd_test_adc, test_adc, adcim dm device sample);
|