소스 검색

Improve documentation week 22

Renamed "typedef enum pnet_im_supported_value" to pnet_im_supported_values.
The more important pnet_im_supported_values_t is not modified.
Jonas Berg 3 년 전
부모
커밋
8a95b587cd

+ 3 - 0
doc/api_documentation.rst

@@ -113,6 +113,9 @@ Selected enums
 .. doxygenenum:: pnet_diag_ch_prop_type_values
 .. doxygenenum:: pnet_diag_ch_prop_dir_values
 .. doxygenenum:: pnet_diag_ch_prop_maint_values
+.. doxygenenum:: pnet_diag_ch_group_values
+.. doxygenenum:: pnet_im_supported_values
+.. doxygenenum:: pnal_eth_mau
 
 
 Selected structs

+ 4 - 4
doc/codesys_details.rst

@@ -139,10 +139,10 @@ parameter.
 Forcing cyclic data values
 --------------------------
 To force an output value from the PLC, open the PLC_PRG window while online.
-Double-click on the value you would like to change, to open the "Prepare value" pop-up.
-Click the "Prepare a new value ..." radio button, and enter the new numerical value in the textbox.
-Click "OK". Right-click the value again, and select "Force all values ...".
-The new value is sent from the PLC to the IO-device. A red "F" symbol is shown.
+In the table on the top of the page, on the line you would like to force click the "Prepared value"
+until it shows "TRUE". Use the line "out_pin_LED" if running the sample application.
+Right-click on the line, and select "Force all values ...". The new value is sent from the PLC to the IO-device.
+A red `F` symbol is shown.
 To stop forcing the value, right-click it and select "Unforce all values ...".
 
 

+ 6 - 0
doc/compliancetest.rst

@@ -903,3 +903,9 @@ scenario, make sure that your alarm input queue can hold at least that number.
 If there are problems in test case Behavior scenario 10 regarding reading and
 writing via SNMP after power cycling, verify that there is proper connection to
 the SNMP daemon immediately at startup.
+
+If you get the error "Device did answer ping request although it shouldn't", the device is probably not powered
+off during the test as required. Make sure your device is not powered via some USB cable, for example.
+
+If the Alarm test case fails with the message "No valid Transport ACK on the Alarm ACK was received",
+then the Ethernet receieve task might have too low priority.

+ 70 - 19
doc/creating_gsdml_files.rst

@@ -3,6 +3,10 @@ Creating GSD (GSDML) files
 A GSD (General Station Description) file is an XML file describing a
 Profinet IO-Device. The XML-based language is called GSDML (GSD Markup Language).
 
+A single GSDML file describes a single VendorID and ProductID combination.
+A family of devices can be described in the same file; Then they will share
+the ProductID but have different DAP (head module) ID values.
+
 For Profinet members, the "Profinet GSD Checker" tool is available for
 download. It contains GSD example files showing different aspects of the file
 format.
@@ -125,14 +129,16 @@ The GSD files are structured like::
           +--ChannelDiagList
           +--ChannelProcessAlarmList
           +--UnitDiagTypeList
+          +--GraphicsList
           +--ExternalTextList
 
+The encoding is given in the first line of the XML file. Use ``utf-8`` if using non-ASCII characters in any of the text fields.
 Do not change the ``<ProfileHeader>`` contents.
 
 In the ``<DeviceIdentity>`` adjust the attributes ``VendorID``, ``DeviceID``.
 Adjust the ``Value`` in ``<VendorName>``.
-In the ``<Family>`` adjust the attributes for ``MainFamily`` (typically "I/O")
-and ``ProductFamily``.
+In the ``<Family>`` adjust the attributes for ``MainFamily`` (typically "I/O", should be from the list of allowed values)
+and ``ProductFamily`` which is vendor specific.
 
 Those values are for example used by the engineering tool to display the device
 in the hardware catalog. The catalog is typically sorted by
@@ -192,18 +198,22 @@ DeviceAccessPointList element hierarchy::
            |           +--Ref
            |
            +--SystemDefinedSubmoduleList
+           |  |
+           |  +--InterfaceSubmoduleItem
+           |  |  |
+           |  |  +--ApplicationRelations
+           |  |     |
+           |  |     +--TimingProperties
+           |  |
+           |  +--PortSubmoduleItem
+           |     |
+           |     +--MAUTypeList
+           |        |
+           |        +--MAUTypeItem
+           |
+           +--Graphics
               |
-              +--InterfaceSubmoduleItem
-              |  |
-              |  +--ApplicationRelations
-              |     |
-              |     +--TimingProperties
-              |
-              +--PortSubmoduleItem
-                 |
-                 +--MAUTypeList
-                    |
-                    +--MAUTypeItem
+              +--GraphicItemRef
 
 The ``<DeviceAccessPointItem>`` element has the attributes:
 
@@ -258,8 +268,8 @@ element has the attributes ``SubslotNumber`` and ``TextId``.
 
 The ``<IOConfigData>`` element has the attributes:
 
-* ``MaxInputLength="24"`` Unsigned16.
-* ``MaxOutputLength="24"`` Unsigned16.
+* ``MaxInputLength="24"`` Unsigned16, valid 0..1440
+* ``MaxOutputLength="24"`` Unsigned16, valid 0..1440
 * ``MaxDataLength="40"`` Defaults to MaxInputLength + MaxOutputLength. Unsigned16.
 
 The values are in bytes and are for all submodules. For details on how to
@@ -285,6 +295,7 @@ One specific detail for a DAP virtual submodule is that it has the
 ``Writeable_IM_Records="1 2 3"`` attribute, which informs about writable
 Identification & Maintenance (I&M) records. Note that record 0 and 5 are
 read only, so they should never appear in this list.
+You must support writing to I&M1-3 for at least one of the DAP submodules.
 
 Other special submodules for DAP modules are ``<InterfaceSubmoduleItem>`` and
 ``<PortSubmoduleItem>``, both subelements to ``<SystemDefinedSubmoduleList>``.
