在Linux内核中添加printx(HTIF)打印的方法
在Linux内核中添加printxHTIF打印的方法1 创建kernel/printx.c并写入如下内容2 创建include/linux/printx.h并写入如下内容3 修改 kernel/Makefile在文件中添加4 然后在需要使用 printx 的 .c 文件中包含此头文件5 printx的使用在模拟器中运行Linux若UART有问题或没有有效的途径来打印输出时对于Linux的运行状态我们无从得知。尤其是需要定位问题时想在Linux内核中添加打印来进行调试的话因无法打印输出会非常的不方便。那么就需要找到一种替换UART的打印输出方式。我们可以在Linux中模仿HTIF原理实现一个printx函数用于打印输出具体步骤如下1 创建kernel/printx.c并写入如下内容#includelinux/init.h#includelinux/io.h#includelinux/dma-mapping.h#includelinux/spinlock.h#includelinux/printk.h#includelinux/string.h#includelinux/kernel.h#includelinux/module.h#includelinux/slab.h#includelinux/export.h#includelinux/printx.h#defineHTIF_SIZEPAGE_SIZE#defineHTIF_TOHOST_OFFSET0x0#defineHTIF_FROMHOST_OFFSET0x8#defineHTIF_DEV_CONSOLE0x1#defineHTIF_CONSOLE_CMD_PUTC0x1#defineHTIF_TOHOST_CMD(dev,cmd,payload)\(((uint64_t)(dev)56)|((uint64_t)(cmd)48)|(uint64_t)(payload))//#define HTIF_FIXED_ADDR 0x40000000staticvoid__iomem*htif_base;staticphys_addr_t htif_phys;staticDEFINE_SPINLOCK(htif_lock);/* * 初始化函数根据是否定义 HTIF_FIXED_ADDR 选择模式 * 若定义 HTIF_FIXED_ADDR则其值作为固定物理地址如 -DHTIF_FIXED_ADDR0x40000000 * 若未定义则动态分配一页内存 */staticint__inithtif_init(void){#ifdefHTIF_FIXED_ADDR/* 固定地址模式 */htif_physHTIF_FIXED_ADDR;htif_baseioremap(htif_phys,HTIF_SIZE);// 将物理地址转换为内核的虚拟地址进行访问if(!htif_base){pr_err(printx: ioremap(0x%llx) failed\n,(u64)htif_phys);return-ENOMEM;}pr_info(printx: using fixed phys 0x%llx\n,(u64)htif_phys);#else/* 动态分配模式 */structpage*page;pagealloc_pages(GFP_KERNEL,get_order(HTIF_SIZE));if(!page){pr_err(printx: alloc_pages failed\n);return-ENOMEM;}htif_basepage_address(page);htif_physpage_to_phys(page);pr_info(printx: allocated phys 0x%llx, virt %p\n,(u64)htif_phys,htif_base);#endif/* 初始清零两个寄存器 */writeq(0,htif_baseHTIF_TOHOST_OFFSET);writeq(0,htif_baseHTIF_FROMHOST_OFFSET);return0;}/* 在 device initcall 阶段自动调用此时 DMA/ioremap 已可用 */device_initcall(htif_init);/* 输出单个字符内部函数带锁 */staticvoidhtif_putc(charch){void__iomem*tohosthtif_baseHTIF_TOHOST_OFFSET;void__iomem*fromhosthtif_baseHTIF_FROMHOST_OFFSET;uint64_tval;if(!htif_base)return;/* 等待 fromhost 为 0空闲 */// while (readq(fromhost) ! 0)// cpu_relax();/* 构造命令 */valHTIF_TOHOST_CMD(HTIF_DEV_CONSOLE,HTIF_CONSOLE_CMD_PUTC,ch);writeq(val,tohost);/* 等待模拟器处理完成fromhost ! 0 */// while (readq(fromhost) 0)// cpu_relax();/* 写 0 确认消费 */writeq(0,fromhost);}voidprintx_str(constchar*str){unsignedlongflags;spin_lock_irqsave(htif_lock,flags);while(*str){if(*str\n)htif_putc(\r);/* 支持回车换行 */htif_putc(*str);}spin_unlock_irqrestore(htif_lock,flags);}EXPORT_SYMBOL(printx_str);voidprintx(constchar*fmt,...){va_list args;charbuf[256];intlen;va_start(args,fmt);lenvsnprintf(buf,sizeof(buf),fmt,args);va_end(args);if(len0)printx_str(buf);}EXPORT_SYMBOL(printx);//////////////////////////////////////////////////////////////////////voidprintx_str_private(constchar*str){while(*str){if(*str\n)htif_putc(\r);/* 支持回车换行 */htif_putc(*str);}}staticunsignedlongg_flags;voidprintx_begin(constchar*fmt,...){va_list args;charbuf[256];intlen;spin_lock_irqsave(htif_lock,g_flags);va_start(args,fmt);lenvsnprintf(buf,sizeof(buf),fmt,args);va_end(args);if(len0)printx_str_private(buf);}EXPORT_SYMBOL(printx_begin);voidprintx_append(constchar*fmt,...){va_list args;charbuf[256];intlen;va_start(args,fmt);lenvsnprintf(buf,sizeof(buf),fmt,args);va_end(args);if(len0)printx_str_private(buf);}EXPORT_SYMBOL(printx_append);voidprintx_end(constchar*fmt,...){va_list args;charbuf[256];intlen;va_start(args,fmt);lenvsnprintf(buf,sizeof(buf),fmt,args);va_end(args);if(len0)printx_str_private(buf);spin_unlock_irqrestore(htif_lock,g_flags);}EXPORT_SYMBOL(printx_end);2 创建include/linux/printx.h并写入如下内容#ifndef_LINUX_PRINTX_H#define_LINUX_PRINTX_H#includelinux/types.hvoidprintx_str(constchar*str);voidprintx(constchar*fmt,...)__printf(1,2);voidprintx_begin(constchar*fmt,...)__printf(1,2);voidprintx_append(constchar*fmt,...)__printf(1,2);voidprintx_end(constchar*fmt,...)__printf(1,2);#endif3 修改 kernel/Makefile在文件中添加obj-yprintx.o4 然后在需要使用 printx 的 .c 文件中包含此头文件#includelinux/printx.h5 printx的使用函数调用就是如下这样很简单。#includelinux/printx.hprintx(123\n);printx(123 0x%x\n,10);HTIFprintx的使用分2种场景。动态分配模式Linux的UART输出可以使用但是存在BUG问题模拟器环境中启动Linux启动Linux过程中会打印“printx: allocated phys xx, virt yy”模拟器中开启HTIF功能将HTIF基址设置为xx可观察到模拟器控制台窗口中有printx打印输出。固定地址模式Linux的UART输出完全无法使用在printx.c中定义#define HTIF_FIXED_ADDR xxxx具体地址xxxx需根据经验选择一个未使用的DRAM地址重新编译Linux在模拟器中启动模拟器中开启HTIF功能将HTIF基址设置为xxxx启动Linux过程中由于UART完全无法使用故看不到启动日志可以在Linux启动完成后添加一条printx以便模拟器打印出来就知道Linux启动完成了后续在Linux中添加的多处printx输出就可以在模拟器中打印出来以方便调试了。注意模拟器需要支持HTIF功能才行其实也比较简单可以自己开发代码量小。也可以找个开源模拟器参考一下代码。

