Linux创建线程读取双口数据,linux环境下读写一次双口ram尽然要十几个毫秒。(附驱动代码)...
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
您可能感興趣的文章:
總結
以上是生活随笔為你收集整理的Linux创建线程读取双口数据,linux环境下读写一次双口ram尽然要十几个毫秒。(附驱动代码)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux编译openssl报错,alp
- 下一篇: linux 校园网开启wifi共享,Li