首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

(转)ok6410学习笔记(10.硬件访问之led控制1)

(转)ok6410学习笔记(10.硬件访问之led控制1)

在对于led控制驱动方式上,我看见了6种方式:
在用户空间角度上说有两种:1.mmap驱动自己写的设备,来把物理地址映射到用户空间。
2.mmap驱动linux内核提供的mem设备,来把物理地址映射到用户空间。
在内核空间角度上说有四种:1.ioremap的字符设备驱动中或者在混杂设备驱动中的应用,把物理地址映射到内核空间。
2.在不管是国嵌的移植好的内核,还是飞凌移植好的内核中,在/driver/char中都有飞凌写好的驱动,直接调用这个第三方驱动。
3.在linux内核中其实系统早就把地址映射到了内核空间,我们的ioremap只是重新映射了一边,所有我们也可以直接操作这些地址,linux有对S3c6410和S3c2440的映射,还把对2440的gpio操作方法进行了封装。
4.I/O内存静态映射,是在宋保华linux设备驱动中的11.5章的 没有尝试过,不是很了解。

mmap自己的驱动见前面 mmap控制led的那节mem设备:[cpp] view plaincopy


  • /*利用linux自身的设备驱动 mem设备进行 用户空间和物理地址的映射*/
  • #include <stdio.h>
  • #include <stdlib.h>
  • #include <string.h>
  • #include <unistd.h>
  • #include <sys/types.h>
  • #include <sys/stat.h>
  • #include <sys/mman.h>
  • #include <fcntl.h>

  • #define uint unsigned int
  • #define uchar unsigned char
  • void delay(volatile unsigned int time)  
  • {  
  •     volatile unsigned int x,y;  
  •     for(x=0;x<2000;x++)  
  •         for(y=0;y<time;y++);  
  • }  

  • int main()  
  • {  
  •             int fd;  
  •             int i;  
  •             volatile unsigned char *map;  
  •             volatile unsigned int *GPMCON;  
  •             volatile unsigned int *GPMDAT;  
  •             volatile unsigned int *GPMPUD;  
  •             char buf[100];  
  •             if(-1==(fd=open ("/dev/mem", O_RDWR)))  //要利用mem设备
  •                      {  
  •                     printf("open dev0 error\n");  
  •                     _exit(EXIT_FAILURE);  
  •                 }  
  •             /*这个过程是在mem驱动中完成的  map传递的物理地址是通过vma->vm_pgoff即偏移量进行传递的*/
  •             /*但是这里PAGE_SHIFT的问题不知道解决没有   不行就用0x7f008000地址进行传递吧*/
  •          map = (volatile unsigned char*)mmap(NULL,1024*5, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x7f008000);  
  •              if(map == NULL)  
  •                 {  
  •                 printf("mmap err!\n");  
  •                 return 0;  
  •             }     
  •             /*GPMCON=(volatile unsigned int*)(map+0x0);
  •             GPMDAT=(volatile unsigned int*)(map+0x04);
  •             GPMPUD=(volatile unsigned int*)(map+0x08);*/

  •             GPMCON=(volatile unsigned int*)(map+0x820);  
  •             GPMDAT=(volatile unsigned int*)(map+0x824);  
  •             GPMPUD=(volatile unsigned int*)(map+0x828);  

  •                 *GPMCON&=~0xffff;  
  •             *GPMCON|=0x1|(0x1<<4)|(0x1<<8)|(0x1<<12);  
  •             *GPMDAT|=0xf;   
  •             printf("init is finishing!\n");  
  •         while(1)  
  •             {  
  •                 for(i=0;i<4;i++)  
  •                 {  
  •                     *GPMDAT=~(1<<i);  
  •                     delay(1500);  
  •                 }  
  •             }  
  •       munmap((char*)map,1024*5);                 
  •         close(fd);  
  • }  

注意:1.物理地址的参数传递是通过vma->vm_pgoff进行的


   2.貌似还存在PAGE_SHIFT的问题 我试了0x7f008820地址 不行。
此应用程序的驱动在\drivers\char\mem.c里面

[cpp] view plaincopy


  • static ssize_t write_mem(struct file *file, const
    char __user *buf,  
  •              size_t count, loff_t *ppos)  
  • {  
  •     unsigned long p = *ppos;  
  •     ssize_t written, sz;  
  •     unsigned long copied;  
  •     void *ptr;  

  •     if (!valid_phys_addr_range(p, count))  
  •         return -EFAULT;  

  •     written = 0;  

  • #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
  •     /* we don't have page 0 mapped on sparc and m68k.. */
  •     if (p < PAGE_SIZE) {  
  •         sz = size_inside_page(p, count);  
  •         /* Hmm. Do something? */
  •         buf += sz;  
  •         p += sz;  
  •         count -= sz;  
  •         written += sz;  
  •     }  
  • #endif

  •     while (count > 0) {  
  •         sz = size_inside_page(p, count);  

  •         if (!range_is_allowed(p >> PAGE_SHIFT, sz))  
  •             return -EPERM;  

  •         /*
  •          * On ia64 if a page has been mapped somewhere as uncached, then
  •          * it must also be accessed uncached by the kernel or data
  •          * corruption may occur.
  •          */
  •         ptr = xlate_dev_mem_ptr(p);  
  •         if (!ptr) {  
  •             if (written)  
  •                 break;  
  •             return -EFAULT;  
  •         }  

  •         copied = copy_from_user(ptr, buf, sz);  
  •         unxlate_dev_mem_ptr(p, ptr);  
  •         if (copied) {  
  •             written += sz - copied;  
  •             if (written)  
  •                 break;  
  •             return -EFAULT;  
  •         }  

  •         buf += sz;  
  •         p += sz;  
  •         count -= sz;  
  •         written += sz;  
  •     }  

  •     *ppos += written;  
  •     return written;  
  • }  


http://blog.csdn.net/mbh_1991/article/details/9063267
返回列表