Skip to content

Commit bed604c

Browse files
authored
Update README.md
1 parent 95c4a16 commit bed604c

File tree

1 file changed

+3
-186
lines changed

1 file changed

+3
-186
lines changed

README.md

Lines changed: 3 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,6 @@ Shows how to measure and calibrate in a task instantiated in multiple threads wi
9191

9292
Use CANape to observe rayon workers calculating a mandelbrot set line by line
9393

94-
### sysinfo_demo
95-
96-
Measure cpu load, memory usage and network activity from system, cpus and processes
97-
9894
### tokio_demo
9995

10096
Demonstrates using XCP in an async tokio based application
@@ -104,11 +100,6 @@ Demonstrates using XCP in an async tokio based application
104100
Measure a lidar point cloud and visualize it in CANapes 3D scene window
105101
Use CDR serialization over XCP and the CDR/IDL schema generator proc-macro
106102

107-
### protobuf_demo
108-
109-
Measure a struct annotated with the prost message derive macro and ProtoBuf tags
110-
Use ProtoBuf serialization over XCP and the proto schema generator proc-macro
111-
This is in experimental state with work in progress, removed from workspace
112103

113104
## Code instrumentation for measurement and calibration
114105

@@ -117,109 +108,14 @@ Xcp is a wrapper for XCPlite. It is a singleton. There is a builder to initializ
117108

118109
CalSeg is a generic type used to encapsulate structs containing calibration parameters. This is called a calibration segment and the parameter struct wrapped is a calibration page. A calibration page must be Copy and may contain nested structs of basic types or arrays with dimension up to 2.
119110

120-
A CalSeg has interior mutability. Parameter mutation happens only in the CalSeg::sync(&self) method, or alernativly by dropping the provided calibration segment guard. This must be repeatedly called by the application code, whenever mutation of calibration parameters is considered ok in the current thread.
111+
A CalSeg has interior mutability. Parameter mutation happens only on acquiring a calibration segment guard.
121112

122-
A CalSeg may be shared among multiple threads. It it cloned like an Arc, implements the Deref trait for convenience and does not do any locks to deref to the inner calibration parameter page struct. A sync method must be called on each clone, to make new calibration changes visible in each thread. The sync method shares a mutex with all clones. Each clone holds a shadow copy of the calibration values on heap.
113+
A CalSeg may be shared among multiple threads. It it cloned like an Arc, implements the Deref trait for convenience and does not do any locks to deref to the inner calibration parameter page struct.
123114

124115
Measurement code instrumentation provides event definition, registration or capture of measurement objects. Measurement objects can be captured (copied to a buffer inside the event) or accessed directly on stack memory after being registered. Capture works for variables on heap or stack. Measurement variables can be registered as single instance or multi instance, which creates one variable instance for each thread instance. Variable names and event names are automatically extended with an index in this case.
125116

126117
The registration of objects has to be completed, before the A2L file is generated. The A2L is created at latest on connect of the XCP client tool. Objects created later, will not be visible to CANape.
127118