相关新闻

老硬件装 Windows 11 卡在 TPM 上?tiny11builder 帮你自动做出精简安装镜像

老硬件装 Windows 11 卡在 TPM 上?tiny11builder 帮你自动做出精简安装镜像

老硬件装 Windows 11 卡在 TPM 上?tiny11builder 帮你自动做出精简安装镜像 【免费下载链接】tiny11builder Scripts to build a trimmed-down Windows 11 image. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder tiny11builder 是 NTDevLa…

2026/9/8 16:56:57 阅读更多 →
OpenLayers选择与编辑:Select+Modify完整方案

OpenLayers选择与编辑:Select+Modify完整方案

做地图应用,画完图形后经常需要编辑——拖拽顶点、修改形状、删除要素。OpenLayers提供了Select和Modify两个交互,但要把它们串成一个完整的编辑器,还需要处理很多细节:选中高亮、顶点显示、编辑完成同步、删除功能。这篇文章把完…

2026/9/8 16:56:57 阅读更多 →
Prometheus 监控 Hyperf 全栈实战:从协程指标到请求延迟的 Swoole 应用可观测性

Prometheus 监控 Hyperf 全栈实战:从协程指标到请求延迟的 Swoole 应用可观测性

Prometheus 监控 Hyperf 全栈实战:从协程指标到请求延迟的 Swoole 应用可观测性Hyperf 是构建在 Swoole 协程引擎之上的高性能 PHP 微服务框架,支撑着无数高并发 API 和实时通信系统。然而,协程模型下的内存常驻、连接池耗尽、请求延迟抖动、…

2026/9/8 16:56:57 阅读更多 →

最新新闻

STM32四旋翼无人机飞控系统开发:从姿态解算到PID控制

STM32四旋翼无人机飞控系统开发:从姿态解算到PID控制