@@ -324,13 +335,13 @@ it is possible to set the attributes ``NumberOfAdditionalInputCR``,
 ``NumberOfAdditionalOutputCR``, ``NumberOfAdditionalMulticastProviderCR`` and
 ``NumberOfMulticastConsumerCR``. Those attributes are not supported by p-net.
 
-Use the ``<TimingProperties>`` element to define the sending of cyclic IO data.
+The ``<TimingProperties>`` element describes the sending of cyclic IO data.
 The ``SendClock`` attribute contains a list of all supported send cycle times,
 in units of 31.25 us. Defaults to "32", which corresponds to 1 ms. Note that the
 list must contain the value ``32``.
-(See also the ``MinDeviceInterval`` attribute in another element).
 The attribute ``ReductionRatio`` defines how much the sending can be slowed down,
-and defaults to "1 2 4 8 16 32 64 128 256 512".
+and it seems that it must be “1 2 4 8 16 32 64 128 256 512”.
+The actual speed of the device should be set by the ``MinDeviceInterval`` attribute in another element.
 
 Ethernet port properties are descried using the ``<PortSubmoduleItem>``, which
 has these attributes:
@@ -346,6 +357,10 @@ Use an ``<MAUTypeItem>`` element to describe the Medium Attachment Unit type,
 which can be radio (0), copper at 100 Mbit/s (16), copper at 1000 Mbit/s (30)
 or fiber optics etc.
 
+With the ``<GraphicItemRef>`` element it is possible to add a logo or other symbol
+to your device. It will appear in the engineering tool. Use a file in the .BMP file format.
+The attribute ``Type`` should typically be ``DeviceSymbol``, and the ``GraphicItemTarget``
+is a reference to the file name given in the ``<GraphicsList>`` (see below).
 
 Additional ports
 ----------------
@@ -636,9 +651,28 @@ ExternalTextList element hierarchy::
 Within each ``<Text>`` element, the attributes ``TextId`` and ``Value``
 are used to store the information.
 
-Only ``<PrimaryLanguage>`` is mandatory. If ``<Language>`` is given, the actual
+Only ``<PrimaryLanguage>`` is mandatory, and corresponds to English.
+If ``<Language>`` is given, the actual
 language is set by for example a ``xml:lang="fr"`` attribute.
 
+This is how the different text fields are used in engineering tools:
+
+======================= ===================================================================================================================
+Item                    TIA portal and Codesys
+======================= ===================================================================================================================
+DeviceIdentity infotext Unclear?
+DAP module name         Device name in hardware catalog, on icon in network view and in Network overview table. Typically some model name.
+DAP module infotext     Device detailed description in hardware catalog. Use up to a few hundred characters.
+DAP submodule name      Codesys show this in the tree on the Device/IOxS page
+DAP submodule infotext  Unclear?
+InterfaceSubmodule      Interface name
+PortSubmodule           Port name
+Module name             List of plugged modules in Device Overview
+Module infotext         Catalog information in Properties -> General
+Submodule name          Codesys show this in the tree on the Device/IOxS page
+Submodule infotext      Unclear?
+======================= ===================================================================================================================
+
 
 Details on diagnosis
 --------------------
@@ -765,3 +799,20 @@ alarms.
 An extension to system defined process alarms is created by the element
 ``<SystemDefinedChannelProcessAlarmItem>``. Profiles can define process alarms
 using the ``<ProfileChannelProcessAlarmItem>`` element.
+
+
+Details on the graphics list
+---------------------------------
+File names for graphic items are mapped to IDs here.
+
+GraphicsList element hierarchy::
+
+    GraphicsList
+    |
+    +--GraphicItem
+
+
+Within each ``<GraphicItem>`` element, the attributes ``ID`` and ``GraphicFile``
+are used to store the information.
+
+The ``GraphicFile`` is the filename without the BMP file extension.

+ 12 - 1
doc/getting_started_freertos.rst

@@ -1,7 +1,16 @@
 Getting started using STM32Cube / FreeRTOS / lwIP
 =================================================
 
-Install ST-link on your laptop to have access to the serial port of the device.
+This tutorial uses the STM32F769i discovery kit, see
+https://www.st.com/en/evaluation-tools/32f769idiscovery.html
+
+Preparations
+------------
+Run the build on a Linux x86 machine. The build chain uses an ARM cross compiler. Install it::
+
+   sudo apt install gcc-arm-none-eabi
+
+Install ST-link on your Linux machine to have access to the serial port of the device.
 
 
 Cloning STM32Cube firmware
@@ -37,3 +46,5 @@ repository::
 When the build completes you can find the sample-app binary in
 ``build.cube/pn_dev.bin``. Flash this binary to your board by
 uploading it to the USB disk as usual for STM32 boards.
+
+A serial port will also be available via the USB cable.

+ 9 - 0
doc/profinet_basics.rst

@@ -261,6 +261,14 @@ Payload
 -------
 The Profinet payload is sent as big endian (network endian) on the wire.
 
+The maximum data (and status) size in total in each direction for a device is 1440 bytes.
+If this is consumed by a single subslot the maximum data size is 1438 byte (plus one or two bytes for IOPS and IOCS).
+See the IOData entry in the GSDML specification.
+
+If the IOPS (producer status) for a subslot goes to BAD, the PLC will indicate an error
+"User data failure of hardware component".
+It will persist until the communication is restarted to the IO-device.
+
 
 I&M data records
 ----------------
@@ -269,6 +277,7 @@ information about the model type, software version etc.
 Some fields are writable, for example where the device is located.
 
 Up to I&M15 is described in the standard. The p-net stack supports I&M0 - I&M4.
+You must support writing to I&M1-3 for at least one of the DAP submodules.
 
 +-------------+-----------+-----------------------+--------------------------------------------------------------+
 | Data record | Mandatory | Controller can write? | Description                                                  |

+ 5 - 0
doc/spelling_wordlist.txt

