主题 : 请教版主,关于mmap系统调用 复制链接 | 浏览器收藏 | 打印
级别: 侠客
UID: 2177
精华: 0
发帖: 70
金钱: 620 两
威望: 463 点
综合积分: 140 分
注册时间: 2008-10-30
最后登录: 2015-01-12
楼主  发表于: 2009-06-06 21:04

 请教版主,关于mmap系统调用

最近在做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环境下应该使用何种方法实现呢?这个问题已经困扰了我好久,希望各位能够帮忙。
-
级别: 侠客
UID: 2177
精华: 0
发帖: 70
金钱: 620 两
威望: 463 点
综合积分: 140 分
注册时间: 2008-10-30
最后登录: 2015-01-12
1楼  发表于: 2009-07-15 20:31
问题解决了,去除触摸屏驱动即可
-
级别: 新手上路
UID: 31873
精华: 0
发帖: 6
金钱: 30 两
威望: 6 点
综合积分: 12 分
注册时间: 2010-11-06
最后登录: 2017-09-13
2楼  发表于: 2010-11-15 08:56
不去除触摸屏的驱动不行吗