Linux创建线程读取双口数据,linux环境下读写一次双口ram尽然要十几个毫秒。(附驱动代码)...

博主在Linux环境下遇到IDT70V28双口RAM读写速度异常慢的问题,实际操作耗时达到十几到几十毫秒,远超手册上纳秒级的预期。驱动代码显示读写函数通过点IO方式访问,且存在多线程访问冲突。博主已尝试调试两周,但未找到问题根源。驱动程序包括ioctl、read、write、open及release函数,通过字符设备接口操作双口RAM。
摘要由CSDN通过智能技术生成

linux环境下读写一次双口ram尽然要十几个毫秒。(附驱动代码)

我用的双口ram是IDT70V28,手册上说的读写时间应该是几个纳秒,我写了个linux驱动,然后做测试,发现读写一次的时间尽然是十几个到几十个毫秒!(通过点IO管脚,用示波器看),而且不能在多个线程访问双口ram(访问不同的地址都不行!)。并且读写数据的时间基本和读写数据的长度没有太多关系,只是和读写次数关系非常明显。

搞了两个星期,也没有找到问题,请高人指点!谢谢帮忙

//以下为驱动程序全文

#include

#include

#include

#include //必须

#include

#include

#undef DPRINTK                               /* undef it, just in case */

#ifdef SDRAM_DEBUG

/* This one if debugging is on, and kernel space */

#define DPRINTK(fmt, args...) printk("can: "fmt, ## args)

#else

#define DPRINTK(fmt, args...) /* not debugging: nothing */

#endif

//定义双口RAM字符设备结构

typedef struct _sdram_dev

{

struct cdev chrdev;

unsigned short * data_addr;                  //数据口

unsigned int data_max;

unsigned int user_idx;

}sdram_dev,*sdram_dev_t;

//全局变量,常量;

static int sdram_major=0;

static struct class* sdram_class;

unsigned int SDRAM_offset=0;

#define DSDRAM_NAME             "double_sdram"

#define DATA_EBI_BASE_ADDRESS   (0x20000000)

#define ADDR_SDRAM_SIZE         (128*1024)

//SDRAM设备指针

static sdram_dev_t DSdram_dev;

//设备指针

static struct platform_device* DSdram_devices = NULL;

//BANK配置

void init_bank_board(void)

{

//bank 2 is set to 16-bit

__raw_writel(0x1000ffef,SMCBCR2);

DPRINTK("GPIO_AINTTYPE1=0x%xrn",__raw_readl(GPIO_AINTTYPE1));

DPRINTK("GPIO_AINTTYPE2=0x%xrn",__raw_readl(GPIO_AINTTYPE2));

}

//**********************************************************

//ioctl函数:

//**********************************************************

static int dsdram_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)

{

SDRAM_offset=arg;

//printk("Set Offset :0x%x rn",SDRAM_offset);

return 0;

}

//write函数

static ssize_t dsdram_write(struct file* file, const char *buffer, size_t length,loff_t* loff)

{

unsigned short *data_addr = NULL;

if (length > ADDR_SDRAM_SIZE) {

printk("Reading more than 128K bytes data, this is not supported.n");

printk("Defaulting to 128K bytes data.n");

length = ADDR_SDRAM_SIZE;

}

//length = length/2;

data_addr = (DSdram_dev->data_addr)+SDRAM_offset;

if(copy_from_user(data_addr, (unsigned short *)buffer, length))

return -EFAULT;

SDRAM_offset=0;

return (length);

}

//读函数

ssize_t dsdram_read(struct file *file, char *buffer, size_t length, loff_t *offset)

{

unsigned short *data_addr = NULL;

if (length > ADDR_SDRAM_SIZE) {

printk("Reading more than 128K bytes data, this is not supported.n");

printk("Defaulting to 128K bytes data.n");

length = ADDR_SDRAM_SIZE;

}

//length = length/2;

data_addr = (DSdram_dev->data_addr)+SDRAM_offset;

if(copy_to_user((unsigned short *)buffer, data_addr, length))

return -EFAULT;

SDRAM_offset=0;

return (length);

}

//open 函数

static int dsdram_open(struct inode *inode, struct file *file)

