免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3599 | 回复: 6
打印 上一主题 下一主题

请教at91rm9200读写SRAM(由FPGA定制生成)的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-12 14:25 |只看该作者 |倒序浏览
一块16KB的SRAM,由FPGA定制产生,挂载在数据总线BANk2。
SRAM主要用于存放临时大量待处理的数据,物理地址从0x30000000开始。
在网上找了些资料看了,说是用ioremap先把实际物理内存映射到内核空间,
再用mmap从内核空间映射到用户空间, 在用户空间对SRAM进行读写,提高处理速度。

驱动代码如下:

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/errno.h>
  4. #include <linux/mm.h>
  5. #include <linux/wrapper.h>  /* for mem_map_(un)reserve */
  6. #include <asm/io.h>          /* for virt_to_phys */
  7. #include <linux/slab.h>   /* for kmalloc and kfree */
  8. #include <linux/init.h>   /* __init __exit */
  9. #include <linux/ioport.h>   
  10. #include <asm/uaccess.h> /*copy_from_user */

  11. #define SRAM_STARTADD  ((volatile unsigned long*)0x30000000L)
  12. #define SRAM_SIZE  (0x400<<4) //16kB

  13. volatile  unsigned short * reserve_virt_addr16;
  14. static struct resource *iomap_wdt_mem=NULL;
  15. static int major=242;

  16. int mmapdrv_open(struct inode *inode, struct file *file);
  17. int mmapdrv_release(struct inode *inode, struct file *file);
  18. int mmapdrv_mmap(struct file *file, struct vm_area_struct *vma);
  19. int mmapdrv_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg) ;

  20. static struct file_operations mmapdrv_fops =
  21. {
  22.   owner:   THIS_MODULE,
  23.   mmap:    mmapdrv_mmap,
  24.   ioctl:      mmapdrv_ioctl,  
  25.   open:    mmapdrv_open,
  26.   release:   mmapdrv_release,
  27. };
  28. static int __init mmapdrv_init_module(void)
  29. {
  30. int ret;
  31.   if ( ( register_chrdev(major, "mmapdrv", &mmapdrv_fops) ) < 0 )
  32.     {
  33.       printk("mmapdrv: unable to register character device\n");
  34.       return (-EIO);
  35.     }
  36.   //printk("mmap device major = %d\n",major );
  37.   //printk( "high memory physical address %ldM\n",virt_to_phys(high_memory)/1024/1024 );

  38.     if(0 == check_mem_region(SRAM_STARTADD,SRAM_SIZE))  
  39.     {  
  40.                     printk("check_region oK\n");
  41.                         if((iomap_wdt_mem=request_mem_region(SRAM_STARTADD,SRAM_SIZE,"mmapdrv"))==NULL)
  42.                 {
  43.                         printk("failed to reserve memory region\n");
  44.                         ret = -ENOENT;
  45.                         goto err_nomap;
  46.                 }
  47.                 else
  48.                         printk("request_region oK\n");
  49.                
  50.                                
  51.     }  
  52.    else  
  53.    {  
  54.                 printk("iomap from 0x%x num %d busy\n",SRAM_STARTADD,SRAM_SIZE);  
  55.                 return -1;  
  56.     }  

  57.   reserve_virt_addr16 = (short *)ioremap( SRAM_STARTADD,SRAM_SIZE);

  58.   if ( reserve_virt_addr )
  59.   {
  60.   }
  61.   else
  62.     {
  63.       unregister_chrdev( major, "mmapdrv" );
  64.        printk("ioremap failed\n");  
  65.         ret = -EINVAL;
  66.         goto err_nomap;
  67.     }

  68.   return 0;
  69. err_nomap:
  70.   if(iomap_wdt_mem)
  71.         release_resource(iomap_wdt_mem);
  72. err_nores:
  73.         return ret;
  74.   
  75. }
  76. /* remove the module */
  77. static void __exit mmapdrv_cleanup_module(void)
  78. {
  79.   if ( reserve_virt_addr )
  80.     iounmap( (void *)reserve_virt_addr );
  81.   if(iomap_wdt_mem)
  82.         release_resource(iomap_wdt_mem);
  83.   unregister_chrdev( major, "mmapdrv" );
  84.   return;
  85. }
  86. int mmapdrv_open(struct inode *inode, struct file *file)
  87. {
  88.   MOD_INC_USE_COUNT;
  89.   return(0);
  90. }
  91.   
  92. int mmapdrv_release(struct inode *inode, struct file *file)
  93. {
  94.   MOD_DEC_USE_COUNT;
  95.   return(0);
  96. }


  97. #define IOMAP_WRITE1 1
  98. #define IOMAP_WRITE2 2
  99. #define IOMAP_READ1  3
  100. #define IOMAP_READ2  4
  101. int mmapdrv_ioctl(struct inode *inode, struct file *file,unsigned int cmd, unsigned long arg)
  102. {
  103.         static int i=0;
  104.         switch(cmd)
  105.         {
  106.                 case IOMAP_WRITE1:
  107.                         {
  108.                                 for(i=0;i<10;i++)
  109.                                 {
  110.                                 *(reserve_virt_addr16+i)=0x55+i;

  111.                                 }
  112.                         }
  113.                         break;
  114.                 case IOMAP_WRITE2:
  115.                         {
  116.                                 short buf[10];
  117.                                 for(i=0;i<10;i++)
  118.                                 {
  119.                                 buf[i]=0x55+i;
  120.                                 }
  121.                                 memcpy(reserve_virt_addr16,buf,10*sizeof(short));
  122.                         }
  123.                         break;
  124.                 case IOMAP_READ1:
  125.                                   {
  126.                                       int i,j;
  127.                                       for ( i=0;i<10;i++)
  128.                                       {
  129.                                            //printk("[%d]:%d\n",i,reserve_virt_addr16[i]);
  130.                                            j=*(unsigned short *)(reserve_virt_addr16+i);
  131.                                           
  132.                                       }
  133.                                  }
  134.                           break;
  135.                 case IOMAP_READ2:
  136.                                 {
  137.                                       short buf[10];
  138.                                       memcpy(buf,reserve_virt_addr16,10*sizeof(short));
  139.                                        
  140.                                 }
  141.                         break;
  142.                 default:
  143.                         printk("default:%d\n",cmd);
  144.                         break;
  145.                
  146.         }
  147.         return 0;
  148.        
  149. }

  150. int mmapdrv_mmap(struct file *file, struct vm_area_struct *vma)
  151. {
  152.   unsigned long offset = vma->vm_pgoff<<PAGE_SHIFT;
  153.   unsigned long size = vma->vm_end - vma->vm_start;

  154.   if ( size > SRAM_SIZE )
  155.     {
  156.       printk("size too big\n");
  157.       return(-ENXIO);
  158.     }
  159.    
  160. if (offset >= __pa(high_memory)||file->f_flags & O_SYNC)
  161. {
  162.         vma->vm_flags |= VM_IO;//设置vm_flags标记为VM_IO,将VMA标记为一个内存映射的I/O区域
  163. }

  164. vma->vm_flags |= VM_RESERVED;//VM_RESERVED标记内存区域不能被换出
  165.        
  166. //vma->vm_flags |= VM_LOCKED;
  167.   offset = offset + SRAM_STARTADD;
  168.   /* we do not want to have this area swapped out, lock it */
  169.   if ( remap_page_range(vma->vm_start,offset,size,PAGE_SHARED))
  170.     {
  171.       printk("remap page range failed\n");
  172.       return -ENXIO;
  173.     }
  174.   
  175.   return(0);
  176. }

  177. MODULE_PARM(SRAM_STARTADD,"i");
  178. MODULE_PARM(SRAM_SIZE,"i");
  179. module_init(mmapdrv_init_module);  
  180. module_exit(mmapdrv_cleanup_module);  

  181. MODULE_AUTHOR ("");  
  182. MODULE_DESCRIPTION ("");  
  183. MODULE_LICENSE("GPL");  
  184. //-----------------------------------------------------------------
  185. 测试代码:
  186. #include <stdio.h>
  187. #include <fcntl.h>
  188. #include <sys/mman.h>

  189. #define DEV_FILE "/dev/mmapdrv"

  190. #define SRAM_STARTADD 0x30000000
  191. #define SRAM_SIZE (0x400<<4) //16kB
  192. #define MMAP_SIZE (1*1024)
  193. #define IOMAP_WRITE1 1
  194. #define IOMAP_WRITE2 2
  195. #define IOMAP_READ1  3
  196. #define IOMAP_READ2  4
  197. int test(int fd ,int cmd,int data)
  198. {
  199.         if(ioctl(fd,cmd,(void *)&data)<0)
  200.         {
  201.                 printf("ioctl failed\n");
  202.                 return -1;
  203.         }
  204.         return 0;
  205. }
  206. int main(int argc ,char **argv)
  207. {
  208. int fd;
  209. int i;
  210. if(argc<2)
  211. {
  212.         return -1;
  213. }
  214. fd = open(DEV_FILE, O_RDWR);
  215. if(!strcmp(argv[1], "-W1"))
  216. {
  217.         test(fd,IOMAP_WRITE1,0);
  218. }
  219. else if(!strcmp(argv[1], "-W2"))
  220. {
  221.         test(fd,IOMAP_WRITE2,0);
  222. }
  223. else if(!strcmp(argv[1], "-R1"))
  224. {
  225.         test(fd,IOMAP_READ1,0);
  226. }
  227. else if(!strcmp(argv[1], "-R2"))
  228. {
  229.         test(fd,IOMAP_READ2,0);
  230. }
  231. else if(!strcmp(argv[1], "-MMAP"))
  232. {
  233.         unsigned short* vadr=NULL;
  234.         vadr = (short*)mmap(NULL, MMAP_SIZE, PROT_READ|PROT_WRITE , MAP_SHARED, fd, 0);
  235.         if (vadr == MAP_FAILED)
  236.         {
  237.         perror("mmap");
  238.         exit(-1);
  239.         }
  240.         for(i=0;i<10;i++)
  241.         {
  242.         *(unsigned short *)(vadr+i)=0xAA+i;
  243.         }
  244.         printf("\n");
  245.        
  246.         for(i=0;i<10;i++)
  247.         {
  248.         printf("[0x%x]",*(unsigned short *)(vadr+i));
  249.         }
  250.         printf("\n");
  251.         munmap(vadr, MMAP_SIZE);
  252. }
  253. else
  254. {
  255.         printf("error\n");
  256. }

  257. close(fd);
  258. return 0;
  259. }
