FNV-1a 64-bit 在 MCU-32bit 上的实现与取舍:从原理、代码到适用边界
FNV-1a 64-bit 在 MCU-32bit 上的实现与取舍:从原理、代码到适用边界先看核心结论FNV-1a 64-bit 的重点,不是“32 位 MCU 能不能跑 64 位整数”,而是下面三件事: 这个散列为什么能工作。 代码实现里每一步到底在做什么。 哪些场景适合用,哪些场景不适合用。 把这三件事讲清楚后,再讨论 32-bit 和 64-bit 的工程取舍,结构会更稳,也更接近实际选型过程。 FNV-1a 的标准更新过程可以概括成一条固定循环: 状态从 offset_basis 开始 每读取一个字节,先异或进状态 再乘上固定的 FNV_Prime 运算结果保留在固定比特宽度内 对 64-bit 版本,标准常量是: 12#define FNV1A64_OFFSET_BASIS 0xCBF29CE484222325ULL#define FNV1A64_PRIME 0x00000100000001B3ULL 这两个常量不是任意挑选出来的。offset_basis 决定初始状态,FNV_Prime 决定每次吸收新字节后如何扩散已有状态。 先把原...
一次由 C 位域非原子写入引发的状态上报异常
@[toc] 一次由 C 位域非原子写入引发的状态上报异常在一套嵌入式控制固件中,出现过一类很典型、但又很容易被忽略的异常:传感器物理状态已经持续触发,心跳报文却长时间仍然上报为 0;重新手动触发一次后,状态又恢复正常。 表面上看,这类问题很像采样抖动、消息队列满、或者 CAN 发送延迟。但沿着发送链路继续深挖后,真正的问题并不在总线,也不在消息队列,而是在 C 语言位域写入不是原子操作 这一点上。 先看现象,不要先怪 CAN异常表现有几个很强的特征: 传感器已经进入触发状态,并且维持了很长时间。 心跳报文仍然持续发送,但目标状态位始终是 0。 再次手动触发一次传感器后,状态恢复正常。 不是“完全没报文”,而是“报文一直有,但某一位一直不对”。 这类现象说明一件事:发送通道本身大概率是通的。如果 CAN 队列、发送线程、或总线仲裁是主因,更常见的表现会是丢帧、延迟、或整帧不发,而不是“整帧一直发,但某一位长期错误”。 因此,排查重点不该先放在“是否发出去”,而应该放在“发出去的那 8 个字节是谁构造的,以及构造时有没有被并发写坏”。 位域写入通常是读改写,不是原子更...
MAX14830 可移植 C 驱动实现分析:一个适合多串口扩展场景的开源基础版本
@[toc] MAX14830 可移植 C 驱动实现分析:一个适合多串口扩展场景的开源基础版本在嵌入式系统中,串口资源不足是一个非常常见的问题。当主控需要同时连接调试接口、通信模组、下位机设备或多路传感器时,片上 UART 数量往往很快成为限制条件。此类场景下,外扩串口芯片通常是更现实的方案,而 MAX14830 就是其中较典型的一种:通过 SPI 或 I2C 总线,可以扩展出 4 路独立 UART,同时提供 FIFO 和 GPIO 能力,适合承担多串口桥接角色。 GitHub 上的 wdfk-prog/max14830,就是一个面向这颗芯片的开源 C 驱动实现。这个项目的重点不在“做了多少高级功能”,而在于它明确采用了 可移植、平台无关、基于 HAL 抽象 的实现思路。对于正在做 MAX14830 接入、板级驱动开发,或者准备搭建多串口扩展方案的人来说,这类代码通常比单平台 Demo 更有参考价值。 仓库地址: https://github.com/wdfk-prog/max14830 项目定位很明确:不是平台示例,而是通用驱动骨架从仓库主页给出的描述来看,...
M104BPCSX-5024 RFID 驱动与应用层开源实现分析
@[toc] M104BPCSX-5024 RFID 驱动与应用层开源实现分析wdfk-prog/m104bpcsx_5024 是一个面向 M104BPCSX-5024 RFID 模块的开源实现,项目以 C 语言编写,围绕 RFID 模块接入的典型嵌入式应用场景,构建了较完整的驱动层与应用层一体化方案。从仓库公开信息来看,该项目不仅提供了底层协议封装与通信接口实现,还进一步覆盖了多通道轮询、RTOS 线程调度、CAN 总线结果上报以及功耗控制等业务逻辑,具备较强的工程参考意义。 与常见仅停留在寄存器读写或单一通信接口封装的示例工程不同,该项目更接近真实产品环境中的 RFID 子系统实现方式,尤其适合作为以下方向的参考样例: 嵌入式驱动分层设计 SPI / UART 双通信路径抽象 基于 RTOS 的设备轮询任务组织 多通道 RFID 读卡器管理 CAN 总线状态上报集成 一、项目定位与功能概述该项目面向 M104BPCSX-5024 RFID 模块,目标是构建一套可移植、可扩展、适用于多硬件接入方案的驱动与应用实现框架。项目核心功能包括: 对多个 RFID...
Qboot V2:让 Bootloader 从“能升级”走向“可持续演进”
@[toc] Qboot V2:让 Bootloader 从“能升级”走向“可持续演进”固件升级这件事,早已不只是“把新程序写进去”这么简单。 在不少 MCU 项目中,最初的目标通常很明确:先把 Bootloader 做出来,先把固件升级跑通,先让设备具备基本的远程维护能力。这样的阶段里,结构简单、接入直接、功能够用,往往比“架构漂亮”更重要。 Qboot V1 正是在这样的背景下体现出价值。它最初的定位就是一个用于快速制作 bootloader 的组件,目标非常务实:把启动、分区、校验、解密、解压、恢复和升级这些关键环节尽快组织起来,让升级链路尽早落地。现有公开版本中,已经包含 AES、GZIP、QuickLZ、FastLZ、HPatchLite、OTA downloader 等能力,本身并不是一个“只有基础功能”的轻量壳子,而是一套已经能够解决实际问题的升级组件。 但项目一旦继续往前推进,问题就会开始变化。 最开始关心的是“能不能升级”,很快就会变成`“升级能不能稳定跑”``“能不能适配更多存储方式”“能不能支持更多算法”“能不能减少包体积”“能...
hid-core
[toc] HID Core:全面了解与深度解析文件路径 / 技术中文名 / 功能概述 文件路径:drivers/hid/hid-core.c 技术中文名:HID 核心层驱动 功能概述:hid-core.c 是 Linux HID 子系统的公共核心实现,负责 HID 报告描述符解析、设备分组、驱动匹配、输入报告解释、事件分发,以及 hidinput、hidraw、hiddev 等上层消费路径的连接。它本身不是 USB、I2C、Bluetooth 这类传输驱动,而是位于这些传输驱动之上的通用 HID 核心。 介绍drivers/hid/hid-core.c 在 Linux HID 栈中的位置非常明确:它属于 HID bus 的公共核心层,不直接负责总线收发,也不直接等同于输入子系统驱动。它的职责是把“某个传输层送上来的 HID 设备”和“上层具体的 HID 驱动、input 接口、hidraw 接口、hiddev 接口”连接起来。 从当前主线实现看,HID 子系统被组织成一种总线模型。传输驱动负责设备发现、底层收发、设备启动与停止;hid-core.c ...
mmci
[toc] MMCI(ARM PrimeCell PL18x 主机控制器驱动):全面了解与深度解析文件路径 / 技术中文名 / 功能概述 文件路径:drivers/mmc/host/mmci.c 技术中文名:MMCI(ARM PrimeCell PL180/PL181 及衍生控制器的 MMC/SD/SDIO Host 驱动) 功能概述:该文件是 Linux MMC host 层驱动实现,负责把 MMC core 发下来的命令与数据请求,转换成 MMCI/SDMMC 控制器寄存器操作,覆盖命令发送、响应接收、数据通路控制、PIO 与 DMA 传输、中断处理、时钟与电源控制,以及不同硬件变体的差异适配。 介绍drivers/mmc/host/mmci.c 属于 Linux MMC 子系统里的 Host Controller Driver。它不负责块层调度,也不负责文件系统,而是直接驱动一类具体的 MMC/SD/SDIO 控制器 IP。 从主线实现看,这个文件不是“单一芯片专用驱动”,而是一个覆盖面...
黄金比例乘法哈希与哈希表大小设计原理
[toc] 黄金比例乘法哈希与哈希表大小设计原理 本文说明一种常见的静态哈希表设计:黄金比例乘法哈希(Multiplicative Hashing) + 2 的幂桶表结构。该方案来源于 Knuth 在《The Art of Computer Programming》中提出的哈希理论,在系统软件与嵌入式环境中被广泛采用。 示例代码通过编译期计算哈希表大小,并使用黄金比例相关常数实现均匀分布的哈希函数。 使用黄金比例常数实现乘法哈希哈希常数定义如下: 1#define PAR_ID_HASH_GOLDEN_RATIO_32 (0x61C88647u) 该常数来源于黄金比例相关公式: 1A = (√5 − 1) / 2 乘法哈希公式: 1h(k) = floor(m * frac(k * A)) 其中: 符号 含义 k key A 常数 m 哈希表大小 在 32 位整数实现中,公式通常转化为: 12hash = key * constantindex = hash >> shift 或: 1index = hash & mask...
将隐藏在副屏的 Windows 11 程序窗口恢复到主屏
将隐藏在副屏的 Windows 11 程序窗口恢复到主屏当 Windows 11 曾连接过副屏时,系统会记录窗口位置。断开副屏后,部分程序可能仍然在“不可见区域”打开。可通过系统自带的“移动”功能将窗口拉回主屏。 使用“移动”功能恢复窗口位置(通用方法)适用于所有常规桌面程序,无需修改显示设置。 1. 切换到目标程序按: 1Alt + Tab 切换到无法看到的那个程序窗口,确保其处于当前活动状态。 2. 打开窗口控制菜单按: 1Alt + 空格 此操作会打开当前窗口的系统菜单。 3. 进入“移动”模式按: 1M 此时系统进入窗口移动状态。 4. 激活移动按一次方向键(例如): 1← 或 → 这一步非常关键,用于激活键盘移动模式。 5. 使用鼠标拖回窗口移动鼠标。 隐藏的窗口会跟随鼠标移动并重新出现在主屏幕上。 在合适位置单击鼠标左键确认。 原理说明Windows 会记录程序上一次关闭时的屏幕坐标。断开副显示器后,这些坐标仍然存在,但对应的显示区域已不可见。通过“移动”功能,可以强制改变窗口坐标,使其回到当前可见屏幕范围。 适用场景 曾使用双屏或扩展屏 笔记本...
显卡DXGI_ERROR_DEVICE_HUNG 的处理指南
[TOC] 显卡DXGI_ERROR_DEVICE_HUNG 的处理指南 背景与成因DXGI_ERROR_DEVICE_HUNG(0x887A0006) 表示图形设备在执行过程中进入“挂起/无响应”状态,常见表现为游戏卡死后闪退。该错误属于 DXGI 错误码的一种。 (Microsoft Learn) 当显存(VRAM)被高分辨率贴图、光线追踪缓存、长时间游玩累积的资源占用推到上限时,显卡需要频繁回收/搬运资源;若某些渲染任务因此耗时过长,可能触发 Windows 的 TDR(超时检测与恢复) 机制,系统会重置图形栈来避免整机无响应,最终表现为游戏崩溃或驱动重置。 (Microsoft Learn) 快速判断是否为“爆显存”触发用任务管理器确认“专用 GPU 内存”是否贴顶 打开 任务管理器 → 性能 → 选择 GPU。 观察 Dedicated GPU memory usage(专用 GPU 内存) 是否长期接近上限,尤其是在崩溃前持续攀升。Windows 的 GPU 内存统计与分解方式在 DirectX 团队说明中有详细解释。 (Microsoft f...