{

sdram_dev_t hdev = NULL;

hdev = DSdram_dev;

if(++hdev->user_idx == 1)

{

//申请内存区域,以检测该地址空间是否被使用;

if (!request_mem_region(DATA_EBI_BASE_ADDRESS,ADDR_SDRAM_SIZE,DSDRAM_NAME))

printk("Error request mem address for 0x20000000 ! rn");

hdev->data_addr = (unsigned short*)ioremap(DATA_EBI_BASE_ADDRESS,ADDR_SDRAM_SIZE);

hdev->data_max  = ADDR_SDRAM_SIZE;

}

DPRINTK("open succeednr");

return 0;

}

//release函数

static int  dsdram_release(struct inode *inode, struct file *file)

{

sdram_dev_t hdev=NULL;

hdev = DSdram_dev;

if(--hdev->user_idx == 0)

{

//取消内存区域映射;

iounmap((unsigned short *)hdev->data_addr);

//释放申请的内存区域;

release_mem_region(DATA_EBI_BASE_ADDRESS,ADDR_SDRAM_SIZE);

}

return 0;

}

//文件操作函数结构

struct file_operations dsdram_fops=

{

.owner      =   THIS_MODULE,

.read       =   dsdram_read,

.write      =   dsdram_write,

.ioctl      = dsdram_ioctl,

.open       =   dsdram_open,

.release    =   dsdram_release,

};

//系统探测函数

static int __devinit dsdram_probe(struct platform_device *pdev)

{

int ret;

dev_t dev_id;

struct class_device* cls_sdram_dev;

sdram_dev_t hdev;

printk("device %s-%d detected!n", pdev->name, pdev->id);

//config gpio and bank

init_bank_board();

DSdram_dev = hdev = kmalloc(sizeof(sdram_dev), GFP_KERNEL);

dev_id = MKDEV(sdram_major, 0);

pdev->dev.devt = dev_id;

cdev_init(&hdev->chrdev, &dsdram_fops);

hdev->chrdev.owner = THIS_MODULE;

hdev->user_idx = 0;

ret = cdev_add(&hdev->chrdev, dev_id, 1);

if (ret)

{

printk("fail to register driver for " DSDRAM_NAME "%d!n", pdev->id);

return ret;

}

platform_set_drvdata(pdev, hdev);

cls_sdram_dev = class_device_create(sdram_class,NULL,dev_id,&pdev->dev,

DSDRAM_NAME);

if (IS_ERR(cls_sdram_dev))

return PTR_ERR(cls_sdram_dev);

printk("driver for "DSDRAM_NAME" registeredn");

return ret;

}

static int __devexit dsdram_remove(struct platform_device *pdev)

{

sdram_dev_t hdev;

class_device_destroy(sdram_class, pdev->dev.devt);

hdev = platform_get_drvdata(pdev);

if (hdev)

{

cdev_del(&hdev->chrdev);

kfree(hdev);

}

platform_set_drvdata(pdev, NULL);

pdev->dev.devt = 0;

printk(DSDRAM_NAME "removed!n");

return 0;

}

#ifdef CONFIG_PM

static int dsdram_suspend(struct platform_device *pdev, pm_message_t state)

{

return 0;

}

static int dsdram_resume(struct platform_device *pdev)

{

return 0;

}

#else

#define dsdram_suspend NULL

#define dsdram_resume NULL

#endif

static struct platform_driver dsdram_driver =

{

.probe      = dsdram_probe,

.remove     = __devexit_p(dsdram_remove),

#ifdef CONFIG_PM

.suspend    = dsdram_suspend,

.resume     = dsdram_resume,

#endif

.driver     =

{

.name   = DSDRAM_NAME,

.owner  = THIS_MODULE,

},

};

//*********************************************************

//初始化模块函数;

//*********************************************************

static int __init dousdram_init_module(void)

{

int ret;

dev_t dev = MKDEV(sdram_major, 0);

DSdram_devices = platform_device_alloc(DSDRAM_NAME, 0);

if (!DSdram_devices)

return -ENOMEM;

ret = platform_device_add(DSdram_devices);

if (ret

您可能感兴趣的文章:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值