Exynos4412 移植Linux-6.1(九)移植tiny4412_backlight驱动的过程及问题解决

系列文章目录

  • Exynos4412 移植Linux-6.1(一)下载、配置、编译Linux-6.1

  • Exynos4412 移植Linux-6.1(二)SD卡驱动——解决无法挂载SD卡的根文件系统

  • Exynos4412 移植Linux-6.1(三)SD卡驱动——解决mmc0: Timeout waiting for hardware interrupt.

  • Exynos4412 移植Linux-6.1(四)NandFlash卡驱动

  • Exynos4412 移植Linux-6.1(五)DM9000网卡驱动

  • Exynos4412 移植Linux-6.1(六)【已解决】SROMC寄存器的数值不正确的问题

  • Exynos4412 移植Linux-6.1 (七)挂载Ramdisk文件系统,【已解决】Couldn’t find valid RAM disk image starting at 0

  • Exynos4412 移植Linux-6.1 (八)LCD驱动,解决error: implicit declaration of function ‘dma_free_writecombine’的问题

  • Exynos4412 移植Linux-6.1(九)移植tiny4412_backlight驱动的过程及问题解决


Exynos4412 移植Linux-6.1(九)移植tiny4412_backlight驱动的过程及问题解决

  • 系列文章目录
  • 1、背光的工作原理及电路
    • (1) 什么是背光:
    • (2)背光电路
    • (3)一线触控
    • (4)背光PWM控制信号接口
  • 2、移植背光驱动程序
    • (1)修改tiny4412_backlight设备树
    • (2)修改backlight驱动
      • 问题1:platform_get_resource无法获取irq资源
      • 问题2:irq指针为NULL
      • 问题3:devm_ioremap_resource不能重复映射res虚拟地址
      • 问题4:rmmod backlight_drv出错
  • 3、测试

LCD的驱动就移植完成了,但是LCD屏幕并没有亮。这有可能是因为没有移植backlight驱动。

1、背光的工作原理及电路

(1) 什么是背光:

