Skip to content

Commit

Permalink
Minor changes
Browse files Browse the repository at this point in the history
  • Loading branch information
RainerZ committed Oct 7, 2024
1 parent 4953212 commit 9e5f8ac
Show file tree
Hide file tree
Showing 23 changed files with 205 additions and 253 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ XCP for Rust - based on XCPlite

Disclaimer:
This code is in experimental state. There is no release yet.
This is no implementation of XCP in Rust, it is an experimental API for measurement and calibration, which uses the ASAM XCP protocol for communication with a measurement and calibration tool like CANape and ASAM A2L for data description.
This is no implementation of XCP in Rust, it is an API for measurement and calibration, which uses the ASAM XCP protocol for communication with a measurement and calibration tool like CANape and ASAM A2L for data description.

Main purpose was to experiment with Rust and to demonstrate some more advanced features of measurement and calibration with CANape:
- Automatic A2L and IDL generation with proc-macros
- A thread safe, transparent wrapper for calibration variables which enables offline calibration, calibration page switching, reinit, load and save to file
- Measurement of dynamic data from stack or heap
- Measurement of data with non static lifetime
- A transparent wrapper for calibration variables which provides synchronized and memory safe calibration access
- Support for offline calibration, calibration page switching, reinit, load and save to json file
- Measurement of dynamic variables from stack or heap
- Measurement of variables with non static lifetime
- Measurement of thread local data instances
- Data objects and containers with dynamic size like point clouds or detection lists, to demonstrate CANape ADAS features
- Support Google protobuf or OMG DDS/CDR serialized data objects with XCP and CANape
Expand Down
8 changes: 4 additions & 4 deletions benches/xcp_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,11 @@ fn xcp_benchmark(c: &mut Criterion) {
let mut signal1: u32 = 0;
let mut signal2: u64 = 0;
let mut signal3: u8 = 0;
let mut signal4: u16 = 0;
let mut signal5: u64 = 0;
let mut signal4: u8 = 0;
let mut signal5: u16 = 0;
let mut signal6: u32 = 0;
let mut signal7: u16 = 0;
let mut signal8: u64 = 0;
let mut signal7: u64 = 0;
let mut signal8: u32 = 0;

// Register a measurement event and bind it to the counter signal
let event = daq_create_event!("mainloop");
Expand Down
75 changes: 38 additions & 37 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,43 +3,44 @@ fn main() {

// Generate XCPlite C code bindings
// Uncomment this to regenerate the bindings

let bindings = bindgen::Builder::default()
.header("xcplib/wrapper.h")
.clang_arg("-Ixcplib/src")
.clang_arg("-Ixcplib")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
//
.blocklist_type("T_CLOCK_INFO")
// Protocol layer
.allowlist_function("XcpInit")
.allowlist_function("XcpStart")
.allowlist_function("XcpDisconnect")
// Transport layer
.allowlist_function("XcpTlInit")
.allowlist_function("XcpTlShutdown")
.allowlist_function("XcpTlCommand")
.allowlist_function("XcpTlTransmitQueuePeekMsg")
.allowlist_function("XcpTlTransmitQueueNextMsg")
.allowlist_function("XcpTlTransmitQueueHasMsg")
// ETH server
.allowlist_function("XcpEthServerInit")
.allowlist_function("XcpEthServerShutdown")
.allowlist_function("XcpEthServerStatus")
.allowlist_function("XcpGetSessionStatus")
// DAQ
.allowlist_function("XcpEvent")
.allowlist_function("XcpEventExt")
// Misc
.allowlist_function("XcpPrint")
.allowlist_function("ApplXcpSetLogLevel")
.allowlist_function("ApplXcpSetA2lName")
.allowlist_function("ApplXcpGetAddr")
.allowlist_function("ApplXcpRegisterCallbacks")
//
.generate()
.expect("Unable to generate bindings");
bindings.write_to_file("src/xcplite.rs").expect("Couldn't write bindings!");
/*
let bindings = bindgen::Builder::default()
.header("xcplib/wrapper.h")
.clang_arg("-Ixcplib/src")
.clang_arg("-Ixcplib")
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
//
.blocklist_type("T_CLOCK_INFO")
// Protocol layer
.allowlist_function("XcpInit")
.allowlist_function("XcpStart")
.allowlist_function("XcpDisconnect")
// Transport layer
.allowlist_function("XcpTlInit")
.allowlist_function("XcpTlShutdown")
.allowlist_function("XcpTlCommand")
.allowlist_function("XcpTlTransmitQueuePeekMsg")
.allowlist_function("XcpTlTransmitQueueNextMsg")
.allowlist_function("XcpTlTransmitQueueHasMsg")
// ETH server
.allowlist_function("XcpEthServerInit")
.allowlist_function("XcpEthServerShutdown")
.allowlist_function("XcpEthServerStatus")
.allowlist_function("XcpGetSessionStatus")
// DAQ
.allowlist_function("XcpEvent")
.allowlist_function("XcpEventExt")
// Misc
.allowlist_function("XcpPrint")
.allowlist_function("ApplXcpSetLogLevel")
.allowlist_function("ApplXcpSetA2lName")
.allowlist_function("ApplXcpGetAddr")
.allowlist_function("ApplXcpRegisterCallbacks")
//
.generate()
.expect("Unable to generate bindings");
bindings.write_to_file("src/xcp/xcplib.rs").expect("Couldn't write bindings!");
*/

// Build a XCP on ETH version of XCPlite as a library
cc::Build::new()
Expand Down
22 changes: 7 additions & 15 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@
// The library crate is named "xcp"
#![crate_name = "xcp"]

#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};

//-----------------------------------------------------------------------------

// Submodule xcp
Expand All @@ -106,11 +103,6 @@ pub use reg::RegistryDataType;
pub use reg::RegistryDataTypeTrait;
pub use reg::RegistryMeasurement;

// XCPlite FFI bindings
mod xcplib {
include!("xcplite.rs");
}

//----------------------------------------------------------------------------------------------
// Manually register a static measurement and calibration variables

Expand All @@ -119,42 +111,42 @@ mod xcplib {
macro_rules! cal_register_static {
( $variable:expr ) => {{
let name = stringify!($variable);
let datatype = unsafe { ($variable).get_type() };
let datatype = ($variable).get_type();
let addr = unsafe { &($variable) as *const _ as u64 };
let c = RegistryCharacteristic::new(None, name.to_string(), datatype, "", datatype.get_min(), datatype.get_max(), "", 1, 1, addr);
Xcp::get().get_registry().lock().unwrap().add_characteristic(c);
}};
( $variable:expr, $comment:expr ) => {{
let name = stringify!($variable);
let datatype = unsafe { ($variable).get_type() };
let datatype = ($variable).get_type();
let addr = unsafe { &($variable) as *const _ as u64 };
let c = RegistryCharacteristic::new(None, name.to_string(), datatype, $comment, datatype.get_min(), datatype.get_max(), "", 1, 1, addr);
Xcp::get().get_registry().lock().unwrap().add_characteristic(c);
}};

( $variable:expr, $comment:expr, $unit:expr ) => {{
let name = stringify!($variable);
let datatype = unsafe { ($variable).get_type() };
let datatype = ($variable).get_type();
let addr = unsafe { &($variable) as *const _ as u64 };
let c = RegistryCharacteristic::new(None, name.to_string(), datatype, $comment, datatype.get_min(), datatype.get_max(), $unit, 1, 1, addr);
Xcp::get().get_registry().lock().unwrap().add_characteristic(c);
}};
}

/// Register a static measurement variable with
/// Register a static measurement variable
#[macro_export]
macro_rules! daq_register_static {
( $variable:expr, $event:ident ) => {{
let name = stringify!($variable);
let datatype = unsafe { ($variable).get_type() };
let datatype = ($variable).get_type();
let addr = unsafe { &($variable) as *const _ as u64 };
let mut c = RegistryCharacteristic::new(None, name.to_string(), datatype, "", datatype.get_min(), datatype.get_max(), "", 1, 1, addr);
c.set_event($event);
Xcp::get().get_registry().lock().unwrap().add_characteristic(c);
}};
( $variable:expr, $event:ident, $comment:expr ) => {{
let name = stringify!($variable);
let datatype = unsafe { ($variable).get_type() };
let datatype = ($variable).get_type();
let addr = unsafe { &($variable) as *const _ as u64 };
let mut c = RegistryCharacteristic::new(None, name.to_string(), datatype, $comment, datatype.get_min(), datatype.get_max(), "", 1, 1, addr);
c.set_event($event);
Expand All @@ -163,7 +155,7 @@ macro_rules! daq_register_static {

( $variable:expr, $event:ident, $comment:expr, $unit:expr ) => {{
let name = stringify!($variable);
let datatype = unsafe { ($variable).get_type() };
let datatype = ($variable).get_type();
let addr = unsafe { &($variable) as *const _ as u64 };
let mut c = RegistryCharacteristic::new(None, name.to_string(), datatype, $comment, datatype.get_min(), datatype.get_max(), $unit, 1, 1, addr);
c.set_event($event);
Expand Down
36 changes: 17 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,7 @@ use xcp::*;
use xcp_type_description::prelude::*;

//-----------------------------------------------------------------------------
// Static variables

lazy_static::lazy_static! {

// Application start time
static ref START_TIME: Instant = Instant::now();

// Stop all tasks if false
static ref RUN: AtomicBool = AtomicBool::new(true);
}
// Static measurement and calibration variables

struct StaticVars {
test_u32: u32,
Expand Down Expand Up @@ -238,6 +229,15 @@ const CAL_PAGE2: CalPage2 = CalPage2 {
//-----------------------------------------------------------------------------
// Demo application cyclic tasks in threads

lazy_static::lazy_static! {

// Application start time
static ref START_TIME: Instant = Instant::now();

// Stop all tasks if false
static ref RUN: AtomicBool = AtomicBool::new(true);
}

// A task which calculates some measurement signals depending on calibration parameters in a shared calibration segment
// This task is instantiated multiple times
fn task2(task_id: usize, calseg: CalSeg<CalPage>, calseg2: CalSeg<CalPage2>) {
Expand Down Expand Up @@ -362,7 +362,7 @@ fn main() {
})
.unwrap();

// Register a static calibration page
// Register static calibration variables (from a const struct)
let calpage00 = CAL_PAGE0.get().unwrap();
cal_register_static!(calpage00.task1_cycle_time_us, "task1 cycle time", "us");
cal_register_static!(calpage00.task2_cycle_time_us, "task2 cycle time", "us");
Expand Down Expand Up @@ -407,27 +407,26 @@ fn main() {
task1(c, calseg1);
});

// Mainloop
xcp_println!("Main task starts");

// Variables on heap and stack
let mut mainloop_counter1: u64 = 0;
let mut mainloop_counter2 = Box::new(0u64);
let mut mainloop_map = Box::new([[0u8; 16]; 16]);

// Create associated event and register
let mut mainloop_event = daq_create_event!("mainloop", 64); // Capture buffer 64 bytes
daq_register!(mainloop_counter1, mainloop_event);

// Mutable static variables
let static_event = xcp.create_event("static_event");
// Mutable static variables (borrowed from a StaticCell)
let static_vars: &'static mut StaticVars = STATIC_VARS.init(StaticVars { test_u32: 0, test_f64: 0.0 });
static_vars.test_u32 = 1;
assert_eq!(static_vars.test_u32, 1);
// Create associated event and register as characteristics with absolute addressing and associated XCP event
let static_event = xcp.create_event("static_event");
daq_register_static!(static_vars.test_u32, static_event, "Test static u32");
daq_register_static!(static_vars.test_f64, static_event, "Test static f64");

// Mainloop
xcp_println!("Main task starts");
let mut current_session_status = xcp.get_session_status();

let mut idle_time = 0.0;
while RUN.load(Ordering::Acquire) {
// @@@@ Dev: Terminate mainloop for shutdown if calibration parameter run is false, for test automation
Expand All @@ -454,7 +453,6 @@ fn main() {
// Measure static variables
static_vars.test_u32 += 1;
static_vars.test_f64 += 0.1;

static_event.trigger();

// Sync
Expand Down
Loading

0 comments on commit 9e5f8ac

Please sign in to comment.