最近在做ad采样频率测试,在用户程序中调用ad驱动的read函数,ad采样频率大概只有1K左右,而我在ADS环境下测试ad采样频率时,频率可以达到100K以上,查看资料,发现驱动中的copy_to_user函数需要在用户空间和内核空间来回拷贝数据,花费了大量的时间,为了减少时间上的损失,可以采用mmap机制。然后我通过在用户程序中直接调用mmap,绕过驱动来对ad进行配置和读取,以下是我的程序代码:
#define S3C2410_ADCCON 0x00
#define S3C2410_ADCDAT0 0x0C
#define S3C2410_ADCCON_PRSCEN (1<<14) //启用ad预分频
#define S3C2410_ADCCON_PRSCVL(x) (((x)&0xFF)<<6) //预分频
#define S3C2410_ADCCON_SELMUX(x) (((x)&0x7)<<3) //选择ad通道
#define S3C2410_ADCCON_ENABLE_START (1<<0) //启动ad转换
#define START_ADC(ch, prescale) S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(prescale) \
| S3C2410_ADCCON_SELMUX(ch) | S3C2410_ADCCON_ENABLE_START
#define LOOP 10000
int main (void)
{
void *map_base;
volatile unsigned int *ADCCON;
volatile unsigned int *ADCDATA;
int fd;
FILE *stream;
unsigned long result = 0;
unsigned int data[LOOP];
unsigned long int i;
clock_t start, finish;
double duration;
if((fd=open("/dev/mem",O_RDWR|O_SYNC))<0)
{
perror("open:");
exit(1);
}
if( (stream = fopen("data_file", "a+")) == NULL )
{
printf("cant't not open file:data_file\n");
exit(1);
}
else
{
start = clock();
map_base = mmap(NULL,0x14,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0x58000000);
ADCCON = (volatile int*)(map_base + S3C2410_ADCCON);
ADCDATA = (volatile int*)(map_base + S3C2410_ADCDAT0);
for (i=0;i<LOOP;i++)
{
*ADCCON = START_ADC(0,255);
do
{
result = *ADCCON;
}
while((unsigned int)result & 0x01);
do
{
result = *ADCCON;
}
while(!(((unsigned int)result) & 0x8000));
data = (*ADCDATA) & 0x3ff;
fprintf(stream,"%d\n",data);
}
}
finish = clock();
duration = (double)( finish-start )/(double)CLOCKS_PER_SEC;
printf( "the duration time is %f\n",duration );
fclose(stream);
exit(0);
}
在用户空间循环读取10000个ad数据,结果用时18s多,比原先调用驱动的read函数所需的时间还长(原先大概是10s),而且我打开data_file中查看数据,发现有部分数据是错误的。现在的问题是,既然芯片本身可以达到100K以上的ad采样频率,我在linux环境下应该使用何种方法实现呢?这个问题已经困扰了我好久,希望各位能够帮忙。