LCD本身是不发光的,因此要想让其显示所要数据和图像,需要一个外部面光源系统来帮助其显示,即背光源(Backlight)。LCD的白光背光源一般由6~8个直下式或侧入式侧发光白色LED灯组成。背光源的工作原理,就是将灯条等点光源,利用导光板、反射片、扩散膜、增光膜(棱镜片)等组件转换成面光源,为LCD产品提供显示所需的外部光源。(https://blog.csdn.net/m0_66322708/article/details/124241892/)

(2)背光电路

EUP 2584是专为驱动白色LED而设计的一种恒流升压变换器。EN引脚用来控制LED的亮灭。FB引脚接收不同的占空比来驱动LCD的背光的亮度。LX引脚为LED背光源提供电源。
在这里插入图片描述

(3)一线触控

在 Cortex-A9智能终端中,LCD 背光开关是通过Exynos4412的GPX3_2作为EINT10,连接EPU2584的EN端口。GPX3_2输出为高电平“1”时,将打开背光;当输出为低电平“0”时,将关闭背光。
在这里插入图片描述

(4)背光PWM控制信号接口

背光PWM控制是通过Cortex-A9智能终端 的GPD0_1 作为TOUT1输出pwm信号给EPU2584的FB端口。在智能终端的背光电路中,通过在10%~90%之间调整PWM占空比,来调整背光电路的输出电流在20.5mA到5.5mA之间变化,从而实现背光灯源亮度的调整。
在这里插入图片描述

2、移植背光驱动程序

与tiny4412的电路是类似的,所以移植tiny4412的背光驱动。比较完整的tiny4412_backlightd 驱动代码如下:https://github.com/hceng/learn/blob/master/tiny4412/01_backlight_drv/backlight_drv.c
但是,在移植该驱动到Linux-6.1的过程中,出现了很多问题。现将问题和解决过程记录下来,以供大家参考。

(1)修改tiny4412_backlight设备树

tiny4412的设备树如下:

/ {
[...]backlight_demo@139D0000{compatible = "tiny4412,backlight";reg = <0x139D0000  0x14>;tiny4412,backlight = <&gpx1 2 GPIO_ACTIVE_HIGH>;pinctrl-names = "backlight_out","backlight_in";pinctrl-0 = <&backlight_out>;pinctrl-1 = <&backlight_in>;interrupts = <0 40 0>;clocks = <&clock CLK_PWM>;clock-names = "timers";};
};
[...]
&pinctrl_1 {backlight_out: backlight_out{samsung,pins = "gpx1-2";samsung,pin-function = <1>;samsung,pin-pud = <0>;samsung,pin-drv = <0>;};backlight_in: backlight_in{samsung,pins = "gpx1-2";samsung,pin-function = <0>;samsung,pin-pud = <0>;samsung,pin-drv = <0>;};
};

根据自己开发板的电路引脚,修改如下:

	backlight {compatible = "tiny4412,backlight";reg = <0x139D0000 0x1000>;pinctrl-names = "backlight_in", "backlight_out";pinctrl-0 = <&backlight_in>;pinctrl-1 = <&backlight_out>;gpios = <&gpx3 2 GPIO_ACTIVE_HIGH>;clock-names = "timers";clocks = <&clock CLK_PWM>;interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;pwms = <&pwm 0 1000000000 0>;};
[...]&pinctrl_1 {backlight_out: backlight_out {samsung,pins = "gpx3-2";samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;};backlight_in: backlight_in {samsung,pins = "gpx3-2";samsung,pin-function = <EXYNOS_PIN_FUNC_INPUT>;samsung,pin-pud = <EXYNOS_PIN_PULL_NONE>;samsung,pin-drv = <EXYNOS4_PIN_DRV_LV1>;};
};

(2)修改backlight驱动

问题1:platform_get_resource无法获取irq资源

tiny4412_backlight中会用到pwm的中断。我没有看懂onewire的原理。为了移植驱动,需要获取irq资源。
原驱动中是通过如下代码获取irq资源的。但是在Linux-6.1里,irq始终都为NULL。

    irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);if (irq == NULL){printk("platform_get_resource irq error\n");return -EINVAL;}