@@ -9,6 +9,7 @@ Avahi
 BaseT
 BaseTX
 BaseTXFD
+baudrate
 Bittwist
 Bonjour
 Bool
@@ -18,6 +19,7 @@ breakpoint
 bsp
 bss
 Buildroot
+bumpless
 ccmake
 CControl
 ccontrol
@@ -48,6 +50,7 @@ dropdown
 dut
 DWord
 Einstellung
+endian
 Endian
 endianness
 enums
@@ -58,6 +61,7 @@ eXtended
 Fieldbus
 fieldbuses
 FilterData
+Gbit
 GByte
 gcc
 gdb
@@ -112,6 +116,7 @@ lwip
 lwIP
 makefiles
 Mbit
+MByte
 MIB
 mib
 microcontroller

+ 20 - 20
doc/use_with_siematic.rst

@@ -7,24 +7,6 @@ This have been tested with:
 It uses a 24 V DC supply voltage.
 
 
-Using Siemens SinecPni (Primary Network Initialization)
--------------------------------------------------------
-This is a tool for configuration of Profinet network equipment. Use it
-to adjust the IP address of your PLC.
-
-Download the program from the Siemens homepage, and unzip the file.
-Start the program by double clicking the SinecPni executable.
-
-To be able to change IP address on a Siemens PLC, make sure that the
-"mode switch" on the front panel is in the "STOP" position.
-
-Click the “Settings” tab, and enable “PROFINET devices” for “Scan Protocol”, and
-click “Save”. On the “Device list” tab, click “Start network scan”.
-Select the “S7-1500” line, and click “Configure Device”. Adjust the IP address
-to ``192.168.0.100`` and netmask to ``255.255.255.0``.
-Click “Load” to store the settings.
-
-
 Install Siemens TIA on a Windows PC
 -----------------------------------
 Install TIA (SIMATIC STEP 7 and WinCC) V15.1
@@ -94,7 +76,7 @@ Connect to the Siemens PLC directly via an Ethernet cable to your laptop. For
 the Simatic S7-1200 PLC you can use any of the two X1 RJ45 connectors. Your
 laptop should have a manual IP address in the same subnet range as the PLC
 (first three groups in IP address should be the same). Changing the subnet
-mask size does not seems to have an impact.
+mask size does not seem to have an impact.
 
 In the project view, in the left menu select the PLC and the subitem "Device
 configuration". In the "Properties" tab, use the "General" sub-tab. Select
@@ -211,7 +193,7 @@ In the "Static" section, add:
 In the program part of the window, insert this::
 
    #oscillator_cycles := #oscillator_cycles + 1;
-   IF #oscillator_cycles > 2000 THEN
+   IF #oscillator_cycles > 400 THEN
       #oscillator_cycles := 0;
       #oscillator_state := NOT #oscillator_state;
    END_IF;
@@ -628,6 +610,24 @@ Accept the name of the datablock.
 The result is the same as above.
 
 
+Using Siemens SinecPni (Primary Network Initialization)
+-------------------------------------------------------
+This is a tool for configuration of Profinet network equipment. Use it
+to adjust the IP address of your PLC.
+
+Download the program from the Siemens homepage, and unzip the file.
+Start the program by double clicking the SinecPni executable.
+
+To be able to change IP address on a Siemens PLC, make sure that the
+"mode switch" on the front panel is in the "STOP" position.
+
+Click the “Settings” tab, and enable “PROFINET devices” for “Scan Protocol”, and
+click “Save”. On the “Device list” tab, click “Start network scan”.
+Select the “S7-1500” line, and click “Configure Device”. Adjust the IP address
+to ``192.168.0.100`` and netmask to ``255.255.255.0``.
+Click “Load” to store the settings.
+
+
 Setting up a Simatic HMI
 ------------------------
 This example uses a "HMI KTP400 Basic", which is a 4 inch touch screen.

+ 3 - 0
doc/using_codesys.rst

@@ -65,6 +65,9 @@ tab "Device" and "Send Echo Service" to verify the communication.
 
 In the Codesys menu "Tools", select "Device Repository". Click "Install" and
 select the GSDML file from your hard drive.
+For the sample application the GSDML file is available in the
+sample_app folder in the repository that you have cloned, or
+from https://github.com/rtlabs-com/p-net/tree/master/sample_app
 
 * On the “Device (CODESY Control for Raspberry Pi SL)” in the left hand panel,
   right-click and select Add Device. Use “Ethernet adapter”, “Ethernet”.

+ 142 - 79
include/pnet_api.h