128-
``` rust
129-
130-
// Calibration parameter segment
131-
// Each calibration parameter struct defines a MEMORY_SEGMENT in A2L and CANape
132-
// The A2L serializer will create an A2L CHARACTERISTIC for each field.
133-
#[derive(Debug, Clone, Copy, XcpTypeDescription)]
134-
struct CalPage {
135-
136-
#[charateristic(comment = "Amplitude")]
137-
#[characteristic(unit = "Volt")]
138-
#[characteristic(min = "0")]
139-
#[characteristic(max = "400")]
140-
ampl: f64,
141-
142-
#[characteristic(comment = "Period")]
143-
#[characteristic(unit = "s")]
144-
#[characteristic(min = "0")]
145-
#[characteristic(max = "1000")]
146-
period: f64,
147-
}
148-
149-
// Default calibration page values (called "FLASH" page of a MEMORY_SEGMENT in CANape)
150-
const CAL_PAGE: CalPage = CalPage {
151-
ampl: 100.0,
152-
period: 5.0,
153-
};
154-
155-
156-
// A single instance demo task
157-
// Calculates some measurement signals depending on calibration parameters in a calibration segment
158-
fn task(calseg: CalSeg<CalPage>) {
159-
160-
let mut channel1: f64 = 0.0;
161-
let mut channel2: f64 = Box::new(0.0);
162-
163-
// Create a measurement event called "task" with a capture buffer of 8 byte
164-
let event = daq_create_event!("task1", 8);
165-
166-
// Register measurement variables on stack
167-
daq_register!(channel, event, "demo: f64", "Volt" /* unit */, 2.0 /* factor */, 0.0 /* offset */);
168-
169-
loop {
170-
thread::sleep(...);
171-
172-
// Calculate channel depending on calibration parameters from calseg (sine wave signal with ampl and period)
173-
channel1 = calseg.ampl * (time/cal_seg.period).sin(); // Use active page in calibration segment
174-
channel2 = calseg.ampl * (time/cal_seg.period).sin(); // Use active page in calibration segment
175-
176-
// Register and capture a variables on heap
177-
daq_capture(channel1);
178-
179-
// Take a timestamp and trigger data acquisition for all variables associated and configured by the tool for this event
180-
event.trigger();
181-
182-
// Synchronize calibration operations in calseg
183-
// All calibration actions (read, write, upload, download, checksum, page switch, freeze, init) on segment "cal_seg" happen only here
184-
// This operation locks a mutex, checks for changes and copies the calibration page
185-
// It could be called more occasionally and in any place where calseg is in scope to update calibrations in this clone
186-
calseg.sync();
187-
}
188-
}
189-
190-
191-
192-
fn main() -> Result<()> {
193-
194-
// Initialize XCP driver singleton, the transport layer UDP and enable the automatic A2L writer and upload
195-
let xcp = XcpBuilder::new("my_module_name").set_log_level(2).set_epk("MY_EPK")
196-
.start_server(XcpTransportLayer::Udp, [127, 0, 0, 1], 5555, 1024*64)?;
197-
198-
// Create a calibration parameter set named "calseg" (struct CalSeg, a MEMORY_SEGMENT in A2L and CANape)
199-
// Calibration segments have 2 pages, a constant default "FLASH" page (CAL_PAGE) and a mutable "RAM" page
200-
// The RAM page can be loaded from a json file (load_json=true)
201-
let calseg = xcp.create_calseg(
202-
"calseg", // name of the calibration segment in A2L as MEMORY_SEGMENT and as .json file
203-
&CAL_PAGE, // default calibration values
204-
).register_fields();
205-
206-
// Use CalSeg::Clone() to share the calibration segments between threads
207-
// No locks, calseg.sync() must be called in each thread
208-
thread::spawn({
209-
let calseg = CalSeg::clone(&calseg);
210-
move || {
211-
task(calseg);
212-
}
213-
});
214-
215-
216-
loop { ... }
217-
218-
Xcp::stop_server();
219-
}
220-
221-
222-
```
223119

224120
## Safety Considerations
225121

@@ -244,21 +140,14 @@ XCP is used during the development process only, it is never integrated in produ
244140

245141
Features are:
246142

247-
- shm_mode
248-
Disable XCP and enable xcp-daemon mode
249-
250143
- a2l_reader
251144
Check A2L file after generation before upload
252145

253-
- metrics
254-
Collect some statistic on A2L generation memory usage
255-
256146
### Build, Run, Test
257147

258148
Build, Run, Test examples:
259149