然后,我在probe函数中添加for循环,打印resource,发现num_resources是1,也就是只有一个reg资源,而没有irq资源。

	printk("num_resources: = %d", pdev->num_resources);int i;for (i = 0; i < pdev->num_resources; i++) {struct resource *r = &pdev->resource[i];printk("resource_type: =%ld\n",resource_type(r));

接着,我试着在probe函数中用以下代码查看Exynos4.dtsi中把pwm转换成platform_device之后的resource,仍然只有一个reg资源,而没有irq资源。

    struct device_node *pwd_node = NULL;struct platform_device *pdev_pwd;    pwd_node = of_find_compatible_node(NULL,NULL,"samsung,exynos4210-pwm");if(pwd_node == NULL){printk("of_find_node_by_name is error\n");return -EINVAL;}pdev_pwd = of_find_device_by_node(pwd_node);if(pdev_pwd == NULL){printk("of_find_node_by_name is error\n");return -EINVAL;}printk("num_resources: = %d", pdev_pwd->num_resources);for (i = 0; i < pdev_pwd->num_resources; i++) {struct resource *r = &pdev_pwd->resource[i];printk("resource_type: =%ld\n",resource_type(r));}

最后,查看of_address_to_resourceof_irq_to_resource等内核代码,想找出没有转换irq资源的原因。但是,逻辑太复杂,没看懂,似乎和父节点还有关系。总之,新版本的内核,对设备树的解析似乎不同以前。
没办法,只能自己通过devic_node来获取irq。在platform_device中有一个成员struct device dev,这个dev中又有一个指针成员struct device_node * of_node。linux的做法就是将这个of_node指针直接指向由设备树转换而来的device_node结构;留给驱动开发者自行处理。
例如,有这么一个struct platform_device* of_test.我们可以直接通过of_test->dev.of_node来访问设备树中的信息。
我的做法是在backlight_probe函数中,添加代码实现以下2个功能。

  1. 利用of_irq_get或者irq_of_parse_and_map获取irq号。
    这两个函数获取的irq号是一样的。这个irq号不是硬件数据手册中的硬件irq号。
  2. 填充irq指针的resource结构体

问题2:irq指针为NULL

这里又出现了另一个问题,就是platform_get_resource无法获取irq资源,导致irq指针始终是NULL。怎样给irq指针赋值呢?我的方法是先获得reg的resource结构体地址res ,然后把res 地址+sizeof(*res),作为irq的地址。
不知道您是否还有更好的方法,请在评论区留言。我的代码如下:

static int backlight_probe(struct platform_device *pdev)
{int ret, irqno;dev_t devid;dev = &pdev->dev;struct device_node *dev_node;printk("enter %s\n", __func__);dev_node = dev->of_node;irqno = of_irq_get(dev_node, 0);printk("of_irq_get No: %d\n", irqno);irqno = irq_of_parse_and_map(dev_node,0);printk("irq_of_parse_and_map No: %d\n", irqno);res = platform_get_resource(pdev, IORESOURCE_MEM, 0);irq = res + sizeof(*res);memset(irq, 0, sizeof(*irq));irq->start = irq->end = irqno;//   irq->flags = IORESOURCE_IRQ;//   irq->name = of_node_full_name(dev_node);

问题3:devm_ioremap_resource不能重复映射res虚拟地址

原驱动中是利用timer = devm_ioremap_resource(&pdev->dev, res);来映射pwm寄存器的虚拟地址的。但是,由于在arch/arm/boot/dts/exynos4.dtsi中,已经定义了pwm节点。如果它的status = "okay",在解析设备树的时候,就已经把reg = <0x139D0000 0x1000>;映射了一次。那么,devm_ioremap_resource再次映射该0x139D0000地址时就会报错。

[T90] timer_phyaddr: 139d0000
[T90] tiny4412_backlight 139d0000.backlight: can't request region for resource [mem 0x139d0000-0x139d0fff]
[T90] timer_virtaddr: fffffff0
[T90] 8<--- cut here ---
[T90] Unable to handle kernel paging request at virtual address fffffff0
[T90] [fffffff0] *pgd=6fffd861, *pte=00000000, *ppte=00000000
[T90] Internal error: Oops: 837 [#1] PREEMPT SMP ARM
[T90] Modules linked in: backlight_drv(O+)

同一个物理地址,可以被映射为多个虚拟地址,所以我的解决方法是直接用ioremap。不知道您是否还有更好的方法,请在评论区留言。

    timer = ioremap(res->start, resource_size(res));if (timer == NULL){printk("devm_ioremap_resource error\n");return -EINVAL;}printk("timer_virtaddr: %x\n", timer);

问题4:rmmod backlight_drv出错

解决了前3个问题之后,就可以交叉编译出backlight_drv.ko。可以在智能终端上正常insmod backlight_drv.ko,但是rmmod backlight_drv会报错。这个问题我还没有解决,如果有小伙伴知道原因之后,在评论区多多指导。
backlight_drv驱动代码资源链接

3、测试

驱动代码资源中有测试程序,可以实现0~127档的亮光调节。
insmod backlight_drv.ko之后,在智能终端中执行如下命令,可以看到backlight的设备号是243。然后,执行mknod /dev/backlight c 243 0创建设备文件。加载了lcd驱动之后,就能显示了。
要注意:

  • 根据自己移植的Linux内核版本来修改Makefile文件。
  • 还需要交叉编译test_backlight.c。
[root@farsight ]# cd /sys/class/onewire_backlight/tiny4412_backlight
[root@farsight tiny4412_backlight]# ls
dev        power      subsystem  uevent
[root@farsight tiny4412_backlight]# cat dev
243:0
[root@farsight 04_backlight_drv]# mknod /dev/backlight c 243 0
[root@farsight 04_backlight_drv]# ./test_backlight
[...]
[  521.416003][   T99] kernel: reg = 126
[  521.416047][   T99] backlight_write
backlight: 126
[  521.472414][   T99] kernel: reg = 127
[  521.472482][   T99] backlight_write
backlight: 127
[  521.525357][   T99] backlight_exit
done!

请添加图片描述
下一步,实现启动系统自动加载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/241149.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于STM32单片机模拟智能电梯步进电机控制升降毕业设计3

STM32单片机模拟智能电梯步进电机控制数码管显示3 演示视频&#xff08;复制到浏览器打开&#xff09;&#xff1a; 基于STM32单片机的智能电梯控制系统模拟智能电梯步进电机控制系统设计数码管显示楼层设计/DIY开发板套件3 产品功能描述&#xff1a; 本系统由STM32F103C8T6单…

龙芯loongarch64服务器编译安装tensorflow-io-gcs-filesystem

前言 安装TensorFlow的时候,会出现有些包找不到的情况,直接使用pip命令也无法安装,比如tensorflow-io-gcs-filesystem,安装的时候就会报错: 这个包需要自行编译,官方介绍有限,这里我讲解下 编译 准备 拉取源码:https://github.com/tensorflow/io.git 文章中…

关于pygame无法打开对应文件解决办法 pyame.error unable to open file

问题描述&#xff1a; 问题原因&#xff1a; 由于pygame版本过低导致无法进行声音播放&#xff0c;升级对应版本即可完成&#xff01; 解决办法&#xff1a; 升级pygame包版本到2.1.2&#xff0c;即可解决该问题&#xff01; pip install --upgrade pygame2.1.2

C语言之指针

目录 函数的参数 对象和地址 取地址运算符 注意 指针 注意 指针运算符 注意 在C语言中&#xff0c;指针是一个十分重要的概念&#xff0c;它的作用是“指示对象”。 例如&#xff1a;你要去一座公寓楼找一位朋友&#xff0c;公寓楼由很多楼层组成&#xff0c;每个楼层…

十八、本地配置Hive

1、配置MYSQL mysql> alter user rootlocalhost identified by Yang3135989009; Query OK, 0 rows affected (0.00 sec)mysql> grant all on *.* to root%; Query OK, 0 rows affected (0.00 sec)mysql> flush privileges; Query OK, 0 rows affected (0.01 sec)2、…

使用html+css+js+three.js写圣诞树

实现效果&#xff1a; <head><meta charset"UTF-8"><title>Musical Christmas Lights</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css"><sty…

网络编程:多进程和多线程编程

1. 多进程编程 1.1 fork #include <sys/types.h> #include <unistd.h> // 调用失败返回 -1 设置 errno pid_t fork( void );子进程返回 0&#xff0c;父进程返回子进程 PID&#xff1b; 信号位图被清除&#xff08;父进程的信号处理函数不再对新进程起作用&…

【网络编程】网络通信基础——简述TCP/IP协议

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 一、ip地…

sql_lab之sqli中的报错注入,less13

报错注入&#xff08;less-13&#xff09; 正常报错注入&#xff1a; 1.输入用户名和密码123 123显示登录错误 2.输入用户名和密码123’ 123显示登录错误 123后面有’)说明是’)注入 3.查询数据库名 1) and updatexml(<a><b></b></a>,concat(1111…

大数据知识图谱解码:从核心概念到技术实战

文章目录 大数据知识图谱解码&#xff1a;从核心概念到技术实战1. 概述什么是知识图谱知识图谱与自然语言处理的关系 2. 发展历程语义网络本体论大数据时代的知识图谱知识图谱与深度学习的融合 3. 研究内容知识图谱的建模与表示知识抽取知识图谱的融合与对齐知识图谱的推理知识…

KMP入门级别算法详解--终于解决了(next数组详解)

对于正常的字符串模式匹配&#xff0c;主串长度为m&#xff0c;子串为n&#xff0c;时间复杂度会到达O&#xff08;m*n&#xff09;&#xff0c;而如果用KMP算法&#xff0c;复杂度将会减少线型时间O&#xff08;mn&#xff09;。 设主串为ptr"ababaaababaa";&#…

Prometheus介绍和安装

Prometheus介绍和安装 1. Prometheus介绍 Prometheus&#xff08;普罗米修斯&#xff09;是一个最初在SoundCloud上构建的监控系统。自2012年成为社区开源项目&#xff0c;拥有非常活跃的开发人员和用户社区。为强调开源及独立维护&#xff0c;Prometheus于2016年加入云原生云…

P4 音频知识点——PCM音频原始数据

目录 前言 01 PCM音频原始数据 1.1 频率 1.2 振幅&#xff1a; 1.3 比特率 1.4 采样 1.5 量化 1.6 编码 02. PCM数据有以下重要的参数&#xff1a; 采样率&#xff1a; 采集深度 通道数 ​​​​​​​ PCM比特率 ​​​​​​​ PCM文件大小计算&#xff1a; ​…

[THUPC 2024 初赛] 二进制 (树状数组单点删除+单点查询)(双堆模拟set)

题解 题目本身不难想 首先注意到所有查询的序列长度都是小于logn级别的 我们可以枚举序列长度len&#xff0c;然后用类似滑动窗口的方法&#xff0c;一次性预处理出每种字串的所有出现位置&#xff0c;也就是开N个set去维护所有的位置。预处理会进行O(logn)轮&#xff0c;每…

KubeSphere金丝雀发布流量分布调节不生效(将所有流量按比例分配给灰度发布版本)

如题 金丝雀发布按照流量比例访问不能生效 1、自制应用生成的路由添加注释: nginx.ingress.kubernetes.io/service-upstream:"true" 2、项目网关开启 3、完成 以上&#xff0c;祝好。

Tomcat远程调试

windows环境 写一个 startup-debug.bat&#xff0c;指定tomcat的根目录&#xff0c;端口自己定义 rem *******设置Tomcat目录*******-- set CATALINE_HOMED:\asd\A8-2\tomcat d: rem 8787为可用端口,为远程调试监听端口-- cd %CATALINE_HOME%/bin set JPDA_ADDRESS8787 set J…

Leetcode—445.两数相加II【中等】

2023每日刷题&#xff08;六十七&#xff09; Leetcode—445.两数相加II 实现代码 /*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/struct ListNode* addTwoNumbers(struct ListNode* l1, struct ListNode* l2…

一个简单的 HTTP 请求和响应服务——httpbin

拉取镜像 docker pull kennethreitz/httpbin:latest 查看本地是否存在存在镜像 docker images | grep kennethreitz/httpbin:latest 创建 deployment&#xff0c;指定镜像 apiVersion: apps/v1 kind: Deployment metadata:labels:app: httpbinname: mm-httpbinnamespace: mm-…

Latex生成的PDF中加入书签/Navigation/导航

本文参考&#xff1a;【Latex学习】在生成pdf中加入书签/目录/提纲_latex 书签-CSDN博客 &#xff08;这篇文章写的真的太棒了&#xff01;非常推荐&#xff09; 题外话&#xff0c;我的碎碎念&#xff0c;这也是我如何提高搜索能力的办法&#xff1a;想在Latex生成的PDF中加入…

2023的AI工具集合,google和claude被禁用解决和edge的copilot

一、前言 AI工具集合 首先&#xff0c;OpenAI的ChatGPT以其深度学习模型和强大的语言处理能力引领了AI聊天机器人的潮流。自2022年11月30日上线以来&#xff0c;它创下了100万用户的注册记录&#xff0c;并被广泛应用于全球财富500强公司。为了实现盈利&#xff0c;OpenAI发布…