@@ -95,8 +95,10 @@ extern "C" {
 #define PNET_PORT_3 3
 #define PNET_PORT_4 4
 
+/**************************** Error codes ***********************************/
+
 /**
- * # Error Codes
+ * Error Codes
  *
  * The Profinet error code consists of 4 values. The data structure for this is
  * defined in the typedef pnet_pnio_status_t.
@@ -358,35 +360,46 @@ extern "C" {
  */
 #define PNET_ERROR_CODE_2_DCTRL_FAULTY_CONNECT_CONTROLCOMMAND 0x08
 
+/******************************** Events ******************************/
+
 /**
  * The events are sent from CMDEV to the application using the
  * \a pnet_state_ind() call-back function.
  */
 typedef enum pnet_event_values
 {
-   PNET_EVENT_ABORT,   /**< The AR has been closed. */
-   PNET_EVENT_STARTUP, /**< A connection has been initiated. */
-   PNET_EVENT_PRMEND,  /**< Controller has sent all write records. */
-   PNET_EVENT_APPLRDY, /**< Controller has acknowledged the APPL_RDY message */
+   /** The AR has been closed. */
+   PNET_EVENT_ABORT,
+
+   /** A connection has been initiated. */
+   PNET_EVENT_STARTUP,
+
+   /** Controller has sent all write records. */
+   PNET_EVENT_PRMEND,
+
+   /** Controller has acknowledged the APPL_RDY message */
+   PNET_EVENT_APPLRDY,
+
+   /** The cyclic data transmission is now properly set up */
    PNET_EVENT_DATA
 } pnet_event_values_t;
 
 /**
- * Values used for IOCS and IOPS.
+ * Values used for IOCS and IOPS. The actual values are important, as they are
+ * sent on the wire.
  */
 typedef enum pnet_ioxs_values
 {
-   /* Values are important */
    PNET_IOXS_BAD = 0x00,
    PNET_IOXS_GOOD = 0x80
 } pnet_ioxs_values_t;
 
 /**
  * Values used when plugging a sub-module using \a pnet_plug_submodule().
+ * The actual values are important, as they are sent on the wire.
  */
 typedef enum pnet_submodule_dir
 {
-   /* Values are important */
    PNET_DIR_NO_IO = 0x00,
    PNET_DIR_INPUT = 0x01,
    PNET_DIR_OUTPUT = 0x02,
@@ -414,8 +427,11 @@ typedef enum pnet_control_command
    PNET_CONTROL_COMMAND_PRM_END,
    PNET_CONTROL_COMMAND_APP_RDY,
    PNET_CONTROL_COMMAND_RELEASE,
-   /* ToDo: These are not currently implemented */
+
+   /** Not yet implemented */
    PNET_CONTROL_COMMAND_RDY_FOR_COMPANION,
+
+   /** Not yet implemented */
    PNET_CONTROL_COMMAND_RDY_FOR_RTC3,
 } pnet_control_command_t;
 
@@ -425,17 +441,28 @@ typedef enum pnet_control_command
  */
 typedef enum pnet_data_status_bits
 {
-   PNET_DATA_STATUS_BIT_STATE = 0,  /** 0 => BACKUP, 1 => PRIMARY */
-   PNET_DATA_STATUS_BIT_REDUNDANCY, /** Meaning depends on STATE bit */
-   PNET_DATA_STATUS_BIT_DATA_VALID, /** 0 => INVALID, 1 => VALID */
+   /** 0 => BACKUP, 1 => PRIMARY */
+   PNET_DATA_STATUS_BIT_STATE = 0,
+
+   /** Meaning depends on STATE bit */
+   PNET_DATA_STATUS_BIT_REDUNDANCY,
+
+   /** 0 => INVALID, 1 => VALID */
+   PNET_DATA_STATUS_BIT_DATA_VALID,
+
    PNET_DATA_STATUS_BIT_RESERVED_1,
-   PNET_DATA_STATUS_BIT_PROVIDER_STATE,            /** 0 => STOP, 1 => RUN */
-   PNET_DATA_STATUS_BIT_STATION_PROBLEM_INDICATOR, /** 0 => Problem detected, 1
-                                                      => Normal operation */
+
+   /** 0 => STOP, 1 => RUN */
+   PNET_DATA_STATUS_BIT_PROVIDER_STATE,
+
+   /** 0 => Problem detected, 1 => Normal operation */
+   PNET_DATA_STATUS_BIT_STATION_PROBLEM_INDICATOR,
+
    PNET_DATA_STATUS_BIT_RESERVED_2,
-   PNET_DATA_STATUS_BIT_IGNORE /** 0 => Evaluate data status, 1 => Ignore the
-                                  data status (typically used on a frame with
-                                  subframes) */
+
+   /** 0 => Evaluate data status,
+    *  1 => Ignore the data status (typically used on a frame with subframes) */
+   PNET_DATA_STATUS_BIT_IGNORE
 } pnet_data_status_bits_t;
 
 /** Network handle */
@@ -452,10 +479,7 @@ typedef struct pnet_pnio_status
    uint8_t error_code_2;
 } pnet_pnio_status_t;
 
-/*
- * Alarm and Diagnosis
- *
- */
+/************************ Alarm and Diagnosis ********************************/
 
 /** Summary of all diagnosis items, sent in an alarm.
    Only valid for alarms attached to the Diagnosis ASE
@@ -478,6 +502,9 @@ typedef struct pnet_alarm_spec
    bool ar_diagnosis;
 } pnet_alarm_spec_t;
 
+/**
+ * Shows location and summary of diagnosis items in an alarm
+ */
 typedef struct pnet_alarm_argument
 {
    uint32_t api_id;
@@ -486,7 +513,6 @@ typedef struct pnet_alarm_argument
    uint16_t alarm_type;
    uint16_t sequence_number;
    pnet_alarm_spec_t alarm_specifier;
-
 } pnet_alarm_argument_t;
 
 /**
@@ -494,11 +520,18 @@ typedef struct pnet_alarm_argument
  */
 typedef struct pnet_result
 {
-   pnet_pnio_status_t pnio_status; /**< Profinet-specific error information. */
-   uint16_t add_data_1; /**< Application-specific error information. */
-   uint16_t add_data_2; /**< Application-specific error information. */
+   /** Profinet-specific error information. */
+   pnet_pnio_status_t pnio_status;
+
+   /** Application-specific error information. */
+   uint16_t add_data_1;
+
+   /** Application-specific error information. */
+   uint16_t add_data_2;
 } pnet_result_t;
 
+/******************************* Callbacks ************************************/
+
 /*
  * Application call-back functions
  *
@@ -857,7 +890,7 @@ typedef int (*pnet_new_data_status_ind) (
    void * arg,
    uint32_t arep,
    uint32_t crep,
-   uint8_t changes, /**< Only modified bits from pnet_data_status_bits_t */
+   uint8_t changes,
    uint8_t data_status);
 
 /**
@@ -1015,14 +1048,20 @@ typedef int (*pnet_signal_led_ind) (pnet_t * net, void * arg, bool led_state);
  * Configuration values are taken as is. No validation is performed.
  */
 
