Skip to content

Commit e47d1af

Browse files
committed
get_session_status, additional callbacks
1 parent 878576c commit e47d1af

File tree

26 files changed

+233
-615
lines changed

26 files changed

+233
-615
lines changed

CANape/xcp_lite_autodetect.a2l

+2-5
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@
152152

153153
/end DAQ
154154

155-
/begin XCP_ON_UDP_IP 0x104 5555 ADDRESS "192.168.179.2" /end XCP_ON_UDP_IP
155+
/begin XCP_ON_UDP_IP 0x104 5555 ADDRESS "172.19.11.24" /end XCP_ON_UDP_IP
156156

157157
/end IF_DATA
158158

@@ -220,11 +220,8 @@
220220
/begin MEASUREMENT mainloop_map "2D map on heap" A_UINT64 NO_COMPU_METHOD 0 0 0 1000000000000 PHYS_UNIT "" ECU_ADDRESS 0x10000 ECU_ADDRESS_EXTENSION 2 MATRIX_DIM 16 16 /begin IF_DATA XCP /begin DAQ_EVENT FIXED_EVENT_LIST EVENT 1 /end DAQ_EVENT /end IF_DATA /end MEASUREMENT
221221

222222
/begin GROUP mainloop "" /begin REF_MEASUREMENT mainloop_counter1 mainloop_counter2 /end REF_MEASUREMENT /end GROUP
223-
/begin GROUP mainloop_map "" /begin REF_MEASUREMENT mainloop_map /end REF_MEASUREMENT /end GROUP
224-
/begin GROUP static_event "" /begin REF_MEASUREMENT /end REF_MEASUREMENT /end GROUP
225223
/begin GROUP task1 "" /begin REF_MEASUREMENT array1 counter counter_u16 counter_u32 counter_u64 counter_u8 /end REF_MEASUREMENT /end GROUP
226-
/begin GROUP task2_inst "" /begin REF_MEASUREMENT channel_1 channel_2 channel_3 channel_4 channel_5 channel_6 channel_7 channel_8 channel_9 /end REF_MEASUREMENT /end GROUP
227-
/begin GROUP task2_static "" /begin REF_MEASUREMENT channel /end REF_MEASUREMENT /end GROUP
224+
/begin GROUP task2_inst "" /begin REF_MEASUREMENT channel_1 channel_2 channel_3 channel_4 channel_5 channel_6 channel_7 channel_8 channel_9 /end REF_MEASUREMENT /end GROUP
228225

229226
/end MODULE
230227
/end PROJECT

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ derive_builder = "0.20.0"
5151
# Raw FFI bindings to platform libraries like libc
5252
libc = "0.2.153"
5353

