• Rust嵌入式编程---动态内存分配器(Vec,String等)


    本教程不是0基础的Rust嵌入式编程,需要有一定的Rust裸机编程的基础知识。
    作为一个比较接近C的例子,适合入门,代码比较容易理解。本次例子使用的是target = “thumbv8m.main-none-eabihf” # Cortex-M33 (with FPU)平台进行编译,生成的二进制文件在Qemu模拟器中运行。
    嵌入式系统编程是不能使用Rust的Std库的,只能使用它的子库:core。以及一些cortex库还有导入的一些外部库,看代码例子即可。
    首先就是安装qemu模拟器和一些Rust编译的工具,这部分可以参考网上教程,有点麻烦。
    下面直接附上内存分配器的代码,这个部分挺重要的,定义之后就可以使用vec、string、hashmap等数据结构,这对于裸机Rust编程是非常重要的,代码里面有详细的注释。下面对动态分配内存和无堆分配内存两种模式进行介绍:

    动态分配内存
    #![feature(alloc_error_handler)]
    #![no_main]
    #![no_std]
    #![feature(alloc)]
    
    extern crate alloc;
    use panic_halt as _;
    
    use alloc::vec;
    use core::alloc::Layout;
    use alloc::string::String;
    
    use alloc_cortex_m::CortexMHeap;
    use cortex_m::asm;
    use cortex_m_rt::entry;
    use cortex_m_semihosting::{hprintln,debug};
    //全局分配器定义
    //为了能够在单片机上开辟一块作为堆的内存,首先要调用cortex_m_rt::heapstart()函数方法
    //分配指定大小HEAP_SIZE的内存,本程序HEAP_SIZE大小定义为1024字节。
    #[global_allocator]
    static ALLOCATOR:CortexMHeap=CortexMHeap::empty();
    const HEAP_SIZE:usize=1024; //byte
    
    #[entry]
    fn main()->!{
        // 初始化内存分配器
        unsafe{ALLOCATOR.init(cortex_m_rt::heap_start() as usize,HEAP_SIZE)}
        //字符串定义,导入之后和std中用法类似。
        let s = String::from("hello");
        for c in s.chars() {
            hprintln!("{}", c);
        }
        //Vec类型,使用方法一致。
        let mut xs=vec![0,1,2];
        xs.push(3);
        //简单的函数调用
        let s=add(1,2);
        hprintln!("{}","qemu vec:").unwrap();
        hprintln!("{:?}",xs).unwrap();
        hprintln!("{:?}",s).unwrap();
        //只有在qemu中模拟才用下面这句,在真机环境不需要。退出qemu
        debug::exit(debug::EXIT_SUCCESS);
        loop{}
    }
    //内存分配错误处理
    #[alloc_error_handler]
    fn alloc_error(_layout:Layout)->!{
        asm::bkpt();
        loop{}
    }
    fn add(a:i32,b:i32)->i32{
        a+b
    }
    

    编译命令(已配置过):
    cargo build --example allocator2
    qemu运行命令:
    qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -semihosting-config enable=on,target=native -kernel target/thumbv8m.main-none-eabihf/debug/examples/allocator2
    代码运行结果如下:
    在这里插入图片描述

    无堆分配内存

    啥叫无堆分配内存呢?heapless不需要设置,因为它的集合不依赖于全局内存分配器,必须预先声明集合的容量。 不重新分配,并具有固定容量,此容量是集合类型签名的一部分。在这种情况下,我们已经声明具有8个元素的容量,即向量最多可以容纳8个元素。上面的动态分配是可以改变内存大小的,和C语言里面的malloc函数一致理解。但是这里不可以,分配了就是固定的,这种缺点显而易见:由于集合具有固定容量,因此将元素插入集合中的所有操作都可能失败,错误处理也是一个比较麻烦的事。
    这里还引入一个概念:最坏情况执行时间(WCET)。
    如果您正在构建时间敏感型应用程序或硬实时应用程序,那么您可能非常关心程序不同部分的最坏情况执行时间。
    有堆分配集合可以重新分配,因此可能增加集合的操作的WCET还将包括重新分配集合所需的时间,这本身取决于集合的运行时容量。这使得很难确定操作的WCET,因为它取决于正在使用的分配器及其运行时容量。
    另一方面,固定容量集合不重新分配,因此所有操作都有可预测的执行时间,例如,在常量时间内执行。
    以下是无堆分配的详细代码:

    #![no_main]
    #![no_std]
    extern crate heapless; // v0.4.x
    use cortex_m_rt::entry;
    use heapless::Vec;
    use heapless::consts::*;
    use panic_halt as _;
    use cortex_m_semihosting::{hprintln,debug};
    
    #[entry]
    fn main() -> ! {
        let mut xs: Vec<_, U8> = Vec::new();
        xs.push(42).unwrap();
        hprintln!("{:?}",xs);
        debug::exit(debug::EXIT_SUCCESS);
        loop{}
    }
    
  • 相关阅读:
    F检验临界值表(Frideman检验表)
    cwe_checker初识别
    《羊了个羊》微信小游戏为什么火了?
    数据可视化,销量第一的新能源汽车是什么?比亚迪新能源汽车销量接近60万辆
    漏斗分析法、假设分析法
    全国所有地级市环境污染、企业、公路、固定资产、外商投资-最新面板数据
    python 模块 — logging模块、smtplib和email模块
    7 天找个 Go 工作,Gopher 要学的条件语句,循环语句 ,第3篇
    Prometheus监控mysql nginx tomcat 黑盒监控
    Control的Invoke和BeginInvoke
  • 原文地址:https://blog.csdn.net/phthon1997/article/details/127093236