当前位置: 技术问答>linux和unix
linux环境下读写一次双口ram尽然要十几个毫秒。(附驱动代码)
来源: 互联网 发布时间:2016-05-08
本文导语: linux环境下读写一次双口ram尽然要十几个毫秒。(附驱动代码) 我用的双口ram是IDT70V28,手册上说的读写时间应该是几个纳秒,我写了个linux驱动,然后做测试,发现读写一次的时间尽然是十几个到几十个毫秒!(通...
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
我用的双口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