-typedef enum pnet_im_supported_value
+/**
+ * Describe which I&M values are supported.
+ *
+ * I&M0 is always supported.
+ *
+ */
+typedef enum pnet_im_supported_values
 {
-   /* I&M0 is always supported */
    PNET_SUPPORTED_IM1 = 0x0002,
    PNET_SUPPORTED_IM2 = 0x0004,
    PNET_SUPPORTED_IM3 = 0x0008,
-   PNET_SUPPORTED_IM4 = 0x0010, /* Should only be used together with Functional
-                                   Safety*/
+
+   /** Should only be used together with functional safety */
+   PNET_SUPPORTED_IM4 = 0x0010,
 } pnet_im_supported_values_t;
 
 /**
@@ -1034,8 +1073,13 @@ typedef struct pnet_im_0
 {
    uint8_t im_vendor_id_hi;
    uint8_t im_vendor_id_lo;
-   char im_order_id[PNET_ORDER_ID_MAX_LEN + 1]; /**< Terminated string */
-   char im_serial_number[PNET_SERIAL_NUMBER_MAX_LEN + 1]; /**< Terminated */
+
+   /** Terminated string */
+   char im_order_id[PNET_ORDER_ID_MAX_LEN + 1];
+
+   /** Terminated string */
+   char im_serial_number[PNET_SERIAL_NUMBER_MAX_LEN + 1];
+
    uint16_t im_hardware_revision;
    char im_sw_revision_prefix;
    uint8_t im_sw_revision_functional_enhancement;
@@ -1044,11 +1088,16 @@ typedef struct pnet_im_0
    uint16_t im_revision_counter;
    uint16_t im_profile_id;
    uint16_t im_profile_specific_type;