260150
```
261-
262151
Build:
263152
cargo b
264153
cargo b --release
@@ -280,85 +169,13 @@ Tests may not run in parallel, as the XCP implementation is a singleton.
280169
Feature a2l_reader is needed for xcp_client based testing
281170

282171
```
283-
284172
cargo test --features=a2l_reader -- --test-threads=1 --nocapture
285173
cargo test --features=a2l_reader -- --test-threads=1 --nocapture --test test_multi_thread
286174
cargo test --features=shm_mode -- --test-threads=1 --nocapture --test test_performance
287-
288175
```
289176

290177
Use --nocapture because the debug output from the XCPlite C library is via normal printf
291178

292-
## Daemon Mode
293-
294-
Feature shm_mode enables the daemon mode and disables XCP mode.
295-
296-
```
297-
298-
Make and start daemon in xcp-daemon repo directory root:
299-
300-
MC_SHM_DIRECTORY=../../xcp-lite-rdm MC_TRANSPORT=udp MC_XCP_SERVER_ADDRESS=127.0.0.1 MC_XCP_SERVER_PORT=5555 make --directory ../xcp-daemon/cpp-daemon daemon
301-
302-
Clean
303-
304-
cmake --build ./cpp-daemon/build/ --target clean
305-
306-
Start daemon and detach process:
307-
308-
MC_SHM_DIRECTORY=../../xcp-lite-rdm MC_TRANSPORT=udp sudo ./cpp-daemon/build/main/main --detach
309-
310-
mc_daemon.a2l is generated in ./cpp-daemon, not in MC_SHM_DIRECTORY
311-
312-
Example im shm_mode starten:
313-
cargo r --features=shm_mode
314-
cargo r --features=shm_mode --example=hello_xcp -- --bind=192.168.8.110
315-
cargo r --features=shm_mode --example=calibration_demo
316-
cargo r --features=shm_mode --example=multi_thread_demo
317-
318-
XCP client starten:
319-
cargo run --example=xcp_client -- -m ".*"
320-
cargo run --example=xcp_client -- -l=4 -d=192.168.239.129:5555 -m ".*"
321-
322-
A2L ist uploaded via XCP to xxxx_autodetect.a2l
323-
324-
325-
You may use A2l tool to perform more strict tests on the generated A2L:
326-
cd a2l_tool
327-
cargo r -- -w -c --strict --metrics -a ../xxxxx.a2l
328-
329-
330-
```
331-
332-
### TODO List Daemon Mode
333-
334-
- Implement register typedef and disable flat mode
335-
-
336-
337-
- Finalize registry problem
338-
339-
- A2L upload takes too long time
340-
341-
shm_mode
342-
[INFO ] start calibration test loop, recalibrate cycle time to 50us for maximum number of calibration checks
343-
[INFO ] calibration test loop done, 4000 iterations, duration=2666ms, 666.6355us per download, 12.0 KBytes/s
344-
[WARN ] Calibration download time (666.6355us) is too high!
345-
346-
xcp_mode
347-
[INFO ] start calibration test loop, recalibrate cycle time to 50us for maximum number of calibration checks
348-
[INFO ] calibration test loop done, 4000 iterations, duration=170ms, 42.6735us per download, 187.5 KBytes/s
349-
[INFO ] Consistent calibration test passed
350-
351-
- Calibration block offset is uint64_t from mc_get_block_offset, but uint16_t in datamodell ????
352-
- Refactor the types to individually represent the use case AND to point out if its a string reference or numeric reference
353-
- Move the address encoding to the daemon and clarify the object semantic (measurement or calibration) and address semantic (calseg or event relativ), don't require specific address encodig schemes
354-
- Load,Save JSON
355-
- Freeze and Init
356-
- Check server/daemon status
357-
- Text event message
358-
- Terminate session event
359-
- First cycle DAQ
360-
- Lock free daq queue
361-
- RCU cal
362179

363180
## Notes
364181

@@ -376,7 +193,7 @@ The proc macro for more convenient A2L generation is still in an experimental st
376193
Measurement of local variables is done with a macro which either copies to a static transfer buffer in the event or directly accesses the value on stack.
377194
This involves a lazy initialization of the structures to build the A2l file describing the local variables.
378195

379-
There are 3 different addressing schemes, indicated by address extension (called _ABS,_DYN and _APP in the code).
196+
There are 4 different addressing schemes, indicated by address extension (called ABS, DYN, REL and APP in the code).
380197
In mode APP, the low word of a calibration parameters memory address in the A2L file is a relative offset in the calibration page struct.
381198
The high word (& 0x7FFF) is the index of the calibration segment in a alphabetic ordered list.
382199
The memory addresses of local measurement variables are relative addresses (mode DYN) in their event capture buffer on stack or to the stack location of the variable holding the event.

0 commit comments

Comments
 (0)