communicate with an object in Embedded rust .for example, call a method from an interrupt handler

Viewed 81

i am working on a Quactel module in rust language .i have an object(Tracking_mgr) and i want to call a method of that object (parse_from_byte) from interrupt handler (CallBack_NMEA_Hdlr) . but i can't because scop of object (in main) is different from scope of interrupt .

#![no_std]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(destructuring_assignment)]
include!("./bindings.rs");
extern crate alloc;
extern crate cty;
extern crate nmea0183;
extern crate ql_alloc;
use alloc::format;
use alloc::string::String;
use alloc::string::ToString;
use core::convert::TryInto;
use core::slice;
use nmea0183::{ParseResult, Parser};
#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

pub fn printUart(mut string: String) {
    unsafe {
        Ql_UART_Write(10, string.as_mut_ptr(), string.len() as u32);
    }
}

pub struct Tracking_mgr {
    point: Point,
    parser: Parser,
}

impl Tracking_mgr {
    pub fn new() -> Tracking_mgr {
        Tracking_mgr {
            point: Point::new(),
            parser: Parser::new(),
        }
    }

    pub fn parse_from_byte(&mut self, buff: u8) {
        self.parser.parse_from_byte(buff);
    }
}

pub trait GpsInterface {
    fn power_on();
    fn power_off();
}

impl GpsInterface for Tracking_mgr {
    fn power_on() {
        unsafe {
            Ql_GNSS_PowerOn(4, Some(CallBack_NMEA_Hdlr), ::core::ptr::null_mut());
        }
    }

    fn power_off() {
        unsafe {
            Ql_GNSS_PowerDown();
        }
    }
}
pub struct Point {
    point: [u8; 5],
}

impl Point {
    pub fn new() -> Point {
        Point {
            point: [0, 0, 0, 0, 0],
        }
    }
}

pub extern "C" fn CallBack_NMEA_Hdlr(
    nmea_buff: *mut u8,
    len: u16,
    customizePara: *mut cty::c_void,
) {
}

pub extern "C" fn CallBack_UART_Notify(
    port: Enum_SerialPort,
    event: Enum_UARTEventType,
    pinLevel: bool,
    customizePara: *mut cty::c_void,
) {
    printUart("CallBack_UART_Notify".to_string());
}

#[no_mangle]
pub extern "C" fn proc_main_task(taskId: i32) {
    let mut msg = ST_MSG {
        message: 0,
        param1: 0,
        param2: 0,
        srcTaskId: 0,
    };
    loop {
        unsafe {
            Ql_OS_GetMessage(&mut msg);
        }
        match msg.message {
            MSG_ID_RIL_READY => unsafe {
                Ql_UART_Register(10, Some(CallBack_UART_Notify), ::core::ptr::null_mut());
                Ql_UART_Open(10, 115200, 1);
                Ql_GPIO_Init(0, 1, 1, 0);
                Ql_GNSS_PowerOn(4, Some(CallBack_NMEA_Hdlr), ::core::ptr::null_mut());
            },
            _ => (),
        }
    }
}

i tried static mut tracking_mgr: Tracking_mgr = Tracking_mgr::new(); before but i got this error "calls in statics are limited to constant functions, tuple structs and tuple variants" can somebody help me ? how can i call a method of object that defined in a main() from interrupt handler? thanks!

1 Answers

As the error message indicates, you can only call const functions to initialize a static. In principle, you could try to make Tracking_mgr::new a const function (pub const fn new()), but that won't work, because it calls other methods that themselves aren't const (Point::new could be const, but Parser::new couldn't, I think).

To solve this, you can store an Option in your static:

static mut tracking_mgr: Option<Tracking_mgr> = None;

And initialize it in your main function:

unsafe { tracking_mgr = Some(Tracking_mgr::new()); }

It looks like you're not building on top of the standard embedded Rust stack (cortex-m/cortex-m-rt). If you were, I'd recommend using RTIC, as that solves the same problem in a much more safe and elegant way.

Related