-   uint8_t im_version_major; /**< Always 1 */
-   uint8_t im_version_minor; /**< Always 1 */
-   uint16_t im_supported;    /**< One bit for each supported I&M1..15.
-                                  I&M0 is always supported.
-                                  Use pnet_im_supported_values_t.*/
+
+   /** Always 1 */
+   uint8_t im_version_major;
+
+   /** Always 1 */
+   uint8_t im_version_minor;
+
+   /** One bit for each supported I&M1..15. I&M0 is always supported.
+       Use pnet_im_supported_values_t. */
+   uint16_t im_supported;
 } pnet_im_0_t;
 
 /**
@@ -1060,8 +1109,11 @@ typedef struct pnet_im_0
  */
 typedef struct pnet_im_1
 {
-   char im_tag_function[32 + 1];                 /**< Terminated string */
-   char im_tag_location[PNET_LOCATION_MAX_SIZE]; /**< Terminated string */
+   /** Terminated string */
+   char im_tag_function[32 + 1];
+
+   /** Terminated string */
+   char im_tag_location[PNET_LOCATION_MAX_SIZE];
 } pnet_im_1_t;
 
 /**
@@ -1073,7 +1125,8 @@ typedef struct pnet_im_1
  */
 typedef struct pnet_im_2
 {
-   char im_date[16 + 1]; /**< "YYYY-MM-DD HH:MM" terminated string */
+   /** Terminated string in the format "YYYY-MM-DD HH:MM"  */
+   char im_date[16 + 1];
 } pnet_im_2_t;
 
 /**
@@ -1085,7 +1138,8 @@ typedef struct pnet_im_2
  */
 typedef struct pnet_im_3
 {
-   char im_descriptor[54 + 1]; /**< Terminated string padded with spaces */
+   /** Terminated string padded with spaces */
+   char im_descriptor[54 + 1];
 } pnet_im_3_t;
 
 /**
@@ -1099,8 +1153,8 @@ typedef struct pnet_im_3
  */
 typedef struct pnet_im_4
 {
-   char im_signature[54]; /**< Non-terminated binary string, padded with zeroes
-                           */
+   /** Non-terminated binary string, padded with zeroes */
+   char im_signature[54];
 } pnet_im_4_t;
 
 /**
@@ -1180,7 +1234,9 @@ typedef struct pnet_port_cfg
  */
 typedef struct pnet_ip_cfg
 {
-   bool dhcp_enable; /**< Not supported by stack. */
+   /** Not yet supported by stack. */
+   bool dhcp_enable;
+
    pnet_cfg_ip_addr_t ip_addr;
    pnet_cfg_ip_addr_t ip_mask;
    pnet_cfg_ip_addr_t ip_gateway;
@@ -1190,18 +1246,21 @@ typedef struct pnet_ip_cfg
  * Interface Configuration
  *
  * Configuration of network interfaces used by the stack.
- * The main_port defines the network interface used by a controller/PLC
+ * The \a main_netif_name defines the network interface used by a controller/PLC
  * to access the device (called Management Port in Profinet).
- * The ports array defines the physical ports connected to the
+ * The \a physical_ports array defines the physical ports connected to the
  * main_port.
  *
- * In the case one network interface is used, \a main_port and
- * \a port[0].phy_port will refer to the same network interface.
+ * In the case one network interface is used, \a main_netif_name and
+ * \a physical_ports[0].netif_name will refer to the same network interface.
  */
 typedef struct pnet_if_cfg
 {
-   const char * main_netif_name; /**< Main (DAP) network interface. */
-   pnet_ip_cfg_t ip_cfg;         /**< IP Settings for main network interface */
+   /** Main (DAP) network interface */
+   const char * main_netif_name;
+
+   /** IP Settings for main network interface */
+   pnet_ip_cfg_t ip_cfg;
 
    pnet_port_cfg_t physical_ports[PNET_MAX_PHYSICAL_PORTS];
 } pnet_if_cfg_t;
@@ -1209,16 +1268,16 @@ typedef struct pnet_if_cfg
 /**
  * This is all the configuration needed to use the Profinet stack.
  *
- * The application must supply the values in the call to function pnet_init().
+ * The application must supply the values in the call to
+ * function \a pnet_init().
  */
 typedef struct pnet_cfg
 {
    /** Tick interval in us.
-    *  Specifies the time between calls to pnet_handle_periodic().
+    *  Specifies the time between calls to \a pnet_handle_periodic().
     */
    uint32_t tick_us;
 
-   /** Application call-backs */
    pnet_state_ind state_cb;
    pnet_connect_ind connect_cb;
    pnet_release_ind release_cb;
@@ -1234,19 +1293,21 @@ typedef struct pnet_cfg
    pnet_alarm_ack_cnf alarm_ack_cnf_cb;
    pnet_reset_ind reset_cb;
    pnet_signal_led_ind signal_led_cb;
-   void * cb_arg; /* Userdata passed to callbacks, not used by stack */
 
-   /** I&M initial data */
+   /** Userdata passed to callbacks, not used by stack */
+   void * cb_arg;
+
    pnet_im_0_t im_0_data;
    pnet_im_1_t im_1_data;
    pnet_im_2_t im_2_data;
    pnet_im_3_t im_3_data;
    pnet_im_4_t im_4_data;
 
-   /** Identities */
    pnet_cfg_device_id_t device_id;
    pnet_cfg_device_id_t oem_device_id;
-   char station_name[PNET_STATION_NAME_MAX_SIZE]; /**< Terminated string */
+
+   /** Default station name. Terminated string */
+   char station_name[PNET_STATION_NAME_MAX_SIZE];
 
    /**
     * Product name
@@ -1255,27 +1316,26 @@ typedef struct pnet_cfg
     * specification. It constitutes the first part of SystemIdentification
     * (sysDescr in SNMP). It may also be used to construct the Chassis ID.
     * See IEC CDV 61158-6-10 ch. 4.10.3.3.1.
+    *
+    * Terminated string.
     */
-   char product_name[PNET_PRODUCT_NAME_MAX_LEN + 1]; /**< Terminated string */
+   char product_name[PNET_PRODUCT_NAME_MAX_LEN + 1];
 
-   /* Timing */
-   uint16_t min_device_interval; /** Smallest allowed data exchange interval, in
-                                    units of 31.25 us. Used for triggering error
-                                    messages to the PLC. Should match GSDML
-                                    file. Typically 32, which corresponds to 1
-                                    ms. Max 0x1000 (128 ms) */
+   /** Smallest allowed data exchange interval, in units of 31.25 us.
+    *  Used for triggering error messages to the PLC. Should match GSDML file.
+    *  Typically 32, which corresponds to 1 ms. Max 0x1000 (128 ms) */
+   uint16_t min_device_interval;
 
    /** Operating system dependent settings */
    pnal_cfg_t pnal_cfg;
 
-   /** Capabilities */
-   bool send_hello; /**< Send DCP HELLO message on startup if true. */
+   /** Send DCP HELLO message on startup if true. */
+   bool send_hello;
 
    /** Number of physical ports. Should respect PNET_MAX_PHYSICAL_PORTS.
        This parameter is useful when shipping a single compiled version of the
        library, but there are several applications with different number of
-       ports.
-    */
+       ports. */
    uint8_t num_physical_ports; // TODO int or uint16_t ?
 
    /** Send diagnosis in the qualified format (otherwise extended format) */
@@ -1288,12 +1348,10 @@ typedef struct pnet_cfg
    pnet_driver_config_t driver_config;
 #endif
 
-   /** Storage between runs */
-   char file_directory[PNET_MAX_DIRECTORYPATH_SIZE]; /**< Terminated string
-                                                          with absolute path.
-                                                          Use NULL or empty
-                                                          string for current
-                                                          directory. */
+   /** Storage between runs
+    *  Terminated string with absolute path.
+    *  Use NULL or empty string for current directory. */
+   char file_directory[PNET_MAX_DIRECTORYPATH_SIZE];
 
 } pnet_cfg_t;
 
@@ -1756,7 +1814,7 @@ PNET_EXPORT int pnet_alarm_send_ack (
 #define PNET_CHANNEL_WHOLE_SUBMODULE 0x8000
 
 /**
- * Channel size in bits.
+ * Channel size in bits. Values 8..255 are reserved.
  */
 typedef enum pnet_diag_ch_prop_type_values
 {
@@ -1768,10 +1826,9 @@ typedef enum pnet_diag_ch_prop_type_values
    PNET_DIAG_CH_PROP_TYPE_16_BIT = 5,
    PNET_DIAG_CH_PROP_TYPE_32_BIT = 6,
    PNET_DIAG_CH_PROP_TYPE_64_BIT = 7,
-   /* 8..255 Reserved */
 } pnet_diag_ch_prop_type_values_t;
 
-/* Channel group or individual channel. Also known as "Accumulative" */
+/** Channel group or individual channel. Also known as "Accumulative" */
 typedef enum pnet_diag_ch_group_values
 {
    PNET_DIAG_CH_INDIVIDUAL_CHANNEL = 0,
@@ -1800,12 +1857,18 @@ typedef enum pnet_diag_ch_prop_maint_values
    PNET_DIAG_CH_PROP_MAINT_QUALIFIED = 3,
 } pnet_diag_ch_prop_maint_values_t;
 
+/**
+ * Diagnosis source.
+ */
 typedef struct pnet_diag_source
 {
    uint32_t api;
    uint16_t slot;
    uint16_t subslot;
-   uint16_t ch; /** 0 - 0x7FFF manufacturer specific, 0x8000 whole submodule */
+
+   /** 0 - 0x7FFF manufacturer specific, 0x8000 whole submodule */
+   uint16_t ch;
+
    pnet_diag_ch_group_values_t ch_grouping;
    pnet_diag_ch_prop_dir_values_t ch_direction;
 } pnet_diag_source_t;

+ 11 - 5
src/common/pf_bg_worker.h

@@ -25,11 +25,17 @@ extern "C" {
  */
 typedef enum pf_bg_job
 {
-   PF_BGJOB_UPDATE_PORTS_STATUS = 0, /**< Update status for all ports  */
-   PF_BGJOB_SAVE_ASE_NVM_DATA,       /**< Save non volatile ASE data to file */
-   PF_BGJOB_SAVE_IM_NVM_DATA,        /**< Save non volatile IM data to file */
-   PF_BGJOB_SAVE_PDPORT_NVM_DATA,    /**< Save non volatile PDPort data to file
-                                      */
+   /** Update status for all ports  */
+   PF_BGJOB_UPDATE_PORTS_STATUS = 0,
+
+   /** Save non volatile ASE data to file */
+   PF_BGJOB_SAVE_ASE_NVM_DATA,
+
+   /** Save non volatile IM data to file */
+   PF_BGJOB_SAVE_IM_NVM_DATA,
+
+   /** Save non volatile PDPort data to file */
+   PF_BGJOB_SAVE_PDPORT_NVM_DATA,
 } pf_bg_job_t;
 
 /**

+ 1 - 1
src/common/pf_file.c

@@ -223,7 +223,7 @@ int pf_file_save (
    size_t size)
 {
    char path[PNET_MAX_FILE_FULLPATH_SIZE]; /**< Terminated string */
-   uint8_t versioning_buffer[8] = {0};     /* Two uint32_t */
+   uint8_t versioning_buffer[8] = {0};     /**< Two uint32_t */
    uint16_t pos = 0;
    int ret = 0;
    uint32_t start_time_us = 0;

+ 5 - 2
src/common/pf_lldp.c

@@ -86,8 +86,11 @@ typedef struct lldp_tlv
 /** Header for Organizationally Specific TLV */
 typedef struct pf_lldp_org_header
 {
-   uint8_t id[3];   /**< Organizationally unique identifier */
-   uint8_t subtype; /**< Organizationally defined subtype */
+   /** Organizationally unique identifier */
+   uint8_t id[3];
+
+   /** Organizationally defined subtype */
+   uint8_t subtype;
 } pf_lldp_org_header_t;
 
 static const char org_id_pnio[] = {0x00, 0x0e, 0xcf};

+ 1 - 1
src/common/pf_ppm.c

@@ -17,7 +17,7 @@
  * @file
  * @brief Implements the Cyclic Provider Protocol Machine (PPM)
  *
- * This handles cyclic sending of data (and IOPS). Initalizes transmit buffers.
+ * This handles cyclic sending of data (and IOPS). Initializes transmit buffers.
  *
  * One instance of PPM exist per CR (together with a CPM).
  *

+ 2 - 1
src/common/pf_scheduler.h

@@ -26,7 +26,8 @@ extern "C" {
  * Initialize the scheduler.
  * @param net              InOut: The p-net stack instance
  * @param tick_interval    In:    System calls the tick function at these
- * intervals, in microseconds.
+ *                                intervals, in microseconds. Must be
+ *                                larger than 0.
  */
 void pf_scheduler_init (pnet_t * net, uint32_t tick_interval);
 

+ 17 - 6
src/common/pf_snmp.h

@@ -222,9 +222,14 @@ typedef struct pf_snmp_system_location
  */
 typedef struct pf_snmp_management_address
 {
-   uint8_t value[1 + 31]; /**< First byte is size of actual address */
-   uint8_t subtype;       /**< 1 for IPv4 */
-   size_t len;            /**< 5 for IPv4 */
+   /** First byte is size of actual address */
+   uint8_t value[1 + 31];
+
+   /** 1 for IPv4 */
+   uint8_t subtype;
+
+   /** 5 for IPv4 */
+   size_t len;
 } pf_snmp_management_address_t;
 
 /**
@@ -235,9 +240,15 @@ typedef struct pf_snmp_management_address
  */
 typedef struct pf_snmp_link_status
 {
-   int32_t auto_neg_supported;         /**< 1 if true, 2 if false */
-   int32_t auto_neg_enabled;           /**< 1 if true, 2 if false */
-   uint8_t auto_neg_advertised_cap[2]; /**< OCTET STRING encoding of BITS */
+   /** 1 if true, 2 if false */
+   int32_t auto_neg_supported;
+
+   /** 1 if true, 2 if false */
+   int32_t auto_neg_enabled;
+
+   /** OCTET STRING encoding of BITS */
+   uint8_t auto_neg_advertised_cap[2];
+
    int32_t oper_mau_type;
 } pf_snmp_link_status_t;
 

+ 69 - 23
src/pf_types.h

@@ -1090,12 +1090,12 @@ typedef struct pf_scheduler_timeouts
        For debugging only */
    bool in_use;
 
-   uint32_t when; /* absolute time of timeout */
-   uint32_t next; /* Next in list */
-   uint32_t prev; /* Previous in list */
+   uint32_t when; /** Absolute time of timeout, in microseconds */
+   uint32_t next; /** Next in list. PF_MAX_TIMEOUTS if none. */
+   uint32_t prev; /** Previous in list. PF_MAX_TIMEOUTS if none.  */
 
-   pf_scheduler_timeout_ftn_t cb; /* Call-back to call on timeout */
-   void * arg;                    /* call-back argument */
+   pf_scheduler_timeout_ftn_t cb; /** Call-back to call on timeout */
+   void * arg;                    /** Call-back argument */
 } pf_scheduler_timeouts_t;
 
 typedef struct pf_scheduler_handle
@@ -2840,7 +2840,9 @@ typedef struct pf_lldp_port
 /** Network interface */
 typedef struct pf_netif
 {
-   char name[PNET_INTERFACE_NAME_MAX_SIZE]; /**< Terminated string */
+   /** Terminated string */
+   char name[PNET_INTERFACE_NAME_MAX_SIZE];
+
    pnet_ethaddr_t mac_address;
    pnal_eth_handle_t * handle;
    bool previous_is_link_up;
@@ -2874,29 +2876,55 @@ struct pnet
 {
    uint32_t pnal_buf_alloc_cnt;
    bool global_alarm_enable;
+
+   /********** CPM **********/
+
    os_mutex_t * cpm_buf_lock;
    atomic_int cpm_instance_cnt;
+
+   /********** PPM **********/
+
    os_mutex_t * ppm_buf_lock;
    atomic_int ppm_instance_cnt;
+
+   /********** DCP **********/
+
    uint16_t dcp_global_block_qualifier;
-   pnet_ethaddr_t dcp_sam; /* Source address (MAC) of current DCP remote peer */
-   bool dcp_delayed_response_waiting; /* A response to DCP IDENTIFY is waiting
-                                         to be sent */
+
+   /** Source address (MAC) of current DCP remote peer */
+   pnet_ethaddr_t dcp_sam;
+
+   /** A response to DCP IDENTIFY is waiting to be sent */
+   bool dcp_delayed_response_waiting;
+
    pf_scheduler_handle_t dcp_led_timeout;
    pf_scheduler_handle_t dcp_sam_timeout;
    pf_scheduler_handle_t dcp_identresp_timeout;
+
+   /********** Profinet frame ID mapping **********/
+
    pf_eth_frame_id_map_t eth_id_map[PF_ETH_MAX_MAP];
    volatile pf_scheduler_timeouts_t scheduler_timeouts[PF_MAX_TIMEOUTS];
    volatile uint32_t scheduler_timeout_first;
    volatile uint32_t scheduler_timeout_free;
    os_mutex_t * scheduler_timeout_mutex;
    uint32_t scheduler_tick_interval; /* microseconds */
+
+   /********** CMDEV **********/
+
    bool cmdev_initialized;
-   pf_device_t cmdev_device;                     /* APIs and diag items */
-   pf_cmina_dcp_ase_t cmina_nonvolatile_dcp_ase; /* Reflects what is/should be
-                                                    stored in nvm */
-   pf_cmina_dcp_ase_t cmina_current_dcp_ase;     /* Reflects current settings
-                                                    (possibly not yet committed) */
+
+   /** APIs and diag items */
+   pf_device_t cmdev_device;
+
+   /********** CMINA **********/
+
+   /** Reflects what is/should be stored in NVM */
+   pf_cmina_dcp_ase_t cmina_nonvolatile_dcp_ase;
+
+   /** Reflects current settings (possibly not yet committed) */
+   pf_cmina_dcp_ase_t cmina_current_dcp_ase;
+
    os_mutex_t * cmina_mutex;
    pf_cmina_state_values_t cmina_state;
    uint8_t cmina_error_decode;
@@ -2905,21 +2933,36 @@ struct pnet
    pf_scheduler_handle_t cmina_hello_timeout;
 
    bool cmina_commit_ip_suite;
+
+   /********** CMRPC **********/
+
    os_mutex_t * p_cmrpc_rpc_mutex;
    uint32_t cmrpc_session_number;
-   pf_ar_t cmrpc_ar[PNET_MAX_AR];                        /* ARs */
-   pf_session_info_t cmrpc_session_info[PF_MAX_SESSION]; /* Sessions */
-   int cmrpc_rpcreq_socket; /* Main socket for incoming requests */
+
+   /** ARs */
+   pf_ar_t cmrpc_ar[PNET_MAX_AR];
+
+   /** Sessions */
+   pf_session_info_t cmrpc_session_info[PF_MAX_SESSION];
+
+   /** Main socket for incoming requests */
+   int cmrpc_rpcreq_socket;
+
    uint8_t cmrpc_dcerpc_input_frame[PF_FRAME_BUFFER_SIZE];
    uint8_t cmrpc_dcerpc_output_frame[PF_FRAME_BUFFER_SIZE];
-   const pnet_cfg_t * p_fspm_default_cfg; /* Default configuration from user.
-                                             Used at factory reset */
-   pnet_cfg_t fspm_cfg; /* Configuration from user. Might be updated by stack
-                           during runtime */
+
+   /********** FSPM **********/
+
+   /** Default configuration from user. Used at factory reset */
+   const pnet_cfg_t * p_fspm_default_cfg;
+
+   /** Configuration from user. Might be updated by stack during runtime */
+   pnet_cfg_t fspm_cfg;
+
    pf_log_book_t fspm_log_book;
    os_mutex_t * fspm_log_book_mutex;
 
-   /* Last time pnet_handle_periodic() was invoked */
+   /** Last \a time pnet_handle_periodic() was invoked */
    uint32_t timestamp_handle_periodic_us;
 
    /* Mutex for protecting access to writable I&M data.
@@ -2929,6 +2972,8 @@ struct pnet
     */
    os_mutex_t * fspm_im_mutex;
 
+   /********** LLDP **********/
+
    /* LLDP mutex
     *
     * This mutex protects information about the peer device.
@@ -2967,7 +3012,8 @@ struct pnet
    const pf_ppm_driver_t * ppm_drv;
    const pf_cpm_driver_t * cpm_drv;
 
-   pf_drv_t * hwo_drv; /* Handle to HW offload driver. NULL if not used */
+   /** Handle to HW offload driver. NULL if not used */
+   pf_drv_t * hwo_drv;
 
 #if PNET_OPTION_SNMP
    pf_snmp_data_t snmp_data;

+ 2 - 2
test/test_port.cpp

@@ -92,7 +92,7 @@ TEST_F (PortUnitTest, PortCheckIterator)
    EXPECT_EQ (pf_port_get_next (&port_iterator), 0);
    EXPECT_EQ (pf_port_get_next (&port_iterator), 0);
 
-   /* Verify behaviour if the interator for unknown reason has
+   /* Verify behaviour if the iterator for unknown reason has
     * value that is out of port range */
    port_iterator.next_port = 10;
    EXPECT_EQ (pf_port_get_next (&port_iterator), 0);
@@ -144,7 +144,7 @@ TEST_F (PortUnitTest, PortCheckIteratorRepeatCyclic)
    EXPECT_EQ (pf_port_get_next_repeat_cyclic (&port_iterator), 2);
    EXPECT_EQ (pf_port_get_next_repeat_cyclic (&port_iterator), 3);
 
-   /* Verify behaviour if the interator for unknown reason has
+   /* Verify behaviour if the iterator for unknown reason has
     * value that is out of port range */
    port_iterator.next_port = 10;
    EXPECT_EQ (pf_port_get_next_repeat_cyclic (&port_iterator), 1);