衡山派TSensor驱动设计说明:基于RT-Thread Sensor框架的温度传感器驱动与HAL层实现
衡山派TSensor驱动设计说明基于RT-Thread Sensor框架的温度传感器驱动与HAL层实现最近在衡山派开发板上做项目需要用到板载的温度传感器TSensor来监控芯片温度。一开始我以为直接读个寄存器就行结果发现RT-Thread下有一套标准的Sensor设备驱动框架用起来虽然规范但对新手来说理解起来有点门槛。折腾了两天总算把驱动流程搞明白了今天就把TSensor驱动的完整设计从框架接入到HAL层实现给大家掰开揉碎了讲清楚。这篇教程适合正在使用衡山派硬件平台并且想在RT-Thread操作系统下开发传感器驱动的朋友。咱们会深入Driver层和HAL层的分工看看中断是怎么处理的关键的数据结构长什么样最后再给一个能直接跑起来的Demo。目标是让你看完后不仅能用好这个TSensor驱动更能理解RT-Thread Sensor框架的设计思路以后自己写其他传感器驱动也能举一反三。1. 源码与模块架构驱动代码在哪怎么组织的拿到一个新的驱动第一件事就是找到源码在哪理清它的组织架构。衡山派TSensor驱动的源代码都放在bsp/artinchip/这个目录下结构很清晰bsp/artinchip/drv/tsen/drv_tsen.c这是Driver层的实现文件。它主要负责对接RT-Thread的Sensor设备驱动框架把我们的硬件操作“包装”成框架能识别的标准接口。简单说它就是框架和硬件之间的“翻译官”。bsp/artinchip/hal/tsen/hal_tsen.c这是HAL层硬件抽象层的实现文件。它包含了直接操作TSensor控制器的底层函数比如初始化硬件、读写寄存器、处理中断等。这部分代码是和硬件强相关的。bsp/artinchip/include/hal/hal_tsen.h这是HAL层的接口头文件里面声明了所有HAL层的函数以及关键的数据结构定义。Driver层就是通过包含这个头文件来调用HAL层功能的。这样的分层设计好处很明显Driver层关心的是“怎么用RT-Thread的规矩办事”保证了驱动能无缝集成到RT-Thread的设备模型中应用层可以用rt_device_find、rt_device_read这些标准API来操作。HAL层关心的是“怎么让衡山派的TSensor硬件动起来”。它把硬件操作的细节封装起来这样即使硬件有变动也只需要修改HAL层上面的Driver层和应用代码基本不用动。原文还特别提到如果你不用RT-Thread而是裸机Baremetal开发你可以直接使用HAL层的接口非常灵活。2. 关键流程设计驱动是怎么启动和工作的理解了代码结构咱们来看看驱动运行的两个核心流程初始化和中断处理。2.1 初始化流程驱动是怎么挂载到系统里的TSensor驱动的初始化入口是drv_tsen_init函数它通过INIT_DEVICE_EXPORT这个宏声明这样RT-Thread系统在启动时就会自动调用它。这个初始化函数主要干了四件事就像给一个设备上电并登记入册初始化模块时钟clk任何外设要工作首先得有时钟信号。这一步就是打开TSensor控制器的时钟源。注册中断告诉系统当TSensor产生中断时该调用哪个函数来处理。这是实现异步数据读取的关键。初始化默认参数给TSensor控制器设置一些默认的工作参数比如采样模式、报警阈值等具体参数在后面的数据结构里讲。向设备框架注册Sensor设备这是最重要的一步。调用rt_hw_sensor_register()这个函数把我们实现好的驱动“设备”和“操作函数”告诉RT-Thread的Sensor子系统。注册成功后在应用层就能通过设备名找到这个温度传感器了。2.2 中断处理流程数据是怎么“主动”送上门的TSensor支持中断方式读取数据这比让应用程序不停地去问轮询要高效得多CPU不用忙等待。这里有两种工作模式非周期模式当应用程序调用驱动接口比如ops-fetch_data()主动要数据时硬件才启动一次温度转换。转换完成后硬件产生一个中断。周期模式TSensor控制器会按照你预先设置好的时间周期自动进行温度转换并产生中断像闹钟一样准时。无论哪种模式中断来了之后处理流程是这样的进入中断处理函数hal_tsen_irq_handle。硬件会通过中断标志位INT Flag告诉我们具体是哪个测量通道的数据准备好了。驱动会逐个检查这些标志位。对于每一个有数据准备好的通道驱动从硬件寄存器里把原始的采样值读出来。这个原始值会被缓存到一个全局变量或结构体成员中比如后面会提到的aic_tsen_ch结构体里的latest_data字段。应用程序随后再读取数据时驱动实际上是从这个缓存里把数据取出来经过换算后返回给应用。这样就完成了一次中断驱动的数据采集。3. 数据结构设计驱动内部怎么管理信息驱动里用两个核心的结构体来管理一切理解它们就理解了驱动内部的数据流转。3.1 struct aic_tsen_dev (Driver层)这个结构体是Driver层内部使用的用来管理整个TSensor控制器设备。你可以把它想象成这个温度传感器设备的“总经理办公室”里面存放着设备的核心档案和资源链接。struct aic_tsen_dev { struct rt_sensor_device dev; // 最重要的成员RT-Thread传感器设备对象 u32 pclk_rate; // 外设时钟频率 struct aic_tsen_ch *ch; // 指向具体通道配置信息的指针 };dev这是RT-Thread框架定义的标准传感器设备结构。驱动通过填充这个结构体向系统表明“我是一个标准的传感器设备”。它里面包含了设备名、类型、厂商信息、以及最重要的——操作函数集 (ops)。pclk_rate记录TSensor模块的时钟频率一些时间相关的计算比如周期采样会用到它。ch一个指针指向具体的通道配置信息。这引出了下一个更详细的结构体。3.2 struct aic_tsen_ch (HAL层)这个结构体属于HAL层它管理着一个TSensor通道的所有配置和状态。如果芯片有多个温度测量点比如CPU核、GPU、外部传感器每个点都会对应一个这样的结构体实例。它就像是每个测量点的“详细工位说明书”。struct aic_tsen_ch { int id; // 通道ID bool available; // 该通道是否可用 char name[16]; // 通道名称 enum aic_tsen_mode mode; // 工作模式周期/非周期 enum aic_tsen_soft_mode soft_mode; // 软件模式 bool diff_mode; // 是否为差分模式 bool inverted; // 数据是否取反 u16 latest_data; // 最新采集的原始数据注意实际温度值 * 10 u16 smp_period; // 周期采样模式下的采样周期单位秒 // 高温报警相关配置 bool hta_enable; u16 hta_thd; // 高温报警阈值实际温度值 * 10 u16 hta_rm_thd; // 高温报警恢复阈值实际温度值 * 10 // 低温报警相关配置 bool lta_enable; u16 lta_thd; // 低温报警阈值 u16 lta_rm_thd; // 低温报警恢复阈值 // 过温保护配置 bool otp_enable; u16 otp_thd; // 过温保护阈值 // 温度校准参数 int slope; // 斜率实际斜率 * 10000 int offset; // 偏移量实际偏移量 * 10000 aicos_sem_t complete; // 用于同步的信号量在等待数据完成时使用 };这里有几个关键点需要注意也是我当初容易搞混的地方latest_data、hta_thd等温度相关值它们存储的是“实际温度值乘以10”后的整数。比如latest_data为 285表示温度是 28.5 度。这样做是为了用整数运算来避免浮点数带来的效率和精度问题。slope和offset这是用来对原始采样值进行线性校准的参数公式一般是实际温度 原始值 * slope offset。它们也被放大了10000倍同样是出于定点数运算的考虑。complete信号量这是一个同步机制。在非周期模式下应用程序调用fetch_data后驱动可能需要在中断处理函数里等待数据转换完成。这个信号量就是用来让驱动线程“睡眠等待”直到中断发生、数据准备好后再“唤醒”它去读取数据。4. Driver层接口设计框架要求我们提供什么Driver层需要实现一个标准的操作函数集struct rt_sensor_ops并赋值给rt_sensor_device结构体。这样Sensor框架就知道怎么调用我们的驱动了。struct rt_sensor_ops { rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len); rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg); };4.1 aic_tsen_fetch - 读取温度数据这个函数对应fetch_data操作。项目说明函数原型rt_size_t aic_tsen_fetch(struct rt_sensor_device* sensor, void* buf, rt_size_t len)功能读取TSensor的温度数据。参数sensor: 传感器设备指针。buf: 用来存放读取结果的缓冲区类型是struct rt_sensor_data。len: 缓冲区的长度以rt_sensor_data为单位。返回值成功读取的数据个数成功时为1失败时返回错误码小于0。注意事项根据原文当前实现仅支持读取CPU位置的TSensor数据。它的内部工作流程通常是检查参数 - 调用HAL层的hal_tsen_get_temp获取温度值 - 将获取到的温度值填充到buf指向的rt_sensor_data结构体中 - 返回1。4.2 aic_tsen_control - 控制接口这个函数对应control操作用来实现一些IO控制命令比如设置采样率、报警阈值等。项目说明函数原型rt_err_t aic_tsen_control(struct rt_sensor_device* sensor, int cmd, void* args)功能TSensor驱动的ioctl接口用于控制设备。参数sensor: 传感器设备指针。cmd: 控制命令码。args: 命令对应的参数。返回值成功返回RT_EOK失败返回错误码。注意事项原文明确指出这个接口目前暂未实现具体的控制命令所以统一返回-1失败。但这不影响基本的温度数据读取功能。5. HAL层接口设计直接操作硬件的“武器库”HAL层的函数声明都在hal_tsen.h里Driver层通过调用它们来实际操作硬件。咱们挑几个核心的看看// 开关TSensor控制器 void hal_tsen_enable(int enable); // 开关某个具体的测量通道 void hal_tsen_ch_enable(u32 ch, int enable); // 初始化一个TSensor通道 int hal_tsen_ch_init(struct aic_tsen_ch *chan, u32 pclk); // 获取温度会进行原始数据到实际温度的转换 int hal_tsen_get_temp(struct aic_tsen_ch *chan, s32 *val); // 将原始数据转换为温度值 s32 hal_tsen_data2temp(struct aic_tsen_ch *chan); // 将温度值转换为原始数据用于设置阈值 u16 hal_tsen_temp2data(struct aic_tsen_ch *chan, s32 temp); // 显示通道状态调试用 void hal_tsen_status_show(struct aic_tsen_ch *chan); // TSensor中断处理函数在初始化时注册给系统 irqreturn_t hal_tsen_irq_handle(int irq, void *arg);这些函数名都很直观hal_tsen_get_temp是Driver层fetch_data最终会调用的核心函数。hal_tsen_data2temp和hal_tsen_temp2data则利用了前面提到的slope和offset参数进行校准计算。6. 实战Demo在应用层怎么使用这个驱动理论说了这么多最后来看看怎么在应用程序里使用这个TSensor驱动。RT-Thread的Sensor组件提供了一个非常方便的测试命令sensor_polling它的部分代码就是最好的Demo。static void sensor_polling(int argc, char **argv) { rt_uint16_t num 10; // 默认读取10次 rt_device_t dev RT_NULL; rt_sensor_t sensor; struct rt_sensor_data data; // 存放传感器数据的结构 rt_size_t res, i; rt_int32_t delay; // 1. 查找设备。argv[1]是设备名比如 temp_cpu dev rt_device_find(argv[1]); if (dev RT_NULL) { LOG_E(Cant find device:%s, argv[1]); return; } // 可以指定读取次数 if (argc 2) num atoi(argv[2]); sensor (rt_sensor_t)dev; // 2. 计算读取延迟使用设备支持的最小周期但不小于100ms delay sensor-info.period_min 100 ? sensor-info.period_min : 100; // 3. 打开设备 rt_device_open(dev, RT_DEVICE_FLAG_RDONLY); // 4. 循环读取数据 for (i 0; i num; i) { // 调用标准设备读取接口内部会调用我们实现的 aic_tsen_fetch res rt_device_read(dev, 0, data, 1); if (res ! 1) { LOG_E(read data failed!size is %d, res); } else { // 显示数据这里会解析data结构体打印出温度值 sensor_show_data(i, sensor, data); } rt_thread_mdelay(delay); // 延迟一段时间再读下一次 } // 5. 关闭设备 rt_device_close(dev); }使用起来非常简单查找设备通过rt_device_find和你在驱动里注册的设备名来找到这个传感器。打开设备以只读方式打开。循环读取在一个循环里调用rt_device_read。驱动框架会自动调用到我们写的aic_tsen_fetch函数把温度数据填充到data里。处理数据data结构体里包含了时间戳、传感器类型和具体的温度数值。关闭设备用完记得关闭。你可以在RT-Thread的MSH命令行里输入类似sensor_polling temp_cpu 5的命令来读取5次CPU温度数据非常方便测试和调试。整个驱动的脉络就是这样应用层调用标准API - RT-Thread Sensor框架 - 衡山派TSensor Driver层 - 衡山派TSensor HAL层 - 硬件寄存器。理解每一层的职责和它们之间的接口是掌握这个驱动乃至任何RT-Thread设备驱动的关键。希望这篇详细的解析能帮你少走弯路。

相关新闻

电影特效制作:ANIMATEDIFF PRO+Nuke后期合成管线

电影特效制作:ANIMATEDIFF PRO+Nuke后期合成管线

电影特效制作:ANIMATEDIFF PRONuke后期合成管线 揭秘好莱坞级特效工作流,体验AI动画与专业合成的完美融合 1. 引言:当AI动画遇见专业后期 还记得那些让你目瞪口呆的电影特效镜头吗?从《阿凡达》的奇幻世界到《复仇者联盟》的震撼…

2026/7/6 1:01:16 阅读更多 →
Stable-Diffusion-v1-5-Archive 工业检测应用模拟:生成缺陷样本供算法训练

Stable-Diffusion-v1-5-Archive 工业检测应用模拟:生成缺陷样本供算法训练

Stable-Diffusion-v1-5-Archive 工业检测应用模拟:生成缺陷样本供算法训练 1. 引言 想象一下,你是一家手机外壳制造厂的质量工程师。每天,成千上万的零件从产线上下来,你需要确保每一个都完美无瑕。但现实是,总会有一…

2026/7/6 3:41:10 阅读更多 →
GTE模型在Linux环境下的高效部署:GPU加速与性能调优指南

GTE模型在Linux环境下的高效部署:GPU加速与性能调优指南

GTE模型在Linux环境下的高效部署:GPU加速与性能调优指南 1. 引言 如果你正在寻找在Linux服务器上快速部署GTE文本嵌入模型的方法,特别是想要充分利用GPU资源来提升推理速度,那么这篇文章就是为你准备的。作为AI开发者和运维工程师&#xff…

2026/7/6 3:25:42 阅读更多 →

最新新闻

基于MC6470 IMU与dsPIC30F4011的运动控制系统设计

基于MC6470 IMU与dsPIC30F4011的运动控制系统设计

1. 项目背景与核心器件选型在工业自动化和机器人控制领域,精确的运动控制和位置感知一直是核心技术挑战。MC6470作为一款6自由度(6DOF)惯性测量单元(IMU),集成了三轴加速度计和三轴陀螺仪,能够提供高精度的运动追踪数据。而dsPIC30F4011是Mic…

2026/7/6 7:09:05 阅读更多 →
N_m3u8DL-RE流媒体下载:3个实用技巧轻松搞定在线视频保存

N_m3u8DL-RE流媒体下载:3个实用技巧轻松搞定在线视频保存

N_m3u8DL-RE流媒体下载:3个实用技巧轻松搞定在线视频保存 【免费下载链接】N_m3u8DL-RE Cross-Platform, modern and powerful stream downloader for MPD/M3U8/ISM. English/简体中文/繁體中文. 项目地址: https://gitcode.com/GitHub_Trending/nm3/N_m3u8DL-RE…

2026/7/6 7:07:05 阅读更多 →
基于74HC32与MKV44F64VLH16的智能键盘设计方案

基于74HC32与MKV44F64VLH16的智能键盘设计方案

1. 项目背景与核心需求在嵌入式系统开发中,按键输入是最基础也最频繁使用的人机交互方式之一。传统方案通常直接将机械按键连接到微控制器的GPIO引脚,但这种做法存在两个显著问题:一是按键抖动会导致误触发,二是占用宝贵的IO资源。…

2026/7/6 7:07:05 阅读更多 →
多通道信号采集系统设计与PIC24 MCU应用

多通道信号采集系统设计与PIC24 MCU应用

1. 项目背景与核心需求在工业自动化、医疗设备和科研仪器等领域,多通道信号采集与实时处理一直是关键需求。传统方案面临两大痛点:一是通道数量受限,难以扩展;二是高采样率下数据处理压力大。TPAFE0808(8通道模拟前端&…

2026/7/6 7:03:04 阅读更多 →
STM32L073RZ与MIC1557定时器低功耗设计实践

STM32L073RZ与MIC1557定时器低功耗设计实践

1. 定时系统设计背景与核心需求在嵌入式系统开发中,精确的时间控制往往是项目成败的关键因素之一。无论是工业自动化中的设备同步、消费电子中的节能管理,还是物联网设备的数据采集周期,都需要依赖稳定可靠的定时机制。传统解决方案通常直接使…

2026/7/6 7:03:04 阅读更多 →
STM32F042C6与KMX63实现低成本手势控制HMI方案

STM32F042C6与KMX63实现低成本手势控制HMI方案

1. 项目背景与核心目标KMX63与STM32F042C6的组合在嵌入式人机界面开发领域正逐渐成为性价比极高的解决方案。作为一名长期从事工业控制设备开发的工程师,我发现这套组合特别适合需要快速响应且成本敏感的场景。KMX63作为一款六轴运动传感器(三轴加速度计…

2026/7/6 7:01:04 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/6 6:52:56 阅读更多 →

月新闻