### Configure Peripheral with gsdtool Source: https://github.com/rahix/profirust/blob/main/README.md This command uses the `gsdtool` from the profirust project to generate configuration code for a PROFIBUS peripheral based on its GSD file. It guides the user through setting up parameters and modules, emitting Rust code for peripheral options and I/O buffers. Ensure you have Rust and Cargo installed to run this command. ```bash cargo run -p gsdtool -- config-wizard path/to/peripheral.gsd ``` -------------------------------- ### Complete PROFIBUS Application Example (ET200B) Source: https://context7.com/rahix/profirust/llms.txt A full working example demonstrating cyclic data exchange with a PROFIBUS ET200B remote I/O station. It includes initialization, peripheral addition, and data handling for inputs and outputs. ```rust use profirust::{Baudrate, fdl, dp, phy}; fn main() { env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")) .format_timestamp_micros() .init(); println!("ET200B Remote I/O Station Example"); let mut dp_master = dp::DpMaster::new(vec![]); // Configuration for ET200B with 8DI/8DO module let options = dp::PeripheralOptions { ident_number: 0x000b, user_parameters: Some(&[0x00, 0x00, 0x00, 0x00, 0x00]), config: Some(&[0x20, 0x10]), max_tsdr: 100, fail_safe: false, ..Default::default() }; let mut buffer_inputs = [0u8; 1]; let mut buffer_outputs = [0u8; 1]; let mut buffer_diagnostics = [0u8; 13]; let handle_io = dp_master.add( dp::Peripheral::new(13, options, &mut buffer_inputs[..], &mut buffer_outputs[..]) .with_diag_buffer(&mut buffer_diagnostics[..]) ); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(0x02, Baudrate::B500000) .slot_bits(4000) .max_retry_limit(3) .watchdog_timeout(profirust::time::Duration::from_secs(2)) .build_verified(&dp_master) ); println!("Connecting to the bus..."); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B500000); let start = profirust::time::Instant::now(); fdl.set_online(); dp_master.enter_operate(); loop { let now = profirust::time::Instant::now(); fdl.poll(now, &mut phy, &mut dp_master); let events = dp_master.take_last_events(); if let Some((p, ev)) = events.peripheral { if ev != dp::PeripheralEvent::DataExchanged { println!("Event for peripheral #{}: {:?}", p.address(), ev); } } if events.cycle_completed { let io = dp_master.get_mut(handle_io); if io.is_running() { println!("Inputs: {:08b}", io.pi_i()[0]); // Toggle outputs every 2 seconds io.pi_q_mut()[0] = if (now - start).secs() % 2 == 0 { 0xAA } else { 0x55 }; } } std::thread::sleep(std::time::Duration::from_micros(3500)); } } ``` -------------------------------- ### Generate Peripheral Configuration with gsdtool Source: https://context7.com/rahix/profirust/llms.txt Generates PROFIBUS peripheral configuration and parameterization code by parsing GSD files using the `gsdtool` command-line utility. This tool produces ready-to-use Rust code for peripheral setup. ```bash # Run configuration wizard interactively cargo run -p gsdtool -- config-wizard path/to/peripheral.gsd # The wizard will generate Rust code like: # let options = profirust::dp::PeripheralOptions { # ident_number: 0x000b, # user_parameters: Some(&[0x00, 0x00, 0x00, 0x00, 0x05]), # config: Some(&[0x20, 0x10]), # max_tsdr: 100, # fail_safe: false, # ..Default::default() # }; # let mut buffer_inputs = [0u8; 8]; # let mut buffer_outputs = [0u8; 4]; # Dump GSD file contents cargo run -p gsdtool -- dump path/to/peripheral.gsd # Interpret extended diagnostics cargo run -p gsdtool -- diagnostics path/to/peripheral.gsd ``` -------------------------------- ### Install gsdtool using Cargo Source: https://github.com/rahix/profirust/blob/main/gsdtool/README.md Installs the gsdtool command-line interface using the Rust package manager, Cargo. This command fetches the latest version from crates.io and compiles it locally. ```bash cargo install gsdtool ``` -------------------------------- ### Initialize PROFIBUS DP Master in Rust Source: https://context7.com/rahix/profirust/llms.txt Demonstrates how to create a PROFIBUS DP master instance in Rust. It shows options for using fixed-size storage for embedded systems or dynamic allocation for general systems, and how to enter the operating state to start communication. ```rust use profirust::{Baudrate, fdl, dp, phy}; // Create DP master with fixed-size storage let buffer: [dp::PeripheralStorage; 4] = Default::default(); let mut dp_master = dp::DpMaster::new(buffer); // Or with dynamic allocation (std only) // let mut dp_master = dp::DpMaster::new(Vec::new()); // Enter operating state to begin communication dp_master.enter_operate(); ``` -------------------------------- ### Generate Live List of PROFIBUS Bus Stations Source: https://context7.com/rahix/profirust/llms.txt Builds a live list of all active stations (masters and slaves) on the PROFIBUS network for network monitoring. This example uses the profirust crate and requires a serial port configured for PROFIBUS. ```rust use profirust::{Baudrate, fdl, phy}; let mut live_list = fdl::live_list::LiveList::new(); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(3, Baudrate::B500000) .slot_bits(4000) .max_retry_limit(3) .gap_wait_rotations(1) .build() ); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B500000); fdl.set_online(); loop { fdl.poll(profirust::time::Instant::now(), &mut phy, &mut live_list); match live_list.take_last_event() { Some(fdl::live_list::StationEvent::Discovered(station)) => { println!("Discovered station #{} ({:?})", station.address, station.state); } Some(fdl::live_list::StationEvent::Lost(address)) => { println!("Lost station #{}", address); } None => (), } // Print all live stations periodically let stations: Vec<_> = live_list.iter_stations().collect(); println!("Live stations: {:?}", stations); std::thread::sleep(std::time::Duration::from_micros(3500)); } ``` -------------------------------- ### Configure Multi-Master PROFIBUS Bus Source: https://context7.com/rahix/profirust/llms.txt Configures and operates a PROFIBUS network in a multi-master setup, allowing multiple masters to share the token ring. This snippet demonstrates initializing a DpMaster and configuring FDL parameters for multi-master communication. ```rust use profirust::{Baudrate, fdl, dp, phy}; let mut dp_master = dp::DpMaster::new(vec![]); // Configure as master #2 in multi-master network let master_address = 2; let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(master_address, Baudrate::B500000) .slot_bits(300) .max_retry_limit(3) // Set highest station address for token ring .highest_station_address(10) // Gap factor controls polling interval .gap_wait_rotations(5) .build_verified(&dp_master) ); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B500000); fdl.set_online(); dp_master.enter_operate(); loop { let now = profirust::time::Instant::now(); fdl.poll(now, &mut phy, &mut dp_master); // Check connectivity state let state = fdl.connectivity_state(); println!("Connectivity: {:?}", state); let events = dp_master.take_last_events(); if events.cycle_completed { // Process peripheral data } std::thread::sleep(std::time::Duration::from_micros(3500)); } ``` -------------------------------- ### Generate Peripheral Configuration with gsdtool Source: https://github.com/rahix/profirust/blob/main/gsdtool/README.md Demonstrates the interactive use of the `gsdtool config-wizard` subcommand to generate PROFIBUS peripheral configuration data. It prompts the user for module selection and parameter values, then outputs Rust code defining `PeripheralOptions` and input/output buffers. ```rust // Options generated by `gsdtool` using "FRAB4711.gsd" let options = profirust::dp::PeripheralOptions { // ....... }; let mut buffer_inputs = [0u8; 4]; let mut buffer_outputs = [0u8; 4]; let mut buffer_diagnostics = [0u8; 57]; ``` -------------------------------- ### Initialize Serial Port PHY in Rust Source: https://context7.com/rahix/profirust/llms.txt Provides Rust code for initializing a physical layer (PHY) interface for RS-485 communication over a serial port. It demonstrates creating a `SerialPortPhy` instance with a device path and baudrate, and includes a commented-out option for Linux-specific RS-485 control. ```rust use profirust::{Baudrate, phy}; // Initialize PHY with device path and baudrate let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B500000); // For Linux-specific RS-485 control // let mut phy = phy::LinuxRs485Phy::new("/dev/ttyUSB0", Baudrate::B500000); ``` -------------------------------- ### Configure FDL Active Station in Rust Source: https://context7.com/rahix/profirust/llms.txt Shows how to configure the Fieldbus Data Link (FDL) layer in Rust for an active station. This involves setting up bus parameters such as master address, baudrate, slot timing, retry limits, and watchdog timeouts, and then bringing the station online. ```rust use profirust::{Baudrate, fdl, dp}; let mut dp_master = dp::DpMaster::new(vec![]); let master_address = 2; // Build FDL parameters with verification let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(master_address, Baudrate::B500000) .slot_bits(4000) .max_retry_limit(3) .watchdog_timeout(profirust::time::Duration::from_secs(2)) .build_verified(&dp_master) ); // Set station online to join token ring fdl.set_online(); ``` -------------------------------- ### Execute Profirust Communication Cycle with FDL Polling Source: https://context7.com/rahix/profirust/llms.txt This snippet demonstrates the main communication loop using Profirust's FDL layer. It initializes the DP master, FDL station, and physical layer, then enters a loop to continuously poll the FDL for token handling, peripheral communication, and event generation. It also shows how to retrieve and handle cycle completion and peripheral events. ```rust use profirust::{Baudrate, fdl, dp, phy}; let mut dp_master = dp::DpMaster::new(vec![]); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(2, Baudrate::B19200) .slot_bits(300) .build_verified(&dp_master) ); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B19200); fdl.set_online(); dp_master.enter_operate(); loop { let now = profirust::time::Instant::now(); // Poll performs token handling and peripheral communication fdl.poll(now, &mut phy, &mut dp_master); // Retrieve events from last poll cycle let events = dp_master.take_last_events(); // Handle cycle completion if events.cycle_completed { // Full data exchange cycle completed } // Handle peripheral events if let Some((handle, event)) = events.peripheral { match event { dp::PeripheralEvent::Online => println!("Peripheral came online"), dp::PeripheralEvent::Configured => println!("Peripheral configured"), dp::PeripheralEvent::DataExchanged => println!("Data exchanged"), dp::PeripheralEvent::Offline => println!("Peripheral went offline"), _ => (), } } std::thread::sleep(std::time::Duration::from_micros(3500)); } ``` -------------------------------- ### Access Profirust Peripheral Process Image Data Source: https://context7.com/rahix/profirust/llms.txt This code illustrates how to interact with a peripheral's process image within the Profirust communication cycle. It adds a peripheral to the DP master, sets up the communication layers, and then within the polling loop, it reads input data and writes output data to the peripheral's process image. Accessing both inputs and outputs simultaneously is also demonstrated. ```rust use profirust::{Baudrate, fdl, dp, phy}; let mut dp_master = dp::DpMaster::new(vec![]); let mut buffer_inputs = [0u8; 8]; let mut buffer_outputs = [0u8; 4]; let peripheral_handle = dp_master.add(dp::Peripheral::new( 7, dp::PeripheralOptions::default(), &mut buffer_inputs[..], &mut buffer_outputs[..] )); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(2, Baudrate::B19200) .slot_bits(300) .build_verified(&dp_master) ); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B19200); fdl.set_online(); dp_master.enter_operate(); loop { let now = profirust::time::Instant::now(); fdl.poll(now, &mut phy, &mut dp_master); let events = dp_master.take_last_events(); if events.cycle_completed { let peripheral = dp_master.get_mut(peripheral_handle); if peripheral.is_running() { // Read input process image let inputs = peripheral.pi_i(); println!("Inputs: {:02x?}", inputs); // Write output process image let outputs = peripheral.pi_q_mut(); outputs[0] = 0xAA; outputs[1] = 0x55; // Or access both simultaneously let (pi_i, pi_q) = peripheral.pi_both(); println!("Input bits: {:08b}, setting outputs", pi_i[0]); pi_q[0] = !pi_i[0]; } } std::thread::sleep(std::time::Duration::from_micros(3500)); } ``` -------------------------------- ### Add Peripheral to DP Master in Rust Source: https://context7.com/rahix/profirust/llms.txt Illustrates adding a PROFIBUS peripheral (slave device) to a DP master in Rust. This includes configuring peripheral options like identifier, user parameters, configuration data, and allocating buffers for process image inputs, outputs, and diagnostics. ```rust use profirust::dp; let mut dp_master = dp::DpMaster::new(vec![]); // Configure peripheral options (best generated using gsdtool) let remoteio_address = 7; let remoteio_options = dp::PeripheralOptions { ident_number: 0x000b, user_parameters: Some(&[0x00, 0x00, 0x00, 0x00, 0x00]), config: Some(&[0x20, 0x10]), max_tsdr: 100, fail_safe: false, ..Default::default() }; // Allocate process image buffers let mut buffer_inputs = [0u8; 8]; let mut buffer_outputs = [0u8; 4]; let mut buffer_diagnostics = [0u8; 64]; // Add peripheral and get handle for later access let remoteio_handle = dp_master.add( dp::Peripheral::new( remoteio_address, remoteio_options, &mut buffer_inputs[..], &mut buffer_outputs[..] ) .with_diag_buffer(&mut buffer_diagnostics[..]) ); ``` -------------------------------- ### Scan PROFIBUS Bus for Peripherals Source: https://context7.com/rahix/profirust/llms.txt Discovers all PROFIBUS peripherals on the bus by scanning addresses and retrieving their identification information. This requires the profirust crate and a configured serial port for PROFIBUS communication. ```rust use profirust::{Baudrate, fdl, dp, phy}; let mut dp_scanner = dp::scan::DpScanner::new(); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(3, Baudrate::B500000) .slot_bits(4000) .max_retry_limit(3) .gap_wait_rotations(1) .build() ); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B500000); fdl.set_online(); loop { fdl.poll(profirust::time::Instant::now(), &mut phy, &mut dp_scanner); match dp_scanner.take_last_event() { Some(dp::scan::DpScanEvent::PeripheralFound(desc)) => { println!("Found peripheral at address {}", desc.address); println!(" Ident: 0x{:04x}", desc.ident); println!(" Master: {:?}", desc.master_address); } Some(dp::scan::DpScanEvent::PeripheralLost(address)) => { println!("Lost peripheral at address {}", address); } None => (), } std::thread::sleep(std::time::Duration::from_micros(3500)); } ``` -------------------------------- ### Request and Read PROFIBUS Diagnostics Source: https://context7.com/rahix/profirust/llms.txt Requests diagnostic information from a PROFIBUS peripheral and parses the response to detect configuration faults, parameter errors, and extended diagnostics. This snippet requires the profirust crate and a serial port interface configured for PROFIBUS communication. ```rust use profirust::{Baudrate, fdl, dp, phy}; let mut dp_master = dp::DpMaster::new(vec![]); let mut buffer_inputs = [0u8; 8]; let mut buffer_outputs = [0u8; 4]; let mut buffer_diagnostics = [0u8; 64]; let peripheral_handle = dp_master.add( dp::Peripheral::new( 7, dp::PeripheralOptions::default(), &mut buffer_inputs[..], &mut buffer_outputs[..] ) .with_diag_buffer(&mut buffer_diagnostics[..]) ); let mut fdl = fdl::FdlActiveStation::new( fdl::ParametersBuilder::new(2, Baudrate::B19200) .slot_bits(300) .build_verified(&dp_master) ); let mut phy = phy::SerialPortPhy::new("/dev/ttyUSB0", Baudrate::B19200); fdl.set_online(); dp_master.enter_operate(); loop { let now = profirust::time::Instant::now(); fdl.poll(now, &mut phy, &mut dp_master); let events = dp_master.take_last_events(); if let Some((_, dp::PeripheralEvent::Diagnostics)) = events.peripheral { let peripheral = dp_master.get_mut(peripheral_handle); if let Some(diag) = peripheral.last_diagnostics() { println!("Diagnostic flags: {:?}", diag.flags); println!("Ident number: 0x{:04x}", diag.ident_number); if diag.flags.contains(dp::DiagnosticFlags::CONFIGURATION_FAULT) { println!("Configuration fault detected"); } if diag.flags.contains(dp::DiagnosticFlags::PARAMETER_FAULT) { println!("Parameter fault detected"); } if diag.flags.contains(dp::DiagnosticFlags::EXT_DIAG) { println!("Extended diagnostics available:"); for block in diag.extended_diagnostics.iter_diag_blocks() { match block { dp::ExtDiagBlock::Channel(ch) => { println!(" Module {}, Channel {}: {:?} {{:?}}", ch.module, ch.channel, ch.dtype, ch.error); } _ => println!(" {:?}", block), } } } } } // Request diagnostics manually let peripheral = dp_master.get_mut(peripheral_handle); peripheral.request_diagnostics(); std::thread::sleep(std::time::Duration::from_micros(3500)); } ``` -------------------------------- ### Parse Device Diagnostics with gsdtool Source: https://github.com/rahix/profirust/blob/main/gsdtool/README.md Shows how to use the `gsdtool diagnostics` subcommand to parse diagnostic data from a GSD file. The tool interprets raw diagnostic bytes and provides a human-readable output, including specific error bits and area values. ```bash gsdtool diagnostics si0380a7.gsd ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.