Comments (7)
Thanks, it works.
from ethercrab.
try_split
is designed in such a way to uphold the invariant that only one PduTx
and PduRx
may be held at a time, otherwise there's the potential for race conditions and other UB if more than one of either of these instances is held concurrently.
Are you able to put the part of your program that needs to be reset in a loop
? That way you can reset as much as you like on failure but only need to call try_split
once.
It would be good if you could describe what you mean by "reset the program" in a bit more detail. Are you encountering NIC issues, program bugs, etc? Does your program crash a thread as opposed to returning a Result::Err(...)
, etc?
from ethercrab.
Thank you for your prompt reply.
Actually, I have a really heavy industrial software with its own business function and multiple communication protocols, which include Ethercat
. Its startup logic is "A. initialize -> B. load config and database -> C. start communication function(and also other business functions) and serve an web". In some situation, such as modifying key configurations, it will be reset and do step B and C again. Which communication protocol to enable depends on configuration and database loaded by step B.
It seems that the only way to solve this issue is add try_split
in the step A. However, I have to pass the parameters layer by layer through many unrelated functions. Worse still, the software is designed for various platform(different architecture, different system, different abi) and it makes it very difficult to disable the feature of ethercrab
during compilation.
I have tried many method for several weeks. I would greatly appreciate it If you have any other good suggestions.
from ethercrab.
If this suits your application, you could use thread::scope
which allows PduStorage
to be non-'static
. Here's a demo that uses smol::block_on
which executes futures on two threads; one the TX/RX, the other the actual task thread:
use env_logger::Env;
use ethercrab::{
error::Error,
std::{tx_rx_task},
Client, ClientConfig, PduStorage, Timeouts,
};
use futures_lite::StreamExt;
use std::{thread, time::Duration};
/// Maximum number of slaves that can be stored. This must be a power of 2 greater than 1.
const MAX_SLAVES: usize = 16;
/// Maximum PDU data payload size - set this to the max PDI size or higher.
const MAX_PDU_DATA: usize = 1100;
/// Maximum number of EtherCAT frames that can be in flight at any one time.
const MAX_FRAMES: usize = 16;
/// Maximum total PDI length.
const PDI_LEN: usize = 64;
fn main() -> Result<(), Error> {
env_logger::Builder::from_env(Env::default().default_filter_or("info")).init();
let interface = std::env::args()
.nth(1)
.expect("Provide network interface as first argument.");
let pdu_storage: PduStorage<MAX_FRAMES, MAX_PDU_DATA> = PduStorage::new();
let (tx, rx, pdu_loop) = pdu_storage.try_split().expect("can only split once");
let client = Client::new(pdu_loop, Timeouts::default(), ClientConfig::default());
thread::scope(|s| {
// TODO: Handle panics!
let _tx_rx_task =
s.spawn(|| smol::block_on(tx_rx_task(&interface, tx, rx).expect("spawn TX/RX task")));
let app_task = s.spawn(|| {
smol::block_on(async {
let mut group = client
.init_single_group::<MAX_SLAVES, PDI_LEN>()
.await
.expect("Init")
.into_op(&client)
.await
.expect("PRE-OP -> OP");
let mut tick_interval = smol::Timer::interval(Duration::from_millis(5));
loop {
group.tx_rx(&client).await.expect("TX/RX");
// Cyclic data sent here
for mut slave in group.iter(&client) {
let (_i, o) = slave.io_raw_mut();
for byte in o.iter_mut() {
*byte = byte.wrapping_add(1);
}
}
tick_interval.next().await;
}
})
});
app_task.join().unwrap()
})
}
If you don't want to use threads, this should also work on an executor that doesn't require 'static
bounds on futures passed to it, for example smol::LocalExecutor
.
There might be other options but I'd need to see your code to tell for sure. I'm available for contracting hours if you have appetite for that.
from ethercrab.
Thanks, I will try it. But run_tx_rx
still require 'static in windows( windows.rs ). Could I change it to 'sto
from ethercrab.
Ah, right, sorry about that! I fixed it a while ago for Linux/UNIX but I don't test on Windows any more so that slipped past.
I've opened #183 to fix. I'm going to test it now but if you want to, try changing your Cargo.toml
to:
ethercrab = { git = "https://github.com/ethercrab-rs/ethercrab.git", branch = "non-static-windows" }
from ethercrab.
If this suits your application, you could use
thread::scope
which allowsPduStorage
to be non-'static
. Here's a demo that usessmol::block_on
which executes futures on two threads; one the TX/RX, the other the actual task thread:
I don't think this suits my application. My application is using tokio
for the whole program.
However, I have a new idea which may make things easier.
Could we add Copy
method to PduStorageRef
, PduRx
, PduTx
and PduLoop
? Then we can call try_split
in lazy_static
and use (tx, rx, pdu_loop)
in my program.
If it's good, I can write and commit the PR.
from ethercrab.
Related Issues (20)
- Add method to `SlaveGroup` to get all slave statuses at once
- Support reading of `std::String` when `std` feature is turned on
- Get AL status for more than one device as bitflags
- Investigate frame timeouts when using `smol::future::zip()` HOT 1
- Optimise slave status read
- #114 broke some of the replay tests
- Expose PDU parsing functionality
- Consistent naming HOT 1
- Invalid SDO response error HOT 1
- Networks with more than one CoE device causes mailbox timeout
- More accessible docs HOT 4
- Issue configuring EL2262 HOT 1
- Add methods to transition out of OP back to INIT
- ek1100.rs example: thread 'main' panicked at 'Init: WorkingCounter ... HOT 10
- Get `defmt` working properly
- Fail gracefully when no devices found
- Add Embassy example with multiple groups HOT 1
- Add RTIC example with multiple groups
- Redundant network interface support HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ethercrab.