ThanksView
|
RK3399为例-GPIO1_A0 在u-boot启动阶段的控制方法 //控制脚GPIO1_A0 32*1+8*0+0 = 32 一般u-boot对GPIO的控制有如下两种方法: 1,传统方式
2,地址映射方式
typedef volatile unsigned int u32;
基于 GPIO子系统的 IO口控制gpio 子系统 API 函数1、gpio_request 函数
gpio_request 函数用于申请一个 GPIO 管脚,在使用一个 GPIO 之前一定要使用 gpio_request int gpio_request ( unsigned gpio , const char *label ) 函数参数和返回值含义如下:
2、gpio_free 函数如果不使用某个 GPIO 了,那么就可以调用 gpio_free 函数进行释放。函数原型如下: void gpio_free ( unsigned gpio )
此函数用于设置某个 GPIO 为输入,函数原型如下所示: int gpio_direction_input ( unsigned gpio )
函数参数和返回值含义如下: gpio:要设置为输入的 GPIO 标号。 返回值:0,设置成功;负值,设置失败。4、gpio_direction_output 函数 此函数用于设置某个 GPIO 为输出,并且设置默认输出值,函数原型如下: int gpio_direction_output ( unsigned gpio , int value ) 函数参数和返回值含义如下: gpio:要设置为输出的 GPIO 标号。value:GPIO 默认输出值。 返回值:0,设置成功;负值,设置失败。 5、gpio_get_value 函数 此函数用于获取某个 GPIO 的值(0 或 1),此函数是个宏,定义所示: int __gpio_get_value(unsigned gpio)2 函数参数和返回值含义如下:
#
define
gpio_get_value
__gpio_get_value
int __gpio_get_value ( unsigned gpio ) gpio:要获取的 GPIO 标号。 返回值:非负值,得到的 GPIO 值;负值,获取失败。6、gpio_set_value 函数 此函数用于设置某个 GPIO 的值,此函数是个宏,定义如下
#
define
gpio_set_value
__gpio_set_value
void __gpio_set_value ( unsigned gpio , int value ) 函数参数和返回值含义如下: gpio:要设置的 GPIO 标号。 value:要设置的值。 返回值:无 关于 gpio 子系统常用的 API 函数就讲这些,这些是我们用的最多的。 GPIO子系统示例 读取按键 /* * @Copyright: * @FileNames: * @Description: 申请全局内存4096 并使用该内存进行 用户和内核之间的数据交换 * @Author: yangyue19@hikvision.com.cn * @Date: 2022-07-29 09:03:02 * @Version: V1.0 * @LastEditTime: 2022-08-05 16:51:03 */ #include <linux/module.h>//MOUDLE_XXX moudle_xxx #include <linux/fs.h> //file_operations register_chrdev_region alloc_chrdev_region #include <linux/init.h> //__init __exit #include <linux/cdev.h> //cdev #include <linux/uaccess.h>//copy_to_user copy_from_user #include <linux/device.h> // device class #include <linux/gpio.h> #define KEY_DEBUG 1 #define KEY_CLASS_NAME "key" //创建的类名称 #define KEY_NODE_NAME "key_0" //创建的节点名称 #define KEY_MAJOR 250 typedef struct { //设备驱动变量 struct cdev cdev; //设备号变量 dev_t devid; int major; int minor; //设备节点相关变量 struct class *class; struct device *device; //按键使用的GPIO编号 int key_index; //用户变量 //上一次读取的按键数值 int last_value; int value; }rtl_key_t; rtl_key_t key; /** * @function: key_open * @description: 打开设备 并将内存清零 * @input: * @output: * @return {*} * @param {inode} *inode * @param {file} *flip */ static int key_open(struct inode *inode ,struct file *flip) { flip->private_data=(void *)(&key); return 0; } /** * @function: key_release * @description: 释放设备节点 * @input: * @output: * @return {*} * @param {inode} *inode * @param {file} *flip */ static int key_release(struct inode *inode ,struct file *flip) { return 0; } /** * @function: key_read * @description: 拷贝数据到用户区 * @input: * @output: * @return {*} * @param {file*} flip 文件结构体 * @param {char __user} *buf 从用户区拷贝出来的数据 * @param {size_t} size 传入数据大小 * @param {loff_t} *ppos 当前数据位置 */ static ssize_t key_read(struct file* flip, char __user *buf,size_t size ,loff_t *ppos) { int ret=0; rtl_key_t* dev=(rtl_key_t*) flip->private_data; ret= gpio_get_value(dev->key_index); copy_to_user(buf,&ret,sizeof(ret)); return 4; } /** * @function: key_write * @description: * @input: * @output: * @return {*} * @param {file*} flip * @param {char __user} *buf * @param {size_t} size * @param {loff_t} *ppos */ static ssize_t key_write(struct file* flip, const char __user *buf,size_t size ,loff_t *ppos) { int ret=0; rtl_key_t* dev=(rtl_key_t*) flip->private_data; if(ret<0)ret=-EFAULT; else{ } return ret; } static const struct file_operations key_fops={ .owner=THIS_MODULE, .open=key_open, .release=key_release, .read=key_read, .write=key_write, }; /** * @function: static void key_setup_cdev(int minor_index) * @description: 根据一个从设备号生成cdev * @input: * @output: * @return {*} */ static void key_setup_cdev(int minor_index) { int ret; //得到设备号 int devno=MKDEV(key.major,minor_index); cdev_init(&key.cdev,&key_fops); key.cdev.owner=THIS_MODULE; ret=cdev_add(&key.cdev,devno,1); if(ret)printk(KERN_INFO"CDEV ADD ERROR:%d\n",minor_index); } /** * @function: key_init * @description: 申请设备号 并且注册cdev * @input: void * @output: * @return {*} */ static int __init key_init(void) { int ret; //如果定义了静态主设备号 就采用静态申请的方式 key.major=KEY_MAJOR; printk(KERN_INFO "KEY INIT\r\n"); key.key_index=58; gpio_request(key.key_index, "key"); ret = gpio_direction_input(key.key_index); if(ret<0)printk(KERN_INFO "CAN NOT SET PIN\n"); //得到需要注册的设备号 key.devid=MKDEV(key.major,key.minor); if(key.major!=0){//从devno 静态申请 一个设备号 ret=register_chrdev_region(key.devid,1,"key"); }else{//从devno 动态申请一个设备号 ret=alloc_chrdev_region(&key.devid,0,1,"key"); key.major=MAJOR(key.devid); key.minor=MINOR(key.devid); } if(KEY_DEBUG){ printk(KERN_INFO "major:%d\n",key.major); printk(KERN_INFO "minor:%d\n",key.minor); } key_setup_cdev(key.minor); //创建设备 创建类 key.class = class_create(THIS_MODULE, KEY_CLASS_NAME); key.device = device_create(key.class, NULL, key.devid, NULL, KEY_NODE_NAME); return 0; } module_init(key_init); static void __exit key_exit(void) { cdev_del(&key.cdev); unregister_chrdev_region(key.devid,1); gpio_free(key.key_index); //删除设备 删除类 device_destroy(key.class, key.devid); class_destroy(key.class); } module_exit(key_exit); MODULE_AUTHOR("YURI"); MODULE_LICENSE("GPL"); /* * @Copyright: * @FileNames: * @Description: * @Author: yangyue19@hikvision.com.cn * @Date: 2022-07-29 13:44:24 * @Version: V1.0 * @LastEditTime: 2022-08-05 17:06:38 */ #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #include <sys/ioctl.h> #define DEVICE_NAME "/dev/key" int main() { int i=0,ret=0,key=0; int fd=open(DEVICE_NAME,O_RDWR); if(ret<0)perror("open error"); while (1) { ret=read(fd,(void*)&key,4); printf("KEY VALUE:%d\n",key); sleep(1); } close(fd); return 0; } 注意 因为权限问题,所以没有办法手动添加设备节点,也没有mdev,udev进行设备节点的管理, 所以需要手动添加设备节点。所以需要改一个脚本 rootfs\tools\mkimg 添加 echo “/dev/key c 666 root root 250 0” >> squashfs-pf-list.txt 打印问题,默认打印等级很低 可以使用echo 8 > /proc/sys/kernel/printk调整打印等级
|
三维半岛官网: http://www.thanksview.com
进入首页-
产品展示
物联网与人工智能 -
方案定制
嵌入式系统与液晶屏方案定制开发 -
技术支持
常见问题分析与解决