PROC文件系统介绍 &&以PROC在线调试LCM && EXPORT_SYMBOL的用法

proc文件系统是一个伪文件系统,它只存在内存当中,而不占用外存空间。它以文件系统的方式为访问系统内核数据的操作提供接口。用户和应用程序可以通过proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息,如进程,是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。它的目录结构包括普通常用目录和数字命名目录:

(1) 用户如果要查看系统信息,可以用cat命令。例如:# cat /proc/interrupts 。

apm :高级电源管理信息

cmdline :内核命令行

Cpuinfo :关于Cpu信息

Devices :可以用到的设备(块设备/字符设备),可通过cat /proc/devices得到主设备号和设备名 

Dma :使用的DMA通道

Filesystems :支持的文件系统

Interrupts :中断的使用

Ioports I/O:端口的使用

Kcore :内核核心印象

Kmsg :内核消息

Ksyms :内核符号表

Loadavg :负载均衡

Locks :内核锁

Meminfo :内存信息

Misc :杂项

Modules :加载模块列表

Mounts :加载的文件系统

Partitions :系统识别的分区表

Rtc :实时时钟

Slabinfo Slab:池信息

Stat :全面统计状态表

Swaps :对换空间的利用情况

Version :内核版本

Uptime :系统正常运行时间

     并不是所有这些目录在你的系统中都有,这取决于你的内核配置和装载的模块。另外,在/proc下还有三个很重要的目录:net,scsi和sys。 Sys目录是可写的,可以通过它来访问或修改内核的参数来优化你的系统。但是你必须很小心,因为可能会造成系统崩溃。而net和scsi则依赖于内核配置。例如,如果系统不支持scsi,则scsi 目录不存在。

(2)除了以上介绍的这些,还有的是一些以数字命名的目录,它们是进程目录。系统中当前运行的每一个进程都有对应的一个目录在/proc下,以进程的 PID号为目录名,它们是读取进程信息的接口。而self目录则是读取进程本身的信息接口,是一个link。Proc文件系统的名字就是由之而起。每个进程目录的结构如下:

目录名称 目录内容

Cmdline 命令行参数

Environ 环境变量值

Fd 一个包含所有文件描述符的目录

Mem 进程的内存被利用情况

Stat 进程状态

Status 进程当前状态,以可读的方式显示出来

Cwd 当前工作目录的链接

Exe 指向该进程的执行命令文件

Maps 内存映象

Statm 进程内存状态信息

Root 链接此进程的root目录

