4386|2

3414

帖子

0

TA的资源

纯净的硅(高级)

楼主
 

【SINA31s评测】NO.6 资源嗅探和GPIO操作 [复制链接]

趁周末,再更一贴

 

Linus saidso nvdiafxxk you
所以linux至今也不完美支持nvidia独立显卡
然后Linussaidthis whole ARM thing is a fxxking pain in the ass
所以linux又有了设备树device tree

设备树的使用过程

简单点理解就是用一个dtsi脚本文件,把外设资源按抬头集中进行预配置
需要使用某个外设资源的时候
就匹配这个外设的抬头,完成这个外设资源的分配
SINA31s有个很有意思的文件,叫sys_config.fex
其实和linux原生的dtsi异曲同工
都是用来按抬头分配硬件资源的脚本文件
文件里头按特定格式,对CPU所有外设进行了配置
比如

外设Twi1(貌似是IIC之类的外设,没有A31S的数据手册,不确定)的初始化信息就在这儿
调用脚本接口函数,就可以对外设Twi1进行匹配

获取到twi1 gpio的配置信息 下面这个是AW官方文档上介绍的脚本匹配函数

GPIO初始化所需要的信息,就填充在script_item_u list的某个子成员中
需要初始化的话,调用到GPIO初始化函数中就ok
大概就是这么个流程
撸几行代码调试看看
sys_config.fex文件中增加一个test_led的资源

使用默认1GPIO配置
补充一下
这个LED在原理图上是GPIOH13管脚

对应底板上的LED4

也就是status LED 编辑完配置文件后,编译内核,打包成img,烧掉

上内核代码

  1. #include "test.h" static int test_major = 0; static int test_minor = 0; #define led_gpio GPIOH(13) int user_data; static struct class *test_class = NULL; static struct device *test_dev = NULL; //static struct device *test_classdev[4]; static int test_drv_open(struct inode *inode, struct file *file) { test_minor = MINOR(inode -> i_rdev);//取出次设备号 printk(KERN_EMERG"test_drv_open,major=%d,minor=%d.....\n",test_major,test_minor); return 0; } static int test_drv_write(struct file *file,const char __user *buf,size_t count,loff_t* ppos) { int fd; printk(KERN_EMERG"test_drv_write.....\n"); fd = copy_from_user(&user_data,buf,count); // copy_to _user(); if(fd) {printk(KERN_EMERG"Got Nothings....\n");} else {printk(KERN_EMERG"Got user_data = %d..\n",user_data);} for(;user_data > 0;user_data--)//从用户空间获取blink次数 { gpio_direction_output(led_gpio,GPIOF_OUT_INIT_HIGH); printk(KERN_EMERG"LED 0n....\n"); mdelay(150); gpio_direction_output(led_gpio,GPIOF_OUT_INIT_LOW); printk(KERN_EMERG"LED off...\n"); mdelay(150); } return 0; } static int test_drv_release(struct inode* inode, struct file* filp) { printk("test_drv_release.....\r\n"); return 0; } static struct file_operations test_drv_fops = { .owner = THIS_MODULE, .open = test_drv_open, .write = test_drv_write, .release = test_drv_release, }; static int test_drv_init(void) { int err,i; script_item_u *val = NULL; script_item_value_type_e type; test_major = register_chrdev(0, "test_drv", &test_drv_fops);//动态分配系统主设备号 if(test_major == -EBUSY) { printk(KERN_EMERG"Device registed failed...\n"); } else{ printk(KERN_EMERG"Device registed sucess,major = %d\n",test_major ); } test_class = class_create(THIS_MODULE,"test_drv_class");//创建设备类 if(!IS_ERR(test_class)) { err = PTR_ERR(test_class); printk(KERN_ALERT"Sucess to create test class,ERR=%d.\n",err); } test_dev = device_create(test_class,NULL,MKDEV(test_major,0),NULL,"test_led");//创建设备 (单个设备) if(!IS_ERR(test_dev)) { err = PTR_ERR(test_dev); printk(KERN_ALERT"Sucess to create test device,ERR=%d.\n",err); } type = script_get_pio_list("test_led", &val); //获取test_led 外设资源和配置 if(type == 0) {printk(KERN_EMERG"Got item Error...\n");} else { printk(KERN_EMERG"test_led used %d gpio(s)\n",type);//打印GPIO数量 } script_dump_mainkey("test_led");//打印GPIO详细配置 for(i = 0; i < type; i++) { if(gpio_request(val[i].gpio.gpio, NULL) != 0) //申请外设资源 {printk(KERN_EMERG"test_led GPIO[%d] be Used...\n",i);} else {printk(KERN_EMERG"test_led GPIO[%d] request ok...\n",i);} if(sw_gpio_setall_range(&(val[i].gpio), i) != 0)//配置test_led外设 { printk(KERN_EMERG"test_led GPIO[%d] init failed...\n",i); } else {printk(KERN_EMERG"test_led GPIO[%d] init ok...\n",i);} } return 0; } static void test_drv_exit(void) { unregister_chrdev(test_major, "test_led");//注销系统设备号 device_destroy(test_class, MKDEV(test_major,0));//注销设备 单个 class_destroy(test_class);//注销设备类 gpio_direction_output(led_gpio,GPIOF_OUT_INIT_LOW); gpio_free(led_gpio);//释放资源 printk(KERN_EMERG"test_drv_exit.....\n"); } module_init(test_drv_init); module_exit(test_drv_exit); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("ljj3166");
复制代码

在调用匹配后的结构体填充驱动数之前
记得用gpio_request来申请一下资源

LCDPWM使用了这个管脚
如果不申请一下的话
驱动执行起来,轻则oops,重则paniccrush
 
写个应用程序测试一下

  1. #include <sys types.h=""> #include <sys stat.h=""> #include <string.h> #include <fcntl.h> #include <stdio.h> void print_usage(char *file)//用法 { printf(&quot;Usage:\n&quot;); printf(&quot;%s <dev> <num>\n&quot;,file); printf(&quot;eg. \n&quot;); printf(&quot;%s led 1\n&quot;, file); printf(&quot;%s led x\n&quot;, file); } int main(int argc,char** argv) { int fd; int val = 255; char filename[20] = &quot;/dev/test_&quot;; printf(&quot;hello,world!\n&quot;);//测试应用 if (argc != 3) //判断入口参数个数,错误则打印使用方法 { print_usage(argv[0]); return 0; } strcat(filename,argv[1]); fd = open(filename,O_RDWR); //打开对应设备 if (fd &lt; 0) {printf(&quot;open %s failed...\n&quot;,filename);} else {printf(&quot;open %s Ok...\n&quot;,filename);} val = atoi(argv[2]); printf(&quot;%d\n&quot;,val); write(fd, &amp;val, 4);//向驱动程序写入值 return 0; }
复制代码

基本就是测试从命令行获取LED blink的次数
看看运行状态
通过匹配fex文件中的配置insmod后
完成设备的和驱动的注册
并打印LED使用的GPIO的信息及初始化结果
执行应用程序后,Blink起来了
还有邪恶滴动图
到这...

 

最新回复

mark 紧跟大神  详情 回复 发表于 2016-10-23 22:54

赞赏

1

查看全部赞赏

点赞 关注
个人签名

So TM what......?


回复
举报

6423

帖子

16

TA的资源

版主

沙发
 
mark
 
个人签名training
 

回复

7172

帖子

195

TA的资源

五彩晶圆(高级)

板凳
 
mark 紧跟大神
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表