系列文章目录
瑞芯微rockchip PX30 串口调试记录
瑞芯微rockchip PX30 显示屏调试
瑞芯微rockchip PX30触摸屏调试记录
瑞芯微rockchip PX30 QT环境搭建
瑞芯微rockchip PX30 GPIO的使用
瑞芯微rockchip PX30 GPIO的使用
前言
前段时间用QT搞了个简单界面到屏幕上,现在要做个息屏的按钮。目前的想法只是简单的按键下后屏幕熄灭,再按一下屏幕亮起,没有对界面控件做屏蔽操作(相当于眼不见为净doge)。
具体做法是,设备树中对引脚进行配置,写一个简单的io驱动,将操作接口通过sysfs开放到命令行,再写个简单脚本检测按键操作以及控制屏幕背光的PWM。
1、开发环境
系统:ubuntu 18.04
芯片:瑞芯微PX30
SDK:rk官方SDK V1.5.0
内核版本:Linux 4.4.194
按键IO:GPIO2_C3
屏幕背光:PWM1
2、设备树修改
在backlight节点增加GPIO属性(screenlock-io),GPIO的pinctrl配置为上拉输入:
backlight: backlight {
compatible = "pwm-backlight";
screenlock-io = <&gpio2 RK_PC3 GPIO_ACTIVE_HIGH>;
pinctrl-names = "gpio";
pinctrl-0 = <&screenlock>;
pwms = <&pwm1 0 10000 0>;
enable-gpios = <&gpio0 RK_PB5 GPIO_ACTIVE_HIGH>;
brightness-levels = <
0 1 2 3 4 5 6 7
...
248 249 250 251 252 253 254 255>;
default-brightness-level = <10>;
};
...
&pinctrl {
backlight {
screenlock: screenlock {
rockchip,pins = <2 RK_PC3 RK_FUNC_GPIO &pcfg_input_high>;
};
};
};
3、编写IO驱动程序
直接贴代码:
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#define BLIO_NAME "blio"
#define BLIO_MINOR 100
#define LOG(x...) printk(KERN_INFO "[backlight io]: "x)
typedef struct blio_type {
struct device_node *nd;
int gpio;
enum of_gpio_flags flags;
}blio_t;
blio_t blio;
static ssize_t blio_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
buf[0] = gpio_get_value(blio.gpio) + 48;
buf[1] = '\0';
return strlen(buf);
}
static ssize_t blio_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size)
{
/* 必须return size,如果return 0会一直循环执行 */
return size;
}
static DEVICE_ATTR(blio, 0444, blio_show,blio_store);
static int blio_open(struct inode *inode, struct file *filp)
{
return 0;
}
static int blio_release(struct inode *inode, struct file *filp)
{
return 0;
}
static const struct file_operations blio_fileops = {
.owner = THIS_MODULE,
.open = blio_open,
.release = blio_release,
};
static struct miscdevice blio_device = {
.minor = BLIO_MINOR,
.name = BLIO_NAME,
.fops = &blio_fileops,
};
static int __init blio_init(void)
{
int ret = 0,err = 0;
ret = misc_register(&blio_device);
if (ret) {
LOG("%s(%d): CHAR registration failed of px30 backlight driver\n",
__func__, __LINE__);
LOG("%s(%d): Error value returned: %d\n",
__func__, __LINE__, ret);
ret = -EINVAL;
goto fail_chrdev_regist;
}
err = device_create_file(blio_device.this_device, &dev_attr_blio);
if (err) {
LOG("Unable to register sysdev entry for gpio");
ret = -EINVAL;
goto fail_create_attr;
}
blio.nd = of_find_node_by_path("/backlight");
if (blio.nd == NULL)
{
LOG("backlight node not find!\r\n");
ret = -EINVAL;
goto fail_get_blionode;
}
LOG("backlight node found!\n");
blio.gpio = of_get_named_gpio_flags(blio.nd, "screenlock-io",0,&blio.flags);
LOG("%s: get property: screenlock-io= %d.\n", __func__, blio.gpio);
if (gpio_is_valid(blio.gpio)) {
// ret = devm_gpio_request_one(blio_device.this_device, blio.gpio ,GPIOF_DIR_OUT, "blio");
// if (ret) {
// LOG("Failed to get screenlock-io\n");
// }else{
// LOG("Succeed to get screenlock-io.\n");
// }
// gpio_set_value(blio.gpio,1);
// gpio_direction_input
// gpio_direction_output
LOG("Succeed to get screenlock-io.\n");
}else{
LOG("%s: screenlock-io is no avaliable.\n", __func__);
ret = -EINVAL;
goto fail_gpio_request;
}
return 0;
fail_gpio_request:
fail_get_blionode:
device_remove_file(blio_device.this_device, &dev_attr_blio);
fail_create_attr:
misc_deregister(&blio_device);
fail_chrdev_regist:
return ret;
}
static void __exit blio_exit(void)
{
device_remove_file(blio_device.this_device, &dev_attr_blio);
misc_deregister(&blio_device);
}
module_init(blio_init);
module_exit(blio_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("zhang");
代码没什么特别,就是misc设备注册,然后在sysfs中创建读写接口,IO口的输入输出方式通过pinctrl另外配置,这里不需要进行配置,只需要正常获取IO号就可以。
4、修改PWM背光驱动
瑞芯微的pinctl配置需要自己在驱动中进行配置,找到背光驱动代码drivers/video/backlight/pwm_bl.c ,在驱动中添加以下代码配置引脚属性:
static int pwm_backlight_probe(struct platform_device *pdev)
{
...
struct pinctrl *pinctrl;
struct pinctrl_state * gpio_state = NULL;
...
pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(pinctrl)) {
printk( "[----------------]failed to find pwm pinctrl\n");
// return PTR_ERR(sub->pinctrl);
}
printk( "[----------------]successed to find pwm pinctrl\n");
gpio_state = pinctrl_lookup_state(pinctrl, "gpio");
pinctrl_select_state(pinctrl, gpio_state);
...
return ret;
}
5、编写脚本
5.1、按键的检测方法
命令行输入命令:
[root@px30_64:/]# cat /sys/class/misc/blio/blio
1
由于设置了上拉输入,没按下时输出1,按下后输出0.
5.2、背光的控制方法
命令行输入命令:
echo xxx >/sys/class/backlight/backlight/brightness
xxx数值为0~255,0表示熄灭。
5.3、编写检测和控制脚本
脚本内容如下:
#!/bin/sh
SCREEN_LOCK_FILE=/sys/class/misc/blio/blio
BACKLIGNT_FILE=/sys/class/backlight/backlight/brightness
BUTTON_STATUS=1
BUTTON_LASTSTATUS=1
PRESSED=0
SCREEN_LOCK=0
screen_lock()
{
echo 0 > $BACKLIGNT_FILE;
}
screen_unlock()
{
echo 100 > $BACKLIGNT_FILE;
}
button_detect()
{
BUTTON_LASTSTATUS=$BUTTON_STATUS;
BUTTON_STATUS=$(cat $SCREEN_LOCK_FILE);
if [ $BUTTON_STATUS = 0 ]
then
if [ $BUTTON_LASTSTATUS = 1 ]
then
PRESSED=1;
if [ $SCREEN_LOCK = 0 ]
then
screen_lock;
SCREEN_LOCK=1;
else
screen_unlock;
SCREEN_LOCK=0;
fi
else
PRESSED=0;
fi
fi
}
printf "Starting screen lock control\n"
while [[ -f "$SCREEN_LOCK_FILE" ]] && [[ -f "$BACKLIGNT_FILE" ]]
do
button_detect;
sleep 0.05;
done
echo "warning! File [ $SCREEN_LOCK_FILE or $BACKLIGNT_FILE] not found"
exit 0
没写过复杂的脚本,写的时候感觉像C风格,尴尬。
最后,在/etc/init.d的启动脚本中将这个脚本后台运行起来即可。
6、总结
这部分没什么复杂的,主要学习到的是pinctrl部分。pinctrl驱动的代码是半导体厂商自己根据自身情况设计的,imx6ull貌似不需要自己去驱动代码中再进行配置,而瑞芯微这边是需要自己在代码中进行配置的,否则没有效果。