(3)正因为采用PROC可以访问linux的内核设备信息,可以采用此种方式在线调试LCM。

       A,首先在帧缓冲驱动中创建proc文件系统。头文件申明:

  1. #define LCM_ONLINE_TUNNING  
  2. #if  defined (LCM_ONLINE_TUNNING)  
  3. #include <linux/proc_fs.h>   //proc file use   
  4. #endif  

       B,外部申明Proc的读写函数

  1. #if defined (LCM_ONLINE_TUNNING)  
  2. extern int  LCM_HW_DumpReg_To_Proc(char *page, char **start, off_t off,int count, int *eof, void *data);  
  3. extern int  LCM_HW_Reg_Debug( struct file *file, const char *buffer, unsigned long count,void *data);  
  4. #endif   

       C,在帧缓冲的PROBE函数中,创建PROC。

  1. #if defined (LCM_ONLINE_TUNNING)  
  2. struct proc_dir_entry *prEntry;  
  3.       prEntry = create_proc_entry("driver/lcm", 0, NULL);   //在/proc创建路径  
  4.       if (prEntry) {  
  5.         prEntry->read_proc = LCM_HW_DumpReg_To_Proc;   
  6.         prEntry->write_proc = LCM_HW_Reg_Debug;   
  7.      }  
  8.      else {  
  9.         printk("add /proc/driver/lcm entry fail \n");    
  10.      }  
  11. #endif  

       D,在AP显示驱动中添加读写函数原型

  1. #define LCM_ONLINE_TUNNING  
  2. #if defined (LCM_ONLINE_TUNNING)  
  3. #include <linux/uaccess.h>  
  4. #endif  

      E,proc写函数原型

  1. #if defined (LCM_ONLINE_TUNNING)  
  2. int  LCM_HW_DumpReg_To_Proc(char *page, char **start, off_t off,int count, int *eof, void *data)  
  3. {  
  4.     return count;  
  5. }  
  6. int  LCM_HW_Reg_Debug( struct file *file, const char *buffer, unsigned long count,void *data)  
  7. {  
  8.         char regBuf[512] = {'\0'} ;  
  9.     char temp[256]={0};   
  10.         u32 u4CopyBufSize = (count < (sizeof(regBuf) - 1)) ? (count) : (sizeof(regBuf) - 1);  
  11.     unsigned int RegAddr;  
  12.     unsigned int RegData[256];  
  13.     char *p = regBuf;  
  14.     int i = 0,param_count = 0;  
  15.   
  16.         if (copy_from_user(regBuf, buffer, u4CopyBufSize))  //读入echo的字符串  
  17.                   return -EFAULT;  
  18.         printk("param : %s\n",regBuf);      //打印echo的字符串  
  19.     sscanf(regBuf, "%2s",  temp) ;      //取regBuf的头两个字符存于temp中        
  20.         sscanf(temp, "%0x",  &RegAddr);     //格式化字符串的头两个字符,转成寄存器地址  
  21.     printk("cmd index : %0x",RegAddr);  
  22.         while((p = strchr(p,' ')) !=NULL)  {        //依次导入该地址要写入的数据  
  23.         p++;  
  24.         sscanf(p, "%2s",  temp);  
  25.         sscanf(temp, "%0x",  &RegData[i]);  
  26.         printk("Cmd data : %0x",RegData[i]);  
  27.         i++;  
  28.         param_count++;  
  29.         }  
  30.     i = 0;  
  31.     printk("param count : %d\n",param_count);  
  32.     lcm_utils.send_cmd(RegAddr) ;       //调用地址写入函数  
  33.     while(i < param_count) {  
  34.         lcm_utils.send_data(RegData[i]) ;   //调用数据写入函数  
  35.         i++;  
  36.     }  
  37.         return count;   
  38. }  
  39. #endif  

          F,调试语句:
如下,连上ADB后,可以单行调试,也可以一次写入多行。第一个是寄存器地址,后面的则是参数。

echo "f1 36 04 00 3c 0f 8f" > /proc/driver/lcm

echo "f2 18 A3 12 02 72 32 FF 12 00" > /proc/driver/lcm

echo "f8 21 04" > /proc/driver/lcm

echo "f9 00 08" > /proc/driver/lcm

echo "36 48" > /proc/driver/lcm

echo "b4 02" > /proc/driver/lcm

           G,DSI的写语句:

以上是DBI的在线调试方法,如果是DSI接口的,则用下面的语句把最后的发送指令及while循环替换掉即可。

lcm_utils.dsi_set_cmdq_V2(RegAddr,param_count,RegData,1);

=================================================================================================

        EXPORT_SYMBOL的一个用法,可以用来调试驱动。比如:在没有串口TRACE的情况下,无法验证一个模块的加载是否成功和加载结果,除了ADB TRACE外,没有其他好方法。但是ADB TRACE是有局限的,它只能显示部分TRACE信息。所以,一个好方法是将要验证的模块TRACE通过一个函数FUNC()用EXPORT_SYMBOL方式输出到内核符号表,在其他可以跑到的模块中输出该FUNC就行。

        比如:在C文件中完成一个信息输出函数,同时用EXPORT_SYMBOL申明。

Mma8452q.c (mediatek\custom\common\kernel\accelerometer\mma8452q):void Info_Printk()
Mma8452q.c (mediatek\custom\common\kernel\accelerometer\mma8452q):EXPORT_SYMBOL(Info_Printk);

        在确定可以加载的模块中,引用该函数。注意:要用extern 申明该函数,否则会报错。

Hwmsen_dev.c (mediatek\source\kernel\drivers\hwmon\hwmsen):extern void Info_Printk();
Hwmsen_dev.c (mediatek\source\kernel\drivers\hwmon\hwmsen): Info_Printk();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值