首页
关于我
Search
1
阿明的个人博客站今日上线
10 阅读
2
V4L2 sensor驱动中.s_ctrl() 自陷死锁问题排查全过程总结
8 阅读
3
RK3588 SD启动卡系统备份
2 阅读
4
AM5728绕过hpd信号,强制输出hdmi/dvi的设置方法
2 阅读
5
新站链接提交百度的方法
1 阅读
嵌入式软件
C/C++
Linux v4l2
RK3588
UEFI
AM5728
嵌入式硬件
网站建设
生活
其他
Search
标签搜索
v4l2
linux driver
sensor
website
RK3588
Linux
u-boot
spl
Armin
累计撰写
5
篇文章
累计收到
2
条评论
首页
栏目
嵌入式软件
C/C++
Linux v4l2
RK3588
UEFI
AM5728
嵌入式硬件
网站建设
生活
其他
页面
关于我
搜索到
5
篇与
的结果
2025-07-03
新站链接提交百度的方法
1、注册百度账号,并登陆。https://ziyuan.baidu.com/site/index2、点击用户中心→站点管理→添加网站。3、选择协议头→输入域名,下一步。4、选择站点属性,下一步。5、验证网站,确定你是该域名拥有者,有三种验证方式: ①HTML标签验证(首选)。操作步骤:复制验证代码,通过网站后台、ftp或登录服务器,置于网站标签内(特殊情况无法置于标签内,放在首页其他位置也可)。 ②文件验证(次选)。 适用情况:当网站首页域名有跳转,如下图网站,输入域名后自动跳转至“域名/index.html”,且无法取消的情况下。(/index.html可在服务器上修改取消,详情见附录一) 操作步骤:下载文件→通过网站ftp、后台或登录服务器,放在网站根目录下。6、提交链接。 常用的方法有两个: ①自动推送。代码复制到标签,争取每个页面都加。 ②sitemap,即网站地图。填入sitemap链接,提交即可。某些后台可自行生成,若无法生成,使用金华站长工具制作sitemap.xml并自行上传至网站根目录。
2025年07月03日
1 阅读
0 评论
0 点赞
2025-07-03
AM5728绕过hpd信号,强制输出hdmi/dvi的设置方法
公司基于 AM5728 处理器为客户定制了一款linux视频源板,主要输出一路hdmi视频信号。由于特殊原因,需要绕过hpd信号,强制hdmi输出视频。最简单的方法当然是直接将hpd信号拉高到板内的3.3v,便可以实现不再检测hpd信号。但由于板卡已经设计完成,强行拉高hpd信号需要飞线,因此只能从内核驱动下手,通过修改linux-drm驱动的方法,绕过hpd信号。另一个问题是板卡输出使用的应用是基于gstreamer的播放程序,sink使用的是waylandsink,热插拔会造成gstreamer播放程序被kill的问题。现将调试解决问题的方法记录如下:omapdrm目录说明AM5728 的hdmi驱动路径是 /linux-sdk/kernel/drivers/gpu/drm/omapdrm/ ,该目录实现的是 TI OMAP DSS 显示子系统的 DRM 驱动(omapdrm),支持 HDMI、DSI、DPI、LVDS 等显示接口。主要负责:实现 DRM framework 所需的 crtc、encoder、connector、plane 等核心对象提供 TI 特有显示硬件的控制逻辑(DSS 管理、VENC、HDMI)子目录说明dss/ — DSS 子系统 HAL 封装层,DSS = Display SubSystem,是 TI SoC 显示硬件的控制核心,提供与具体硬件寄存器、时钟、reset、overlay、video port 等的接口。此处并不直接处理 DRM 接口,而是为 DRM CRTC/Plane 提供驱动支撑。 displays/ — 具体显示屏的 panel 驱动,实现具体 LCD 面板或显示器的驱动逻辑,注册 panel 信息给 DRM,如果自己开发了一个 LCD 面板,可以仿照这里写法。当前的hdmi接了一个 TPD12S015 芯片,该芯片是HDMI 接口保护和信号路由集成器件,主要应用于 HDMI 发射端(HDMI_TX)电路中,因此也在这个目录下。关键代码说明1、 encoder-tpd12s015.c 中的 tpd_hpd_isr 函数最终调用 omap_connector.c 中的 omap_connector_hpd_cb 函数,里边的 drm_kms_helper_hotplug_event 函数会影响并关闭gstreamer程序。"encoder-tpd12s015.c" static irqreturn_t tpd_hpd_isr(int irq, void *data) { struct panel_drv_data *ddata = data; mutex_lock(&ddata->hpd_lock); if (ddata->hpd_enabled && ddata->hpd_cb) { enum drm_connector_status status; if (tpd_detect(&ddata->dssdev)) status = connector_status_connected; else status = connector_status_disconnected; ddata->hpd_cb(ddata->hpd_cb_data, status); } mutex_unlock(&ddata->hpd_lock); return IRQ_HANDLED; }板卡开机,linux内核启动过程中的hpd连接检测不在 tpd_hpd_isr 里,第一次触发 tpd_hpd_isr 时,if判断条件中的ddata->hpd_cb还不满足,此时还没有注册热插拔callback函数。因此该函数主要处理的是进入系统之后的热插拔操作。2、linux内核启动过程中的hpd连接检测使用的是 omap_connector_detect 函数,让该函数直接返回 connector_status_connected ,后续的hdmi控制器配置初始化便可以继续进行。"omap_connector.c" static enum drm_connector_status omap_connector_detect( struct drm_connector *connector, bool force) { struct omap_connector *omap_connector = to_omap_connector(connector); struct omap_dss_device *dssdev = omap_connector->dssdev; struct omap_dss_driver *dssdrv = dssdev->driver; enum drm_connector_status ret; pr_info("ydbg : skip hpd detect\n"); return connector_status_connected;//ydbg 202506+ 跳过hpd检测,开机直接强制输出,不返回已连接的话,后续驱动不会初始化hdmi if (dssdrv->detect) { if (dssdrv->detect(dssdev)) ret = connector_status_connected; else ret = connector_status_disconnected; } else if (dssdev->type == OMAP_DISPLAY_TYPE_DPI || dssdev->type == OMAP_DISPLAY_TYPE_DBI || dssdev->type == OMAP_DISPLAY_TYPE_SDI || dssdev->type == OMAP_DISPLAY_TYPE_DSI) { ret = connector_status_connected; } else { ret = connector_status_unknown; } VERB("%s: %d (force=%d)", omap_connector->dssdev->name, ret, force); return ret; }static void omap_connector_hpd_cb(void *cb_data, enum drm_connector_status status) { struct omap_connector *omap_connector = cb_data; struct drm_connector *connector = &omap_connector->base; struct drm_device *dev = connector->dev; enum drm_connector_status old_status; status = connector_status_connected; pr_info("ydbg : force the status to be connector_status_connected\n"); mutex_lock(&dev->mode_config.mutex); old_status = connector->status; connector->status = status; mutex_unlock(&dev->mode_config.mutex); /*if (old_status != status) drm_kms_helper_hotplug_event(dev);*/ //ydbg encoder-tpd12s015.c中的tpd_hpd_isr这里会调用这里,会影响并关闭gstreamer应用,因此注释掉 }同时注释掉 drm_kms_helper_hotplug_event ,在进入系统之后便不会因为拔插连接器而关闭gstreamer播放程序。{lamp/}**最终跳过hpd并强制输出hdmi/dvi的方法:omap_connector.c中 omap_connector_detect 函数直接返回 connector_status_connected 。注释 drm_kms_helper_hotplug_event 。hdmi5.c中的函数 hdmi_set_hdmi_mode 令 hdmi.cfg.hdmi_dvi_mode 等于HDMI_HDMI或者HDMI_DVI,即可设置输出类型是HDMI或DVI。**
2025年07月03日
2 阅读
0 评论
0 点赞
2025-05-23
RK3588 SD启动卡系统备份
一、制作rootfs.img和userdata.img映像文件 1.ubuntu虚拟机进入 rk3588_linux_release_v1.2.1/output/firmware/ 目录。 2.插上准备备份的SD卡,并查看需要备份的 rootfs、userdata 分区的大小。 3.使用如下命令,创建img映像文件。 dd if=/dev/zero of=rootfs.img bs=1M count=1600 dd if=/dev/zero of=userdata.img bs=1M count=5count=1600是因为rootfs的大小是860M,设置两倍大小足够保存所有文件,userdata同理。 4.设置文件系统,添加LABEL。 mkfs.ext4 -L rootfs rootfs.img mkfs.ext4 -L userdata userdata.img 5.创建目录,将刚刚创建的 rootfs.img 和 userdata.img 映像文件挂载到新建的目录。 mkdir rootfs mkdir userdata sudo mount rootfs.img rootfs sudo mount userdata.img userdata 6.拷贝SD卡rootfs和userdata分区的所有文件到刚刚创建的rootfs和userdata目录中去。 sudo cp -a /media/admin123/rootfs/* rootfs/ sudo cp -a /media/admin123/userdata/* userdata/ 7.取消挂载,删除文件夹。 sudo umount rootfs sudo umount userdata sudo rm -r rootfs sudo rm -r userdata二、其他映像文件的制作 1. uboot.img : 在 rk3588_linux_release_v1.2.1/ 目录下运行./build.sh uboot 即可在 rk3588_linux_release_v1.2.1/output/firmware/ 生成(软链接形式,实际文件不在该目录,不影响使用)。 2. boot.img : 在 rk3588_linux_release_v1.2.1/ 目录下运行./build.sh kernel 即可在 rk3588_linux_release_v1.2.1/output/firmware/ 生成(软链接形式,实际文件不在该目录,不影响使用)。 3. MiniLoaderAll.bin : 在 rk3588_linux_release_v1.2.1/ 目录下运行命令./build.sh uboot 即可生成,该文件的内容是 TPL+SPL 。 运行以上编译脚本时,最终生成的MiniLoaderAll.bin是从SDK中预编译好的文件直接拷贝后改了个名字得到的。 如果想要使用自己修改的,以修改spl文件为例: 修改 rk3588_linux_release_v1.2.1/u-boot/arch/arm/mach-rockchip/spl.c 文件后,运行以下命令编译一次。./build.sh uboot 编译的spl文件保存在 rk3588_linux_release_v1.2.1/u-boot/spl/u-boot-spl.bin,将预编译的spl原文件备份一下mv rkbin/bin/rk35/rk3588_spl_v1.12.bin rkbin/bin/rk35/bak_rk3588_spl_v1.12.bin 然后运行以下命令将预编译的spl文件替换为刚刚编译的spl文件。cp u-boot/spl/u-boot-spl.bin rkbin/bin/rk35/rk3588_spl_v1.12.bin 再次运行 ./build.sh uboot ,生成的 MiniLoaderAll.bin 即为修改后的。 4. oem.img、misc.img、parameter.txt : 在 rk3588_linux_release_v1.2.1/ 目录下运行以下命令即可编译生成。./build.sh firmware 5. recovery.img : 使用官方工具, RKDevTool.3.15 ->高级功能->固件->选择“创龙TL3588_SDK\4-软件资料\Linux\Makesdboot\v2.2\update.img”文件->点击解包。在 RKDevTool.3.15 根目录下会生成一个 Output 文件夹,其中 Output\Android\Image 目录里有update.img包含的所有映像文件,选择拷贝即可。三、打包所有映像文件 1.修改 rk3588_linux_release_v1.2.1/device/rockchip/rk3588/rk3588-package-file 文件,该文件是打包选项。 2.由于是完整包,因此可以包含所有的选项, # 号是注释,代表取消该选项,打包所有映像文件的示例如下。 # NAME PATH package-file package-file parameter parameter.txt bootloader MiniLoaderAll.bin uboot uboot.img misc misc.img boot boot.img #backup RESERVED rootfs rootfs.img recovery recovery.img oem oem.img userdata userdata.img 3.update.img :在 rk3588_linux_release_v1.2.1/ 目录下运行以下命令,将所有文件打包生成update.img。./build.sh updateimg四、批量制作SD卡 1.连接:使用读卡器将SD卡与PC连接。 2.清理磁盘:使用官方软件工具 SD_Firmware_Tool_1.74 (其他版本应该也可以),点击恢复磁盘,将SD卡格式化。 3.创建:SD_Firmware_Tool_1.74->选择磁盘设备->勾选SD启动->选择第三节生成的update.img->开始创建。 4.等待创建完成即可。如果不放在板卡上启动一次,userdata分区的空间大小是userdata.img的大小,上电启动一次后会自动扩展。
2025年05月23日
2 阅读
0 评论
0 点赞
2025-05-15
V4L2 sensor驱动中.s_ctrl() 自陷死锁问题排查全过程总结
一、问题背景在开发 LT9211C 的 V4L2 子设备驱动时,实现了一个控制接口:v4l2-ctl -d /dev/v4l-subdevX --set-ctrl=chip_init=1该命令触发 .s_ctrl() 中的设备初始化逻辑。驱动中使用了 mutex 来保护共享状态:mutex_lock(<9211c->confctl_mutex); ... mutex_unlock(<9211c->confctl_mutex);但执行命令时,.s_ctrl() 永远卡在 mutex_lock(),导致控制操作无法完成。二、初步怀疑与验证1:其他线程(如 workqueue)持有锁存在工作队列周期性使用 mutex_trylock(),怀疑抢占了锁注释掉所有 schedule_work() 和工作队列逻辑结果:问题仍然存在,.s_ctrl() 卡住不动2:驱动中其他路径加了锁全局查找所有 mutex_lock()、mutex_trylock() 路径结果:确认无其他加锁路径三、深入排查尝试用 mutex_is_locked() 检查锁状态在 .s_ctrl() 内部加打印:pr_info("locked = %d\n", mutex_is_locked(<->confctl_mutex));结果显示锁始终处于加锁状态,但代码中没人持有锁。四、关键线索发现在控件初始化函数中:handler->lock = <9211c->confctl_mutex; lt9211c->chip_init_ctrl = v4l2_ctrl_new_custom(handler, <9211c_ctrl_chip_init, NULL);.s_ctrl() 回调正好是 chip_init 控件对应的处理函数。这意味着:V4L2 框架在调用 .s_ctrl() 之前已经自动加了 handler->lock 对应的 mutex五、框架调用链分析VIDIOC_S_CTRL └── v4l2_ctrl_handler_setup() └── mutex_lock(handler->lock); //框架加锁 └── ctrl->ops->s_ctrl() //调用驱动 .s_ctrl() └── mutex_unlock(handler->lock);因此 .s_ctrl() 执行时已经处于加锁状态,若再次 mutex_lock() 同一把锁,就会死锁(线程阻塞等待自己)。六、最终修复方式删除 .s_ctrl() 中的重复加锁:- mutex_lock(<->confctl_mutex); // 不需要 ... - mutex_unlock(<->confctl_mutex); // 不需要改为直接执行逻辑(由框架管理加解锁)。七、验证结果编译驱动重新执行控制命令:v4l2-ctl --set-ctrl=chip_init=1控制操作立即成功返回,卡死问题彻底解决。八、经验总结项目说明问题类型自陷死锁(Self-deadlock)原因.s_ctrl() 中手动 mutex_lock() 框架已加锁的 mutex最大误导点锁好像“被别人持有”,实际是“自己卡自己”排查突破口handler->lock 设置 → 框架自动加锁机制分析根本解决方法不在 .s_ctrl() 中重复加锁 handler->lock 指向的 mutex凡设置了 handler->lock 的 V4L2 控制器,.s_ctrl() 中禁止重复加锁,否则极易造成自陷死锁。九、其他调试方法pr_info("s_ctrl: current thread = %s, is_locked = %d\n", current->comm, mutex_is_locked(<->confctl_mutex));可以查看当前的锁被谁持有。
2025年05月15日
8 阅读
0 评论
1 点赞
2025-04-19
阿明的个人博客站今日上线
女朋友需要一个网站来展示个人简历的缘故,在RackNerd租了一台很便宜的服务器。帮她做好以后,便萌生了建一个自己的博客的念头。曾经在seo公司待过的原因,建过模版网站,对服务器、域名、网站后台都比较熟悉,加上目前在做嵌入式工作,对linux也比较熟悉,所以总体下来没遇到太难的问题。服务器服务器使用的是RackNerd的VPS,主要配置如下:| CPU |内存| 硬盘 | 流量 | 价格 ||1核心|1GB|24GB SSD|200GB 1Gbps|$11.29/年 |系统安装的Ubuntu 22.04.1 LTS,又在ubuntu上安装了宝塔,方便进行网站管理。博客系统博客系统使用的是Typecho,一款PHP开发的轻量级开源博客系统。首先尝试了WordPress,但是安装上后感觉很卡顿,因此改为更轻量级的Typecho。因为曾经使用过织梦CMS、米拓、pbootcms和WordPress,所以即使第一次使用Typecho搭建网站,总体而言也不算太难,原理都是相通的。主题使用的是JOE,一款免费的Typecho主题,界面和后台设置我都很喜欢。域名域名是在阿里云注册的,cn域名每年39元,com每年90元,博客主要在国内使用,就没必要使用com了,直接使用cn。域名注册后解析到服务器,并修改了DNS为cloudflare,使用cloudflare做加速服务。网站上线后,在国内测试访问速度很快。{lamp/}至此,我的博客网站便搭建成功了,今后会不定时地更新一些嵌入式工作中的一些调试记录、学习笔记,也可能会有其他的杂七杂八的东西。我的目标是,成为一个很厉害的人。 ::(吐舌)
2025年04月19日
10 阅读
2 评论
3 点赞