复制代码

//-----------------------
其中的SRAM是由FPGA定制生成的。
上面对SRAM物理地址的ioremap映射的过程是正确的,
在/proc/iomem中可以查看到映射的物理地址段。
借助FPGA软件可以查看到在内核空间一次写一个字节写数据的时候,片选,地址,写信号线都是正确的,
但是当每次写许多个字节数据的时候,时而出现写信号不对的情况。对SRAM读操作的,不管一次读一个数据还是一次读多个数据信号线都是错误的。
如:
reserve_virt_addr16 = ioremap( SRAM_STARTADD,SRAM_SIZE);
在内核空间写数据操作:
1)这种方式写:分析软件参看正常
int i;
for(i=0;i<10;i++)
*(reserve_virt_addr16+i) =(short)i;
2)这种方式写:分析软件参看出现信号不对
short buf[100];
int i;
for(i=0;i<10;i++)
buf=(short)i;
memcpy(reserve_virt_addr,buf,100*sizeof(char));
在内核空间读数据操作
3)一次读一个:
short c;
int i;
for(i=0;i<10;i++)
c=*(reserve_virt_addr16+i);
4)一次读多个数据:
memcpy(buf,reserve_virt_addr16,100);

5)把SRAM从内核空间用mmap()映射到应用层进行写操作,采用1)或2)方式的写操作,还是3)或4)方式的读操作,软件分析查看都是错误的
请大家帮帮忙啊,为什么会出现上述的不同情况?
6)上面采用不同方式的读写造成时序的变化,是否跟EBI_SMC2_CSR寄存器配置有关,又如何配置该寄存器值?


