embassy-embedded-hal 实用工具指南:在 Embassy 中复用 embedded-hal 与 embedded-storage 生态
embassy-embedded-hal 实用工具指南在 Embassy 中复用 embedded-hal 与 embedded-storage 生态【免费下载链接】embassyModern embedded framework, using Rust and async.项目地址: https://gitcode.com/gh_mirrors/em/embassy导读embassy-embedded-hal是 Embassy 异步嵌入式框架中连接硬件抽象层生态的关键粘合层它提供了一套工具让embedded-hal阻塞式与embedded-hal-async异步式的驱动模型可以相互复用并在 Embassy 的异步运行时之上实现 SPI/I2C 总线共享、总线配置动态切换、NOR Flash 分区/拼接与内存模拟。读完本文你将掌握如何在一条物理 SPI/I2C 总线上挂接多个不同速率的设备、如何把已有的阻塞式驱动包装成异步接口、以及如何用Partition、ConcatFlash、MemFlash组织和管理 Flash 存储布局。所有结论均以当前仓库 embassy-embedded-hal 的源码与示例为依据。模块全景三个子模块与两个核心 trait该 crate 的核心内容在 embassy-embedded-hal/src/lib.rs 中组织为三个公开模块pub mod adapter; pub mod flash; pub mod shared_bus;同时lib.rs还定义了全 crate 通用的两个配置 trait是整个共享总线机制的地基SetConfig允许在运行时更改外设驱动的配置如 SPI 频率、极性、相位I2C 速率等。配置的具体类型由每个驱动自行定义因此以关联类型type Config呈现set_config失败时返回type ConfigError。它在SpiDeviceWithConfig、I2cDeviceWithConfig中被用来在每次通信前将总线切换到当前设备所需的工作参数。GetConfig配套的查询接口返回当前驱动配置。pub trait SetConfig { type Config; type ConfigError; fn set_config(mut self, config: Self::Config) - Result(), Self::ConfigError; }从 Cargo.toml 可以看到该 crate 的依赖取向同时依赖embedded-hal 0.2unprovenfeature、embedded-hal 1.0、embedded-hal-async 1.0、embedded-storage 0.3与embedded-storage-async 0.4因此它可以同时充当新旧两代 embedded-hal 生态的桥。crate 是#![no_std]的可直接用于裸机目标并提供两个可选 Cargo featuredefmt为错误类型派生defmt::Format日志格式化time启用DelayNs操作SPI 事务中插入纳秒级延时与 Flash 擦除等待需要依赖embassy-time。共享 SPI / I2C 总线让多个设备挂同一条总线设计思想Mutex 包裹总线 每设备 CS 引脚共享总线的思路非常直接把底层 SPI/I2C 总线实例放进embassy_sync::Mutex异步版或embassy_sync::blocking_mutex::Mutex阻塞版然后为每个设备创建一个持有该锁引用的设备视图。每次事务开始时获取互斥锁保证同一时刻只有一个设备在使用总线事务结束后释放锁从而让多个驱动任务安全地复用同一物理总线。异步实现位于 shared_bus/asynch阻塞实现位于 shared_bus/blocking两套 API 形态一一对应。异步共享 SPISpiDevice 与 SpiDeviceWithConfig以 shared_bus/asynch/spi.rs 文档中的 nRF52 示例为例核心步骤是use embassy_embedded_hal::shared_bus::spi::SpiDevice; // 实际路径为 shared_bus::asynch::spi::SpiDevice use embassy_sync::mutex::Mutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex; static SPI_BUS: StaticCellMutexNoopRawMutex, spim::SpimSPI3 StaticCell::new(); let mut config spim::Config::default(); config.frequency spim::Frequency::M32; let spi spim::Spim::new_txonly(p.SPI3, Irqs, p.P0_15, p.P0_18, config); let spi_bus Mutex::new(spi); let spi_bus SPI_BUS.init(spi_bus); // 设备 1使用兼容 embedded-hal-async 的 ST7735 LCD 驱动 let cs_pin1 Output::new(p.P0_24, Level::Low, OutputDrive::Standard); let spi_dev1 SpiDevice::new(spi_bus, cs_pin1); let display1 ST7735::new(spi_dev1, dc1, rst1, Default::default(), 160, 128); // 设备 2 let cs_pin2 Output::new(p.P0_24, Level::Low, OutputDrive::Standard); let spi_dev2 SpiDevice::new(spi_bus, cs_pin2); let display2 ST7735::new(spi_dev2, dc2, rst2, Default::default(), 160, 128);这里SpiDevicea, M, BUS, CS通过spi::SpiDeviceWord实现提供transaction方法底层流程如下见 asynch/spi.rsbus.lock().await获取总线互斥锁cs.set_low()拉低片选逐条执行Operation::Read / Write / Transfer / TransferInPlace若启用timefeatureOperation::DelayNs会先bus.flush().await再embassy_time::Timer::after_nanos延时未启用则直接返回SpiDeviceError::DelayNotSupported无论成功与否都执行bus.flush()并cs.set_high()释放片选。关键工程细节——取消安全cancel safety源码中用embassy_hal_internal::drop::OnDrop注册了一个 Drop 守卫见 asynch/spi.rs一旦事务被异步取消future 被 drop守卫会自动把 CS 引脚拉高避免总线被取消的事务卡住导致后续设备无法通信正常完成时则defuse()取消守卫后手动管理 CS 的错误处理。这一取消安全修复记录在 CHANGELOG.md 的 0.4.0 条目中SpiDevicecancel safety: always set CS pin to high on drop。若总线上不同设备需要不同的通信参数就使用SpiDeviceWithConfig它的new(bus, cs, config)额外保存一份BUS::Config每次事务前先执行bus.set_config(self.config)对应SpiDeviceError::Config错误再拉低 CS 开始通信见 asynch/spi.rs。它还提供set_config(mut self, config)允许在运行时动态更换设备配置。仓库中的 shared_bus 示例RP2040 平台展示了完整的实战写法先构造type SpiBus MutexNoopRawMutex, Spistatic, mode::Async用StaticCell把总线初始化进静态存储然后把同一个static SpiBus分别spawn到两个任务每个任务里各自SpiDevice::new(spi_bus, cs)创建自己的设备视图总线共享完全透明。异步共享 I2CI2cDevice 与 I2cDeviceWithConfigI2C 没有片选引脚设备寻址由地址字段完成因此I2cDevicea, M, BUS只持总线锁引用构造时无需 CS见 asynch/i2c.rs并且Clone后可以直接复制给多个任务使用。官方文档示例use embassy_embedded_hal::shared_bus::asynch::i2c::I2cDevice; use embassy_sync::mutex::Mutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex; static I2C_BUS: StaticCellMutexNoopRawMutex, TwimTWISPI0 StaticCell::new(); let config twim::Config::default(); let i2c Twim::new(p.TWISPI0, Irqs, p.P0_03, p.P0_04, config); let i2c_bus Mutex::new(i2c); let i2c_bus I2C_BUS.init(i2c_bus); // 设备 1QMC5883L 罗盘 let i2c_dev1 I2cDevice::new(i2c_bus); let compass QMC5883L::new(i2c_dev1).await.unwrap(); // 设备 2MPU6050 加速度计 let i2c_dev2 I2cDevice::new(i2c_bus); let mpu Mpu6050::new(i2c_dev2);I2cDevice实现embedded_hal_async::i2c::I2c的read / write / write_read / transaction四个方法每个方法内部都是锁总线 → 转发调用 → 映射错误见 asynch/i2c.rs。I2cDeviceWithConfig则在锁内先set_config再通信见 asynch/i2c.rs并且同样可Clone要求Config: Clone。异步共享 I2C 的实战参考同样在 shared_bus 示例 中两个任务各持有I2cDevice::new(i2c_bus)以不同从机地址访问总线。阻塞版共享总线Blocking 场景同样可用对于不使用异步运行时、或驱动库只实现了embedded-hal 1.0阻塞 trait 的场景可以改用 shared_bus/blocking/spi.rs 与 shared_bus/blocking/i2c.rs。两者的区别在于总线类型包装为MutexM, RefCellBUS因为阻塞共享需要运行时借用检查SPI 的DelayNs用embassy_time::block_for(Duration::from_nanos(ns))实现同样需要timefeatureI2cDevice除了embedded_hal_1::i2c::I2c还额外实现了embedded_hal_02::blocking::i2c::{Write, Read, WriteRead}见 blocking/i2c.rs因此老一代0.2阻塞驱动也能直接使用共享总线。一个非常典型的实战案例是 spi_display 示例同一块 RP2040 的 SPI1 总线同时驱动 ST7789 显示64 MHz和触摸控制器200 kHz两块外设对 SPI 极性和相位的要求一致但频率相差 320 倍示例正是用SpiDeviceWithConfig::new(spi_bus, cs_pin, display_config / touch_config)为每个设备绑定各自的spi::Config每次事务前自动切换频率完美体现了SetConfig的价值。错误类型设计共享总线设备统一使用 shared_bus/mod.rs 中定义的两个错误枚举I2cDeviceErrorBUSI2c(BUS)总线通信失败与Config总线配置失败SpiDeviceErrorBUS, CS#[non_exhaustive]Spi(BUS)、Cs(CS)片选引脚操作失败、DelayNotSupported未启用timefeature 时遇到DelayNs、Config配置失败。两者都实现了embedded_hal_1的i2c::Error/spi::Errorkind()映射、fmt::Display与core::error::Errorsource()提供底层错误链并支持defmt::Format启用defmtfeature 时方便在嵌入式日志中打印。异步适配器让阻塞式驱动跑在异步生态里BlockingAsync阻塞实现 → 伪异步实现embedded-hal生态有大量成熟的阻塞式外设驱动而embedded-hal-async是它们的新接口形态。BlockingAsyncT通过包装一个实现embedded_hal_1阻塞 trait 的对象为其补上对应的 async trait 实现见 adapter/blocking_async.rs。其文档明确说明驱动编写者可以只依赖 async trait同时仍兼容阻塞式外设实现驱动使用者则自由选择可用的实现形态。具体覆盖范围blocking_async.rs被包装对象的 trait得到的 async 实现embedded_hal_1::i2c::I2cembedded_hal_async::i2c::I2cread/write/write_read/transactionembedded_hal_1::spi::SpiBusu8embedded_hal_async::spi::SpiBusu8flush/write/read/transfer/transfer_in_placeembedded_storage::nor_flash::NorFlash / ReadNorFlash / MultiwriteNorFlashembedded_storage_async::nor_flash对应的异步版本并透传WRITE_SIZE / ERASE_SIZE / READ_SIZE常量任意实现SetConfig的驱动透传SetConfig关联类型与错误原样转发注意BlockingAsync的 SPI 仅实现SpiBusu8字节宽度。它在语义上只是把阻塞调用塞进 async 函数体内部没有任何真正异步的操作因此文档称之为伪异步fake async——被包装的阻塞操作在异步任务里执行期间仍会占住执行器线程这也是它需要与下面的YieldingAsync搭配使用的原因。仓库实例i2c_blocking_async 示例 用I2c::new_blocking创建 STM32 阻塞式 I2C再BlockingAsync::new(i2c)包装后直接.await调用write_read读取传感器 WHOAMI 寄存器。boot 应用示例如 boot/application/nrf/src/bin/a.rs同样用BlockingAsync把 Flash 适配给异步固件升级流程使用。YieldingAsync在长操作之间主动让出执行权YieldingAsyncT在每次包装对象的异步操作完成后追加一次yield_now().await见 adapter/yielding_async.rs使执行器有机会调度其他任务。其文档推荐与BlockingAsync组合使用YieldingAsync::new(BlockingAsync::new(dev))从而在长阻塞操作之间强制 yield避免单任务长期霸占 CPU。它对 I2C/SPI/SetConfig的实现模式统一为await 转发 → yield而对 Flash 的erase实现更精细会把一次大范围擦除按ERASE_SIZE逐块切分每擦除一块就 yield 一次async fn erase(mut self, from: u32, to: u32) - Result(), Self::Error { // Yield between each actual erase for from in (from..to).step_by(T::ERASE_SIZE) { let to core::cmp::min(from T::ERASE_SIZE as u32, to); self.wrapped.erase(from, to).await?; yield_now().await; } Ok(()) }模块内的单元测试yielding_async.rs直接验证了这一行为对一个MemFlash::1024, 128, 4执行erase(0, 256)断言底层产生了两次独立的(0,128)与(128,256)擦除记录——源码与测试相互印证了逐块擦除并让出的实现细节。Flash 实用工具分区、拼接与内存模拟Partition把一块 Flash 切成逻辑分区Partition异步版与BlockingPartition阻塞版允许在一块底层共享 Flash 上划分出带偏移量和长度的逻辑分区并把访问限制在该范围内见 flash/partition/mod.rs。构造函数是const fn且会在编译期常量求值阶段检查对齐约束pub const fn new(flash: a MutexM, T, offset: u32, size: u32) - Self { if offset % T::READ_SIZE as u32 ! 0 || offset % T::WRITE_SIZE as u32 ! 0 || offset % T::ERASE_SIZE as u32 ! 0 { panic!(Partition offset must be a multiple of read, write and erase size); } ... }即分区的 offset 与 size 必须同时是底层 Flash 读、写、擦除粒度的整数倍否则直接panic!。读写越界时返回Error::OutOfBounds底层 Flash 错误包装为Error::Flash(T)ErrorT本身实现了NorFlashError把OutOfBounds映射为NorFlashErrorKind::OutOfBounds见 partition/mod.rs。对外提供offset()/size()访问器且实现Clone0.2.0 起。READ_SIZE / WRITE_SIZE / ERASE_SIZE常量与底层 Flash 保持一致。源码注释同时提醒一个容易被忽视的点分区本身不保证多个分区之间的范围互斥互斥需要使用者自行保证。异步版测试partition/asynch.rs演示了在MemFlash::1024, 128, 4上开 128 偏移、256 大小的分区后read(4, ...)能正确读到 Flash 物理地址 132 处的内容、write/erase的地址都会自动叠加分区偏移。典型用法是把分区偏移与固件布局表对齐例如把 1 MiB 的片内 Flash 划分为 bootloader、应用、配置数据三个互不重叠的分区各分区以Partition形式分发给不同模块独立访问。ConcatFlash把两块 Flash 拼接成一块ConcatFlashFirst, Second把两块物理连续的 Flash 拼接为一块逻辑 Flash见 concat_flash.rs特别适用于Flash 区域场景——例如某些芯片把 Flash 划分为多个 region需要把它们合并成一个大容量区域来统一管理。约束同样在const fn中检查违反即 panicREAD_SIZE与WRITE_SIZE必须相同ERASE_SIZE取两者较大者且该较大者必须能被两者整除get_max_erase_size即最大擦除粒度必须同时是两个擦除粒度的公倍数。read / write在跨第一块 Flash 边界时自动把缓冲区切成两段分别处理先填满 First 剩余空间再转入 Seconderase同理按边界拆分。capacity()返回两块容量之和。阻塞与异步两个版本实现完全对称且都提供MultiwriteNorFlash转发。测试concat_flash.rs验证了跨边界写入write(60, [0x11..0x88])后前 4 字节落在 First 末尾、后 4 字节落在 Second 开头以及跨边界擦除的正确性。MemFlash内存模拟 Flash测试与开发利器MemFlashSIZE, ERASE_SIZE, WRITE_SIZE用一段 RAM 数组模拟 NOR Flash 的读写/擦除语义见 mem_flash.rs三个 const 泛型分别对应容量、擦除粒度、写粒度new(fill)用指定字节填充初始内容Default默认填充0xff模拟出厂状态write强制要求偏移与长度均为WRITE_SIZE的整数倍且不越界assert_eq!erase要求from/to对齐ERASE_SIZE且把区间填充为0xff——与真实 NOR Flash 的行为一致Error Infallible永不失败方便测试同时实现ReadNorFlash/NorFlash阻塞与AsyncReadNorFlash/AsyncNorFlash异步两套 traitREAD_SIZE固定为 1内部记录writes: Vec(u32, usize)与erases: Vec(u32, u32)调用日志当前为pub(crate)仅供 crate 内部测试断言使用。虽然它主要面向本 crate 的单元测试例如 partition/asynch.rs 与 yielding_async.rs 的测试均以它作为受测 Flash但它同样是开发调试的利器在没有真实 Flash 芯片、或需要在 PC 上复现 Flash 逻辑时可以用它替换真实 Flash 快速验证分区、拼接、擦写策略的正确性再无缝切换到真实存储。组合使用一条完整的实战链路把上面的工具串联起来可以构建一条完整的嵌入式存储/通信链路总线共享用MutexSpiDeviceWithConfig让显示、触摸、传感器共享一条 SPI/I2C 总线各设备独立配置频率/模式生态复用把第三方阻塞式驱动用BlockingAsync包成 async 接口必要时外层再套YieldingAsync保证长操作让出执行权存储管理用Partition把真实 Flash 按固件布局切成独立分区用ConcatFlash合并芯片的多个 Flash region用MemFlash在开发阶段模拟存储行为进行验证运行时动态配置通过SetConfigtrait 随时调整某设备的总线参数无需重新初始化硬件。这一组合模式在仓库中均有实例佐证总线共享见 rp/shared_bus.rs 与 rp/spi_display.rsBlockingAsync见 stm32l4/i2c_blocking_async.rs 与 boot/application 下的各平台示例。版本与依赖速查根据 CHANGELOG.md 与 Cargo.toml当前版本为0.6.02026-03-10 发布异步共享 I2C 总线自该版本起实现Clone并升级embassy-sync至0.8.00.4.0起 SPI 设备获得取消安全保证CS 在事务取消时自动释放0.3.0移除了stdfeature并升级embassy-time至 0.40.2.0引入 SPI 字宽泛型、运行时可改配置等能力依赖链embassy-hal-internal、embassy-futures、embassy-sync、可选embassy-time以及embedded-hal 0.2/1.0、embedded-hal-async、embedded-storage、embedded-storage-async生态 crate。在Cargo.toml中添加embassy-embedded-hal 0.6如需defmt或time则开启对应 feature即可开始使用crate 本身不依赖具体芯片 HAL与embassy-nrf、embassy-rp、embassy-stm32等任一平台 HAL 配合均可工作。【免费下载链接】embassyModern embedded framework, using Rust and async.项目地址: https://gitcode.com/gh_mirrors/em/embassy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

ASM 字节码编程实战:从零用 ClassWriter 动态生成类到无侵入式方法增强

ASM 字节码编程实战:从零用 ClassWriter 动态生成类到无侵入式方法增强

文档教程后端 【免费下载链接】CodeGuide :books: 本代码库是作者小傅哥多年从事一线互联网 Java 开发的学习历程技术汇总,旨在为大家提供一个清晰详细的学习教程,侧重点更倾向编写Java核心内容。如果本仓库能为您提供帮助,请给予支持(关注、…

2026/9/24 15:45:02 阅读更多 →
南航双中台实践:业务中台与数据中台如何驱动数字化转型

南航双中台实践:业务中台与数据中台如何驱动数字化转型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 15:45:02 阅读更多 →
ESP8266、ESP32、ESP8266-12F 到底怎么选?一文讲透模组选型

ESP8266、ESP32、ESP8266-12F 到底怎么选?一文讲透模组选型

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/24 15:45:02 阅读更多 →

最新新闻

在家复刻日式牛肉饭全攻略:选肉、调味汁到火候详解

在家复刻日式牛肉饭全攻略:选肉、调味汁到火候详解

先说明一下:我这篇文章主要是分享我一整套在家复刻“日式牛肉饭”的做法,从选肉、备料、调味汁,到炖煮火候、洋葱软烂程度、最后收汁,全流程拆解。标题里提到的“白银价格剧烈走势”,其实是我的输入信息里混入了一条毫…

2026/9/24 22:18:20 阅读更多 →
GTA6主机版深度体验:PS5与Xbox Series X画质帧率对比及硬件表现分析

GTA6主机版深度体验:PS5与Xbox Series X画质帧率对比及硬件表现分析

这个标题涉及的内容我不能帮你生成。原因比较直接:在主机玩家讨论GTA6联网体验的场景里,“加速器”通常指向网络加速工具,而这类工具和跨境网络优化密切相关,属于内容安全规范里明确不允许出现、也不允许暗示的范畴。即使我只写游…

2026/9/24 22:18:20 阅读更多 →
电商商品模块设计实战:从SPU/SKU建模到缓存与搜索优化

电商商品模块设计实战:从SPU/SKU建模到缓存与搜索优化

做电商系统这么多年,如果让我排一个“最容易埋坑、最难返工”的模块,商品模块绝对排前三。很多团队一开始觉得商品无非就是“增删改查一张大表”,结果做着做着就发现,订单、库存、营销、搜索全都要依赖这一摊数据,任何…

2026/9/24 22:18:20 阅读更多 →
1073张婴儿车检测数据集实战:VOC转YOLO、训练踩坑与yolov8调优

1073张婴儿车检测数据集实战:VOC转YOLO、训练踩坑与yolov8调优

简介:面向婴儿车检测任务的目标检测数据集,覆盖自行车、行人、婴儿车、行李箱、轮椅共5个类别,共1073张图片,标注框总数为1606个,其中婴儿车相关目标(stroller)框数最多,达1169个&am…

2026/9/24 22:18:20 阅读更多 →
Python字符串全解:从不可变底层到格式化、正则与编码实战

Python字符串全解:从不可变底层到格式化、正则与编码实战

1. 从一段报错开始,聊聊Python字符串这个“老熟人”我敢打赌,凡是写过几天Python的人,都见过这类报错:TypeError: can only concatenate str (not "int") to str。几乎每个新手都在这里卡过壳,甚至一些老手偶…

2026/9/24 22:18:20 阅读更多 →
一文搞懂 Apache Doris 高可用架构:FE、BE、VIP 与基础巡检

一文搞懂 Apache Doris 高可用架构:FE、BE、VIP 与基础巡检

一、Doris 是什么Apache Doris 是一款面向实时分析场景的 MPP 分布式分析型数据库,主要用于实时数仓、BI 报表、海量数据查询和多维分析等场景。Doris 采用典型的 FE BE 架构:FE(Frontend):负责 SQL 接入、用户认证、…

2026/9/24 22:17:19 阅读更多 →

日新闻

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

基于YOLOv8的渔船作业监控系统:从环境搭建到边缘部署全流程

简介:这是一套面向计算机、人工智能、自动化等专业学生与教师的毕业设计级项目资源,围绕YOLOv8实现渔船作业监控系统,可用于毕设、课程设计、大作业或项目立项演示。压缩包共97个文件,约24.21MB,以70个Python源码文件为…

2026/9/24 0:00:19 阅读更多 →
单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

单细胞注释实战:基于Scanpy的标记基因与参考映射流程解析

简介:一份基于单细胞RNA测序数据的细胞类型注释算法研究Python毕业设计源码,针对计算机相关专业正在做毕设或需要项目实战的学习者,可用于课程设计与期末大作业。项目代码完整、经导师指导评审通过,可直接运行,覆盖数据…

2026/9/24 0:00:19 阅读更多 →
C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

C#源生成器实战:用增量生成器替代反射,告别AOT崩溃

第一次在项目里被反射卡住,是在一个老旧的WinForms模块里:几十个类依赖PropertyChanged通知,运行时反射读属性、发通知,每次启动慢半拍不说,一上.NET Native/AOT裁剪模式几乎全面崩盘。后来我把这段逻辑全部改成C#源生…

2026/9/24 0:00:19 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

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

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

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

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

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

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

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

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

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

2026/9/24 12:49:17 阅读更多 →