論壇徽章: 0
20 可用積分
linux環(huán)境下讀寫一次雙口ram盡然要十幾個(gè)毫秒。(附驅(qū)動(dòng)代碼)
我用的雙口ram是IDT70V28,手冊(cè)上說(shuō)的讀寫時(shí)間應(yīng)該是幾個(gè)納秒,我寫了個(gè)linux驅(qū)動(dòng),然后做測(cè)試,發(fā)現(xiàn)讀寫一次的時(shí)間盡然是十幾個(gè)到幾
十個(gè)毫秒。ㄍㄟ^(guò)點(diǎn)IO管腳,用示波器看),而且不能在多個(gè)線程訪問(wèn)雙口ram(訪問(wèn)不同的地址都不行!)。并且讀寫數(shù)據(jù)的時(shí)間基本和讀寫
數(shù)據(jù)的長(zhǎng)度沒(méi)有太多關(guān)系,只是和讀寫次數(shù)關(guān)系非常明顯。
搞了兩個(gè)星期,也沒(méi)有找到問(wèn)題,請(qǐng)高人指點(diǎn)!謝謝幫忙
//以下為驅(qū)動(dòng)程序全文
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/ioport.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/timer.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/arch/hardware.h> //必須
#include <asm/io.h>
#include <asm/irq.h>
#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字符設(shè)備結(jié)構(gòu)
typedef struct _sdram_dev
{
struct cdev chrdev;
unsigned short * data_addr; //數(shù)據(jù)口
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設(shè)備指針
static sdram_dev_t DSdram_dev;
//設(shè)備指針
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%x\r\n",__raw_readl(GPIO_AINTTYPE1));
DPRINTK("GPIO_AINTTYPE2=0x%x\r\n",__raw_readl(GPIO_AINTTYPE2));
}
//**********************************************************
//ioctl函數(shù):
//**********************************************************
static int dsdram_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)
{
SDRAM_offset=arg;
//printk("Set Offset :0x%x \r\n",SDRAM_offset);
return 0;
}
//write函數(shù)
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);
}
//讀函數(shù)
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 函數(shù)
static int dsdram_open(struct inode *inode, struct file *file)
{
sdram_dev_t hdev = NULL;
hdev = DSdram_dev;
if(++hdev->user_idx == 1)
{
//申請(qǐng)內(nèi)存區(qū)域,以檢測(cè)該地址空間是否被使用;
if (!request_mem_region(DATA_EBI_BASE_ADDRESS,ADDR_SDRAM_SIZE,DSDRAM_NAME))
printk("Error request mem address for 0x20000000 ! \r\n");
hdev->data_addr = (unsigned short*)ioremap(DATA_EBI_BASE_ADDRESS,ADDR_SDRAM_SIZE);
hdev->data_max = ADDR_SDRAM_SIZE;
}
DPRINTK("open succeed\n\r");
return 0;
}
//release函數(shù)
static int dsdram_release(struct inode *inode, struct file *file)
{
sdram_dev_t hdev=NULL;
hdev = DSdram_dev;
if(--hdev->user_idx == 0)
{
//取消內(nèi)存區(qū)域映射;
iounmap((unsigned short *)hdev->data_addr);
//釋放申請(qǐng)的內(nèi)存區(qū)域;
release_mem_region(DATA_EBI_BASE_ADDRESS,ADDR_SDRAM_SIZE);
}
return 0;
}
//文件操作函數(shù)結(jié)構(gòu)
struct file_operations dsdram_fops=
{
.owner = THIS_MODULE,
.read = dsdram_read,
.write = dsdram_write,
.ioctl = dsdram_ioctl,
.open = dsdram_open,
.release = dsdram_release,
};
//系統(tǒng)探測(cè)函數(shù)
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" registered\n");
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,
},
};
//*********************************************************
//初始化模塊函數(shù);
//*********************************************************
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 < 0) {
platform_device_put(DSdram_devices);
return ret;
}
/* Figure out our device number. */
if (sdram_major)
ret = register_chrdev_region(dev, 1, DSDRAM_NAME);
else
{
ret = alloc_chrdev_region(&dev, 0, 1, DSDRAM_NAME);
if (ret)
{
printk(KERN_WARNING "DSDRAM_MODULE_NAME: unable to get major %d\n", sdram_major);
return ret;
}
sdram_major = MAJOR(dev);
}
//create class
sdram_class = class_create(THIS_MODULE, DSDRAM_NAME);
if (IS_ERR(sdram_class))
return PTR_ERR(sdram_class);
ret = platform_driver_register(&dsdram_driver);
return ret;
}
//*********************************************************
//清除模塊函數(shù);
//*********************************************************
static void __exit dousdram_cleanup_module(void)
{
platform_driver_unregister(&dsdram_driver);
class_destroy(sdram_class);
unregister_chrdev_region(MKDEV(sdram_major, 0), 1);
platform_device_unregister(DSdram_devices);
DPRINTK("unregister driver " DSDRAM_NAME "\n");
}
module_init(dousdram_init_module);
module_exit(dousdram_cleanup_module);
MODULE_LICENSE("GPL");
我來(lái)回答