diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bcddbdb..144865ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +## 2021-03-03 +### Changed +- Set thread priority and stack size via configuration + +## 2021-02-19 +### Changed +- Split options.h into two files. +- Simplify configuration + +## 2020-02-03 +### Added + - Improved support for multiple ports + ## 2021-01-29 ### Changed - -Move remaining Linux sample app files to src/ports/linux + - Move remaining Linux sample app files to src/ports/linux ## 2020-01-11 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 583de6f7..8ad8f107 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ set(PNET_MAX_PHYSICAL_PORTS 1 set(PNET_MAX_LOG_BOOK_ENTRIES 16 CACHE STRING "") set(PNET_MAX_ALARMS 3 - CACHE STRING "Per AR and queue. One queue for high and one for low priority alarms.") + CACHE STRING "Per AR and queue. One queue for high and one for low priority alarms. 'Automated RT Tester' uses 2.") set(PNET_MAX_ALARM_PAYLOAD_DATA_SIZE 28 CACHE STRING "Min 24 or PNET_MAX_DIAG_MANUF_DATA_SIZE + 12. Max is 1408") set(PNET_MAX_DIAG_ITEMS 200 diff --git a/README.md b/README.md index d43a5ade..a18d5e91 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Web resources * Source repository: [https://github.com/rtlabs-com/p-net](https://github.com/rtlabs-com/p-net) * Documentation: [https://rt-labs.com/docs/p-net](https://rt-labs.com/docs/p-net) * Continuous integration: [https://github.com/rtlabs-com/p-net/actions](https://github.com/rtlabs-com/p-net/actions) -* RT-Labs: [https://rt-labs.com](https://rt-labs.com) +* RT-Labs (stack integration, certification services and training): [https://rt-labs.com](https://rt-labs.com) [![Build Status](https://github.com/rtlabs-com/p-net/workflows/Build/badge.svg?branch=master)](https://github.com/rtlabs-com/p-net/actions?workflow=Build) @@ -59,12 +59,11 @@ Limitations or not yet implemented: * This is a device stack, which means that the IO-controller/master/PLC side is not supported. * No media redundancy (No MRP support) -* No startup mode legacy +* Legacy startup mode is not fully implemented * No support for RT_CLASS_UDP * No support for DHCP * No fast start-up * No MC multicast device-to-device -* No support of shared device (connection to multiple controllers) * No iPar (parameter server) support * No support for time synchronization * No UDP frames at alarm (just the default alarm mechanism is implemented) @@ -99,17 +98,40 @@ having 8 digital inputs and 8 digital outputs (one bit each). The values are sent and received each millisecond (PLC watchdog setting 3 ms). +Getting started +--------------- +See the tutorial in the documentation: [https://rt-labs.com/docs/p-net/tutorial.html](https://rt-labs.com/docs/p-net/tutorial.html) + +Note that you need to include submodules when cloning: + +``` +git clone --recurse-submodules https://github.com/rtlabs-com/p-net.git +``` + Dependencies ------------ +Some of the platform-dependent parts are located in the OSAL repository and the +cmake-tools repository. + +* [https://github.com/rtlabs-com/osal](https://github.com/rtlabs-com/osal) +* [https://github.com/rtlabs-com/cmake-tools](https://github.com/rtlabs-com/cmake-tools) + +Those are downloaded automatically during install. + The p-net stack contains no third party components. Its external dependencies are: * C-library * An operating system (if used) +* For conformance class B you need an SNMP implementation. On Linux is + net-snmp (BSD License) used [http://www.net-snmp.org](http://www.net-snmp.org) -Tools used for building and documentation (not shipped in the resulting binaries): +Tools used for building, testing and documentation (not shipped in the resulting binaries): -* cmake (BSD 3-clause License) -* Sphinx (BSD license) +* cmake (BSD 3-clause License) [https://cmake.org](https://cmake.org) +* gtest (BSD-3-Clause License) [https://github.com/google/googletest](https://github.com/google/googletest) +* Sphinx (BSD license) [https://www.sphinx-doc.org](https://www.sphinx-doc.org) +* Doxygen (GPL v2) [https://www.doxygen.nl](https://www.doxygen.nl/index.html) +* clang-format (Apache License 2.0) [https://clang.llvm.org](https://clang.llvm.org/docs/ClangFormat.html) Contributions diff --git a/doc/abbreviations.rst b/doc/abbreviations.rst index 174c5f94..91e33f9d 100644 --- a/doc/abbreviations.rst +++ b/doc/abbreviations.rst @@ -11,7 +11,8 @@ Commissioning Engineering tool A desktop program for configuring PLC. For example Siemens TIA portal. Parameterization - Write parameter values to all submodules + Write parameter values to all submodules. Parameterization is done via + the Write and Control commands. Record data Data that can be accessed with acyclic Profinet Read and Write. Addressed by slot, subslot and index. diff --git a/doc/additional_linux_details.rst b/doc/additional_linux_details.rst index 12663431..0a21008f 100644 --- a/doc/additional_linux_details.rst +++ b/doc/additional_linux_details.rst @@ -127,19 +127,30 @@ Study the resulting core:: SNMP (Conformance class B) -------------------------- Conformance class B requires SNMP support. Linux uses net-snmp as agent, -see http://www.net-snmp.org/. P-Net for Linux implements -a Net-SNMP subagent that handles the Profinet mandatory MIB:s. Also +see http://www.net-snmp.org/. The name of the SNMP agent binary is ``snmpd``. + +P-Net for Linux implements a Net-SNMP subagent that handles the Profinet +mandatory MIB:s. Also see :ref:`network-topology-detection` for information regarding SNMP. -Enable SNMP by setting ``PNET_OPTION_SNMP`` to ``ON``. Net-SNMP also needs to +Enable SNMP by setting ``PNET_OPTION_SNMP`` to ``ON`` in the p-net compilation +options. Net-SNMP also needs to be installed. On Ubuntu you can install the required packages using:: sudo apt install -y snmpd libsnmp-dev -The p-net SNMP subagent will handle the system objects so the default -SNMP system module should be disabled by adding the snmpd argument -``-I -system_mib``, otherwise the subagent will complain about -"registering pdu failed" at startup. On Ubuntu Linux you should change +To show the installed version of ``snmpd``, use:: + + snmpd -v + + +Change snmpd command line arguments +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The p-net SNMP subagent will handle the system objects, so the default +SNMP "system" module should be disabled by adding the snmpd argument +``-I -system_mib``. Otherwise the subagent will complain about +"registering pdu failed" at startup. If you use systemd init system (for +example on Ubuntu Linux) you should change ``/lib/systemd/system/snmpd.service`` to read:: [Unit] @@ -166,13 +177,30 @@ To restart the service after modification:: sudo systemctl daemon-reload sudo systemctl restart snmpd.service +The command line arguments ``-u`` and ``-g`` are for the user id and group id +of the snmpd process will use after its initial startup. +They are not necessary to use snmpd. +However snmpd must be started with permissions to open relevant sockets, +typically root permissions. + +If you use "system V init" instead of systemd, then snmpd is typically started +by a script file named ``/etc/init.d/snmpd``. Change the snmpd command line +arguments in the file, typically via ``SNMPDOPTS``. Stop and start the +service with:: + + sudo /etc/init.d/snmpd stop + sudo /etc/init.d/snmpd start + + +Configuration file for snmpd +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The file ``snmpd.conf`` controls access to the snmp agent. It should be set to listen on all interfaces and allow read-write access to the Profinet MIB:s. On Ubuntu Linux you should change ``/etc/snmp/snmpd.conf`` to read:: master agentx - agentaddress 0.0.0.0,[::1] + agentaddress udp:161 view systemonly included .1.3.6.1.2.1.1 view systemonly included .1.3.6.1.2.1.2.2 view systemonly included .1.0.8802.1.1.2 @@ -189,6 +217,8 @@ See :ref:`network-topology-detection` for more details on SNMP and how to verify the SNMP communication to the p-net stack. +Start your application after snmpd +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You probably would like your application to wait for the ``snmpd`` application to be up and running. If you use systemd as init system, modify this line in the ``[Unit]`` part of your ``.service`` file:: @@ -200,6 +230,42 @@ You might also need to add this to the ``[Service]`` part of your ExecStartPre=/usr/bin/sleep 0.3 +If the p-net application fails to connect to snmpd, a message "Warning: Failed +to connect to the agentx master agent" will be written to the p-net sample +app log file every 15 seconds. + + +Debugging snmpd settings +^^^^^^^^^^^^^^^^^^^^^^^^ +The command line argument ``-LOw`` for snmpd sets the snmpd logging to +standard out with log level "warning". +To change to log level debug, use ``-LOd``. You should also use the ``-D`` flag +to select which debug messages you are interested in. Use the ``-Dagentx`` +command line argument to debug the agentx communication between the snmpd and +the subagent in the p-net stack. A log example when asked for a single OID:: + + Connection from UDP: [192.168.0.30]:43833->[192.168.0.50]:161 + agentx/master: agentx master handler starting, mode = 0xa0 + agentx/master: request for variable (iso.3.6.1.2.1.1.4.0) + agentx/master: sending pdu (req=0x8,trans=0x7,sess=0x6) + agentx_build: packet built okay + agentx/master: got response errstat=0, (req=0x8,trans=0x7,sess=0x6) + agentx/master: agentx_got_response() beginning... + agentx/master: handle_agentx_response: processing: iso.3.6.1.2.1.1.4.0 + agentx/master: handle_agentx_response() finishing... + +Note that there might be a warning message "pcilib: Cannot open /proc/bus/pci" +in the snmpd log if you specify that it should use all interfaces. +That is because it will look also for (possibly non-existing) PCI interfaces. + +To trouble-shoot snmpd issues, verify that no other snmpd instances are running:: + + ps -ef | grep snmpd + +and verify that no other process is using UDP port 161:: + + sudo lsof -i udp -n -P + snmpd in a Yocto build ---------------------- @@ -232,3 +298,78 @@ commands to analyze the startup:: systemd-analyze systemd-analyze blame systemd-analyze critical-chain pnet-sampleapp.service + + +Debug the sample application on a Linux Laptop +---------------------------------------------- +It can be convenient to be able to run the sample application and the p-net +stack in a debugger tool. It is easy using gdb and the Visual Studio Code +editor. + +First make sure you can run the application from a terminal on your Linux +laptop. + +Next step is to be able to run it from the terminal within Visual Studio Code. +In case of compilation error messages, you can click on the code line given +in the terminal (within Visual Studio Code) and the corresponding file will +be opened. + +To use debug features while running (for example breakpoints) you need to adapt +the settings file for Visual Studio Code. Click the "Run and Debug" icon +in the left side tool bar. Then click "Create a launch.json file". In the +"Select environment", use "C++ (GDB/LLDB)". + +Modify the ``launch.json`` file to point at the correct executable, working +directory and to use correct command line arguments. + +If you need to run the application with root permissions, you need to add a path in the +``"miDebuggerPath"`` field. It should point to a text file typically named +``gdb``, with this content:: + + pkexec /usr/bin/gdb "$@" + +Put the ``gdb`` file for example in the ``.vscode`` subdirectory within +the ``p-net`` directory. Set the executable flag:: + + chmod +x gdb + +An example of a ``launch.json`` file:: + + { + "version": "0.2.0", + "configurations": [ + + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/build/pn_dev", + "args": ["-vv", "-i", "enp0s31f6"], + "stopAtEntry": false, + "cwd": "${workspaceFolder}/build/", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "miDebuggerPath": "${workspaceFolder}/.vscode/gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + + ] + } + +The given ``"args"`` command line arguments in the example is for +increasing the verbosity level and to set the Ethernet interface name. +Adapt those and also paths to your particular setup. + +Use the CMAKE_BUILD_TYPE setting as ``Debug`` when running the executable +via the debugger. + +Start the debugging by clicking on the small green "Run" icon on the +"Run and Debug" page. It will stop at any breakpoint. Set a breakpoint in +any file by clicking on a line to the left of the line number. diff --git a/doc/applications_and_porting.rst b/doc/applications_and_porting.rst index 4a6f976c..6cb3b506 100644 --- a/doc/applications_and_porting.rst +++ b/doc/applications_and_porting.rst @@ -55,6 +55,21 @@ Hardware requirements for the Ethernet ports: * Auto negotiation (should be possible to turn off for fast startup) +Interacting with other parts of your application software +--------------------------------------------------------- +When the PLC sends a "factory reset" command, not only the p-net stack but +also the rest of your application should be reset to factory settings. + +If there is a method to do a factory reset of your application, it should also +reset the p-net stack. + +It is possible to set the IP-address, netmask and gateway address via Profinet +from a PLC. Consider how this affects other aspects of your application. + +Serial number, software version, model name etc should be available for the +p-net stack to use. + + Minimum cycle time for your application and hardware ---------------------------------------------------- At PLC configuration, there are two adjustable parameters regarding the diff --git a/doc/capturing_packets.rst b/doc/capturing_packets.rst index 4d9f98de..a2ae9163 100644 --- a/doc/capturing_packets.rst +++ b/doc/capturing_packets.rst @@ -23,8 +23,8 @@ For details on how to add yourself to the ``wireshark`` user group, see https://linuxhint.com/install_wireshark_ubuntu/ -Filtering frames in Wirehark based on protocol ----------------------------------------------- +Filtering frames in Wireshark based on protocol +----------------------------------------------- To show only frames with specific protocols, enter this into the "display filter" text box:: @@ -34,6 +34,32 @@ To hide frames with specific protocols:: not (pn_ptcp or arp or mdns or llmnr or ssdp or dhcp or dhcpv6 or icmpv6 or igmp or nbns or browser or ipv6) ++--------------------------+----------------------------------------------------+ +| Filter expression | Wireshark protocol names | ++==========================+====================================================+ +| arp | ARP | ++--------------------------+----------------------------------------------------+ +| epm | EPM | ++--------------------------+----------------------------------------------------+ +| lldp | LLDP | ++--------------------------+----------------------------------------------------+ +| pn_dcp | PN-DCP | ++--------------------------+----------------------------------------------------+ +| pn_io | PNIO and PNIO_PS and PNIO-AL | ++--------------------------+----------------------------------------------------+ +| pn_io_controller | PNIO-CM (application ready) | ++--------------------------+----------------------------------------------------+ +| pn_io_device | PNIO-CM (connect, read, read implicit, write, | +| | param end, release) | ++--------------------------+----------------------------------------------------+ +| pn_ptcp | PN-PTCP | ++--------------------------+----------------------------------------------------+ +| snmp | SNMP | ++--------------------------+----------------------------------------------------+ +| syslog | Syslog | ++--------------------------+----------------------------------------------------+ + + Filter frames in Wireshark based on frame contents -------------------------------------------------- @@ -131,6 +157,10 @@ Use the ``-i`` argument to specify Ethernet interface. Transfer the resulting file to your laptop, where you can open it in Wireshark. +Note that Wireshark and tcpdump modifies the network interface settings on Linux. +The promiscuous bit will be enabled, as seen when looking at +``/sys/class/net/eth0/flags``. It will not be visible via ``ifconfig`` though. + Hardware for capturing packets on network ----------------------------------------- diff --git a/doc/codesys_details.rst b/doc/codesys_details.rst new file mode 100644 index 00000000..5ff12b6d --- /dev/null +++ b/doc/codesys_details.rst @@ -0,0 +1,178 @@ +Codesys Details +=============== +This page contains additional information on how to use the Codesys soft PLC. + + +Adjust PLC timing settings +-------------------------- +It is possible to adjust the cycle time that the IO-controller (PLC) is using +for cyclic data communication with an IO-device. + +In the left menu, double-click the "P_Net_Sample_App", and open the "General" +tab. The "Communication" section shows the send clock in milliseconds, as read +from the GSDML file. By using the "Reduction ratio" you can slow down the +communication, by multiplying the cycle time by the factor given in the +dropdown. + +It is also possible to increase the watchdog time, after which the PLC will set +an alarm for missing incoming cyclic data. The watchdog will also shut down the +communication, and trigger a subsequent restart of communication. + +In case of problems, increase the reduction ratio (and timeout) value a lot, +and then gradually reduce it to find the smallest usable value. + + +Displaying errors +----------------- +Click on the IO-device in the tree structure in the left part of the screen. +Use the "Log" tab to display errors. + + +Connection status +----------------- +Go to the Profinet IO-device page, and see the "PNIO IEC objects" tab. Expand +the topmost row. The states of these boolean fields are shown: + +* xRunning: Periodic data is sent +* xBusy: The controller is trying to connect to the IO-device +* xError: Failure to connect to the IO-device + +If there is no connection at all to the IO-device, the state will shift to +xBusy from xError once every 5 seconds. + + +Change IP address of IO-device +------------------------------ +Change the IP address by double-clicking the "P_Net_Sample_App" node +in the left menu, using the "General" tab. Set the IP-address to new value. + +The IO-controller will send the new IP address in a "DCP Set" message to the +IO-device having the given station name. Then it will use ARP messages to +the IO-device to find its MAC address, and to detect IP address collisions. + + +Scan for devices, assign IP address, reset devices and change station name +-------------------------------------------------------------------------- + +Scan +^^^^ +In the left side menu, right-click the PN_Controller and select "Scan for +devices". The running IO-devices will show up, and it is possible to see which +modules are plugged into which slot. +Note that the texts in the columns "Device name" and "Device type" are from the +available GSDML files in Codesys. If a corresponding GSDML file not has been +loaded, the text "Attention: The device was not found in the repository" is +shown together with the Vendor-ID and Product-ID. + +This is implemented in Codesys by sending the "Ident request, all" DCP +message from the IO-controller. +It works also if there are no IO-devices loaded in the left side hierarchy menu. +An IO-device will respond with the "Ident OK" DCP message. Then the IO-controller +will do a "Read implicit request" for "APIData", on which the IO device +responds with the APIs it supports. A similar request for +"RealIdentificationData for one API" is done by the IO-controller, on which the +IO-device responds which modules (and submodules) are plugged into which slots +(and subslots). + +Factory reset +^^^^^^^^^^^^^ +To factory reset a device, select it in the list of scanned devices and click +the "reset" button. + +At a factory reset, the IO-controller sends a "Set request" DCP message +with suboption "Reset factory settings". After sending a response, the +IO-device will do the factory reset and also send a LLDP message with the +new values. Then the IO-controller sends a "Ident request, all", to which +the IO-device responds. + +Set name and IP +^^^^^^^^^^^^^^^ +To modify the station name or IP address, change the corresponding fields +in the list of scanned devices, and the click "Set name and IP". + +The IO-controller sends a "Set request" DCP message +with suboptions "Name of station" and "IP parameter". After sending a +response, the IO-device will change IP address and station name. It will +also send a LLDP message with the new values. Then the +IO-controller sends a "Ident request, all", to which the IO-device responds. + +Flash LED +^^^^^^^^^ +There is functionality to flash a LED on an IO-device. Select your device in +the list of scanned devices, and click the "Blink LED" button. The button +remains activated until you click it again. + +LED-blinking is done by sending the "Set request" DCP message with suboption +"Signal" once every 5 seconds as long as the corresponding button is activated. + +Identification & Maintenance (I&M) data +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In order the read Identification & Maintenance (I&M) data, the device needs to +be present as an IO-device connected to the IO-controller in the left side menu. +Select the device in the list of scanned devices, and click the "I&M" button. + +Reading I&M data is done by the IO-controller by sending four "Read implicit" +request DCP messages, one for each of I&M0 to I&M3. + +When writing I&M data from Codesys, it will send a connect, write and release. + + +Writing and reading IO-device parameters +---------------------------------------- +The parameters for different submodules are written as part of normal startup. + +To adjust the values sent at startup, you must first be offline. +Then double-click the DIO_8xLogicLevel device in the left menu. Use the +General tab, and the Settings part of the page. Click the corresponding +value in the table, and adjust it. + +While offline (with regards to the PLC, it is possible to manually trigger +parameter reading and writing. Right-click the parameter you would like +to send, and select "Write to device". It is also possible to read a +parameter similarly. + +To read all or write all parameters, use the corresponding buttons. +When clicking the "Write All Values" icon, one write request is sent per +parameter. + + +Displaying alarms sent from IO-device +------------------------------------- +Incoming process alarms and diagnosis alarms appear on multiple places in +the Codesys desktop application. + +* Codesys Raspberry Pi: The "Log" tab show process and diagnosis alarms. +* PN_Controller: The "Log" tab show process and diagnosis alarms. +* IO-device: The "Log" tab show process and diagnosis alarms. The + “Status” tab shows alarms related to built-in (DAP) modules. +* Plugged module in IO-device: Process and diagnosis alarms are displayed on + the “Status” tab. + + +Setting output producer status (IOPS) +------------------------------------- +Normally Codesys will set the Output PS to GOOD (0x80 = 128) when running. +Clicking the "Output PS" checkbox on the "IOxS" tab on the Profinet IO-device +sets the value to BAD (0). + + +Enabling checking of peer stationname and port ID +------------------------------------------------- +It is possible to have the IO-device verify that it is connected to the +correct neighbour (peer) by checking its station name and port ID (as sent +in LLDP frames by the neighbour). + +Double-click the “P_Net_Sample_App” node in the left menu. On the "options" +tab in the resulting window, use the fields "Peer station" and "port". It +seems only possible to select station names from other devices or controllers +already available in the project. + +During startup the PLC will send the given values to the IO-Device via a +write command. If the correct neighbour is not present, an alarm will be sent +by the IO-device to the PLC. + + +Writing PLC programs +-------------------- +Documentation of available function blocks is found at +https://help.codesys.com/webapp/_pnio_f_profinet_io_configuration;product=core_ProfinetIO_Configuration_Editor diff --git a/doc/compliancetest.rst b/doc/compliancetest.rst index 740155d4..bede6f3b 100644 --- a/doc/compliancetest.rst +++ b/doc/compliancetest.rst @@ -40,7 +40,9 @@ load. This is tested by a separate tool (not the "Automated RT tester"). Installation of Automated RT tester on a Windows PC --------------------------------------------------- Unzip the downloaded file, and double-click the -"AutomatedRtTester_2.4.1.3_Setup.exe" file. +"AutomatedRtTester_VERSION_Setup.exe" file. + +Verify that you use the latest available version. Adjust the Ethernet network card on a Windows PC @@ -112,6 +114,10 @@ When communication is verified, enable all relevant test cases. The ART tester tool stores Wireshark files (.pcap files) in the project directory. See the ``EthernetDump`` subdirectory. +To export test reports as PDF, click the small printer icon in the top +toolbar. + + Additional hardware ------------------- Some of the test cases requires additional hardware; a Profinet-enabled switch diff --git a/doc/implementation_details.rst b/doc/implementation_details.rst index 945c08ce..2af3d435 100644 --- a/doc/implementation_details.rst +++ b/doc/implementation_details.rst @@ -163,10 +163,11 @@ Sections in 61158-5-10 (services) describing diagnosis: | 7.1.4.5.3.6 | Channel and channel numbers | +---------------+-------------------------------------------------------------+ | 7.3.1.5.6.3 | Behavior of the Module Diff Block regarding diagnosis | +| | (failed parameterization) | +---------------+-------------------------------------------------------------+ | 7.3.1.6.1.2 | Alarm types attached to diagnosis ASE | +---------------+-------------------------------------------------------------+ -| 7.3.1.6.5.1 | Alarm Notification | +| 7.3.1.6.5.1 | "Alarm Notification" Lists of diagnosis data | +---------------+-------------------------------------------------------------+ | 7.3.2.5 | Observer class (PD Port Data Check etc) | +---------------+-------------------------------------------------------------+ @@ -192,6 +193,9 @@ Sections in 61158-6-10 (protocol) describing diagnosis: See also the "Diagnosis for Profinet" Guideline published by the Profinet organisation. +For general discussions on diagnosis usage, see the section "A.6 PROFINET +Diagnosis" in the "Specification for GSDML" document. + An array of PNET_MAX_DIAG_ITEMS diagnosis items is available for use. Each subslot uses a linked list of diagnosis items, and stores the index to the head of its list. @@ -428,6 +432,33 @@ ETH Registers and invokes frame handlers for incoming raw Ethernet frames. +Module diff block +----------------- +Informs about differences between expected and plugged modules, +and also about diagnosis in modules etc. The information for each submodule +is indicated by bit fields in a 16-bit number. + +Relevant sections in 61158-5-10 (services): + ++--------------------------+--------------------------------------------------+ +| Section | Description | ++==========================+==================================================+ +| 7.3.1.5.5.5 - 7.3.1.5.6 | "Read Module Diff Block for one AR" | ++--------------------------+--------------------------------------------------+ + +Relevant sections in 61158-6-10 (protocol): + ++---------------+-------------------------------------------------------------+ +| Section | Description | ++===============+=============================================================+ +| 5.1.2 | "APDU abstract syntax" | ++---------------+-------------------------------------------------------------+ +| 5.2.5.65 | "Coding of the field SubmoduleState" | ++---------------+-------------------------------------------------------------+ +| 5.2.42.3.6 | "ModuleDiffBlock" | ++---------------+-------------------------------------------------------------+ + + LLDP - Link Layer Discovery Protocol ------------------------------------ Sections in 61784-2 (profiles) describing LLDP: @@ -469,7 +500,6 @@ Sections in 61158-6-10 (protocol) describing LLDP: +---------------+-------------------------------------------------------------+ - Simple Network Management Protocol (SNMP) ----------------------------------------- @@ -528,14 +558,80 @@ organisation, and the list of supported OIDs in the test case specification "Topology discovery check". +Legacy startup mode +------------------- +The startup mode is parsed at connect. It uses legacy start up mode when +this value is set to false:: + + p_ar->ar_param.ar_properties.startup_mode + +Section 17 "Startup Mode" in the guideline "PROFINET IRT Engineering" discusses +the differences between legacy and advanced startup modes. + +Sections in 61784-2 (profiles) describing Legacy Startup mode: + ++---------------+-------------------------------------------------------------+ +| Section | Description | ++===============+=============================================================+ +| 7.1.9.2 | "Index" ARFSUDataAdjust (0xE050) | ++---------------+-------------------------------------------------------------+ + +Sections in 61158-5-10 (services) describing Legacy Startup mode: + ++---------------+-------------------------------------------------------------+ +| Section | Description | ++===============+=============================================================+ +| 7.3.1.3.4 | "Attributes" Allowed values for Startup Mode and for CM | +| | Initiator Activity Timeout Factor. The fields "IR Info | +| | Block", "SR Info Block", "Redundancy Info" and "List of | +| | AR Vendor Blocks" only in advanced startup mode. | ++---------------+-------------------------------------------------------------+ +| 7.3.1.3.5.1.2 | "Connect" Usage of "IR Info Block" , "SR Info Block" and | +| | "AR Server Block" | ++---------------+-------------------------------------------------------------+ +| 7.3.1.3.5.11 | "Read Expected Fast Startup Data" Only in legacy mode, and | +| | only for fast startup. | ++---------------+-------------------------------------------------------------+ +| 7.3.1.3.5.12 | "Write Expected Fast Startup Data" Only in legacy mode, and | +| | only for fast startup. | ++---------------+-------------------------------------------------------------+ +| 7.3.1.3.6.3 | "IO controller during startup" Record data ARFSUDataAdjust | +| | (0xE050) supported only for legacy mode | ++---------------+-------------------------------------------------------------+ +| 7.3.1.4.4 | "Attributes" RT Class and startup mode combinations | ++---------------+-------------------------------------------------------------+ + +Sections in 61158-6-10 (protocol) describing Legacy Startup mode: +(search for "startupmode") + ++---------------+-------------------------------------------------------------+ +| Section | Description | ++===============+=============================================================+ +| 5.1.2 | "APDU abstract syntax" IODConnectReq with StartupMode:=1 | ++---------------+-------------------------------------------------------------+ +| 5.2.4.4.4 | "Record index" Index 0xE050 ARFSUDataAdjust | ++---------------+-------------------------------------------------------------+ +| 5.2.42.2.4 | "ARBlockReq" Checking of CMInitiatorActivityTimeoutFactor | ++---------------+-------------------------------------------------------------+ +| 5.6.3.1.1 | "General" Use profinet v 2.2 for Legacy startup mode. | ++---------------+-------------------------------------------------------------+ +| 5.6.3.3.4 | "CMSU state table" Legacy startup mode implemented in CMSU, | +| | PPM and CPM. | ++---------------+-------------------------------------------------------------+ +| Figure A.2 | Startup in advanced mode | ++---------------+-------------------------------------------------------------+ +| Figure B.2 | Startup in legacy mode | ++---------------+-------------------------------------------------------------+ + + Conformance class D ------------------- 7.1.3.2.1 Communication (Class D should support one additional Device Access AR) -Start up procedure ------------------- +Messages and function calls at startup +-------------------------------------- +------------------+--------------------+-----------------------+--------------------------------------------+-------------------------------------+ | | Incoming | | Outgoing | | CMDEV | Application | Other | @@ -679,6 +775,21 @@ This will format the commit using clang-format. Examine and stage modified files before finalizing the commit. +Static code analyzer +-------------------- +To install the clang static analyzer tool:: + + sudo apt-get install clang-tools + +Run it using:: + + rm -rf build + scan-build cmake -B build + scan-build -o clangreports make -C build -j4 + +The resulting HTML reports will end up in the ``clangreports`` subdirectory. + + Workflow -------- We have chosen to host the code on Github to ease the collaboration between @@ -688,9 +799,9 @@ Github workflow: * Open a Github issue on https://github.com/rtlabs-com/p-net/ for each separate bug found. * Fork the repository to your own account on Github, and make a local - clone on your work station. + clone on your laptop. * Create a branch with a descriptive name. -* Commit your fix to the branch. Add the line "Closes #123" (for example) +* Commit your fix to the branch. Add the line ``Closes #123`` (for example) in the commit message, to indicate which Github issue it closes. * Push the branch to your Github account. * Create a pull request to https://github.com/rtlabs-com/p-net diff --git a/doc/index.rst b/doc/index.rst index feb9f3f4..06baeb32 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -19,6 +19,7 @@ documentation. additional_linux_details.rst getting_started_rtkernel.rst using_codesys.rst + codesys_details.rst use_with_siematic.rst capturing_packets.rst sampleapp_details.rst diff --git a/doc/multiple_ports.rst b/doc/multiple_ports.rst index 3ec2ad81..88cfcc8b 100644 --- a/doc/multiple_ports.rst +++ b/doc/multiple_ports.rst @@ -144,6 +144,22 @@ To disable the creation of the bridge at reboot:: sudo systemctl disable systemd-networkd +If you do not use systemd, then a script ``enable_bridge.sh`` might be handy:: + + ip link add name br0 type bridge + ip link set br0 up + ip link set eth0 up + ip link set eth1 up + ip link set eth0 master br0 + ip link set eth1 master br0 + +And correspondingly ``disable_bridge.sh``:: + + ip link set eth0 nomaster + ip link set eth1 nomaster + ip link set br0 down + ip link delete br0 type bridge + Configuration of p-net stack and sample application --------------------------------------------------------- diff --git a/doc/network_topology_detection.rst b/doc/network_topology_detection.rst index 67949e6e..f69a9134 100644 --- a/doc/network_topology_detection.rst +++ b/doc/network_topology_detection.rst @@ -193,7 +193,7 @@ configuration file in your home directory. For example:: Read and write a single OID --------------------------- -Read only the "SNMPv2-MIB::sysLocation.0" OID:: +Read only the ``SNMPv2-MIB::sysLocation.0`` OID:: $ snmpget -v1 -c public 192.168.0.99 1.3.6.1.2.1.1.6.0 iso.3.6.1.2.1.1.6.0 = STRING: "sysLocation Not Set" @@ -295,7 +295,7 @@ Other Profinet-relevant MIB files on Linux: Walking a subtree using snmpwalk -------------------------------- -By default the ``snmpwalk`` searches the SNMPv2-SMI::mib-2 subtree. You can +By default the ``snmpwalk`` searches the ``SNMPv2-SMI::mib-2`` subtree. You can search a smaller or larger subtree by giving the OID (or the corresponding name) to ``snmpwalk`` as the argument after the host argument. @@ -402,7 +402,7 @@ Device details: +--------------------------------+-----------------------------------------------------------------+ | sysServices | 78 (dec) for Profinet devices | +--------------------------------+-----------------------------------------------------------------+ -| lldpConfigManAddrPortsTxEnable | On/off for ports. Writable | +| lldpConfigManAddrPortsTxEnable | On/off for ports. Writable? | +--------------------------------+-----------------------------------------------------------------+ Interface statistics, for each port: @@ -422,7 +422,7 @@ Interface statistics, for each port: +----------------+-----------------------------------------------------------------+ | ifPhysAddress | MAC address | +----------------+-----------------------------------------------------------------+ -| ifAdminStatus | Up, down etc. Writable | +| ifAdminStatus | Up, down etc. Writable? | +----------------+-----------------------------------------------------------------+ | ifOperStatus | Up, down etc. | +----------------+-----------------------------------------------------------------+ @@ -458,7 +458,7 @@ Readable fields related to ports and interfaces: +----------------------+--------------------------------------+-----------------+------------+-------------+ | Index | | | | x | +----------------------+--------------------------------------+-----------------+------------+-------------+ -| ManAddrSubtype | Typically ?=IP | x | | x | +| ManAddrSubtype | Typically 1=IP | x | | x | +----------------------+--------------------------------------+-----------------+------------+-------------+ | ManAddr | Management (IP) address | x | | x | +----------------------+--------------------------------------+-----------------+------------+-------------+ @@ -486,7 +486,11 @@ Note that some objects are listed "Not accessible" in the standard. These are read indirectly via other objects (used as table index, and appended to the OID of other objects), so the information must thus be available. -See the standard for the corresponding numerical OID values. +See the Profinet standard for the corresponding numerical OID values. + +Enable SNMP when running p-net on Linux +--------------------------------------- +See the page "Additional Linux details" in this documentation. Verification of SNMP communication to p-net @@ -537,6 +541,9 @@ Download "Proneta Basic" (free version) from the Siemens web page. Unzip the downloaded file onto a Windows personal computer. Double-click the ``PRONETA.exe`` file to start the program. +Turn off the ART tester tool before starting Proneta, otherwise Proneta can +not scan the network. + On the settings page, select which Ethernet network adapter to use on your computer. On the home screen, select "Network analysis" and use the "Online" tab. @@ -546,14 +553,22 @@ the connections between all ports. An example screenshot is shown below. .. image:: illustrations/proneta_example.png -The program will show the list of current diagnosis for IO-devices. -It will also show details about interfaces and ports. +The program will show details about interfaces and ports, and which of the slots +that are populated by modules. +It will also show the list of current diagnosis for IO-devices. +Proneta will read out the diagnostics buffer every 5 seconds, as long as the +device is selected in the graphical view. By right-clicking on a device in the graphical view, you can set the station name and IP address (temporarily or permanently). It is also possible to edit the I&M information, to flash the signal LED and to do a factory reset. +For PRONETA to be able to map the connection to the closest device, you need to +enable LLDP transmission on the Ethernet interface of your laptop. Note that +this interferes with the ART tester software. See the section on installing +ART tester in this documentation. + Full SNMP readout example ------------------------- diff --git a/doc/prepare_raspberrypi.rst b/doc/prepare_raspberrypi.rst index fbc7cdaf..60afb95c 100644 --- a/doc/prepare_raspberrypi.rst +++ b/doc/prepare_raspberrypi.rst @@ -1,7 +1,12 @@ +.. _prepare_raspberry: + Installation and configuration of Raspberry Pi ============================================== -The p-net stack and sample application -has been tested with: +This page consists an installation guide to use if you have a Linux laptop, +and a separate guide to use with a Windows laptop. + +The p-net stack and sample application has been tested with: + * Raspberry Pi 3 Model B+ To avoid problems it is recommended to start with a fresh @@ -9,15 +14,20 @@ Raspberry Pi OS image. When running the Raspberry Pi as a profinet IO-device using p-net, the network settings of the Raspberry Pi will be changed by Profinet. -Therefore it is highly recommended to use the serial console and not ssh -or you may end up in a situation were you have difficulties connecting to, -or recovering your device. If you currently do not have a suitable serial -dongle you can still build and run p-net with the sample application but -you will run into problem when a PLC is used for configuration. - -Installation using Linux ------------------------- -Burn a SD-card with Raspberry Pi OS, by using the Raspberry Pi imager. +Therefore it is highly recommended to use a keyboard, mouse and monitor or +a serial cable. + +If you use ssh you may end up in a situation were you have difficulties +connecting to, or recovering your device. If you currently do not have a +suitable USB-to-serial cable you can still build and run p-net with the +sample application but you might run into problem when a PLC is used for +configuration. + + +Installation using a Linux laptop +--------------------------------- +Burn a SD-card with Raspberry Pi OS, by using the "Raspberry Pi imager" +software and a SD card reader. A card size of 16 - 32 GByte is recommended. Follow the instructions on the page https://www.raspberrypi.org/software/ Select the standard "Raspberry Pi OS" operating system. @@ -70,8 +80,15 @@ Log in to it:: Enter the password mentioned just above. -Installation using Windows --------------------------- +If you would connect your Raspberry Pi to a WiFi network, follow the +guide in https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md + +.. note:: If you are following the tutorial and are setting up the IO-device, + you should head back now. See :ref:`tutorial`. + + +Installation using a Windows laptop +----------------------------------- This section describes how to install the Raspberry Pi OS and how to enable ssh and serial console so that the Raspberry Pi can be used in headless mode without a display and keyboard connected. @@ -132,16 +149,24 @@ Reboot and the Raspberry Pi is now ready to run the p-net sample application:: sudo reboot +If you would connect your Raspberry Pi to a WiFi network, follow the +guide in https://www.raspberrypi.org/documentation/configuration/wireless/wireless-cli.md -Connect a serial cable to Raspberry Pi --------------------------------------- +.. note:: If you are following the tutorial and are setting up the IO-device, + you should head back now. See :ref:`tutorial`. + + +Optionally connect a serial cable to Raspberry Pi +------------------------------------------------- The p-net Profinet stack will change the IP-address of the Raspberry Pi when running it as an IO-Device (as requested by the PLC), why it can be -inconvenient to connect to it via ssh. Using a serial cable to connect it to -your laptop can then be helpful. +inconvenient to connect to it via ssh. You can use a keyboard, mouse and a +monitor to connect to the Raspberry Pi. Using a serial cable to connect it to +your laptop can then be helpful if a keyboard etc not is available. Use a USB-to-serial adapter cable with 3.3 V logic levels. For example -Adafruit sells a popular version of those cables. +Adafruit sells a popular version of those cables. Connect the USB end to your +laptop and the other end to the header connector on the Raspberry Pi. If not already done, enable the serial port console by writing the line ``enable_uart=1`` in the file ``/boot/config.txt``. @@ -239,10 +264,15 @@ Instead modify the file ``/etc/dhcpcd.conf`` to include these lines:: You can still ping the .local address to find it on the network. To re-enable DHCP, remove the lines again from ``/etc/dhcpcd.conf``. +Once you have prepared the IP address etc on the Raspberry Pi intended for +use as a PLC, it is time to install the Codesys runtime on it. See +:ref:`using-codesys`. + Advanced users only: Automatic start of sample application ---------------------------------------------------------- -Use systemd to automatically start the p-net sample application on startup. +Use systemd to automatically start the p-net sample application at boot on a +Raspberry Pi. Place a systemd unit file here: ``/lib/systemd/system/pnet-sampleapp.service`` An example file is available in the ``sample_app/`` directory of this diff --git a/doc/profinet_details.rst b/doc/profinet_details.rst index dd0b65a9..f89e777b 100644 --- a/doc/profinet_details.rst +++ b/doc/profinet_details.rst @@ -220,6 +220,7 @@ Examples of block identifiers: * 0x0002 AlarmNotificationLow * 0x0008 IODWriteReqHeader * 0x0009 IODReadReqHeader +* 0x0010 DiagnosisData * 0x0019 LogBookData * 0x0020 I&M0 * 0x0021 I&M1 @@ -307,6 +308,8 @@ Examples of pre-defined indexes: +-----------------------------+--------------------------------------------------------+ | ExpectedIdentificationData | | +-----------------------------+--------------------------------------------------------+ +| I&M0FilterData | | ++-----------------------------+--------------------------------------------------------+ | LogBookData | | +-----------------------------+--------------------------------------------------------+ | ModuleDiffBlock | | @@ -337,7 +340,7 @@ Examples of pre-defined indexes: +-----------------------------+--------------------------------------------------------+ | PDPortDataRealExtended | | +-----------------------------+--------------------------------------------------------+ -| PDPortStatistic | Sent and recieved bytes. Errors and discards. | +| PDPortStatistic | Sent and received bytes. Errors and discards. | +-----------------------------+--------------------------------------------------------+ | PDRealData | Actual values and statistics for interface and port. | +-----------------------------+--------------------------------------------------------+ @@ -424,7 +427,7 @@ TLV types: * 3: Time to live in seconds * 4: Port description * 5: System name -* 7: Capabilites (Router, Bridge, Telephone etc) +* 7: Capabilities (Router, Bridge, Telephone etc) * 8: Management address (optional for LLDP, mandatory in Profinet). Includes IP address and interface number. Address subtype 1: IPv4 2: IPv6 * 127: Organisation specific (optional for LLDP. See below.). Has an diff --git a/doc/spelling_wordlist.txt b/doc/spelling_wordlist.txt index 0ffbf31e..fd858cab 100644 --- a/doc/spelling_wordlist.txt +++ b/doc/spelling_wordlist.txt @@ -10,6 +10,7 @@ Bonjour Bool boolean booleans +breakpoint bsp bss Buildroot @@ -24,6 +25,7 @@ cnf Codesys collab Commonmark +conformant COntroller Datagram DControl diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 8284ec8f..7cdefcec 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -1,6 +1,7 @@ +.. _tutorial: + Tutorial ======== - In this tutorial we will run the p-net Profinet device stack and its sample application on a Raspberry Pi, which is an embedded Linux board. You can optionally connect two LEDs and two buttons to the Raspberry Pi @@ -9,6 +10,25 @@ for easier interaction with the sample application. We will use a second Raspberry Pi as a PLC (Programmable Logic Controller = IO controller) running Codesys soft PLC. +Necessary hardware to complete the tutorial: + +* 1 Raspberry Pi as IO-device +* 1 Raspberry Pi as IO-controller (alternatively a Siemens PLC). +* 1 Ethernet switch +* 3 Ethernet cables + +Optional hardware: + +* Keyboard, mouse and monitor for the Raspberry Pi running as IO-device. If + this not is available it is helpful with a USB-to-serial cable for talking + to the Raspberry Pi (as it will automatically change IP address now and then). +* LEDs and buttons for connecting to the Raspberry Pi running as IO-device. + +It will take approximately 30 minutes to get p-net running on a Raspberry Pi. +After this the sample application will wait for incoming connects. +An additional hour is required to get another Raspberry Pi up and running +as an IO-controller (PLC), and to study the sample application data. + Sample app description ---------------------- @@ -82,14 +102,15 @@ the slots 1 to 4. In this example we will use the "8 bit in + 8 bit out" module in slot 1. -Set up the Raspberry Pi for running p-net ------------------------------------------ +Set up the IO-device Raspberry Pi for running p-net +--------------------------------------------------- As the PLC typically will change the IP address of the IO-device, -we recommend that you use a serial cable for communicating with the Raspberry -Pi running the p-net sample application. +we recommend that you connect a keyboard, mouse and monitor to the Raspberry +Pi running the p-net sample application. Alternatively you can use a +USB-to-serial cable to communicate with the Raspberry Pi from your laptop. To setup Raspbian on a Raspberry Pi, and optionally connect buttons and LEDs, -see "Install Raspbian on the Raspberry Pi (by using a Linux laptop)". +see :ref:`prepare_raspberry`. A LED is controlled by the Linux sample app by writing to a file, for example ``/sys/class/gpio/gpio17/value``. A ``0`` or ``1`` will be written to the @@ -105,8 +126,8 @@ Install dependencies Your Raspberry Pi needs to be connected to Internet via LAN or WiFi to be able to download software. -In order to compile p-net on Raspberry Pi, you need a recent version of cmake. -Install it:: +In order to compile p-net on Raspberry Pi, you need a recent version of +``cmake``. Install it:: sudo apt update sudo apt install snapd @@ -190,41 +211,41 @@ Usage of the IO-device sample application: .. code-block:: none - $ ./pn_dev --help + pi@pndevice-pi:~/profinet/build$ ./pn_dev -h - Demo application for p-net Profinet device stack. + Sample application for p-net Profinet device stack. - Wait for connection from IO-controller. - Then read buttons (input) and send to controller. - Listen for application LED output (from controller) and set application LED state. - It will also send a counter value (useful also without buttons and LED). - Button1 value is sent in the periodic data. - Button2 cycles through triggering an alarm, setting diagnosis and creating logbook entries. + Wait for connection from IO-controller. + Then read buttons (input) and send to controller. + Listen for application LED output (from controller) and set application LED state. + It will also send a counter value (useful also without buttons and LED). + Button1 value is sent in the periodic data. + Button2 cycles through triggering an alarm, setting diagnosis and creating logbook entries. - Also the mandatory Profinet signal LED is controlled by this application. + Also the mandatory Profinet signal LED is controlled by this application. - The LEDs are controlled by the script set_profinet_leds - located in the same directory as the application binary. - A version for Raspberry Pi is available, and also a version writing - to plain text files (useful for demo if no LEDs are available). + The LEDs are controlled by the script set_profinet_leds + located in the same directory as the application binary. + A version for Raspberry Pi is available, and also a version writing + to plain text files (useful for demo if no LEDs are available). - Assumes the default gateway is found on .1 on same subnet as the IP address. + Assumes the default gateway is found on .1 on same subnet as the IP address. - Optional arguments: - --help Show this help text and exit - -h Show this help text and exit - -v Incresase verbosity - -f Reset to factory settings, and store to file. Exit. - -r Remove stored files and exit. - -g Show stack details and exit. Repeat for more details. - -i INTERF Name of Ethernet interface to use. Defaults to eth0 - -s NAME Set station name. Defaults to rt-labs-dev Only used - if not already available in storage file. - -b FILE Path (absolute or relative) to read Button1. Defaults to not read Button1. - -d FILE Path (absolute or relative) to read Button2. Defaults to not read Button2. - -p PATH Absolute path to storage directory. Defaults to use current directory. + Optional arguments: + --help Show this help text and exit + -h Show this help text and exit + -v Incresase verbosity. Can be repeated. + -f Reset to factory settings, and store to file. Exit. + -r Remove stored files and exit. + -g Show stack details and exit. Repeat for more details. + -i INTERF Name of Ethernet interface to use. Defaults to eth0 + -s NAME Set station name. Defaults to rt-labs-dev Only used + if not already available in storage file. + -b FILE Path (absolute or relative) to read Button1. Defaults to not read Button1. + -d FILE Path (absolute or relative) to read Button2. Defaults to not read Button2. + -p PATH Absolute path to storage directory. Defaults to use current directory. - p-net revision: 0.1.0+5965c46 + p-net revision: 0.1.0+bb4177a Enable the Ethernet interface and set the initial IP address:: @@ -234,13 +255,157 @@ Run the sample application:: sudo ./pn_dev -v +Example output: + +.. code-block:: none + + pi@pndevice-pi:~/profinet/build$ sudo ./pn_dev -v + + ** Starting Profinet sample application 0.1.0+bb4177a ** + Number of slots: 5 (incl slot for DAP module) + P-net log level: 3 (DEBUG=0, FATAL=4) + App verbosity level: 1 + Number of ports: 1 + Network interfaces: eth0 + Button1 file: + Button2 file: + Station name: rt-labs-dev + Management port: eth0 + Physical port [1]: eth0 + Current hostname: pndevice-pi + Current IP address: 192.168.0.50 + Current Netmask: 255.255.255.0 + Current Gateway: 192.168.0.1 + Storage directory: /home/pi/profinet/build + + Profinet signal LED call-back. New state: 0 + Network script for eth0: Set IP 192.168.0.50 Netmask 255.255.255.0 Gateway 192.168.0.1 Permanent: 1 Hostname: rt-labs-dev Skip setting hostname: true + Module plug call-back + Pull old module. API: 0 Slot: 0 Slot was empty. + Plug module. API: 0 Slot: 0 Module ID: 0x1 + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 0 Subslot: 1 Subslot was empty. + Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 1 Submodule ID: 0x1 "DAP Identity 1" + Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 0 Subslot: 32768 Subslot was empty. + Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 32768 Submodule ID: 0x8000 "DAP Interface 1" + Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 0 Subslot: 32769 Subslot was empty. + Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 32769 Submodule ID: 0x8001 "DAP Port 1" + Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) + Waiting for connect request from IO-controller + The IP settings are stored to file. If you accidentally have run the application when IP settings were wrong, use this command to remove the stored settings:: sudo ./pn_dev -r -Input buttons -^^^^^^^^^^^^^ +Now you have installed the sample app on the Raspberry Pi, congratulations! +In order to see it in action, you need to connect it to a PLC. + + +Set up the PLC +-------------- +We suggest that you use Codesys soft PLC. +Install Raspberry Pi OS on the second Raspberry Pi. No serial cable or LEDs are +required. + +See :ref:`prepare_raspberry` and :ref:`using-codesys` for how to set it up as an IO-controller (PLC). + +Connect the two Raspberry Pi boards and your laptop via an Ethernet switch. + + +Print-out from Linux sample application when connecting to PLC +-------------------------------------------------------------- + +.. highlight:: none + +This is the typical output from the Linux sample application at startup if +you enable verbose output:: + + pi@pndevice-pi:~/profinet/build$ sudo ./pn_dev -v -b /sys/class/gpio/gpio22/value -d /sys/class/gpio/gpio27/value + + ** Starting Profinet sample application 0.1.0+bb4177a ** + Number of slots: 5 (incl slot for DAP module) + P-net log level: 3 (DEBUG=0, FATAL=4) + App verbosity level: 1 + Number of ports: 1 + Network interfaces: eth0 + Button1 file: /sys/class/gpio/gpio22/value + Button2 file: /sys/class/gpio/gpio27/value + Station name: rt-labs-dev + Management port: eth0 + Physical port [1]: eth0 + Current hostname: pndevice-pi + Current IP address: 192.168.0.50 + Current Netmask: 255.255.255.0 + Current Gateway: 192.168.0.1 + Storage directory: /home/pi/profinet/build + + Profinet signal LED call-back. New state: 0 + Network script for eth0: Set IP 0.0.0.0 Netmask 0.0.0.0 Gateway 0.0.0.0 Permanent: 1 Hostname: rt-labs-dev Skip setting hostname: true + No valid default gateway given. Skipping setting default gateway. + Module plug call-back + Pull old module. API: 0 Slot: 0 Slot was empty. + Plug module. API: 0 Slot: 0 Module ID: 0x1 + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 0 Subslot: 1 Subslot was empty. + Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 1 Submodule ID: 0x1 "DAP Identity 1" + Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 0 Subslot: 32768 Subslot was empty. + Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 32768 Submodule ID: 0x8000 "DAP Interface 1" + Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 0 Subslot: 32769 Subslot was empty. + Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 32769 Submodule ID: 0x8001 "DAP Port 1" + Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) + Waiting for connect request from IO-controller + + Network script for eth0: Set IP 192.168.0.50 Netmask 255.255.255.0 Gateway 0.0.0.0 Permanent: 0 Hostname: rt-labs-dev Skip setting hostname: true + No valid default gateway given. Skipping setting default gateway. + Module plug call-back + Pull old module. API: 0 Slot: 1 Slot was empty. + Plug module. API: 0 Slot: 1 Module ID: 0x32 + Submodule plug call-back. + Pull old submodule. API: 0 Slot: 1 Subslot: 1 Subslot was empty. + Plug submodule. API: 0 Slot: 1 Module ID: 0x32 Subslot: 1 Submodule ID: 0x1 "Input 8 bits output 8 bits" + Data Dir: INPUT_OUTPUT In: 1 Out: 1 (Exp Data Dir: INPUT_OUTPUT In: 1 Out: 1) + Connect call-back. AREP: 1 Status codes: 0 0 0 0 + Callback on event PNET_EVENT_STARTUP AREP: 1 + New data status callback. AREP: 1 Data status changes: 0x35 Data status: 0x35 + Run, Valid, Primary, Normal operation, Evaluate data status + Parameter write call-back. AREP: 1 API: 0 Slot: 1 Subslot: 1 Index: 123 Sequence: 2 Length: 4 + Bytes: 00 00 00 05 + Parameter write call-back. AREP: 1 API: 0 Slot: 1 Subslot: 1 Index: 124 Sequence: 3 Length: 4 + Bytes: 00 00 00 06 + Dcontrol call-back. AREP: 1 Command: PRM_END + Callback on event PNET_EVENT_PRMEND AREP: 1 + Set input data and IOPS for slot 0 subslot 1 "DAP Identity 1" size 0 IOXS_GOOD + Set input data and IOPS for slot 0 subslot 32768 "DAP Interface 1" size 0 IOXS_GOOD + Set input data and IOPS for slot 0 subslot 32769 "DAP Port 1" size 0 IOXS_GOOD + Set input data and IOPS for slot 1 subslot 1 "Input 8 bits output 8 bits" size 1 IOXS_GOOD + Set output IOCS for slot 1 subslot 1 "Input 8 bits output 8 bits" + Application will signal that it is ready for data. + Callback on event PNET_EVENT_APPLRDY AREP: 1 + Setting outputs to default values. + Ccontrol confirmation call-back. AREP: 1 Status codes: 0 0 0 0 + Callback on event PNET_EVENT_DATA AREP: 1 + Setting outputs to default values. + +The exact output will depend on for example which modules you use when setting +up the PLC. + + +Input buttons and LEDs, or files for simulation +----------------------------------------------- +If you use plain files as output instead of LEDs, use this to study the file +for the "Data LED":: + + watch -n 0.1 cat /home/pi/profinet/build/pnet_led_1.txt + If you would like to use physical input buttons you must set up the GPIO files for buttons properly first:: @@ -268,98 +433,6 @@ to be able to run these commands. That is done by adding a ``&`` at the end of the command to start ``pn_dev`` . Later on kill the ``pn_dev`` process by using ``sudo pkill pn_dev``. -LEDs -^^^^ -If you use plain files as output instead of LEDs, use this to study the file -for the "Data LED":: - - watch -n 0.1 cat /home/pi/profinet/build/pnet_led_1.txt - - -Set up the PLC --------------- -Now you have installed the sample app on the Raspberry Pi, congratulations! -In order to see it in action, you need to connect it to a PLC. - -We suggest that you use Codesys soft PLC. -Install Raspberry Pi OS on the second Raspberry Pi. No serial cable or LEDs are -required. - -See "Using Codesys soft PLC" for how to set it up as an IO-controller (PLC). - - -Print-out from Linux sample application ---------------------------------------- - -.. highlight:: none - -This is the typical output from the Linux sample application at startup if -you enable verbose output:: - - sudo ./pn_dev -v -b /sys/class/gpio/gpio22/value -d /sys/class/gpio/gpio27/value - - ** Starting Profinet sample application ** - Number of slots: 5 (incl slot for DAP module) - P-net log level: 4 (DEBUG=0, FATAL=4) - App verbosity level: 1 - Ethernet interface: eth0 - Button1 file: /sys/class/gpio/gpio22/value - Button2 file: /sys/class/gpio/gpio27/value - Default station name: rt-labs-dev - MAC address: B8:27:EB:F3:9A:B2 - Current hostname: pndevice-pi - Current IP address: 192.168.0.50 - Current Netmask: 255.255.255.0 - Current Gateway: 192.168.0.1 - Storage directory: /home/pi/profinet/build - - Profinet signal LED call-back. New state: 0 - Network script for eth0: Set IP 192.168.0.50 Netmask 255.255.255.0 Gateway 192.168.0.1 Permanent: 1 Hostname: rt-labs-dev Skip setting hostname: true - Module plug call-back - Pull old module. API: 0 Slot: 0 Slot was empty. - Plug module. API: 0 Slot: 0 Module ID: 0x1 - Submodule plug call-back. - Pull old submodule. API: 0 Slot: 0 Subslot: 1 Subslot was empty. - Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 1 Submodule ID: 0x1 "DAP Identity 1" - Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) - Submodule plug call-back. - Pull old submodule. API: 0 Slot: 0 Subslot: 32768 Subslot was empty. - Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 32768 Submodule ID: 0x8000 "DAP Interface 1" - Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) - Submodule plug call-back. - Pull old submodule. API: 0 Slot: 0 Subslot: 32769 Subslot was empty. - Plug submodule. API: 0 Slot: 0 Module ID: 0x1 Subslot: 32769 Submodule ID: 0x8001 "DAP Port 1" - Data Dir: NO_IO In: 0 Out: 0 (Exp Data Dir: NO_IO In: 0 Out: 0) - Waiting for connect request from IO-controller - - Network script for eth0: Set IP 192.168.0.50 Netmask 255.255.255.0 Gateway 192.168.0.50 Permanent: 0 Hostname: rt-labs-dev Skip setting hostname: true - Module plug call-back - Pull old module. API: 0 Slot: 1 Slot was empty. - Plug module. API: 0 Slot: 1 Module ID: 0x32 - Submodule plug call-back. - Pull old submodule. API: 0 Slot: 1 Subslot: 1 Subslot was empty. - Plug submodule. API: 0 Slot: 1 Module ID: 0x32 Subslot: 1 Submodule ID: 0x1 "Input 8 bits output 8 bits" - Data Dir: INPUT_OUTPUT In: 1 Out: 1 (Exp Data Dir: INPUT_OUTPUT In: 1 Out: 1) - Connect call-back. AREP: 1 Status codes: 0 0 0 0 - Callback on event PNET_EVENT_STARTUP AREP: 1 - New data status callback. AREP: 1 Data status changes: 0x35 Data status: 0x35 - Parameter write call-back. AREP: 1 API: 0 Slot: 1 Subslot: 1 Index: 123 Sequence: 2 Length: 4 - Bytes: 00 00 00 00 - Parameter write call-back. AREP: 1 API: 0 Slot: 1 Subslot: 1 Index: 124 Sequence: 3 Length: 4 - Bytes: 00 00 00 00 - Dcontrol call-back. AREP: 1 Command: PRM_END - Callback on event PNET_EVENT_PRMEND AREP: 1 - Set input data and IOPS for slot 0 subslot 1 "DAP Identity 1" size 0 IOXS_GOOD - Set input data and IOPS for slot 0 subslot 32768 "DAP Interface 1" size 0 IOXS_GOOD - Set input data and IOPS for slot 0 subslot 32769 "DAP Port 1" size 0 IOXS_GOOD - Set input data and IOPS for slot 1 subslot 1 "Input 8 bits output 8 bits" size 1 IOXS_GOOD - Set output IOCS for slot 1 subslot 1 "Input 8 bits output 8 bits" - Application will signal that it is ready for data. - Callback on event PNET_EVENT_APPLRDY AREP: 1 - The controller reports IOCS 96 for slot 1 - Ccontrol confirmation call-back. AREP: 1 Status codes: 0 0 0 0 - Callback on event PNET_EVENT_DATA AREP: 1 - Study the resulting communication --------------------------------- @@ -430,14 +503,16 @@ the "Using Codesys soft PLC" page for workarounds. Troubleshooting --------------- +If you have network problems on your IO-device Raspberry Pi, re-run the +``ifconfig`` command given above. + If you have problems establishing a connection to your PLC, connect it directly to your laptop and run the program Wireshark on the corresponding -Ethernet interface. See another page in this documentation for details on -Wireshark usage. - -The PLC will send LLDP frames once per 5 seconds. Study one of these frames -in Wireshark. The "Management Address" block shows the IP address of the PLC. +Ethernet interface. Study the DCP and LLDP frames to see the current PLC +settings. See another page in this documentation for details on Wireshark usage. +The "Management Address" block in a LLDP frame shows the IP address of the PLC. There are also other blocks describing the MAC address and the port ID. +You can find the expected IO-device station name in some DCP frames. Advanced users: OSAL diff --git a/doc/use_with_siematic.rst b/doc/use_with_siematic.rst index 5d280227..1a986dff 100644 --- a/doc/use_with_siematic.rst +++ b/doc/use_with_siematic.rst @@ -69,7 +69,7 @@ the directory with your GSD file. Mark the line with the file, and click In the project view, in the left menu select the PLC and the subitem "Device configuration". Click the "Network view" tab. At the right edge open the "Hardware catalog". Select "Other field devices" > Profinet IO > I/O > rt-labs > -rt-labs dev > "rt-labs DEMO device". Double-click it, and it will appear in the +rt-labs dev > "P-Net Sample App". Double-click it, and it will appear in the main window. Use the "Network view" tab, and right-click "Not assigned" on the rt-labs-dev @@ -272,14 +272,23 @@ There is also a "Diagnosis status" page that shows a summary of the current status. +Scan for devices from TIA portal +-------------------------------- +In the "Portal view", click "Online & Diagnostics" and then "Accessible devices". +In the pop-up window, select "PN/IE" and the name of the Ethernet interface +of your laptop. Click "Start search". +You can flash a LED on your device by marking the relevant line in the +result table, and mark the "Flash LED" check-box. + + Troubleshooting --------------- Note that the PLC might complain if there is a non-Profinet switch between the IO-device and the IO-controller. This is probably due to wrong port names in LLDP messages. -Factory reset of Simatic ET200SP --------------------------------- +Factory reset of Simatic ET200SP CPU +------------------------------------ Use the mode switch on the front panel to do a factory reset. See the user manual for details. This will reset also the IP address. diff --git a/doc/using_codesys.rst b/doc/using_codesys.rst index c3a52d0d..3f09de46 100644 --- a/doc/using_codesys.rst +++ b/doc/using_codesys.rst @@ -1,3 +1,5 @@ +.. _using-codesys: + Using Codesys soft PLC ====================== We run the Codesys ("COntroller DEvelopment SYStem") runtime on a Raspberry Pi, @@ -15,21 +17,25 @@ Download "CODESYS Development System V3". The file is named for example the icon. Also download "CODESYS Control for Raspberry Pi SL". +You can still download it without paying the listed price, but it will then +run as a trial version for which you need to restart the Codesys runtime on the +Raspberry Pi every two hours. Install it by double-clicking the ``.package`` file. Restart the program after the installation. -If you use the trial version, you need to restart the Codesys runtime on the -Raspberry Pi every two hours. - -Scan network to find Raspberry Pi, and install the Codesys runtime onto it --------------------------------------------------------------------------- +Scan network to find your PLC Raspberry Pi, and install the Codesys runtime onto it +----------------------------------------------------------------------------------- Make sure your Windows machine and the Raspberry Pi are connected to the same local network. In Codesys on Windows, use the menu Tools -> "Update Raspberry Pi". Click "Scan" to find the IP address. +In this tutorial the IP address of the PLC Raspberry Pi is ``192.168.0.100``. + +It is possible to install the runtime on the PLC Raspberry Pi as long as you +know its IP address, even if it doesn't show up during the scan. Click "Install" for the Codesys Runtime package. Use "Standard" runtime in the pop-up window. @@ -61,8 +67,8 @@ select the GSDML file from your hard drive. right-click and select Add Device. Use “Ethernet adapter”, “Ethernet”. * On the "Ethernet", right-click and select Add Device. Use "Profinet IO master", "PN-Controller". -* On the "PN_Controller", right-click and select Add Device. Use "rt-labs DEMO device". -* On the "rt_labs_DEMO_device", right-click and select Add Device. Use "8 bits I 8 bits 0". +* On the "PN_Controller", right-click and select Add Device. Use "P-Net Sample App". +* On the "P_Net_Sample_App", right-click and select Add Device. Use "DIO 8xLogicLevel". Double-click the "Ethernet" node in the left menu. Select interface "eth0". The IP address will be updated accordingly. @@ -70,10 +76,12 @@ The IP address will be updated accordingly. Double-click the "PN_controller" node in the left menu. Adjust the IP range using "First IP" and "Last IP" to both have the existing IP-address of your IO-device (for example a Linux laptop or embedded Linux board running the -sample_app). +sample_app). For this tutorial we use the “First IP” ``192.168.0.50`` +and “Last IP” ``192.168.0.60``. -Double-click the "rt_labs_DEMO_device" node in the left menu. Set the +Double-click the "P_Net_Sample_App" node in the left menu. Set the IP-address to the existing address of your IO-device. +In this tutorial we use ``192.168.0.50``. Structured Text programming language for PLCs @@ -121,9 +129,12 @@ Program section:: END_IF in_pin_button_LED_previous := in_pin_button_LED; -On the "_8_bits_I_8_bits_O" node, right-click and select "Edit IO mapping". -Double-click the row that you would like the edit. -Map "Input Bit 7" to "in_pin_button_LED", and "Output Bit 7" to "out_pin_LED" +On the "DIO_8xLogicLevel" node in the left-side menu, +right-click and select "Edit IO mapping". +Open the "Input 8 bits" row by clicking the small ``+`` sign. +Double-click the icon on the row that you would like the edit. +Map "Input Bit 7" (found via Application/PLC_PRG) to "in_pin_button_LED", +and "Output Bit 7" to "out_pin_LED". In the "Application -> MainTask" select "Cyclic" with 4 ms. @@ -152,174 +163,10 @@ IP address, and a PN-DCP packet to ask for the IO-device with the name Running the application ----------------------- -See the "Tutorial" page. +Now it is time to run the application, so head back to the :ref:`tutorial` page. Once the Codesys softplc running on the Raspberry Pi has been configured, you can turn off the personal computer (running the Codesys desktop application) used to configure it. Remember that you need to power cycle the Raspberry Pi running the softplc every two hours, if using the trial version. - -The remaining text on this page is about advanced topics, and not necessary -for running the sample app in the tutorial. - - -Adjust PLC timing settings --------------------------- -It is possible to adjust the cycle time that the IO-controller (PLC) is using -for cyclic data communication with an IO-device. - -In the left menu, double-click the "rt_labs_DEMO_device", and open the "General" -tab. The "Communication" section shows the send clock in milliseconds, as read -from the GSDML file. By using the "Reduction ratio" you can slow down the -communication, by multiplying the cycle time by the factor given in the -dropdown. - -It is also possible to increase the watchdog time, after which the PLC will set -an alarm for missing incoming cyclic data. The watchdog will also shut down the -communication, and trigger a subsequent restart of communication. - -In case of problems, increase the reduction ratio (and timeout) value a lot, -and then gradually reduce it to find the smallest usable value. - - -Writing and reading IO-device parameters ----------------------------------------- -The parameters for different submodules are written as part of normal startup. - -To manually trigger parameter sending via Codesys, double-click the -_8_bits_I_8_bits_O device in the left menu. Use the General tab, and the -Settings part of the page. Right-click the parameter you would like to send, -and select "Write to device". - -It is also possible to read a parameter similarly. - -When clicking the "Write All Values" icon, one write request is sent per -parameter. - -In order to change a parameter value in the Codesys GUI, you need to first go -offline. - - -Setting output producer status (IOPS) -------------------------------------- -Normally Codesys will set the Output PS to GOOD (0x80 = 128) when running. -Clicking the "Output PS" checkbox on the "IOxS" tab on the Profinet IO-device -sets the value to BAD (0). - - -Displaying errors ------------------ -Click on the IO-device in the tree structure in the left part of the screen. -Use the "Log" tab to display errors. - - -Displaying alarms sent from IO-device -------------------------------------- -Incoming process alarms and diagnosis alarms appear on multiple places in the Codesys desktop application. - -* Codesys Raspberry Pi: The "Log" tab show process and diagnosis alarms. -* PN_Controller: The "Log" tab show process and diagnosis alarms. -* IO-device: The "Log" tab show process and diagnosis alarms. The “Status” tab shows alarms related to built-in (DAP) modules. -* Plugged module in IO-device: Process and diagnosis alarms are displayed on the “Status” tab. - - -Connection status ------------------ -Go to the Profinet IO-device page, and see the "PNIO IEC objects" tab. Expand -the topmost row. The states of these boolean fields are shown: - -* xRunning: Periodic data is sent -* xBusy: The controller is trying to connect to the IO-device -* xError: Failure to connect to the IO-device - -If there is no connection at all to the IO-device, the state will shift to -xBusy from xError once every 5 seconds. - - -Change IP address of IO-device ------------------------------- -Change the IP address by double-clicking the "rt_labs_DEMO_device" node -in the left menu, using the "General" tab. Set the IP-address to new value. - -The IO-controller will send the new IP address in a "DCP Set" message to the -IO-device having the given station name. Then it will use ARP messages to -the IO-device to find its MAC address, and to detect IP address collisions. - - -Scan for devices, assign IP address, reset devices and change station name --------------------------------------------------------------------------- - -Scan -^^^^ -In the left side menu, right-click the PN_Controller and select "Scan for -devices". The running IO-devices will show up, and it is possible to see which -modules are plugged into which slot. - -This is implemented in Codesys by sending the "Ident request, all" DCP -message from the IO-controller. -It works also if there are no IO-devices loaded in the left side hierarchy menu. -An IO-device will respond with the "Ident OK" DCP message. Then the IO-controller -will do a "Read implicit request" for "APIData", on which the IO device -responds with the APIs it supports. A similar request for -"RealIdentificationData for one API" is done by the IO-controller, on which the -IO-device responds which modules (and submodules) are plugged into which slots -(and subslots). - -Factory reset -^^^^^^^^^^^^^ -To factory reset a device, select it in the list of scanned devices and click -the "reset" button. - -At a factory reset, the IO-controller sends a "Set request" DCP message -with suboption "Reset factory settings". After sending a response, the -IO-device will do the factory reset and also send a LLDP message with the -new values. Then the IO-controller sends a "Ident request, all", to which -the IO-device responds. - -Set name and IP -^^^^^^^^^^^^^^^ -To modify the station name or IP address, change the corresponding fields -in the list of scanned devices, and the click "Set name and IP". - -The IO-controller sends a "Set request" DCP message -with suboptions "Name of station" and "IP parameter". After sending a -response, the IO-device will change IP address and station name. It will -also send a LLDP message with the new values. Then the -IO-controller sends a "Ident request, all", to which the IO-device responds. - -Flash LED -^^^^^^^^^ -There is functionality to flash a LED on an IO-device. Select your device in -the list of scanned devices, and click the "Blink LED" button. The button -remains activated until you click it again. - -LED-blinking is done by sending the "Set request" DCP message with suboption -"Signal" once every 5 seconds as long as the corresponding button is activated. - -Identification & Maintenance (I&M) data -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -In order the read Identification & Maintenance (I&M) data, the device needs to -be present as an IO-device connected to the IO-controller in the left side menu. -Select the device in the list of scanned devices, and click the "I&M" button. - -Reading I&M data is done by the IO-controller by sending four "Read implicit" -request DCP messages, one for each of I&M0 to I&M3. - -When writing I&M data from Codesys, it will send a connect, write and release. - - -Enabling checking of peer stationname and port ID -------------------------------------------------- -It is possible to have the IO-device verify that it is connected to the -correct neighbour (peer) by checking its station name and port ID (as sent -in LLDP frames by the neighbour). - -Double-click the “rt_labs_DEMO_device” node in the left menu. On the "options" -tab in the resulting window, use the fields "Peer station" and "port". It -seems only possible to select station names from other devices or controllers -already available in the project. - -During startup the PLC will send the given values to the IO-Device via a -write command. If the correct neighbour is not present, an alarm will be sent -by the IO-device to the PLC. diff --git a/include/pnet_api.h b/include/pnet_api.h index 8cd0610a..29e78112 100644 --- a/include/pnet_api.h +++ b/include/pnet_api.h @@ -246,6 +246,8 @@ extern "C" { #define PNET_ERROR_CODE_2_CMRPC_ARSET_PARAM_CONFLICT 0x0B #define PNET_ERROR_CODE_2_CMRPC_PDEV_PORTS_WO_INTERFACE 0x0C +#define PNET_ERROR_CODE_2_CTLDINA_ARP_MULTIPLE_IP_ADDRESSES 0x07 + #define PNET_ERROR_CODE_2_CMSM_INVALID_STATE 0x00 #define PNET_ERROR_CODE_2_CMSM_SIGNALED_ERROR 0x01 @@ -527,7 +529,7 @@ typedef struct pnet_result * @param net InOut: The p-net stack instance * @param arg InOut: User-defined data (not used by p-net) * @param arep In: The AREP. - * @param p_result Out: Detailed error information. + * @param p_result Out: Detailed error information if return != 0. * @return 0 on success. * -1 if an error occurred. */ @@ -554,7 +556,7 @@ typedef int (*pnet_connect_ind) ( * @param net InOut: The p-net stack instance * @param arg InOut: User-defined data (not used by p-net) * @param arep In: The AREP. - * @param p_result Out: Detailed error information. + * @param p_result Out: Detailed error information if return != 0. * @return 0 on success. * -1 if an error occurred. */ @@ -584,7 +586,7 @@ typedef int (*pnet_release_ind) ( * @param arg InOut: User-defined data (not used by p-net) * @param arep In: The AREP. * @param control_command In: The DControl command code. - * @param p_result Out: Detailed error information. + * @param p_result Out: Detailed error information if return != 0. * @return 0 on success. * -1 if an error occurred. */ @@ -857,9 +859,8 @@ typedef int (*pnet_new_data_status_ind) ( * This functionality is used for alarms triggered by the IO-controller. * * When receiving this indication, the application shall - * respond with \a pnet_alarm_send_ack(). - * pnet_alarm_send_ack may be called in the context of this - * callback. + * respond with \a pnet_alarm_send_ack(), which + * may be called in the context of this callback. * * @param net InOut: The p-net stack instance * @param arg InOut: User-defined data (not used by p-net) @@ -1309,12 +1310,16 @@ PNET_EXPORT void pnet_handle_periodic (pnet_t * net); /** * Application signals ready to exchange data. * - * Sends a ccontrol request to the IO-controller. + * Sends a CControl request to the IO-controller. * * This function must be called _after_ the application has received * the \a pnet_state_ind() user callback with PNET_EVENT_PRMEND, * in order for a connection to be established. * + * If this CControl request ("Application ready") is sent (to the PLC) before + * the DControl response ("Param end") is sent (to the PLC) there will + * be problems at startup. + * * If this function does not see all PPM data and IOPS areas are set (by the * app) then it returns error and the application must try again - otherwise the * startup will hang. @@ -1430,6 +1435,7 @@ PNET_EXPORT int pnet_pull_submodule ( * @param p_data In: Data buffer. * @param data_len In: Bytes in data buffer. * @param iops In: The device provider status. + * See pnet_ioxs_values_t * @return 0 if a sub-module data and IOPS was set. * -1 if an error occurred. */ @@ -1453,6 +1459,7 @@ PNET_EXPORT int pnet_input_set_data_and_iops ( * @param slot In: The slot. * @param subslot In: The sub-slot. * @param p_iocs Out: The controller consumer status. + * See pnet_ioxs_values_t * @return 0 if a sub-module IOCS was set. * -1 if an error occurred. */ @@ -1487,6 +1494,7 @@ PNET_EXPORT int pnet_input_get_iocs ( * @param p_data_len In: Size of receive buffer. * Out: Received number of data bytes. * @param p_iops Out: The controller provider status (IOPS). + * See pnet_ioxs_values_t * @return 0 if a sub-module data and IOPS is retrieved. * -1 if an error occurred. */ @@ -1503,7 +1511,7 @@ PNET_EXPORT int pnet_output_get_data_and_iops ( /** * Set the device consumer status for one sub-slot. * - * This function is use to set the device consumer status (IOCS) + * This function is used to set the device consumer status (IOCS) * of a specific sub-slot. * * @param net InOut: The p-net stack instance @@ -1511,6 +1519,7 @@ PNET_EXPORT int pnet_output_get_data_and_iops ( * @param slot In: The slot. * @param subslot In: The sub-slot. * @param iocs In: The device consumer status. + * See pnet_ioxs_values_t * @return 0 if a sub-module IOCS was set. * -1 if an error occurred. */ @@ -1815,6 +1824,9 @@ PNET_EXPORT int pnet_diag_std_add ( * Update the "extended channel error additional value", for a diagnosis entry * in the standard format. * + * The Profinet standard says that diagnosis updates should not be done at a + * higher frequency than 1 Hz. + * * This sends a diagnosis alarm. * * @param net InOut: The p-net stack instance. @@ -1866,8 +1878,9 @@ PNET_EXPORT int pnet_diag_std_remove ( * Use \a pnet_diag_usi_update() instead if you would like to have an error * if the diagnosis is missing when trying to update it. * - * A diagnosis in USI format is always assigned to the channel - * "whole submodule" (not individual channels). The severity is always "Fault". + * A diagnosis in USI format is always assigned to the channel “whole submodule” + * (not individual channels). The severity is always “Fault”, the accumulative + * flag is false and the direction is "Manufacturer specific". * * It is recommended to use the standard diagnosis format in most cases. * Use the manufacturer specific format ("USI format") only if it's not @@ -1875,6 +1888,7 @@ PNET_EXPORT int pnet_diag_std_remove ( * * Note that the PLC can set the max alarm payload length at startup, and * that affects how large diagnosis entries can be sent via alarms. + * This payload limit can be 200 to 1432 bytes. * * This sends a diagnosis alarm. * @@ -1913,6 +1927,10 @@ PNET_EXPORT int pnet_diag_usi_add ( * * Note that the PLC can set the max alarm payload length at startup, and * that affects how large diagnosis entries can be sent via alarms. + * This payload limit can be 200 to 1432 bytes. + * + * The Profinet standard says that diagnosis updates should not be done at a + * higher frequency than 1 Hz. * * This sends a diagnosis alarm. * @@ -1973,6 +1991,7 @@ PNET_EXPORT int pnet_diag_usi_remove ( * * Note that the PLC can set the max alarm payload length at startup, and * that affects how large diagnosis entries can be sent via alarms. + * This payload limit can be 200 to 1432 bytes. * * This sends a diagnosis alarm. * @@ -2031,6 +2050,7 @@ PNET_EXPORT int pnet_diag_add ( * * Note that the PLC can set the max alarm payload length at startup, and * that affects how large diagnosis entries can be sent via alarms. + * This payload limit can be 200 to 1432 bytes. * * This sends a diagnosis alarm. * diff --git a/sample_app/sampleapp_common.c b/sample_app/sampleapp_common.c index 28b05133..dbb9e83c 100644 --- a/sample_app/sampleapp_common.c +++ b/sample_app/sampleapp_common.c @@ -422,13 +422,7 @@ static int app_connect_ind ( if (p_appdata->arguments.verbosity > 0) { - printf ( - "Connect call-back. AREP: %u Status codes: %d %d %d %d\n", - arep, - p_result->pnio_status.error_code, - p_result->pnio_status.error_decode, - p_result->pnio_status.error_code_1, - p_result->pnio_status.error_code_2); + printf ("Connect call-back. AREP: %u\n", arep); } /* * Handle the request on an application level. @@ -449,14 +443,7 @@ static int app_release_ind ( if (p_appdata->arguments.verbosity > 0) { - printf ( - "Release (disconnect) call-back. AREP: %u Status codes: %d %d %d " - "%d\n", - arep, - p_result->pnio_status.error_code, - p_result->pnio_status.error_decode, - p_result->pnio_status.error_code_1, - p_result->pnio_status.error_code_2); + printf ("Release (disconnect) call-back. AREP: %u\n", arep); } app_set_outputs_default_value (p_appdata->arguments.verbosity); @@ -724,8 +711,8 @@ static int app_state_ind ( uint32_t arep, pnet_event_values_t state) { - uint16_t err_cls = 0; - uint16_t err_code = 0; + uint16_t err_cls = 0; /* Error code 1 */ + uint16_t err_code = 0; /* Error code 2 */ uint16_t slot = 0; uint16_t subslot_ix = 0; const char * error_class_description = ""; @@ -775,6 +762,16 @@ static int app_state_ind ( break; } break; + case PNET_ERROR_CODE_1_CTLDINA: + error_class_description = + "CTLDINA = Name and IP assignment from controller"; + switch (err_code) + { + case PNET_ERROR_CODE_2_CTLDINA_ARP_MULTIPLE_IP_ADDRESSES: + error_code_description = "Multiple users of same IP address"; + break; + } + break; } printf ( " Error class: 0x%02x %s \n" @@ -884,7 +881,7 @@ static int app_exp_module_ind ( if (slot >= PNET_MAX_SLOTS) { printf ( - "Wrong slot number recieved: %u It should be less than %u\n", + "Wrong slot number received: %u It should be less than %u\n", slot, PNET_MAX_SLOTS); return -1; @@ -1574,6 +1571,9 @@ void app_copy_ip_to_struct ( /** * Send application ready to the controller * + * When the controller later responds, the app_ccontrol_cnf() callback + * will be triggered. + * * @param net InOut: p-net stack instance * @param arep In: Arep * @param verbosity In: Verbosity @@ -1596,11 +1596,6 @@ static void app_handle_send_application_ready ( printf ("Error returned when application telling that it is ready for " "data. Have you set IOCS or IOPS for all subslots?\n"); } - - /* - * cm_ccontrol_cnf(+/-) is indicated later (app_state_ind(DATA)), when the - * confirmation arrives from the controller. - */ } /** @@ -1826,7 +1821,7 @@ static void app_handle_send_alarm ( .ch_grouping = PNET_DIAG_CH_INDIVIDUAL_CHANNEL, .ch_direction = APP_DIAG_CHANNEL_DIRECTION}; - /* Look for first input slot */ + /* Loop though slots and subslots to find first input subslot */ while (!found_inputslot && (slot < PNET_MAX_SLOTS)) { for (subslot_ix = 0; !found_inputslot && (subslot_ix < PNET_MAX_SUBSLOTS); diff --git a/src/common/pf_alarm.c b/src/common/pf_alarm.c index 598b2df2..33d6810b 100644 --- a/src/common/pf_alarm.c +++ b/src/common/pf_alarm.c @@ -232,62 +232,73 @@ static const char * pf_alarm_apmr_state_to_string (pf_apmr_state_values_t state) void pf_alarm_show (const pf_ar_t * p_ar) { - printf ("Alarms (low)\n"); + printf ("Alarms\n"); + printf (" PNET_MAX_ALARMS = %d\n", PNET_MAX_ALARMS); + printf ("Alarms (low prio)\n"); printf ( - " alpmi_state = %s\n", + " alpmi_state = %s\n", pf_alarm_alpmi_state_to_string (p_ar->alpmx[0].alpmi_state)); printf ( - " alpmr_state = %s\n", + " alpmr_state = %s\n", pf_alarm_alpmr_state_to_string (p_ar->alpmx[0].alpmr_state)); printf ( - " apms_state = %s\n", + " apms_state = %s\n", pf_alarm_apms_state_to_string (p_ar->apmx[0].apms_state)); printf ( - " apmr_state = %s\n", + " apmr_state = %s\n", pf_alarm_apmr_state_to_string (p_ar->apmx[0].apmr_state)); printf ( - " exp_seq_count = 0x%x\n", + " exp_seq_count = 0x%x\n", (unsigned)p_ar->apmx[0].exp_seq_count); printf ( - " exp_seq_count_o = 0x%x\n", + " exp_seq_count_o = 0x%x\n", (unsigned)p_ar->apmx[0].exp_seq_count_o); printf ( - " send_seq_count = 0x%x\n", + " send_seq_count = 0x%x\n", (unsigned)p_ar->apmx[0].send_seq_count); printf ( - " send_seq_count_o = 0x%x\n", + " send_seq_count_o = 0x%x\n", (unsigned)p_ar->apmx[0].send_seq_count_o); printf ( - " sequence_number = %u\n", + " sequence_number = %u\n", (unsigned)p_ar->alpmx[0].sequence_number); - printf ("Alarms (high)\n"); + printf (" Incoming alarm queue (mbox) = %p\n", p_ar->apmx[0].p_alarm_q); printf ( - " alpmi_state = %s\n", + " Message number in incoming queue = %u\n", + p_ar->apmx[0].apmr_msg_nbr); + + printf ("Alarms (high prio)\n"); + printf ( + " alpmi_state = %s\n", pf_alarm_alpmi_state_to_string (p_ar->alpmx[1].alpmi_state)); printf ( - " alpmr_state = %s\n", + " alpmr_state = %s\n", pf_alarm_alpmr_state_to_string (p_ar->alpmx[1].alpmr_state)); printf ( - " apms_state = %s\n", + " apms_state = %s\n", pf_alarm_apms_state_to_string (p_ar->apmx[1].apms_state)); printf ( - " apmr_state = %s\n", + " apmr_state = %s\n", pf_alarm_apmr_state_to_string (p_ar->apmx[1].apmr_state)); printf ( - " exp_seq_count = 0x%x\n", + " exp_seq_count = 0x%x\n", (unsigned)p_ar->apmx[1].exp_seq_count); printf ( - " exp_seq_count_o = 0x%x\n", + " exp_seq_count_o = 0x%x\n", (unsigned)p_ar->apmx[1].exp_seq_count_o); printf ( - " send_seq_count = 0x%x\n", + " send_seq_count = 0x%x\n", (unsigned)p_ar->apmx[1].send_seq_count); printf ( - " send_seq_count_o = 0x%x\n", + " send_seq_count_o = 0x%x\n", (unsigned)p_ar->apmx[1].send_seq_count_o); printf ( - " sequence_number = %u\n", + " sequence_number = %u\n", (unsigned)p_ar->alpmx[1].sequence_number); + printf (" Incoming alarm queue (mbox) = %p\n", p_ar->apmx[1].p_alarm_q); + printf ( + " Message number in incoming queue = %u\n", + p_ar->apmx[1].apmr_msg_nbr); } /*****************************************************************************/ @@ -309,8 +320,8 @@ void pf_alarm_init (pnet_t * net) * * @param net InOut: The p-net stack instance * @param p_apmx InOut: The APMX instance. - * @param err_cls In: The ERRCLS variable. - * @param err_code In: The ERRCODE variable. + * @param err_cls In: The ERRCLS variable. ErrorCode1. + * @param err_code In: The ERRCODE variable. ErrorCode2. */ static void pf_alarm_error_ind ( pnet_t * net, @@ -822,8 +833,10 @@ static void pf_alarm_apms_timeout ( { LOG_INFO ( PF_ALARM_LOG, - "Alarm(%d): Re-sending alarm frame\n", - __LINE__); + "Alarm(%d): Re-sending %s prio alarm frame in %p\n", + __LINE__, + p_apmx->high_priority ? "high" : "low", + p_apmx->p_rta); (void)pf_eth_send ( net, p_apmx->p_ar->p_sess->eth_handle, @@ -889,9 +902,10 @@ static void pf_alarm_apms_timeout ( LOG_DEBUG ( PF_ALARM_LOG, "Alarm(%d): Skip scheduled alarm retransmission as we are in in state " - "%s. Free saved RTA buffer %p\n", + "%s. Free saved %s prio alarm output buffer %p\n", __LINE__, pf_alarm_apms_state_to_string (p_apmx->apms_state), + p_apmx->high_priority ? "high" : "low", p_apmx->p_rta); if (p_apmx->p_rta != NULL) { @@ -925,6 +939,12 @@ static int pf_alarm_apmx_activate (pnet_t * net, pf_ar_t * p_ar) int ret = 0; /* Assume all goes well */ uint16_t ix; + LOG_DEBUG ( + PF_ALARM_LOG, + "Alarm(%d): Activating ALPMX for AREP %u\n", + __LINE__, + p_ar->arep); + for (ix = 0; ix < NELEMENTS (p_ar->apmx); ix++) { if (p_ar->apmx[ix].apms_state != PF_APMS_STATE_CLOSED) @@ -1020,7 +1040,7 @@ static int pf_alarm_apmx_activate (pnet_t * net, pf_ar_t * p_ar) * * APMS: A_Data_ind (Implements parts of it. This ia LMPM_A_Data.ind via macro) * - * Does free the incoming alarm frame buffer. + * Does free the outgoing alarm frame buffer. * * @param net InOut: The p-net stack instance * @param p_apmx InOut: The APMX instance. @@ -1049,8 +1069,10 @@ static int pf_alarm_apms_a_data_ind ( LOG_DEBUG ( PF_AL_BUF_LOG, - "Alarm(%d): Free saved RTA buffer %p\n", + "Alarm(%d): Valid TACK received. Free saved outgoing %s prio " + "alarm buffer if necessary %p\n", __LINE__, + p_apmx->high_priority ? "high" : "low", p_apmx->p_rta); if (p_apmx->p_rta != NULL) { @@ -1171,10 +1193,6 @@ static int pf_alarm_apms_a_data_req ( } else { - LOG_DEBUG ( - PF_AL_BUF_LOG, - "Alarm(%d): Allocate RTA output buffer\n", - __LINE__); p_rta = pnal_buf_alloc (PF_FRAME_BUFFER_SIZE); if (p_rta == NULL) { @@ -1196,6 +1214,13 @@ static int pf_alarm_apms_a_data_req ( } else { + LOG_DEBUG ( + PF_AL_BUF_LOG, + "Alarm(%d): Allocated alarm output buffer for %s %p\n", + __LINE__, + pf_alarm_pdu_type_to_string (p_fixed->pdu_type.type), + p_rta); + /* Insert destination MAC address */ pf_put_mem ( &p_apmx->da, @@ -1345,16 +1370,20 @@ static int pf_alarm_apms_a_data_req ( { LOG_DEBUG ( PF_AL_BUF_LOG, - "Alarm(%d): Save RTA alarm output buffer for later use.\n", - __LINE__); + "Alarm(%d): Save alarm output buffer for later use. %p\n", + __LINE__, + p_rta); p_apmx->p_rta = p_rta; } else { LOG_ERROR ( PF_ALARM_LOG, - "Alarm(%d): RTA alarm output buffer with TACK lost!!\n", - __LINE__); + "Alarm(%d): RTA alarm output buffer with TACK lost! " + "Free %p Existing buffer %p\n", + __LINE__, + p_rta, + p_apmx->p_rta); pnal_buf_free (p_rta); } } @@ -1363,8 +1392,9 @@ static int pf_alarm_apms_a_data_req ( /* ACK, NAK and ERR buffers are not saved for retransmission. */ LOG_DEBUG ( PF_AL_BUF_LOG, - "Alarm(%d): Free unsaved RTA alarm output buffer\n", - __LINE__); + "Alarm(%d): Free unsaved alarm output buffer %p\n", + __LINE__, + p_rta); pnal_buf_free (p_rta); } } @@ -1548,9 +1578,12 @@ static int pf_alarm_apmx_close (pnet_t * net, pf_ar_t * p_ar, uint8_t err_code) LOG_DEBUG ( PF_AL_BUF_LOG, - "Alarm(%d): Free saved RTA buffer %p if necessary\n", + "Alarm(%d): Free saved %s prio alarm output buffer %p for AREP %u if " + "necessary\n", __LINE__, - p_ar->apmx[ix].p_rta); + p_ar->apmx[ix].high_priority ? "high" : "low", + p_ar->apmx[ix].p_rta, + p_ar->arep); if (p_ar->apmx[ix].p_rta != NULL) { p_rta = p_ar->apmx[ix].p_rta; @@ -1985,14 +2018,16 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) { /* Got something - extract! */ p_buf = p_alarm_msg->p_buf; - pos = p_alarm_msg->frame_id_pos + sizeof (uint16_t); /* Skip - frame_id */ + + /* Skip frame_id */ + pos = p_alarm_msg->frame_id_pos + sizeof (uint16_t); get_info.result = PF_PARSE_OK; get_info.is_big_endian = true; get_info.p_buf = (uint8_t *)p_buf->payload; get_info.len = p_buf->len; + /* Parse fixed part of incoming alarm frame */ memset (&fixed, 0, sizeof (fixed)); pf_get_alarm_fixed (&get_info, &pos, &fixed); var_part_len = pf_get_uint16 (&get_info, &pos); @@ -2004,8 +2039,10 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) case PF_RTA_PDU_TYPE_ACK: LOG_DEBUG ( PF_ALARM_LOG, - "Alarm(%d): Alarm ACK frame received\n", - __LINE__); + "Alarm(%d): Got %s prio alarm ACK frame from mbox. %p\n", + __LINE__, + p_apmx->high_priority ? "high" : "low", + p_buf); if (var_part_len == 0) { /* Tell APMS to check for and handle ACK */ @@ -2015,7 +2052,8 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) { LOG_ERROR ( PF_ALARM_LOG, - "Alarm(%d): Wrong var_part_len %u for ACK frame\n", + "Alarm(%d): Wrong var_part_len %u for incoming ACK " + "frame\n", __LINE__, (unsigned)var_part_len); ret = 0; /* Just ignore */ @@ -2024,8 +2062,10 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) case PF_RTA_PDU_TYPE_NACK: LOG_DEBUG ( PF_ALARM_LOG, - "Alarm(%d): Alarm NACK frame received\n", - __LINE__); + "Alarm(%d): Got %s prio alarm NACK frame from mbox. %p\n", + __LINE__, + p_apmx->high_priority ? "high" : "low", + p_buf); /* APMS: A_Data_ind (Implements parts of it, for NACK) */ if (var_part_len == 0) { @@ -2036,7 +2076,8 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) { LOG_ERROR ( PF_ALARM_LOG, - "Alarm(%d): Wrong var_part_len %u for NACK frame\n", + "Alarm(%d): Wrong var_part_len %u for incoming " + "NACK frame\n", __LINE__, (unsigned)var_part_len); ret = 0; /* Just ignore */ @@ -2045,8 +2086,14 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) case PF_RTA_PDU_TYPE_DATA: LOG_DEBUG ( PF_ALARM_LOG, - "Alarm(%d): Alarm DATA frame received\n", - __LINE__); + "Alarm(%d): Got incoming %s prio alarm DATA frame from " + "mbox. %p. " + "Length on wire: %d Var part len: %d\n", + __LINE__, + p_apmx->high_priority ? "high" : "low", + p_buf, + p_buf->len, + var_part_len); ret = pf_alarm_apmr_a_data_ind ( net, p_apmx, @@ -2069,10 +2116,11 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) case PF_APMR_STATE_OPEN: LOG_DEBUG ( PF_ALARM_LOG, - "Alarm(%d): Alarm received from IO-controller. " - "Error code 1 (ERRCLS): %u Error code 2 (ERRCODE): " - "%u \n", + "Alarm(%d): Got incoming alarm ERROR frame from " + "mbox. %p. Error code 1 (ERRCLS): %0x02x " + "Error code 2 (ERRCODE): %0x02x\n", __LINE__, + p_buf, pnio_status.error_code_1, pnio_status.error_code_2); pf_alarm_error_ind ( @@ -2102,8 +2150,8 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) { LOG_ERROR ( PF_ALARM_LOG, - "Alarm(%d): Alarm received from IO-controller, but has " - "wrong var_part_len %u\n", + "Alarm(%d): Alarm ERROR frame received from " + "IO-controller, but it has wrong var_part_len %u\n", __LINE__, (unsigned)var_part_len); /* Ignore */ @@ -2113,7 +2161,8 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) default: LOG_ERROR ( PF_ALARM_LOG, - "Alarm(%d): Wrong PDU-Type.type %u\n", + "Alarm(%d): Alarm received from IO-controller, but it " + "has wrong PDU-Type.type %u\n", __LINE__, (unsigned)fixed.pdu_type.type); /* Ignore */ @@ -2125,7 +2174,8 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) { LOG_ERROR ( PF_ALARM_LOG, - "Alarm(%d): Wrong PDU-Type.version %u\n", + "Alarm(%d): Alarm received from IO-controller, but it " + "has wrong PDU-Type.version %u\n", __LINE__, (unsigned)fixed.pdu_type.version); /* Ignore */ @@ -2134,8 +2184,9 @@ static int pf_alarm_apmr_periodic (pnet_t * net, pf_ar_t * p_ar) LOG_DEBUG ( PF_AL_BUF_LOG, - "Alarm(%d): Free received buffer\n", - __LINE__); + "Alarm(%d): Free received buffer %p\n", + __LINE__, + p_buf); pnal_buf_free (p_buf); p_buf = NULL; } @@ -2367,7 +2418,11 @@ int pf_alarm_close (pnet_t * net, pf_ar_t * p_ar) { int ret = 0; - LOG_DEBUG (PF_ALARM_LOG, "Alarm(%d): Closing alarm instance.\n", __LINE__); + LOG_DEBUG ( + PF_ALARM_LOG, + "Alarm(%d): Closing alarm instance for AREP %u.\n", + __LINE__, + p_ar->arep); if (pf_alarm_alpmx_close (p_ar) != 0) { ret = -1; @@ -2541,7 +2596,10 @@ int pf_alarm_periodic (pnet_t * net) p_ar = pf_ar_find_by_index (net, ix); if ((p_ar != NULL) && (p_ar->in_use == true)) { + /* Handle incoming alarm frames */ (void)pf_alarm_apmr_periodic (net, p_ar); + + /* Handle outgoing alarm messages */ (void)pf_alarm_almpi_periodic (net, p_ar); } } diff --git a/src/common/pf_cpm.c b/src/common/pf_cpm.c index ad28d2b9..74599c4a 100644 --- a/src/common/pf_cpm.c +++ b/src/common/pf_cpm.c @@ -117,7 +117,7 @@ static void pf_cpm_state_ind ( * pf_scheduler_timeout_ftn_t * * @param net InOut: The p-net stack instance - * @param arg In: The IOCR instance. + * @param arg In: The IOCR instance. pf_iocr_t * @param current_time In: The current system time, in microseconds, * when the scheduler is started to execute * stored tasks. @@ -239,7 +239,12 @@ int pf_cpm_close_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) pf_cpm_t * p_cpm = &p_ar->iocrs[crep].cpm; uint32_t cnt; - LOG_DEBUG (PF_CPM_LOG, "CPM(%d): Closing\n", __LINE__); + LOG_DEBUG ( + PF_CPM_LOG, + "CPM(%d): Closing CPM for AREP %u CREP %u\n", + __LINE__, + p_ar->arep, + crep); p_cpm->ci_running = false; /* StopTimer */ if (p_cpm->ci_timer != UINT32_MAX) { @@ -407,7 +412,7 @@ static void pf_cpm_get_buf ( * @param frame_id In: The frame id of the frame. * @param p_buf In: The received data. * @param frame_id_pos In: Position of the frame id in the buffer. - * @param p_arg In: The IOCR instance. + * @param p_arg In: The IOCR instance. pf_iocr_t * @return 0 If the frame was NOT handled by this function. * 1 If the frame was handled and the buffer freed. */ @@ -568,6 +573,16 @@ int pf_cpm_activate_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) p_iocr = &p_ar->iocrs[crep]; p_cpm = &p_iocr->cpm; + + LOG_DEBUG ( + PF_CPM_LOG, + "CPM(%d): Activating CPM for output data reception. " + "AREP %u CREP %u FrameID: 0x%04x\n", + __LINE__, + p_ar->arep, + crep, + p_iocr->param.frame_id); + switch (p_cpm->state) { case PF_CPM_STATE_W_START: @@ -784,9 +799,10 @@ int pf_cpm_get_data_and_iops ( p_ar->err_code = PNET_ERROR_CODE_2_CPM_INVALID_STATE; LOG_DEBUG ( PF_CPM_LOG, - "CPM(%d): Get data in wrong state: %u\n", + "CPM(%d): Get data in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->cpm.state); + p_iocr->cpm.state, + p_ar->arep); break; case PF_CPM_STATE_FRUN: case PF_CPM_STATE_RUN: @@ -840,9 +856,10 @@ int pf_cpm_get_data_and_iops ( default: LOG_DEBUG ( PF_CPM_LOG, - "CPM(%d): Set data in wrong state: %u\n", + "CPM(%d): Set data in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->cpm.state); + p_iocr->cpm.state, + p_ar->arep); break; } } @@ -890,9 +907,10 @@ int pf_cpm_get_iocs ( p_ar->err_code = PNET_ERROR_CODE_2_CPM_INVALID_STATE; LOG_DEBUG ( PF_CPM_LOG, - "CPM(%d): Get iocs in wrong state: %u\n", + "CPM(%d): Get iocs in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->cpm.state); + p_iocr->cpm.state, + p_ar->arep); break; case PF_CPM_STATE_FRUN: case PF_CPM_STATE_RUN: @@ -931,9 +949,10 @@ int pf_cpm_get_iocs ( default: LOG_DEBUG ( PF_CPM_LOG, - "CPM(%d): Get iocs in wrong state: %u\n", + "CPM(%d): Get iocs in wrong state: %u for AREP %u\n", __LINE__, - (unsigned)p_iocr->cpm.state); + (unsigned)p_iocr->cpm.state, + p_ar->arep); break; } } diff --git a/src/common/pf_dcp.c b/src/common/pf_dcp.c index b7a84fa8..6cf2b47b 100644 --- a/src/common/pf_dcp.c +++ b/src/common/pf_dcp.c @@ -280,7 +280,7 @@ static bool pf_dcp_check_sam (pnet_t * net, const pnet_ethaddr_t * mac) * and also that it matches the local MAC address. * * This check was added to handle situation where network - * interface is in promiscous mode and the need to filter out + * interface is in promiscuous mode and the need to filter out * DCP requests intended for other devices. * * @param local_mac In: Local MAC address. Should be the @@ -1981,6 +1981,11 @@ void pf_dcp_init (pnet_t * net) net->dcp_identresp_timeout = 0; net->dcp_sam = mac_nil; + LOG_DEBUG ( + PF_DCP_LOG, + "DCP(%d): Activate. Register frame handlers.\n", + __LINE__); + /* Insert handlers for our specific frame_ids */ pf_eth_frame_id_map_add (net, PF_DCP_HELLO_FRAME_ID, pf_dcp_hello_ind, NULL); pf_eth_frame_id_map_add (net, PF_DCP_GET_SET_FRAME_ID, pf_dcp_get_set, NULL); diff --git a/src/common/pf_eth.c b/src/common/pf_eth.c index 8034c35c..b3f134c8 100644 --- a/src/common/pf_eth.c +++ b/src/common/pf_eth.c @@ -258,7 +258,7 @@ void pf_eth_frame_id_map_add ( { LOG_DEBUG ( PF_ETH_LOG, - "ETH(%d): Add FrameIds %#x at index %u\n", + "ETH(%d): Framehandler is adding FrameId %#x at index %u.\n", __LINE__, (unsigned)frame_id, (unsigned)ix); diff --git a/src/common/pf_ppm.c b/src/common/pf_ppm.c index 76356b25..92e6e901 100644 --- a/src/common/pf_ppm.c +++ b/src/common/pf_ppm.c @@ -382,11 +382,13 @@ int pf_ppm_activate_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) LOG_DEBUG ( PF_PPM_LOG, - "PPM(%d): Starting cyclic data transmission for CREP %" PRIu32 ", period " - "%" PRIu32 " microseconds\n", + "PPM(%d): Starting cyclic input data transmission with PPM. AREP %u " + "CREP %" PRIu32 ", period %" PRIu32 " microseconds. FrameID 0x%04x\n", __LINE__, + p_ar->arep, crep, - p_ppm->control_interval); + p_ppm->control_interval, + p_iocr->param.frame_id); /* Needed for counter calculations */ p_ppm->send_clock_factor = p_iocr->param.send_clock_factor; @@ -417,7 +419,12 @@ int pf_ppm_close_req (pnet_t * net, pf_ar_t * p_ar, uint32_t crep) pf_ppm_t * p_ppm; uint32_t cnt; - LOG_DEBUG (PF_PPM_LOG, "PPM(%d): Closing\n", __LINE__); + LOG_DEBUG ( + PF_PPM_LOG, + "PPM(%d): Closing PPM for AREP %u CREP %u\n", + __LINE__, + p_ar->arep, + crep); p_ppm = &p_ar->iocrs[crep].ppm; p_ppm->ci_running = false; if (p_ppm->ci_timer != UINT32_MAX) @@ -558,9 +565,10 @@ int pf_ppm_set_data_and_iops ( p_ar->err_code = PNET_ERROR_CODE_2_PPM_INVALID_STATE; LOG_DEBUG ( PF_PPM_LOG, - "PPM(%d): Set data in wrong state: %u\n", + "PPM(%d): Set data in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->ppm.state); + p_iocr->ppm.state, + p_ar->arep); break; case PF_PPM_STATE_RUN: if ( @@ -603,9 +611,10 @@ int pf_ppm_set_data_and_iops ( default: LOG_ERROR ( PF_PPM_LOG, - "PPM(%d): Set data in wrong state: %u\n", + "PPM(%d): Set data in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->ppm.state); + p_iocr->ppm.state, + p_ar->arep); break; } } @@ -651,9 +660,10 @@ int pf_ppm_set_iocs ( p_ar->err_code = PNET_ERROR_CODE_2_PPM_INVALID_STATE; LOG_DEBUG ( PF_PPM_LOG, - "PPM(%d): Set iocs in wrong state: %u\n", + "PPM(%d): Set iocs in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->ppm.state); + p_iocr->ppm.state, + p_ar->arep); break; case PF_PPM_STATE_RUN: if (iocs_len == p_iodata->iocs_length) @@ -687,9 +697,10 @@ int pf_ppm_set_iocs ( default: LOG_ERROR ( PF_PPM_LOG, - "PPM(%d): Set data in wrong state: %u\n", + "PPM(%d): Set data in wrong state: %u for AREP %u\n", __LINE__, - (unsigned)p_iocr->ppm.state); + (unsigned)p_iocr->ppm.state, + p_ar->arep); break; } } @@ -737,9 +748,10 @@ int pf_ppm_get_data_and_iops ( p_ar->err_code = PNET_ERROR_CODE_2_PPM_INVALID_STATE; LOG_DEBUG ( PF_PPM_LOG, - "PPM(%d): Get data in wrong state: %u\n", + "PPM(%d): Get data in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->ppm.state); + p_iocr->ppm.state, + p_ar->arep); break; case PF_PPM_STATE_RUN: if ( @@ -777,9 +789,10 @@ int pf_ppm_get_data_and_iops ( default: LOG_ERROR ( PF_PPM_LOG, - "PPM(%d): Get data in wrong state: %u\n", + "PPM(%d): Get data in wrong state: %u for AREP %u\n", __LINE__, - (unsigned)p_iocr->ppm.state); + (unsigned)p_iocr->ppm.state, + p_ar->arep); break; } } @@ -837,9 +850,10 @@ int pf_ppm_get_iocs ( p_ar->err_code = PNET_ERROR_CODE_2_PPM_INVALID_STATE; LOG_DEBUG ( PF_PPM_LOG, - "PPM(%d): Get iocs in wrong state: %u\n", + "PPM(%d): Get iocs in wrong state: %u for AREP %u\n", __LINE__, - p_iocr->ppm.state); + p_iocr->ppm.state, + p_ar->arep); break; case PF_PPM_STATE_RUN: if (*p_iocs_len >= p_iodata->iocs_length) @@ -868,9 +882,10 @@ int pf_ppm_get_iocs ( default: LOG_ERROR ( PF_PPM_LOG, - "PPM(%d): Get iocs in wrong state: %u\n", + "PPM(%d): Get iocs in wrong state: %u for AREP %u\n", __LINE__, - (unsigned)p_iocr->ppm.state); + (unsigned)p_iocr->ppm.state, + p_ar->arep); break; } } diff --git a/src/common/pf_scheduler.c b/src/common/pf_scheduler.c index d56b8545..553d49bc 100644 --- a/src/common/pf_scheduler.c +++ b/src/common/pf_scheduler.c @@ -414,7 +414,9 @@ void pf_scheduler_show (pnet_t * net) uint32_t ix; uint32_t cnt; - printf ("Scheduler (time now=%u):\n", (unsigned)os_get_current_time_us()); + printf ( + "Scheduler (time now=%u microseconds):\n", + (unsigned)os_get_current_time_us()); if (net->scheduler_timeout_mutex != NULL) { diff --git a/src/device/pf_block_reader.c b/src/device/pf_block_reader.c index 42f23ab8..6acc40f0 100644 --- a/src/device/pf_block_reader.c +++ b/src/device/pf_block_reader.c @@ -311,6 +311,14 @@ static void pf_get_exp_submodule ( p_sub->data_descriptor[1].length_iops = pf_get_byte (p_info, p_pos); p_sub->nbr_data_descriptors = 2; } + + LOG_DEBUG ( + PNET_LOG, + "BR(%d): Subslot 0x%04x. Expected submodule 0x%x with direction %u\n", + __LINE__, + p_sub->subslot_number, + p_sub->submodule_ident_number, + p_sub->submodule_properties.type); } /* ======================== Public functions ======================== */ @@ -489,6 +497,15 @@ void pf_get_exp_api_module ( p_mod->module_ident_number = pf_get_uint32 (p_info, p_pos); p_mod->module_properties = pf_get_uint16 (p_info, p_pos); p_mod->nbr_submodules = pf_get_uint16 (p_info, p_pos); + + LOG_DEBUG ( + PNET_LOG, + "BR(%d): Slot %u. Expected module 0x%x with %u submodules.\n", + __LINE__, + p_mod->slot_number, + p_mod->module_ident_number, + p_mod->nbr_submodules); + for (iy = 0; iy < p_mod->nbr_submodules; iy++) { pf_get_exp_submodule (p_info, p_pos, &p_mod->submodules[iy]); diff --git a/src/device/pf_block_reader.h b/src/device/pf_block_reader.h index 9ba7a274..1dd43f60 100644 --- a/src/device/pf_block_reader.h +++ b/src/device/pf_block_reader.h @@ -102,6 +102,9 @@ void pf_get_ar_param (pf_get_info_t * p_info, uint16_t * p_pos, pf_ar_t * p_ar); /** * Extract an IOCR param block from a buffer. + * + * Updates p_ar->iocrs[ix].param + * * @param p_info Inout: The parser state. * @param p_pos InOut: Position in the buffer. * @param ix In: The current index into p_ar->iocr[]. diff --git a/src/device/pf_block_writer.c b/src/device/pf_block_writer.c index f08827f7..3a85a159 100644 --- a/src/device/pf_block_writer.c +++ b/src/device/pf_block_writer.c @@ -40,14 +40,14 @@ /** * @internal * Insert a block header into a buffer. - * @param is_big_endian In: true if buffer is big-endian. - * @param bh_type In: Block type. - * @param bh_length In: Block length. - * @param bh_ver_high In: Block version high. - * @param bh_ver_low In: Block version low. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: true if buffer is big-endian. + * @param bh_type In: Block type. + * @param bh_length In: Block length. + * @param bh_ver_high In: Block version high. + * @param bh_ver_low In: Block version low. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_block_header ( bool is_big_endian, @@ -80,11 +80,11 @@ static void pf_put_block_header ( * If the string is shorter than the destination size then the destination * is padded with spaces. * The destination buffer does not contain any terminating NUL byte. - * @param p_src In: The string. - * @param src_size In: The destination string size. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param p_src In: The string. + * @param src_size In: The destination string size. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_str ( const void * p_src, @@ -119,11 +119,11 @@ static void pf_put_str ( /** * @internal * Insert a UUID into a buffer. - * @param is_big_endian In: true if buffer is big-endian. - * @param p_uuid In: The UUID to insert. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: true if buffer is big-endian. + * @param p_uuid In: The UUID to insert. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_uuid ( bool is_big_endian, @@ -140,11 +140,11 @@ static void pf_put_uuid ( /** * Put rpc UUID into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_uuid In: The UUID to insert. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_uuid In: The UUID to insert. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_uuid ( bool is_big_endian, @@ -468,10 +468,10 @@ void pf_put_alarm_cr_result ( /** * @internal * Insert bits into a uint32_t. - * @param val In: The value of the bit field. - * @param len In: The number of bits to insert. - * @param pos In: The position in p_bits to insert the bits at. - * @param p_bits InOut:The resulting uint32_t. + * @param val In: The value of the bit field. + * @param len In: The number of bits to insert. + * @param pos In: The position in p_bits to insert the bits at. + * @param p_bits InOut: The resulting uint32_t. */ static void pf_put_bits ( uint32_t val, @@ -487,11 +487,11 @@ static void pf_put_bits ( /** * @internal * Insert a sub-module diff into a buffer. - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_diff In: The sub-module diff information. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_diff In: The sub-module diff information. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_submodule_diff ( bool is_big_endian, @@ -539,11 +539,11 @@ static void pf_put_submodule_diff ( /** * @internal * Insert a module diff into a buffer. - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_diff In: The module diff information. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_diff In: The module diff information. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_module_diff ( bool is_big_endian, @@ -596,12 +596,12 @@ static void pf_put_module_diff ( /** * @internal * Insert AR diff blocks into a buffer. - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_ar In: Contains the AR diff to insert. - * @param api_ix In: The specific AR diff to add. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_ar In: Contains the AR diff to insert. + * @param api_ix In: The specific AR diff to add. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_api_diff ( bool is_big_endian, @@ -819,12 +819,12 @@ void pf_put_ar_vendor_result ( /** * @internal * Insert an IOCR struct into a buffer. - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_ar In: The AR instance. - * @param ix In: The IOCR indice. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_ar In: The AR instance. + * @param ix In: The IOCR indice. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_iocr ( bool is_big_endian, @@ -952,13 +952,13 @@ static void pf_put_rs_info ( /** * Insert one AR to a buffer. - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_ar In: The AR to insert. - * @param api_filter In: true => Insert only specific API. - * @param api_id In: The api id. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_ar In: The AR to insert. + * @param api_filter In: true => Insert only specific API. + * @param api_id In: The api id. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_one_ar ( bool is_big_endian, @@ -1619,12 +1619,12 @@ void pf_put_read_result ( * * Inserts subslot number and submodule ID. * - * @param is_big_endian In: Endianness of the destination buffer. - * @param block_type In: Specifies REAL or EXP ident number to insert. - * @param p_subslot In: The sub-slot instance. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param block_type In: Specifies REAL or EXP ident number to insert. + * @param p_subslot In: The sub-slot instance. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_ident_subslot ( bool is_big_endian, @@ -1667,16 +1667,17 @@ static void pf_put_ident_subslot ( * Inserts slot number, module ID, number of subslots and then uses * \a pf_put_ident_subslot() to insert more info. * - * @param is_big_endian In: Endianness of the destination buffer. - * @param block_type In: Specifies REAL or EXP ident number to insert. - * @param filter_level In: The filter starting level. - * @param stop_level In: The amount of detail to include (ending level). - * @param p_ar In: If != NULL then filter by AR. - * @param p_slot In: The slot instance. - * @param subslot_nbr In: Sub-slot number to filter by. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param block_type In: Specifies REAL or EXP ident number to insert. + * @param filter_level In: The filter starting level. + * @param stop_level In: The amount of detail to include (ending + * level). + * @param p_ar In: If != NULL then filter by AR. + * @param p_slot In: The slot instance. + * @param subslot_nbr In: Sub-slot number to filter by. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_ident_slot ( bool is_big_endian, @@ -1789,17 +1790,18 @@ static void pf_put_ident_slot ( * Inserts API ID, number of slots and then uses \a pf_put_ident_slot() to * insert more info. * - * @param is_big_endian In: Endianness of the destination buffer. - * @param block_type In: Specifies REAL or EXP ident number to insert. - * @param filter_level In: The filter starting level. - * @param stop_level In: The amount of detail to include (ending level). - * @param p_ar In: If != NULL then filter by AR. - * @param p_api In: The api instance. - * @param slot_nbr In: Slot number to filter by. - * @param subslot_nbr In: Sub-slot number to filter by. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param block_type In: Specifies REAL or EXP ident number to insert. + * @param filter_level In: The filter starting level. + * @param stop_level In: The amount of detail to include (ending + * level). + * @param p_ar In: If != NULL then filter by AR. + * @param p_api In: The api instance. + * @param slot_nbr In: Slot number to filter by. + * @param subslot_nbr In: Sub-slot number to filter by. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_ident_api ( bool is_big_endian, @@ -1905,18 +1907,19 @@ static void pf_put_ident_api ( * Inserts number of APIs, and then uses \a pf_put_ident_api() to insert * more info. * - * @param is_big_endian In: Endianness of the destination buffer. - * @param block_type In: Specifies REAL or EXP ident number to insert. - * @param filter_level In: The filter starting level. - * @param stop_level In: The amount of detail to include (ending level). - * @param p_ar In: If != NULL then filter by AR. - * @param p_device In: The device instance. - * @param api_id In: API id to filter by. - * @param slot_nbr In: Slot number to filter by. - * @param subslot_nbr In: Sub-slot number to filter by. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param block_type In: Specifies REAL or EXP ident number to insert. + * @param filter_level In: The filter starting level. + * @param stop_level In: The amount of detail to include (ending + * level). + * @param p_ar In: If != NULL then filter by AR. + * @param p_device In: The device instance. + * @param api_id In: API id to filter by. + * @param slot_nbr In: Slot number to filter by. + * @param subslot_nbr In: Sub-slot number to filter by. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_ident_device ( bool is_big_endian, @@ -2537,12 +2540,12 @@ void pf_put_log_book_data ( * * Used both for creating an alarm frame and a diagnostics read answer frame. * - * @param is_big_endian In: true if buffer is big-endian. - * @param p_item In: The diag item to insert. - * @param insert_usi In: Insert USI field if true. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: true if buffer is big-endian. + * @param p_item In: The diag item to insert. + * @param insert_usi In: Insert USI field if true. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_diag_item ( bool is_big_endian, @@ -4267,11 +4270,11 @@ void pf_put_pd_interface_adj ( /** * Put rpc epm floor count into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param count In: Floor count. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param count In: Floor count. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_floor_count ( bool is_big_endian, @@ -4285,11 +4288,11 @@ static void pf_put_rpc_floor_count ( /** * Put rpc epm floor 1 configuration into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_floor In: Floor configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_floor In: Floor configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_floor_1_uuid ( bool is_big_endian, @@ -4332,11 +4335,11 @@ static void pf_put_rpc_floor_1_uuid ( /** * Put rpc epm floor 2 configuration into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_floor In: Floor configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_floor In: Floor configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_floor_2_uuid ( bool is_big_endian, @@ -4350,11 +4353,11 @@ static void pf_put_rpc_floor_2_uuid ( /** * Put rpc epm floor 3 configuration into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_floor In: Floor configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_floor In: Floor configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_floor_3_rpc ( bool is_big_endian, @@ -4389,11 +4392,11 @@ static void pf_put_rpc_floor_3_rpc ( /** * Put rpc epm floor 4 configuration into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_floor In: Floor configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_floor In: Floor configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_floor_4_udp ( bool is_big_endian, @@ -4423,11 +4426,11 @@ static void pf_put_rpc_floor_4_udp ( /** * Put rpc epm floor 5 configuration into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_floor In: Floor configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_floor In: Floor configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_floor_5_ip ( bool is_big_endian, @@ -4471,11 +4474,11 @@ static void pf_put_rpc_floor_5_ip ( * SWRevision VisibleString[9] 4.10.3.3.5 * EndTerm '\0' * - * @param p_cfg In: Configuration data used to generate - * annotation. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param p_cfg In: Configuration data used to generate + * annotation. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_epm_annotation ( const pnet_cfg_t * p_cfg, @@ -4512,11 +4515,11 @@ static void pf_put_rpc_epm_annotation ( /** * Put rpc epm protocol tower into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_tower In: Protocol tower configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_tower In: Protocol tower configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_tower_entry ( bool is_big_endian, @@ -4606,11 +4609,11 @@ static void pf_put_tower_entry ( /** * Put rpc handle into a buffer - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_handle In: Rpc handle - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_handle In: Rpc handle + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_handle ( bool is_big_endian, @@ -4637,12 +4640,12 @@ static void pf_put_rpc_handle ( /** * Put rpc epm entry into a buffer. If no no protocol tower is * configured / actual_count == 0, a empty entry is written. - * @param is_big_endian In: Endianness of the destination buffer. - * @param p_entry In: Rpc epm entry including protocol - * tower configuration. - * @param res_len In: Size of destination buffer. - * @param p_bytes Out: Destination buffer. - * @param p_pos InOut:Position in destination buffer. + * @param is_big_endian In: Endianness of the destination buffer. + * @param p_entry In: Rpc epm entry including protocol + * tower configuration. + * @param res_len In: Size of destination buffer. + * @param p_bytes Out: Destination buffer. + * @param p_pos InOut: Position in destination buffer. */ static void pf_put_rpc_epm_entry ( bool is_big_endian, diff --git a/src/device/pf_cmdev.c b/src/device/pf_cmdev.c index ae6b12eb..6c0a71cf 100644 --- a/src/device/pf_cmdev.c +++ b/src/device/pf_cmdev.c @@ -879,6 +879,16 @@ int pf_cmdev_plug_submodule ( /* Inherit AR from slot module */ p_subslot->p_ar = p_slot->p_ar; + + LOG_DEBUG ( + PNET_LOG, + "CMDEV(%d): Plugged submodule ident 0x%08x number in api %u " + "slot %u subslot %u\n", + __LINE__, + (unsigned)submod_ident_nbr, + (unsigned)api_id, + (unsigned)slot_nbr, + (unsigned)subslot_nbr); } else { @@ -1699,7 +1709,7 @@ int pf_cmdev_check_ar_type (uint16_t ar_type) * @internal * Check the AR param for errors. * @param p_ar InOut: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if no error was detected. * -1 if an error was detected. */ @@ -2065,7 +2075,7 @@ static int pf_cmdev_get_exp_sub_data_descriptor ( * @param p_ar In: The AR instance. * @param p_iocr InOut: The IOCR instance. * @param dir In: The data direction to consider. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information. Not used. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -2141,14 +2151,16 @@ static int pf_cmdev_iocr_setup_iocs ( { LOG_INFO ( PNET_LOG, - "CMDEV(%d) Read IOCS size from API %u slot %u subslot %u with " - "data direction %u. Data %u bytes, IOPS %u bytes, IOCS %u " - "bytes\n", + "CMDEV(%d) Read IOCS size from API %u slot %u subslot " + "0x%04x with data direction %u. AREP %u CREP %u Data %u " + "bytes, IOPS %u bytes, IOCS %u bytes\n", __LINE__, (unsigned)api_id, (unsigned)slot_nbr, (unsigned)subslot_nbr, (unsigned)p_desc->data_direction, + p_ar->arep, + p_iocr->crep, (unsigned)p_desc->submodule_data_length, (unsigned)p_desc->length_iops, p_desc->length_iocs); @@ -2222,7 +2234,7 @@ static int pf_cmdev_iocr_setup_iocs ( * @param p_ar In: The AR instance. * @param p_iocr InOut: The IOCR instance. * @param dir In: The data direction to consider. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information. Not used. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -2300,13 +2312,15 @@ static int pf_cmdev_iocr_setup_data_iops ( LOG_INFO ( PNET_LOG, "CMDEV(%d) Read data and IOPS size from API %u slot %u subslot " - "%u with data direction %u. Data %u bytes, IOPS %u bytes, IOCS " - "%u bytes\n", + "0x%04x with data direction %u. AREP %u CREP %u Data %u bytes, " + "IOPS %u bytes, IOCS %u bytes\n", __LINE__, (unsigned)api_id, (unsigned)slot_nbr, (unsigned)subslot_nbr, (unsigned)p_desc->data_direction, + p_ar->arep, + p_iocr->crep, (unsigned)p_desc->submodule_data_length, (unsigned)p_desc->length_iops, p_desc->length_iocs); @@ -2405,7 +2419,7 @@ static int pf_cmdev_iocr_setup_data_iops ( * expected (sub-)modules. * @param p_ar InOut: The AR instance. * @param crep In: The IOCR index. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information. Not used. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -2515,7 +2529,7 @@ int pf_cmdev_check_no_straddle ( * Check if a data_desc overlaps any previous data_desc in same iocrs[]. * @param p_iocr In: The iocrs instance. * @param ix_this In: The data_desc index to verify. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 If this area does not overlap any previously defined area. * -1 If there is overlap. */ @@ -2602,6 +2616,7 @@ static int pf_cmdev_check_iocr_overlap ( } } } + if (ret != 0) { pf_set_error ( @@ -2649,6 +2664,7 @@ static int pf_cmdev_check_iocr_overlap ( } } } + if (ret != 0) { pf_set_error ( @@ -2667,7 +2683,7 @@ static int pf_cmdev_check_iocr_overlap ( * @internal * Perform final validation of IOCR APIs, after the data_desc has been set up. * @param p_ar In: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if no error was found. * -1 if an error was found. */ @@ -3040,7 +3056,7 @@ static int pf_cmdev_check_iocr_apis (pf_ar_t * p_ar, pnet_result_t * p_stat) * Check the IOCR param of an AR for errors. * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if no error was found * -1 if an error was found. */ @@ -3412,7 +3428,7 @@ static int pf_cmdev_check_iocr_param ( * @param p_exp_mod In: The expected sub-module instance. * @param p_cfg_api InOut: The configured API instance. * @param p_cfg_slot InOut: The configured module instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -3813,7 +3829,7 @@ static int pf_cmdev_exp_submodule_configure ( * @param net InOut: The p-net stack instance * @param p_exp_api In: The expected API instance. * @param p_cfg_api InOut: The configured API instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -3977,7 +3993,7 @@ static int pf_cmdev_exp_modules_configure ( * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -4036,7 +4052,7 @@ static int pf_cmdev_exp_apis_configure ( * @internal * Check the alarm CR block for errors. * @param p_ar InOut: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -4174,8 +4190,11 @@ static int pf_cmdev_check_alarm_cr (pf_ar_t * p_ar, pnet_result_t * p_stat) /** * @internal * Check the AR RPC block for errors. + * + * Validates that the UDP port is in correct range. + * * @param p_ar InOut: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -4213,7 +4232,7 @@ static int pf_cmdev_check_ar_rpc (pf_ar_t * p_ar, pnet_result_t * p_stat) * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param p_stat Out: Detailed error information. + * @param p_stat Out: Detailed error information if return != 0; * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -4350,6 +4369,7 @@ int pf_cmdev_generate_submodule_diff (pnet_t * net, pf_ar_t * p_ar) { return -1; } + /* Generate a diff including all expected (sub)modules */ for (exp_api_ix = 0; exp_api_ix < p_ar->nbr_exp_apis; exp_api_ix++) { @@ -4615,6 +4635,14 @@ static void pf_cmdev_fix_frame_id (pf_ar_t * p_ar) if (frame_id <= stop) { p_iocr_param->frame_id = frame_id; + LOG_DEBUG ( + PNET_LOG, + "CMDEV(%d): Using FrameID 0x%04x for output CR with AREP %u " + "CREP %u\n", + __LINE__, + frame_id, + p_ar->arep, + p_ar->iocrs[ix].crep); } else { diff --git a/src/device/pf_cmdev.h b/src/device/pf_cmdev.h index f59f7c46..662e0a79 100644 --- a/src/device/pf_cmdev.h +++ b/src/device/pf_cmdev.h @@ -261,7 +261,8 @@ int pf_cmdev_get_diag_item ( pf_diag_item_t ** pp_item); /** - * Allocate a new diag item entry (already cleared) from the free list. + * Allocate a new diag item entry from the free list. + * The entry is also cleared. * @param net InOut: The p-net stack instance * @param p_item_ix Out: Index of the allocated item. * @return 0 If an item was allocated. @@ -376,7 +377,7 @@ int pf_cmdev_cmio_info_ind (pnet_t * net, pf_ar_t * p_ar, bool data_possible); * Handle an RPC connect request. * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param p_connect_result Out: Detailed result of the connect operation. + * @param p_connect_result Out: Detailed error information if return != 0; * @return 0 if operation succeeded. * -1 if an error occurred. */ @@ -393,7 +394,7 @@ int pf_cmdev_rm_connect_ind ( * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param p_release_result Out: Detailed result of the connect operation. + * @param p_release_result Out: Detailed error information if return != 0; * @return 0 if operation succeeded. * -1 if an error occurred. */ @@ -450,7 +451,7 @@ int pf_cmdev_cm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar); * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. * @param p_control_io In: The control block. - * @param p_ccontrol_result Out: Detailed result of the connect operation. + * @param p_ccontrol_result InOut: Detailed error information if return != 0. * @return 0 if operation succeeded. * -1 if an error occurred. */ diff --git a/src/device/pf_cmio.c b/src/device/pf_cmio.c index 1ca745f1..133d1a77 100644 --- a/src/device/pf_cmio.c +++ b/src/device/pf_cmio.c @@ -90,9 +90,10 @@ static void pf_cmio_set_state (pf_ar_t * p_ar, pf_cmio_state_values_t state) { LOG_DEBUG ( PNET_LOG, - "CMIO(%d): New state %s\n", + "CMIO(%d): New state %s for AREP: %u\n", __LINE__, - pf_cmio_state_to_string (state)); + pf_cmio_state_to_string (state), + p_ar->arep); p_ar->cmio_state = state; } } @@ -163,10 +164,11 @@ int pf_cmio_cmdev_state_ind ( LOG_DEBUG ( PNET_LOG, - "CMIO(%d): Received event %s from CMDEV. Our state %s.\n", + "CMIO(%d): Received event %s from CMDEV. Our state %s. AREP %u\n", __LINE__, pf_cmdev_event_to_string (event), - pf_cmio_state_to_string (p_ar->cmio_state)); + pf_cmio_state_to_string (p_ar->cmio_state), + p_ar->arep); switch (p_ar->cmio_state) { @@ -300,10 +302,11 @@ int pf_cmio_cpm_state_ind ( { LOG_INFO ( PNET_LOG, - "CMIO(%d): CPM state change. CMIO state is WDATA. crep: %u, CPM " - "start=%s\n", + "CMIO(%d): CPM state change. CMIO state is WDATA. CREP: %u " + "AREP: %u CPM start=%s\n", __LINE__, crep, + p_ar->arep, start ? "true" : "false"); } p_ar->iocrs[crep].cpm.cmio_start = start; @@ -318,10 +321,11 @@ int pf_cmio_cpm_state_ind ( { LOG_INFO ( PNET_LOG, - "CMIO(%d): CPM is stopping. CMIO state is DATA. Aborting. crep: " - "%u\n", + "CMIO(%d): CPM is stopping. CMIO state is DATA. Aborting. CREP: " + "%u AREP: %u\n", __LINE__, - crep); + crep, + p_ar->arep); /* if (crep != crep.mcpm) not possible - handled elsewhere */ (void)pf_cmdev_state_ind (net, p_ar, PNET_EVENT_ABORT); @@ -350,9 +354,11 @@ int pf_cmio_cpm_new_data_ind (pf_ar_t * p_ar, uint16_t crep, bool new_data) { LOG_DEBUG ( PNET_LOG, - "CMIO(%d): New data ind from CPM. (crep=%u) new_data=%s\n", + "CMIO(%d): New data ind from CPM. CREP: %u AREP: %u " + "new_data=%s\n", __LINE__, crep, + p_ar->arep, new_data ? "true" : "false"); } diff --git a/src/device/pf_cmpbe.c b/src/device/pf_cmpbe.c index 0c2683ef..3eb11905 100644 --- a/src/device/pf_cmpbe.c +++ b/src/device/pf_cmpbe.c @@ -13,6 +13,13 @@ * full license information. ********************************************************************/ +/** + * @file + * @brief Implements the Parameter Begin End Protocol Machine (PBE) + * + * Disables and enables alarm sending. + */ + #ifdef UNIT_TEST #endif @@ -131,9 +138,11 @@ int pf_cmpbe_rm_dcontrol_ind ( LOG_DEBUG ( PNET_LOG, - "CMPBE(%d): dcontrol %x in state %s\n", + "CMPBE(%d): Received DControl command bitfield 0x%04x for AREP %u " + "in state %s\n", __LINE__, p_control_io->control_command, + p_ar->arep, pf_cmpbe_state_to_string (p_ar->cmpbe_state)); switch (p_ar->cmpbe_state) { diff --git a/src/device/pf_cmpbe.h b/src/device/pf_cmpbe.h index 9cab52f3..47e2a3ae 100644 --- a/src/device/pf_cmpbe.h +++ b/src/device/pf_cmpbe.h @@ -49,7 +49,7 @@ int pf_cmpbe_cm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar); * Handle a CControl confirmation for a specific AR. * @param p_ar InOut: The AR instance. * @param p_control_io In: The CControl block. - * @param p_result Out: The result information. + * @param p_result Out: The result information. Not used. * @return 0 if the operation succeeded. * -1 if an error occurred. */ diff --git a/src/device/pf_cmrpc.c b/src/device/pf_cmrpc.c index d54a89d6..99a5ba1a 100644 --- a/src/device/pf_cmrpc.c +++ b/src/device/pf_cmrpc.c @@ -675,7 +675,12 @@ static int pf_ar_allocate (pnet_t * net, pf_ar_t ** pp_ar) if (ix < PNET_MAX_AR) { net->cmrpc_ar[ix].arep = ix + 1; /* Avoid AREP == 0 */ - LOG_DEBUG (PF_RPC_LOG, "CMRPC(%d): Allocate AR %u\n", __LINE__, ix); + LOG_DEBUG ( + PF_RPC_LOG, + "CMRPC(%d): Allocate AR %u (AREP %u)\n", + __LINE__, + ix, + net->cmrpc_ar[ix].arep); } return ret; @@ -694,9 +699,10 @@ static void pf_ar_release (pf_ar_t * p_ar) { LOG_DEBUG ( PF_RPC_LOG, - "CMRPC(%d): Free AR %u\n", + "CMRPC(%d): Free AR %u (AREP %u)\n", __LINE__, - p_ar->arep - 1); + p_ar->arep - 1, + p_ar->arep); memset (p_ar, 0, sizeof (*p_ar)); } else @@ -1020,7 +1026,8 @@ static void pf_cmrpc_send_with_timeout ( { LOG_ERROR ( PF_RPC_LOG, - "CMRPC(%d): pf_scheduler_add failed for response fragment\n", + "CMRPC(%d): pf_scheduler_add failed for " + "pf_cmrpc_send_with_timeout()\n", __LINE__); } } @@ -1177,7 +1184,8 @@ static int pf_cmrpc_rm_connect_interpret_ind ( LOG_DEBUG ( PF_RPC_LOG, "CMRPC(%d): Requested start up mode: \"%s\" Initiator " - "station name: \"%s\" port: 0x%04x Timeout: %u x 100 ms\n", + "station name: \"%s\" UDP port: 0x%04x Timeout: " + "%u x 100 ms\n", __LINE__, p_ar->ar_param.ar_properties.startup_mode ? "Advanced" : "Legacy", @@ -1192,14 +1200,19 @@ static int pf_cmrpc_rm_connect_interpret_ind ( LOG_DEBUG ( PF_RPC_LOG, - "CMRPC(%d): Requested send cycle time %u (in 1/32 of millisec) " - "Reduction ratio:%u Watchdog factor:%" PRIu32 - " Data hold factor:%u\n", + "CMRPC(%d): Requested send cycle time: %u (in 1/32 of millisec) " + "AREP %u CREP %u %6s Reduction ratio: %u Watchdog factor: " + "%" PRIu32 " Data hold factor: %u FrameID: 0x%04x\n", __LINE__, p_ar->iocrs[p_ar->nbr_iocrs].param.send_clock_factor, + p_ar->arep, + p_ar->nbr_iocrs, + pf_iocr_type_to_string ( + p_ar->iocrs[p_ar->nbr_iocrs].param.iocr_type), p_ar->iocrs[p_ar->nbr_iocrs].param.reduction_ratio, p_ar->iocrs[p_ar->nbr_iocrs].param.watchdog_factor, - p_ar->iocrs[p_ar->nbr_iocrs].param.data_hold_factor); + p_ar->iocrs[p_ar->nbr_iocrs].param.data_hold_factor, + p_ar->iocrs[p_ar->nbr_iocrs].param.frame_id); /* Count the types for error discovery */ if (p_ar->iocrs[p_ar->nbr_iocrs].param.iocr_type == PF_IOCR_TYPE_INPUT) @@ -1509,6 +1522,17 @@ static int pf_cmrpc_rm_connect_interpret_ind ( first_block = false; } + LOG_DEBUG ( + PF_RPC_LOG, + "CMRPC(%d): Connect request AR param: %u CR: %u Input: %u Output: %u " + "Alarm: %u\n", + __LINE__, + p_ar->nbr_ar_param, + p_ar->nbr_iocrs, + p_ar->input_cr_cnt, + p_ar->output_cr_cnt, + p_ar->nbr_alarm_cr); + if (ret == 0) { /* Error discovery. */ @@ -1760,7 +1784,7 @@ static void pf_cmrpc_rm_connect_rsp ( * * @param net InOut: The p-net stack instance * @param p_sess InOut: The session instance. Will be released on - * error. + * error. * @param req_pos In: Position in the request buffer. * @param res_size In: The size of the response buffer. * @param p_res Out: The response buffer. @@ -1886,8 +1910,9 @@ static int pf_cmrpc_rm_connect_ind ( /** * @internal * Parse all blocks in a release RPC request. - * @param p_sess InOut:The RPC session instance. - * @param req_pos In: Position in the request buffer. + * @param p_sess InOut: The RPC session instance. The rpc_result + * field is written when return != 0. + * @param req_pos In: Position in the request buffer. * @param p_release_io Out: The release control block. * @return 0 if operation succeeded. * -1 if an error occurred. @@ -2174,6 +2199,11 @@ static int pf_cmrpc_rm_release_ind ( (pf_ar_find_by_uuid (net, &release_io.ar_uuid, &p_ar) == 0) && (release_io.session_key == p_ar->ar_param.session_key)) { + LOG_DEBUG ( + PF_RPC_LOG, + "CMRPC(%d): Releasing for AREP %u\n", + __LINE__, + p_ar->arep); /* Overwrite response with correct AR UUID etc */ pf_cmrpc_rm_release_rsp ( p_sess, @@ -2839,7 +2869,7 @@ static int pf_cmrpc_rm_read_ind ( /** * @internal - * Take a DCE RPC EPM LOOKUP request and create a response. + * Take a DCE RPC EPM LOOKUP request and create a response. * No callbacks or updates of configuration is triggered * * @param net InOut: The p-net stack instance @@ -3632,9 +3662,10 @@ int pf_cmrpc_rm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar) /* NOT a fragmented request - all fits into send buffer */ LOG_DEBUG ( PF_RPC_LOG, - "CMRPC(%d): Send CControl request, total %u bytes (not " + "CMRPC(%d): Send CControl request for AREP %u, total %u bytes (not " "fragmented).\n", __LINE__, + p_ar->arep, p_sess->out_buf_len); p_sess->out_buf_send_len = p_sess->out_buf_len; } @@ -3643,9 +3674,10 @@ int pf_cmrpc_rm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar) /* We need to send a fragmented answer - Send the first fragment now */ LOG_DEBUG ( PF_RPC_LOG, - "CMRPC(%d): Send fragmented CControl request, total %u, max per " - "frame %u bytes.\n", + "CMRPC(%d): Send fragmented CControl request AREP %u, total %u, " + "max per frame %u bytes.\n", __LINE__, + p_ar->arep, p_sess->out_buf_len, max_req_len); p_sess->out_buf_send_len = max_req_len; /* This is what is sent in the @@ -3724,7 +3756,8 @@ int pf_cmrpc_rm_ccontrol_req (pnet_t * net, pf_ar_t * p_ar) /** * @internal * Parse all blocks in a CControl RPC response message. - * @param p_sess InOut: The session instance. + * @param p_sess InOut: The session instance. The rpc_result field is + * set if return != 0. * @param req_pos In: The position in the input buffer. * @param p_control_io Out: The CControl control block. * @return 0 if operation succeeded. @@ -3870,7 +3903,10 @@ static int pf_cmrpc_rm_ccontrol_cnf ( pf_control_block_t ccontrol_io; pf_ar_t * p_ar = p_sess->p_ar; - LOG_INFO (PF_RPC_LOG, "Incoming CCONTROL response via DCE RPC on UDP\n"); + LOG_INFO ( + PF_RPC_LOG, + "CMRPC(%d): Incoming CCONTROL response via DCE RPC on UDP\n", + __LINE__); CC_ASSERT (p_ar != NULL); memset (&ccontrol_io, 0, sizeof (ccontrol_io)); @@ -3902,12 +3938,18 @@ static int pf_cmrpc_rm_ccontrol_cnf ( } else { - LOG_DEBUG (PF_RPC_LOG, "CMRPC(%d): \n", __LINE__); + LOG_DEBUG ( + PF_RPC_LOG, + "CMRPC(%d): pf_cmpbe_rm_ccontrol_cnf() failed.\n", + __LINE__); } } else { - LOG_DEBUG (PF_RPC_LOG, "CMRPC(%d): \n", __LINE__); + LOG_DEBUG ( + PF_RPC_LOG, + "CMRPC(%d): pf_cmdev_rm_ccontrol_cnf() failed.\n", + __LINE__); } } else diff --git a/src/device/pf_cmsm.c b/src/device/pf_cmsm.c index 80d3fd9c..74cc139d 100644 --- a/src/device/pf_cmsm.c +++ b/src/device/pf_cmsm.c @@ -167,10 +167,11 @@ int pf_cmsm_cmdev_state_ind ( LOG_DEBUG ( PNET_LOG, - "CMSM(%d): Received event %s from CMDEV. Our state %s.\n", + "CMSM(%d): Received event %s from CMDEV. Our state %s. AREP %u\n", __LINE__, pf_cmdev_event_to_string (event), - pf_cmsm_state_to_string (p_ar->cmsm_state)); + pf_cmsm_state_to_string (p_ar->cmsm_state), + p_ar->arep); switch (p_ar->cmsm_state) { @@ -213,7 +214,11 @@ int pf_cmsm_cmdev_state_ind ( case PNET_EVENT_ABORT: if (p_ar->cmsm_timer != UINT32_MAX) { - LOG_DEBUG (PNET_LOG, "CMSM(%d): Stopping timer.\n", __LINE__); + LOG_DEBUG ( + PNET_LOG, + "CMSM(%d): Stopping communication start-up timer. AREP %u\n", + __LINE__, + p_ar->arep); pf_scheduler_remove (net, cmsm_sync_name, p_ar->cmsm_timer); p_ar->cmsm_timer = UINT32_MAX; /* unused */ } diff --git a/src/device/pf_cmsu.h b/src/device/pf_cmsu.h index 4c5f6f34..3f53d1e4 100644 --- a/src/device/pf_cmsu.h +++ b/src/device/pf_cmsu.h @@ -47,7 +47,9 @@ int pf_cmsu_cmdev_state_ind ( * Start all state machines for a specific AR. * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param p_stat Out: The result information. + * @param p_stat Out: Detailed error info if returning != 0 + * Note that only the fields error_code_1 and + * error_code_2 are set. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -55,10 +57,13 @@ int pf_cmsu_start_req (pnet_t * net, pf_ar_t * p_ar, pnet_result_t * p_stat); /** * Handle CPM error indications for a specific AR. + * + * Closes the AR with PNET_EVENT_ABORT + * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param err_cls In: ERR_CLS. - * @param err_code In: ERR_CODE. + * @param err_cls In: ERR_CLS. ErrorCode1. + * @param err_code In: ERR_CODE. ErrorCode2. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -70,10 +75,13 @@ int pf_cmsu_cpm_error_ind ( /** * Handle PPM error indications for a specific AR. + * + * Closes the AR with PNET_EVENT_ABORT + * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param err_cls In: ERR_CLS. - * @param err_code In: ERR_CODE. + * @param err_cls In: ERR_CLS. ErrorCode1. + * @param err_code In: ERR_CODE. ErrorCode2. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -85,10 +93,13 @@ int pf_cmsu_ppm_error_ind ( /** * Handle alarm error indications for a specific AR. + * + * Closes the AR with PNET_EVENT_ABORT + * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param err_cls In: ERR_CLS. - * @param err_code In: ERR_CODE + * @param err_cls In: ERR_CLS. ErrorCode1. + * @param err_code In: ERR_CODE. ErrorCode2. * @return 0 if the operation succeeded. * -1 if an error occurred. */ @@ -101,10 +112,13 @@ int pf_cmsu_alarm_error_ind ( /* Not used */ /** * Handle DMC error indications for a specific AR. + * + * Closes the AR with PNET_EVENT_ABORT + * * @param net InOut: The p-net stack instance * @param p_ar InOut: The AR instance. - * @param err_cls In: ERR_CLS - * @param err_code In: ERR_CODE + * @param err_cls In: ERR_CLS. ErrorCode1. + * @param err_code In: ERR_CODE. ErrorCode2. * @return 0 if the operation succeeded. * -1 if an error occurred. */ diff --git a/src/device/pf_cmwrr.c b/src/device/pf_cmwrr.c index 38a318de..341b72d9 100644 --- a/src/device/pf_cmwrr.c +++ b/src/device/pf_cmwrr.c @@ -135,12 +135,12 @@ int pf_cmwrr_cmdev_state_ind ( * Triggers the \a pnet_write_ind() user callback for some values. * * @param net InOut: The p-net stack instance - * @param p_ar In: The AR instance. - * @param p_write_request In: The IODWrite request. - * @param p_req_buf In: The request buffer. - * @param data_length In: Size of the data to write. - * @param p_req_pos InOut:Position within the request buffer. - * @param p_result Out: Detailed error information. + * @param p_ar In: The AR instance. + * @param p_write_request In: The IODWrite request. + * @param p_req_buf In: The request buffer. + * @param data_length In: Size of the data to write. + * @param p_req_pos InOut: Position within the request buffer. + * @param p_result Out: Detailed error information if returning != 0 * @return 0 if operation succeeded. * -1 if an error occurred. */ @@ -235,12 +235,18 @@ static int pf_cmwrr_write ( { LOG_INFO ( PNET_LOG, - "CMRSR(%d): Could not write index 0x%04X for slot %u subslot " - "0x%04X.\n", + "CMRWRR(%d): Could not write index 0x%04X for slot %u subslot " + "0x%04X. Error 0x%02X %02X %02X %02X Add %u %u\n", __LINE__, p_write_request->index, p_write_request->slot_number, - p_write_request->subslot_number); + p_write_request->subslot_number, + p_result->pnio_status.error_code, + p_result->pnio_status.error_decode, + p_result->pnio_status.error_code_1, + p_result->pnio_status.error_code_2, + p_result->add_data_1, + p_result->add_data_2); } return ret; } @@ -251,9 +257,9 @@ int pf_cmwrr_rm_write_ind ( const pf_iod_write_request_t * p_write_request, pf_iod_write_result_t * p_write_result, pnet_result_t * p_result, - const uint8_t * p_req_buf, /* request buffer */ + const uint8_t * p_req_buf, uint16_t data_length, - uint16_t * p_req_pos) /* In/out: position in request buffer */ + uint16_t * p_req_pos) { int ret = -1; diff --git a/src/device/pf_cmwrr.h b/src/device/pf_cmwrr.h index 1d3b61db..cdc22244 100644 --- a/src/device/pf_cmwrr.h +++ b/src/device/pf_cmwrr.h @@ -56,7 +56,7 @@ int pf_cmwrr_cmdev_state_ind ( * @param p_ar InOut: The AR instance. * @param p_write_request In: The write request block. * @param p_write_result Out: The write result block. - * @param p_result Out: The result codes. + * @param p_result Out: Detailed error information if returning != 0 * @param p_req_buf In: The RPC request buffer. * @param data_length In: The length of the data to write. * @param p_req_pos In: Position in p_req_buf. diff --git a/src/device/pf_fspm.c b/src/device/pf_fspm.c index 9864a771..edfad622 100644 --- a/src/device/pf_fspm.c +++ b/src/device/pf_fspm.c @@ -496,9 +496,15 @@ void pf_fspm_create_log_book_entry ( LOG_DEBUG ( PNET_LOG, - "FSPM(%d): Added logbook entry to position %u\n", + "FSPM(%d): Added logbook entry to position %u. Error: " + "0x%02X 0x%02X 0x%02X 0x%02X Detail: %" PRIu32 "\n", __LINE__, - put); + put, + p_pnio_status->error_code, + p_pnio_status->error_decode, + p_pnio_status->error_code_1, + p_pnio_status->error_code_2, + entry_detail); } } @@ -1171,9 +1177,10 @@ void pf_fspm_state_ind ( LOG_DEBUG ( PNET_LOG, - "FSPM(%d): Triggering user state-change callback with %s\n", + "FSPM(%d): Triggering user state-change callback with %s for AREP %u\n", __LINE__, - pf_cmdev_event_to_string (event)); + pf_cmdev_event_to_string (event), + p_ar->arep); if (net->fspm_cfg.state_cb != NULL) { diff --git a/src/device/pf_fspm.h b/src/device/pf_fspm.h index 72d7aa13..856eff5f 100644 --- a/src/device/pf_fspm.h +++ b/src/device/pf_fspm.h @@ -72,14 +72,14 @@ void pf_fspm_create_log_book_entry ( * If index indicates I&M data records then handle here. * * If index is user-defined then call application - * call-back \a pnet_write_ind() (if defined). + * call-back \a pnet_write_ind() if defined. * * @param net InOut: The p-net stack instance * @param p_ar In: The AR instance. * @param p_write_request In: The write request record. * @param write_length In: Length in bytes of write data. * @param p_write_data In: The data to write. - * @param p_result Out: Result informantion. + * @param p_result Out: Detailed error information if returning != 0 * @return 0 if operation succeeded. * -1 if an error occurred. */ @@ -96,11 +96,12 @@ int pf_fspm_cm_write_ind ( * Triggers the \a pnet_read_ind() user callback for some values. * * @param net InOut: The p-net stack instance - * @param p_ar In: The AR instance. - * @param p_read_request In: The read request record. - * @param pp_read_data Out: A pointer to the source data. - * @param p_read_length Out: Size of the source data. - * @param p_result Out: The result information. + * @param p_ar In: The AR instance. + * @param p_read_request In: The read request record. + * @param pp_read_data Out: A pointer to the source data. + * @param p_read_length InOut: The maximum (in) and actual (out) length in + * bytes of the binary value. + * @param p_result Out: The result information. * @return 0 if operation succeeded. * -1 if not handled or an error occurred. */ @@ -129,8 +130,8 @@ void pf_fspm_ccontrol_cnf ( /** * Call user call-back \a pnet_connect_ind() when a new connection is requested. * @param net InOut: The p-net stack instance - * @param p_ar In: The AR instance. - * @param p_result Out: The result information. + * @param p_ar In: The AR instance. + * @param p_result Out: The result information if return != 0. * @return 0 if operation succeeded. * -1 if an error occurred. */ @@ -142,8 +143,8 @@ int pf_fspm_cm_connect_ind ( /** * Call user call-back \a pnet_release_ind() when a connection is released. * @param net InOut: The p-net stack instance - * @param p_ar In: The AR instance. - * @param p_result Out: The result information. + * @param p_ar In: The AR instance. + * @param p_result Out: Detailed error information if return != 0. * @return 0 if operation succeeded. * -1 if an error occurred. */ @@ -155,6 +156,9 @@ int pf_fspm_cm_release_ind ( /** * Call user call-back \a pnet_dcontrol_ind() to indicate a control request * from the ProfiNet controller. + * + * Create a logbook entry. + * * @param net InOut: The p-net stack instance * @param p_ar In: The AR instance. * @param control_command In: The control command. diff --git a/src/device/pnet_api.c b/src/device/pnet_api.c index 2c11442c..4723a747 100644 --- a/src/device/pnet_api.c +++ b/src/device/pnet_api.c @@ -290,6 +290,12 @@ int pnet_set_primary_state (pnet_t * net, bool primary) uint16_t cr_ix; pf_ar_t * p_ar = NULL; + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application sets primary state to %d\n", + __LINE__, + primary); + for (ar_ix = 0; ar_ix < PNET_MAX_AR; ar_ix++) { p_ar = pf_ar_find_by_index (net, ar_ix); @@ -315,6 +321,12 @@ int pnet_set_redundancy_state (pnet_t * net, bool redundant) uint16_t cr_ix; pf_ar_t * p_ar = NULL; + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application sets redundancy state to %d\n", + __LINE__, + redundant); + for (ar_ix = 0; ar_ix < PNET_MAX_AR; ar_ix++) { p_ar = pf_ar_find_by_index (net, ar_ix); @@ -340,6 +352,12 @@ int pnet_set_provider_state (pnet_t * net, bool run) uint16_t cr_ix; pf_ar_t * p_ar = NULL; + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application sets provider state to %d\n", + __LINE__, + run); + for (ar_ix = 0; ar_ix < PNET_MAX_AR; ar_ix++) { p_ar = pf_ar_find_by_index (net, ar_ix); @@ -363,6 +381,12 @@ int pnet_application_ready (pnet_t * net, uint32_t arep) int ret = -1; pf_ar_t * p_ar = NULL; + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application calls application ready for AREP %u\n", + __LINE__, + arep); + if (pf_ar_find_by_arep (net, arep, &p_ar) == 0) { ret = pf_cmdev_cm_ccontrol_req (net, p_ar); @@ -376,6 +400,12 @@ int pnet_ar_abort (pnet_t * net, uint32_t arep) int ret = -1; pf_ar_t * p_ar = NULL; + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application calls AR abort for AREP %u\n", + __LINE__, + arep); + if (pf_ar_find_by_arep (net, arep, &p_ar) == 0) { ret = pf_cmdev_cm_abort (net, p_ar); @@ -389,6 +419,8 @@ int pnet_factory_reset (pnet_t * net) uint16_t ix; pf_ar_t * p_ar = NULL; + LOG_DEBUG (PNET_LOG, "API(%d): Application calls factory reset.\n", __LINE__); + /* Look for active connections */ for (ix = 0; ix < PNET_MAX_AR; ix++) { @@ -407,6 +439,12 @@ int pnet_factory_reset (pnet_t * net) int pnet_remove_data_files (const char * file_directory) { + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application removes data files in %s\n", + __LINE__, + file_directory); + return pf_cmina_remove_all_data_files (file_directory); } @@ -468,6 +506,13 @@ int pnet_alarm_send_ack ( int ret = -1; pf_ar_t * p_ar = NULL; + LOG_DEBUG ( + PNET_LOG, + "API(%d): Application sends alarm ack for slot %u subslot 0x%04x.\n", + __LINE__, + p_alarm_argument->slot_nbr, + p_alarm_argument->subslot_nbr); + if (pf_ar_find_by_arep (net, arep, &p_ar) == 0) { ret = diff --git a/src/pf_types.h b/src/pf_types.h index 99f52a77..fe817d66 100644 --- a/src/pf_types.h +++ b/src/pf_types.h @@ -1297,9 +1297,8 @@ typedef struct pf_ar_properties uint16_t companion_ar; /** pf_companion_ar_values_t */ bool acknowledge_companion_ar; /** whether companion_ar is needed */ bool combined_object_container; /** See IEC61158-6-10 */ - bool startup_mode; /** false: legacy (do not use), true: advanced */ - bool pull_module_alarm_allowed; /** false: mandatory support, true: optional - */ + bool startup_mode; /** false: legacy, true: advanced */ + bool pull_module_alarm_allowed; /** false: mandatory, true: optional */ } pf_ar_properties_t; typedef struct pf_ar_param @@ -1443,7 +1442,7 @@ typedef struct pf_submodule_state bool maintenance_demanded; /** Bit 5 */ bool fault; /** Bit 6 */ uint8_t ar_info; /** Bits 7..10: pf_submod_ar_info_t */ - uint8_t ident_info; /** Bits 11..14: pf_ident_info_values_t */ + uint8_t ident_info; /** Bits 11..14: pf_submod_plug_state_t */ bool format_indicator; /** Bit 15: Always 1 (true) */ } pf_submodule_state_t; @@ -1738,9 +1737,11 @@ typedef struct pf_iodata_object /* Individual sub-slot data */ uint16_t data_offset; uint16_t data_length; + /* The provider status */ uint16_t iops_offset; uint16_t iops_length; + /* The consumer status */ uint16_t iocs_offset; uint16_t iocs_length; @@ -1850,13 +1851,14 @@ typedef struct pf_apmx uint16_t exp_seq_count; uint16_t exp_seq_count_o; - /* The receive queue */ + /* The receive queue (mailbox, contains pointers to messages) */ os_mbox_t * p_alarm_q; - /* The messages sent via the mailbox */ + + /* The actual incoming messages handled in the receive queue (mailbox) */ pf_apmr_msg_t apmr_msg[PNET_MAX_ALARMS]; uint16_t apmr_msg_nbr; - /* Latest sent alarm */ + /* Latest sent alarm, for possible retransmission */ pnal_buf_t * p_rta; bool high_priority; /* True for high priority APMX. For printouts. */ @@ -2019,8 +2021,8 @@ typedef struct pf_ar pf_ar_rpc_request_t ar_rpc_request; /* From connect.req */ pf_ar_rpc_result_t ar_rpc_result; /* From connect.ind */ - uint16_t nbr_iocrs; /* From connect.req */ - pf_iocr_t iocrs[PNET_MAX_CR]; + uint16_t nbr_iocrs; /* From connect.req */ + pf_iocr_t iocrs[PNET_MAX_CR]; /* Each has a CPM and a PPM */ uint16_t nbr_exp_apis; pf_exp_api_t exp_apis[PNET_MAX_API]; /* From connect.req */ @@ -2045,8 +2047,8 @@ typedef struct pf_ar bool ready_4_data; /* Global error codes */ - uint8_t err_cls; - uint8_t err_code; + uint8_t err_cls; /* Error code 1 */ + uint8_t err_code; /* Error code 2 */ pf_cmsm_state_values_t cmsm_state; uint32_t cmsm_timer; diff --git a/src/pnal.h b/src/pnal.h index 595c9516..ab776d6a 100644 --- a/src/pnal.h +++ b/src/pnal.h @@ -165,7 +165,7 @@ typedef struct pnal_eth_status_t /* Is autonegotiation supported on this port? */ bool is_autonegotiation_enabled; - /* Capabilites advertised to link partner during autonegotiation. + /* Capabilities advertised to link partner during autonegotiation. * * See macros PNAL_ETH_AUTONEG_CAP_xxx. */