54+
# A macro to generate structures which behave like bitflags
55+
bitflags = "2.6.0"
56+
5457
# Logging
5558
log = "0.4.21"
5659
env_logger = "0.11.3"

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,13 @@ fn task(calseg: CalSeg<CalPage>) {
167167
fn main() {
168168

169169
// Initialize XCP driver singleton, the transport layer UDP and enable the automatic A2L writer and upload
170-
XcpBuilder::new("xcp_lite").set_log_level(XcpLogLevel::Warn).enable_a2l(true).set_epk("???")
170+
let xcp = XcpBuilder::new("xcp_lite").set_log_level(XcpLogLevel::Warn).enable_a2l(true).set_epk("???")
171171
.start_server(XcpTransportLayer::Udp,[127, 0, 0, 1],5555, 1400,).unwrap();
172172

173173
// Create a calibration parameter set named "calsseg" (struct CalSeg, a MEMORY_SEGMENT in A2L and CANape)
174174
// Calibration segments have 2 pages, a constant default "FLASH" page (CAL_PAGE) and a mutable "RAM" page
175175
// The RAM page can be loaded from a json file (load_json=true)
176-
let calseg = Xcp::create_calseg(
176+
let calseg = xcp.create_calseg(
177177
"calseg", // name of the calibration segment in A2L as MEMORY_SEGMENT and as .json file
178178
&CAL_PAGE, // default calibration values
179179
true, // load RAM page from file "cal_seg1".json

build.rs

+24-25
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,30 @@ fn main() {
66
// Generate XCPlite C code bindings
77
// Uncomment this to regenerate the bindings
88

9-
// let bindings = bindgen::Builder::default()
10-
// .header("xcplib/wrapper.h")
11-
// .clang_arg("-Ixcplib/src")
12-
// .clang_arg("-Ixcplib")
13-
// // Tell cargo to invalidate the built crate whenever any of the included header files changed.
14-
// .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
15-
// //
16-
// .blocklist_type("T_CLOCK_INFO")
17-
// .allowlist_function("XcpInit")
18-
// .allowlist_function("XcpEvent")
19-
// .allowlist_function("XcpEventExt")
20-
// .allowlist_function("XcpPrint")
21-
// .allowlist_function("XcpEthServerInit")
22-
// .allowlist_function("XcpEthServerShutdown")
23-
// .allowlist_function("XcpEthServerStatus")
24-
// .allowlist_function("ApplXcpSetLogLevel")
25-
// .allowlist_function("ApplXcpSetA2lName")
26-
// .allowlist_function("ApplXcpGetAddr")
27-
// .allowlist_function("ApplXcpRegisterCallbacks")
28-
// //
29-
// .generate()
30-
// .expect("Unable to generate bindings");
31-
// bindings
32-
// .write_to_file("src/xcplite.rs")
33-
// .expect("Couldn't write bindings!");
9+
let bindings = bindgen::Builder::default()
10+
.header("xcplib/wrapper.h")
11+
.clang_arg("-Ixcplib/src")
12+
.clang_arg("-Ixcplib")
13+
// Tell cargo to invalidate the built crate whenever any of the included header files changed.
14+
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
15+
//
16+
.blocklist_type("T_CLOCK_INFO")
17+
.allowlist_function("XcpInit")
18+
.allowlist_function("XcpGetSessionStatus")
19+
.allowlist_function("XcpEvent")
20+
.allowlist_function("XcpEventExt")
21+
.allowlist_function("XcpPrint")
22+
.allowlist_function("XcpEthServerInit")
23+
.allowlist_function("XcpEthServerShutdown")
24+
.allowlist_function("XcpEthServerStatus")
25+
.allowlist_function("ApplXcpSetLogLevel")
26+
.allowlist_function("ApplXcpSetA2lName")
27+
.allowlist_function("ApplXcpGetAddr")
28+
.allowlist_function("ApplXcpRegisterCallbacks")
29+
//
30+
.generate()
31+
.expect("Unable to generate bindings");
32+
bindings.write_to_file("src/xcplite.rs").expect("Couldn't write bindings!");
3433

3534
// Build a XCP on ETH version of XCPlite as a library
3635
Build::new()

examples/hello_xcp/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ fn main() {
3838

3939
env_logger::Builder::new().filter_level(log::LevelFilter::Debug).init();
4040

41-
XcpBuilder::new("xcp_demo")
41+
let xcp = XcpBuilder::new("xcp_demo")
4242
.set_log_level(XcpLogLevel::Debug)
4343
.enable_a2l(true)
4444
.set_epk("EPK_")
4545
.start_server(XcpTransportLayer::Udp, [127, 0, 0, 1], 5555, 1464)
4646
.unwrap();
4747

48-
let calseg = Xcp::create_calseg("calseg", &CAL_PAGE, true);
48+
let calseg = xcp.create_calseg("calseg", &CAL_PAGE, true);
4949

5050
let mut counter: u16 = calseg.min;
5151

examples/multi_thread_demo/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ fn main() {
108108
// Calibration segments have 2 pages, a constant default "FLASH" page and a mutable "RAM" page
109109
// FLASH or RAM can be selected runtime (XCP set_cal_page), saves to json (XCP freeze) freeze, reinitialized from FLASH (XCP copy_cal_page)
110110
// RAM page can be loaded from json in new
111-
let calseg = Xcp::create_calseg(
111+
let calseg = xcp.create_calseg(
112112
"calseg", // name of the calibration segment and the .json file
113113
&CAL_PAGE, // default calibration values
114114
true, // load RAM page from file "cal_seg1".json

examples/point_cloud_demo/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ fn main() {
118118
.start_server(XcpTransportLayer::Udp, BIND_ADDR, 5555, 8000 - 20 - 8)
119119
.unwrap();
120120

121-
let params = Xcp::create_calseg("Params", &PARAMS, true);
121+
let params = xcp.create_calseg("Params", &PARAMS, true);
122122

123123
let mut point_cloud = create_point_cloud();
124124
let mut event_point_cloud = daq_create_event!("point_cloud", POINT_COUNT * 12 + 8);

examples/rayon_demo/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn main() {
146146
.start_server(XcpTransportLayer::Udp, BIND_ADDR, 5555, 8000 - 20 - 8)
147147
.unwrap();
148148

149-
let mandelbrot = Xcp::create_calseg("mandelbrot", &MANDELBROT, true);
149+
let mandelbrot = xcp.create_calseg("mandelbrot", &MANDELBROT, true);
150150

151151
// The pixel array on heap
152152
let mut pixels = vec![0; X_RES * Y_RES];

examples/scoped_threads/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ fn main() {
6868
.start_server(XcpTransportLayer::Udp, [127, 0, 0, 1], 5555, 1464)
6969
.unwrap();
7070

71-
let calseg = Xcp::create_calseg("calseg", &CAL_PAGE, true);
71+
let calseg = xcp.create_calseg("calseg", &CAL_PAGE, true);
7272

7373
thread::scope(|s| {
7474
for _ in 0..2 {

examples/single_thread_demo/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ fn main() {
6969
// FLASH or RAM can be switched during runtime (XCP set_cal_page), saved to json (XCP freeze) freeze, reinitialized from FLASH (XCP copy_cal_page)
7070
// The RAM page can be reloaded from a json file (load_json==true)
7171
// If A2L is enabled (enable_a2l), the A2L description will be generated and provided for upload by CANape
72-
let calseg = Xcp::create_calseg(
72+
let calseg = xcp.create_calseg(
7373
"calseg", // name of the calibration segment and the .json file
7474
&CAL_PAGE, // default calibration values
7575
true, // load RAM page from file "cal_seg".json

src/cal/cal_seg.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ mod cal_tests {
513513

514514
#[test]
515515
fn test_calibration_segment_basics() {
516-
xcp_test::test_setup(log::LevelFilter::Info);
516+
let xcp = xcp_test::test_setup(log::LevelFilter::Info);
517517

518518
is_sync::<Xcp>();
519519
is_sync::<XcpEvent>();
@@ -529,7 +529,7 @@ mod cal_tests {
529529
const CAL_PAGE: CalPage0 = CalPage0 { stop: true };
530530

531531
// Intended use
532-
let cal_seg1 = Xcp::create_calseg("calseg1", &CAL_PAGE, false);
532+
let cal_seg1 = xcp.create_calseg("calseg1", &CAL_PAGE, false);
533533
cal_seg1.sync();
534534
assert!(cal_seg1.stop);
535535
let c1 = CalSeg::clone(&cal_seg1);
@@ -559,7 +559,7 @@ mod cal_tests {
559559
const CAL_PAGE2: CalPage4 = CalPage4 { test: 0x55 }; // FLASH
560560
let cal_page2 = CalPage4 { test: 0xAA }; // RAM
561561
cal_page2.save_to_file("calseg2.json");
562-
let cal_seg2 = Xcp::create_calseg("calseg2", &CAL_PAGE2, true);
562+
let cal_seg2 = xcp.create_calseg("calseg2", &CAL_PAGE2, true);
563563
Xcp::get().set_ecu_cal_page(XcpCalPage::Ram);
564564
let r = &cal_seg2.test;
565565
assert_eq!(*r, 0xAA); // RAM page
@@ -605,7 +605,7 @@ mod cal_tests {
605605
mut_page.save_to_file("test_cal_seg.json");
606606

607607
// Create a cal_seg with a mut_page from file test_cal_seg.json aka CAL_PAR_RAM, and a default page from CAL_PAR_FLASH
608-
let cal_seg = &Xcp::create_calseg("test_cal_seg", &CAL_PAR_FLASH, true);
608+
let cal_seg = &xcp.create_calseg("test_cal_seg", &CAL_PAR_FLASH, true);
609609
let cal_seg1 = cal_seg.clone();
610610
let cal_seg2 = cal_seg.clone();
611611

@@ -681,7 +681,7 @@ mod cal_tests {
681681
let mut_page: CalPage2 = CalPage2 { a: 1, b: 3, c: 5 };
682682
mut_page.save_to_file("test1.json");
683683
mut_page.save_to_file("test2.json");
684-
let cal_seg = Xcp::create_calseg("test1", &FLASH_PAGE2, true); // active page is RAM from test1.json
684+
let cal_seg = xcp.create_calseg("test1", &FLASH_PAGE2, true); // active page is RAM from test1.json
685685
assert_eq!(xcp.get_ecu_cal_page(), XcpCalPage::Ram, "XCP should be on RAM page here, there is no independant page switching yet");
686686
test_is_mut!(cal_seg); // Default page must be mut_page
687687
xcp.set_ecu_cal_page(XcpCalPage::Flash); // Simulate a set cal page to default from XCP master
@@ -713,8 +713,7 @@ mod cal_tests {
713713
// @@@@ Bug: Test fails occasionally
714714
#[test]
715715
fn test_cal_page_freeze() {
716-
xcp_test::test_setup(log::LevelFilter::Warn);
717-
let _xcp = Xcp::get();
716+
let xcp = xcp_test::test_setup(log::LevelFilter::Warn);
718717

719718
assert!(std::mem::size_of::<CalPage1>() == 12);
720719
assert!(std::mem::size_of::<CalPage2>() == 12);
@@ -724,7 +723,7 @@ mod cal_tests {
724723
mut_page1.save_to_file("test1.json");
725724

726725
// Create calseg1 from def
727-
let calseg1 = Xcp::create_calseg("test1", &FLASH_PAGE1, true);
726+
let calseg1 = xcp.create_calseg("test1", &FLASH_PAGE1, true);
728727
test_is_mut!(calseg1);
729728

730729
// Freeze calseg1 to new test1.json
@@ -734,7 +733,7 @@ mod cal_tests {
734733

735734
// Create calseg2 from freeze file test1.json of calseg1
736735
std::fs::copy("test1.json", "test2.json").unwrap();
737-
let calseg2 = Xcp::create_calseg("test2", &FLASH_PAGE2, true);
736+
let calseg2 = xcp.create_calseg("test2", &FLASH_PAGE2, true);
738737
test_is_mut!(calseg2);
739738

740739
std::fs::remove_file("test1.json").ok();
@@ -746,7 +745,7 @@ mod cal_tests {
746745

747746
#[test]
748747
fn test_cal_page_trait() {
749-
xcp_test::test_setup(log::LevelFilter::Info);
748+
let xcp = xcp_test::test_setup(log::LevelFilter::Info);
750749

751750
#[derive(Debug, Copy, Clone, Serialize, Deserialize, XcpTypeDescription)]
752751
struct Page1 {
@@ -767,9 +766,9 @@ mod cal_tests {
767766

768767
const PAGE3: Page3 = Page3 { c: 1 };
769768

770-
let s1 = &Xcp::create_calseg("test1", &PAGE1, true);
771-
let s2 = &Xcp::create_calseg("test2", &PAGE2, true);
772-
let s3 = &Xcp::create_calseg("test3", &PAGE3, true);
769+
let s1 = &xcp.create_calseg("test1", &PAGE1, true);
770+
let s2 = &xcp.create_calseg("test2", &PAGE2, true);
771+
let s3 = &xcp.create_calseg("test3", &PAGE3, true);
773772

774773
info!("s1: {}", s1.get_name());
775774
info!("s2: {}", s2.get_name());
@@ -814,7 +813,7 @@ mod cal_tests {
814813

815814
#[test]
816815
fn test_attribute_macros() {
817-
xcp_test::test_setup(log::LevelFilter::Info);
816+
let xcp = xcp_test::test_setup(log::LevelFilter::Info);
818817

819818
#[derive(Debug, Copy, Clone, Serialize, Deserialize, XcpTypeDescription)]
820819
struct CalPage {
@@ -843,7 +842,7 @@ mod cal_tests {
843842
],
844843
};
845844

846-
let calseg = &Xcp::create_calseg("calseg", &CAL_PAGE, false);
845+
let calseg = xcp.create_calseg("calseg", &CAL_PAGE, false);
847846
let c: RegistryCharacteristic = Xcp::get().get_registry().lock().unwrap().find_characteristic("CalPage.a").unwrap().clone();
848847

849848
assert_eq!(calseg.get_name(), "calseg");

src/lib.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub use xcp::XcpBuilder;
3030
pub use xcp::XcpCalPage;
3131
pub use xcp::XcpEvent;
3232
pub use xcp::XcpLogLevel;
33+
pub use xcp::XcpSessionStatus;
3334
pub use xcp::XcpTransportLayer;
3435

3536
// Submodule cal
@@ -134,9 +135,9 @@ macro_rules! daq_register_static {
134135
#[macro_export]
135136
macro_rules! xcp_println {
136137
( $fmt:expr ) => {
137-
Xcp::print(&format!($fmt));
138+
Xcp::get().print(&format!($fmt));
138139
};
139140
( $fmt:expr, $( $arg:expr ),* ) => {
140-
Xcp::print(&format!($fmt, $( $arg ),*));
141+
Xcp::get().print(&format!($fmt, $( $arg ),*));
141142
};
142143
}

src/main.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ fn main() {
397397
// The initial RAM page can be loaded from a json file (load_json=true) or set to the default FLASH page (load_json=false)
398398

399399
// Create a alibration segment wrapper for CAL_PAGE, add fields manually to registry
400-
let calseg = Xcp::add_calseg(
400+
let calseg = xcp.add_calseg(
401401
"CalPage", // name of the calibration segment and the .json file
402402
&CAL_PAGE, // default calibration values with static lifetime, trait bound from CalPageTrait must be possible
403403
);
@@ -408,8 +408,8 @@ fn main() {
408408
.add_field(calseg_field!(CAL_PAGE.cycle_time_us, "us", "main task cycle time"));
409409

410410
// Create calibration segments for CAL_PAGE1 and CAL_PAGE2, add fields with macro derive(XcpTypeDescription))
411-
let calseg1 = Xcp::create_calseg("CalPage1", &CAL_PAGE1, true);
412-
let calseg2 = Xcp::create_calseg("CalPage2", &CAL_PAGE2, true);
411+
let calseg1 = xcp.create_calseg("CalPage1", &CAL_PAGE1, true);
412+
let calseg2 = xcp.create_calseg("CalPage2", &CAL_PAGE2, true);
413413

414414
// Task2 - 9 instances
415415
// To demonstrate the difference between single instance and multi instance events and measurement values
@@ -449,6 +449,7 @@ fn main() {
449449
daq_register_static!(static_vars.test_u32, static_event, "Test static u32");
450450
daq_register_static!(static_vars.test_f64, static_event, "Test static f64");
451451

452+
let mut current_session_status = xcp.get_session_status();
452453
while RUN.load(Ordering::Acquire) {
453454
// @@@@ Dev: Terminate mainloop for shutdown if calibration parameter run is false, for test automation
454455
if !calseg.run {
@@ -480,11 +481,18 @@ fn main() {
480481

481482
// Check if the XCP server is still alive
482483
// Optional
483-
if !Xcp::check_server() {
484+
if !xcp.check_server() {
484485
warn!("XCP server shutdown!");
485486
break;
486487
}
487488

489+
// Check if the XCP session status has changed and print info
490+
let session_status = xcp.get_session_status();
491+
if session_status != current_session_status {
492+
info!("XCP session status: {:?}", session_status);
493+
current_session_status = session_status;
494+
}
495+
488496
// @@@@ Dev:
489497
// Finalize A2l after 2s delay
490498
// This is just for testing, to force immediate creation of A2L file
@@ -514,5 +522,5 @@ fn main() {
514522
info!("All tasks finished");
515523

516524
// Stop and shutdown the XCP server
517-
Xcp::stop_server();
525+
xcp.stop_server();
518526
}

0 commit comments

Comments
 (0)