PROFINET Controller Demo Application
Overview
The PROFINET Controller Demo Application (profinet_controller_demo_app.c) demonstrates a complete working implementation of the RAPIDSEA PROFINET Controller stack. It showcases a two-device setup — an Advantech ADAM-6100PN and an RT-Labs reference device — and walks through the full lifecycle: controller initialization, device discovery, network configuration, connection establishment, cyclic IO data exchange, and graceful shutdown.
The application is structured as a finite state machine and serves as a reference starting point for integrating the RAPIDSEA PROFINET Controller stack into custom applications.
Compile-Time Feature Flags
Two feature flags control optional application behaviour at compile time:
Macro |
Default |
Description |
|---|---|---|
|
|
When set to |
|
|
When set to |
Device State Flag Bits
Each managed device tracks its progression through discovery and connection using a bitmask stored in device_info_t.device_state:
Flag |
Description |
|---|---|
|
Set in |
|
Indicates that a station name change has been requested for this device. |
|
Indicates that a network reconfiguration (IP/subnet/gateway) has been requested for this device. |
|
Set once the device’s network parameters have been successfully configured via DCP SET commands. |
|
Indicates that the device is ready to proceed to RPC connection establishment. |
|
Set in |
Application State Machine
The demo is driven by a single while(1) loop executing a switch on the current app_state_t. rs_pn_controller_process() is called unconditionally on every iteration regardless of state. The states and their transitions are described below:
The state transition flow is illustrated below:
CONTROLLER_OPEN → DISCOVERY → DISCOVERY_DELAY → CONFIGURATION
→ CONNECT_DEVICE ↔ WAIT_FOR_CONNECTION
→ RUNNING → RELEASE_DEVICE → CONNECT_DEVICE (loop)
→ CONTROLLER_CLOSE → exit
Demo Device Configurations
When PN_XML_CONFIG_ENABLED is 0, two static rs_pn_device_config_t structures are compiled in and copied into g_pn_controller_config.device_config[] before the main loop starts.
Advantech ADAM-6100PN (Device Index 0)
Station Name |
|
Vendor ID / Device ID |
|
RT Class |
|
Send Clock Factor / Reduction Ratio |
|
Modules |
2 (slot 0: DAP + port submodules; slot 1: digital IO module) |
Submodules |
5 (4 DAP/port submodules in slot 0; 1 bidirectional IO submodule in slot 1, subslot 0x0001) |
IO Data Length (in/out) |
1 byte each |
Input / Output Image Offset |
|
RT-Labs Reference Device (Device Index 1)
Station Name |
|
Vendor ID / Device ID |
|
RT Class |
|
Send Clock Factor / Reduction Ratio |
|
Modules |
2 (slot 0: DAP + port submodules; slot 1: IO module) |
Submodules |
4 (3 DAP/port submodules in slot 0; 1 bidirectional IO submodule in slot 1, subslot 0x0001) |
IO Data Length (in/out) |
1 byte each |
Input / Output Image Offset |
|
Note
The two devices are mapped to adjacent 1-byte offsets in the IO image (offset 0 for the Advantech device and offset 1 for the RT-Labs device), demonstrating how multiple devices share a single flat IO image.
Default Controller Configuration
When PN_CONSOLE_ENABLED is 0, the following hard-coded defaults are used:
Controller IP Address |
|
Subnet Mask |
|
Gateway |
|
Device IP Scan Range |
|
Station Name |
|
Timeout |
5000 ms |
Device Port |
|
Network Interface |
|
Supported Device Count |
2 |
Note
The global g_pn_controller_config also carries a static compile-time initializer (IP 192.168.10.10, port 0x8894, interface enp0s8, timeout 1000 ms). When PN_CONSOLE_ENABLED is 0, get_controller_config() overwrites the relevant fields with the defaults listed above. Ensure the interface name matches the actual Ethernet interface on the target system.
Cyclic IO Data Exchange
During STATE_RUNNING, the demo iterates over a lookup table (dio_lookup[MAX_DIG_INPUT]) of 8 entries. Each entry maps an input image offset and expected input byte value to a corresponding output image offset and output byte value.
For each lookup entry:
rs_pn_controller_read_pnio_data()is called withRS_PN_PNIO_IOCS_GOODas the local consumer status.The returned
iops_statusis checked againstRS_PN_PNIO_IOPS_GOOD(0x80) before the data is used.If the read byte matches the
in_cmp_valfor that entry,rs_pn_controller_write_pnio_data()is called to write the correspondingout_data_valto the output image offset.
This pattern demonstrates the recommended practice of always validating the provider status (IOPS) before acting on received input data.
Index |
Input Offset |
Output Offset |
Compare Value |
Output Value |
|---|---|---|---|---|
0 |
0x00000000 |
0x00000000 |
0 |
0 |
1 |
0x00000000 |
0x00000000 |
2 |
1 |
2 |
0x00000000 |
0x00000000 |
4 |
4 |
3 |
0x00000000 |
0x00000000 |
8 |
8 |
4 |
0x00000000 |
0x00000000 |
16 |
16 |
5 |
0x00000000 |
0x00000000 |
32 |
32 |
6 |
0x00000000 |
0x00000000 |
64 |
64 |
7 |
0x00000000 |
0x00000000 |
128 |
127 |
Note
All lookup entries currently use offset 0x00000000 for both input and output. In a production application these offsets should be updated to match the actual input_image_start_offset and output_image_start_offset of each configured device.
Callback Implementations
The demo provides stub implementations for all required stack callbacks. Only the two callbacks relevant to device lifecycle management contain non-trivial logic:
Callback |
Demo Behaviour |
|---|---|
|
Iterates over all configured devices and compares |
|
If |
|
Stub — returns |
|
Stub — returns |
|
Stub — returns |
|
Stub — returns |
|
Stub — returns |
|
Stub — returns |
|
Stub — returns |
Console Configuration (PN_CONSOLE_ENABLED)
When PN_CONSOLE_ENABLED is set to 1, the function get_controller_config() prompts the operator for all controller network parameters via stdin before the main loop begins. The following internal helpers are used:
Function |
Description |
|---|---|
|
Reads a newline-terminated string from |
|
Prompts for an integer within a specified |
|
Prompts for a dotted-decimal IPv4 address and validates all four octets are in the range 0–255. Retries up to |
|
Prompts for a string up to |
The prompts and their corresponding rs_pn_controller_config_t fields are: Timeout (ms) → timeout_ms; Interface Name → raw_sock_config.iface_name; Device Port → device_port; Station Name → stn_name / stn_name_len; Controller IP → ip_addr; Subnet Mask → subnet_mask; Gateway → gateway; Device IP Start → dev_ip_start; Device IP End → dev_ip_end.
Key Constants
Constant |
Value |
Description |
|---|---|---|
|
100 |
First octet of the device IP scan range (last octet). |
|
254 |
Last octet upper bound for device IP scan range. |
|
5000 |
Per-device connection timeout in milliseconds. |
|
8 |
Number of entries in the digital IO lookup table. |
|
1440 |
Bytes allocated per device IO buffer. |
|
3 |
Maximum re-prompt attempts for invalid console input ( |
Building and Running
Ensure the RAPIDSEA library (
rs_lib.h) and the PROFINET Controller header (rs_profinet_controller.h) are on the include path.Link against the RAPIDSEA stack library.
If
PN_XML_CONFIG_ENABLEDis1, also compile and linkutils_xml_parser.cand provide a valid XML configuration file.Set
raw_sock_config.iface_nameto the Ethernet interface connected to the PROFINET network (default:enp0s8).Run the binary with sufficient privileges for raw socket access (e.g.,
sudoon Linux).
Note
Raw socket operations (AF_PACKET) require either root privileges or the CAP_NET_RAW capability on Linux.
Dependency
This demo depends on the PROFINET Controller stack and its underlying interfaces:
Source Reference
Warning
doxygenfile: Cannot find file “profinet_controller_demo_app.c