[ 本帖最后由 cth2008 于 2009-6-12 15:38 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-06-12 15:26 |只看该作者

回复 #1 cth2008 的帖子

help help

论坛徽章:
0
3 [报告]
发表于 2009-06-13 19:27 |只看该作者
太多了,看花眼了, 你先不要MMAP 看看读写数据对不对, 然后再使用MMAP

论坛徽章:
0
4 [报告]
发表于 2009-06-14 22:48 |只看该作者

回复 #3 star316 的帖子

我在内核先对物理地址映射后的虚拟地址进行读写测试,发现用内核提供的读写函数:
unsigned readb(address);
unsigned readw(address);
unsigned readl(address);
void writeb(unsigned value, address);
void writew(unsigned value, address);
void writel(unsigned value, address);
操作,读写正常。
那为什么不能用下面的读写方法呢?
好像只有1)可以
reserve_virt_addr16 = ioremap( SRAM_STARTADD,SRAM_SIZE);
1)这种方式写:分析软件参看正常
int i;
for(i=0;i<10;i++)
*(reserve_virt_addr16+i) =(short)i;
2)这种方式写:分析软件参看出现信号不对
short buf[100];
int i;
for(i=0;i<10;i++)
buf=(short)i;
memcpy(reserve_virt_addr,buf,100*sizeof(char));
在内核空间读数据操作
3)一次读一个:
short c;
int i;
for(i=0;i<10;i++)
c=*(reserve_virt_addr16+i);
4)一次读多个数据:
memcpy(buf,reserve_virt_addr16,100);

论坛徽章:
0
5 [报告]
发表于 2009-06-14 23:04 |只看该作者

回复 #3 star316 的帖子

用2)3)4)方式的读写操作,数据流时而有,时而无,没有规律

论坛徽章:
0
6 [报告]
发表于 2009-06-16 09:04 |只看该作者
somebody help ?

论坛徽章:
0
7 [报告]
发表于 2009-06-16 16:25 |只看该作者
学习了~~~~~~~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP