embassy 串口链路层实现

使用embassy在nrf52833上实现一个蓝牙网关功能。因为要跟主芯片通信,于是定义了link层通信协议:

构思了link层要实现的功能:

帧的解析封装都比较好实现:

///发送封装
pub fn pack_send_msg(
    func_code: FuncCode,
    msg_id: u16,
    msg: &[u8],
) -> Result<Vec<u8, MSG_DATA_LEN_MAX>, ComLinkError> {
    let mut buf = Vec::new();
    buf.push(0xA5)?; //frame head high byte
    buf.push(0x5A)?; //frame head low byte
    buf.push(func_code.into())?; //function code
    buf.extend_from_slice(&msg_id.to_be_bytes())?; //msg id
    buf.extend_from_slice(&(msg.len() as u16).to_be_bytes())?; //msg length
    buf.extend_from_slice(msg)?; //msg data
    let crc = crc16(0xffff, &buf[2..]);
    buf.extend_from_slice(&crc.to_be_bytes())?; //crc16
    Ok(buf)
}

pub struct MsgParser {
    state: ParseState, //parse state
    calc_crc: u16,     //calculated crc value
    msg: MsgRecv,      // msg storage when parsing
}

#[derive(Debug, Clone, Default)]
struct DataVec(Vec<u8, MSG_RECV_PARSE_BUF_LEN>);
impl Format for DataVec {
    fn format(&self, fmt: defmt::Formatter) {
        defmt::write!(fmt, "{:02x}", Bytes(&self.0))
    }
}

#[derive(Debug, Clone, Default, Format)]
pub struct MsgRecv {
    func_code: FuncCode,
    msg_id: u16,
    msg_len: u16,
    data: DataVec,
    recv_crc: u16, //received crc value
}
///接收解析
    pub fn parse(&mut self, data: &[u8]) -> MsgRecvVec {
        let mut msg_recv_vec = MsgRecvVec::default();
        let mut i = 0;

        while i < data.len() {
            match self.state {
                ParseState::BeginH => {
                    if data[i] == 0xA5 {
                        self.state = ParseState::BeginL;
                    }
                    i += 1;
                }
                ParseState::BeginL => {
                    if data[i] == 0x5A {
                        self.state = ParseState::FuncCode;
                    } else
Rust 中的异步运行时框架 **Tokio** 和 **embassy** 是为不同应用场景设计的,它们在目标平台、资源占用、功能特性以及适用场景上有显著差异。以下是对两者的详细对比分析: ### 目标平台与适用环境 - **Tokio** 主要面向通用操作系统和服务器端应用,适用于 Linux、Windows、macOS 等主流操作系统[^4]。 - **embassy** 则专注于嵌入式系统和裸机环境,特别适合在没有操作系统的微控制器(如 ARM Cortex-M 系列)上运行,强调低功耗和实时性[^1]。 ### 运行时模型与调度机制 - **Tokio** 采用多线程调度模型,支持 I/O 多路复用(epoll/kqueue/iocp),可以高效地处理大量并发连接。它内置了定时器、任务调度器、异步通道等组件,适合构建高并发网络服务[^4]。 - **embassy** 使用单线程或协程式的调度模型,依赖于硬件中断和事件驱动机制。其任务调度是静态分配的,通常基于固定的优先级策略,适用于对实时性和确定性要求较高的嵌入式场景[^1]。 ### 内存管理与资源消耗 - **Tokio** 在运行时会动态分配内存以支持灵活的任务调度和 I/O 操作,因此在资源丰富的环境中表现良好。 - **embassy** 设计为“零分配”模式,在编译期就完成大部分资源分配,避免运行时堆内存使用,从而更适合内存受限的嵌入式设备[^2]。 ### 异步生态与标准库支持 - **Tokio** 提供了完整的异步标准库接口,包括文件、网络、进程间通信等模块,兼容 `std` 环境,并广泛用于企业级后端开发[^4]。 - **embassy** 需要在 `no_std` 环境下运行,依赖于轻量级的异步抽象(如 `futures` crate),并提供了针对嵌入式平台的 GPIO、SPI、I2C 等外设绑定。 ### 实际生产案例 - **Tokio** 被广泛应用于 AWS SDK、tower 框架、FusionCore 边缘计算平台等高性能网络服务中,支持温室集群监测等复杂并发任务。 - **embassy** 已被用于嵌入式异步运行时项目,例如 Fuchsia OS 的部分网络栈实现中,展示了其在低功耗物联网设备中的实用性[^1]。 ### 总结对比表 | 特性 | Tokio | embassy | |---------------------|-------------------------------|------------------------------| | 平台支持 | 通用 OS(Linux/Windows/macOS)| 嵌入式 MCU(ARM/RISC-V) | | 调度模型 | 多线程 + I/O 多路复用 | 单线程 + 事件驱动 | | 内存使用 | 动态分配 | 静态分配 / 零分配 | | 标准库依赖 | `std` | `no_std` | | 适用场景 | 高并发网络服务、后端 API | IoT 设备控制、传感器采集 | | 社区活跃度与生态 | 高 | 中等 | ### 示例代码对比 #### Tokio 示例:HTTP 请求处理 ```rust use tokio::net::TcpListener; use tokio::io::{AsyncReadExt, AsyncWriteExt}; #[tokio::main] async fn main() { let listener = TcpListener::bind("127.0.0.1:8080").await.unwrap(); loop { let (mut socket, _) = listener.accept().await.unwrap(); tokio::spawn(async move { let mut buf = [0; 1024]; let n = socket.read(&mut buf).await.unwrap(); socket.write_all(&buf[0..n]).await.unwrap(); }); } } ``` #### embassy 示例:LED 控制 ```rust use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; use embassy_stm32::gpio::{Level, Output, Pin}; #[embassy_executor::task] async fn blink_led(mut led: Output<'static, PA5>) { loop { led.set_high(); Timer::after(Duration::from_millis(500)).await; led.set_low(); Timer::after(Duration::from_millis(500)).await; } } #[embassy_executor::main] fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); let led = Output::new(p.PA5, Level::Low); spawner.spawn(blink_led(led)).unwrap(); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值