简介:一套基于STM32单片机的四轴无人机控制系统完整代码包,面向嵌入式开发学习者、无人机爱好者、电子设计竞赛队伍及本科毕业设计人群。方案覆盖硬件结构搭建、系统建模、硬件模块设计、传感器数据采集、姿态检测融合算法、控制算法设计以及环境下的程序…

2026/9/8 17:33:23 阅读更多 →
机器人操作中的In-Context Learning:原理、技术路线与工程实践解析

机器人操作中的In-Context Learning:原理、技术路线与工程实践解析

做机器人操作研究的人,最近肯定都有同一个感受:打开arXiv,十个做learning的组有五个在讨论In-Context Learning(ICL)怎么用在机器人上,从VIMA、RT-2聊到OpenVLA,再到最近的π0,每篇都…

2026/9/8 17:33:23 阅读更多 →
怎样在自己 Windows 电脑上搭 gitea

怎样在自己 Windows 电脑上搭 gitea

Gitea 是轻量自托管 Git 代码托管系统,对标 GitLab,内存占用小,支持代码仓库、Issue、PR、Wiki、CI Actions、团队权限管理,适合内网军工 / 项目团队部署使用。Windows 本地搭建 Gitea两种方案:Docker Desktop&#xf…

2026/9/8 17:33:23 阅读更多 →
Angular DevTools 完全使用指南:安装打开、应用检测机制、组件调试与性能剖析

Angular DevTools 完全使用指南:安装打开、应用检测机制、组件调试与性能剖析

Angular DevTools 完全使用指南:安装打开、应用检测机制、组件调试与性能剖析 【免费下载链接】angular Deliver web apps with confidence 🚀 项目地址: https://gitcode.com/GitHub_Trending/an/angular Angular DevTools 是 Angular 官方为 An…

2026/9/8 17:33:23 阅读更多 →
FPGA测控程序开发实战:从框架搭建到时序收敛的关键经验

FPGA测控程序开发实战:从框架搭建到时序收敛的关键经验

做FPGA开发这些年,我经手过不少测控类的项目,从简单的传感器采集到多通道同步控制系统都有涉及。说实话,测控程序和纯通信或图像处理类的FPGA设计有本质区别——它更像是在写一套“实时操作系统”,只是这个系统跑在硬件逻辑上&…

2026/9/8 17:33:23 阅读更多 →
GitHub CLI 的 gh skill 命令实战:Agent Skills 的搜索、预览、安装、更新与发布

GitHub CLI 的 gh skill 命令实战:Agent Skills 的搜索、预览、安装、更新与发布

GitHub CLI 的 gh skill 命令实战:Agent Skills 的搜索、预览、安装、更新与发布 【免费下载链接】cli GitHub’s official command line tool 项目地址: https://gitcode.com/GitHub_Trending/cli/cli 本文基于 GitHub CLI(cli/cli)仓…

2026/9/8 17:32:22 阅读更多 →

日新闻

加密资产价值投资:原理、方法与实战策略

加密资产价值投资:原理、方法与实战策略

1. 价值投资视角下的加密资产本质剖析作为践行格雷厄姆-多德学派十余年的价值投资者,我首次接触比特币白皮书时的震撼感至今记忆犹新。那是在2013年的一次金融科技研讨会上,当看到"去中心化电子现金系统"这个定义时,我的职业本能立…

2026/9/8 0:00:18 阅读更多 →
ODT光学测距技术原理与工业应用实践

ODT光学测距技术原理与工业应用实践

1. ODT技术全景解析ODT(Optical Distance Technology)作为现代精密测量领域的核心技术,近年来在工业检测、自动驾驶和医疗影像等领域展现出越来越广泛的应用价值。这项技术通过光学手段实现非接触式距离测量,其典型测量精度可达微…

2026/9/8 0:00:18 阅读更多 →
模板代码版本兼容实战:从单片机到服务端的隐性依赖与重构

模板代码版本兼容实战:从单片机到服务端的隐性依赖与重构

1. 模板代码为什么会"过期":三个最常见的失效场景 先说个我自己的经历。前阵子从旧电脑往新电脑迁移工作区,把一套写了快两年的单片机模板工程直接拷过去,Keil 一打开、编译,满屏的 error。仔细一看,不是芯片…

2026/9/8 0:00:18 阅读更多 →

周新闻

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 9:44:40 阅读更多 →
超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/7 21:08:44 阅读更多 →
基于CNN的调制信号识别:MATLAB实现时频图分类实战

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/8 2:03:15 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/8 0:22:41 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/8 1:17:14 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/8 3:16:24 阅读更多 →