1. Добавил скрипт build.sh - собирает библиотеку pnet и группирует получившиеся файлы в папку install, туда же помещает библиотеку osal. Теперь все библиотеки и их заголовки в одном месте, а не распизаны по папкам в папке build. 2. Добавил проект sample_app в папку profinet_test. Он отвязан от процесса сборки pnet и использует уже собранную библиотеку из папки install.
429 lines
12 KiB
C
429 lines
12 KiB
C
/*********************************************************************
|
|
* _ _ _
|
|
* _ __ | |_ _ | | __ _ | |__ ___
|
|
* | '__|| __|(_)| | / _` || '_ \ / __|
|
|
* | | | |_ _ | || (_| || |_) |\__ \
|
|
* |_| \__|(_)|_| \__,_||_.__/ |___/
|
|
*
|
|
* www.rt-labs.com
|
|
* Copyright 2018 rt-labs AB, Sweden.
|
|
*
|
|
* This software is dual-licensed under GPLv3 and a commercial
|
|
* license. See the file LICENSE.md distributed with this software for
|
|
* full license information.
|
|
********************************************************************/
|
|
|
|
#ifndef APP_UTILS_H
|
|
#define APP_UTILS_H
|
|
|
|
/**
|
|
* @file
|
|
* @brief Application utilities and helper functions
|
|
*
|
|
* Functions for getting string representation of
|
|
* P-Net events, error codes and more.
|
|
*
|
|
* API, slot and subslot administration.
|
|
*
|
|
* Initialization of P-Net configuration from app_gsdml.h.
|
|
*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#include "osal.h"
|
|
#include "pnal.h"
|
|
#include <pnet_api.h>
|
|
|
|
typedef struct app_utils_netif_name
|
|
{
|
|
char name[PNET_INTERFACE_NAME_MAX_SIZE];
|
|
} app_utils_netif_name_t;
|
|
|
|
typedef struct app_utils_netif_namelist
|
|
{
|
|
app_utils_netif_name_t netif[PNET_MAX_PHYSICAL_PORTS + 1];
|
|
} app_utils_netif_namelist_t;
|
|
|
|
/* Forward declaration */
|
|
typedef struct app_subslot app_subslot_t;
|
|
|
|
/**
|
|
* Callback for updated cyclic data
|
|
*
|
|
* @param subslot InOut: Subslot structure
|
|
* @param tag InOut: Typically a handle to a submodule
|
|
*/
|
|
typedef void (*app_utils_cyclic_callback) (app_subslot_t * subslot, void * tag);
|
|
|
|
/**
|
|
* Information of submodule plugged into a subslot.
|
|
*
|
|
* Note that submodule data is not stored here but must
|
|
* be handled by the submodule implementation.
|
|
*
|
|
* All parameters are initialized by the app_utils_plug_submodule()
|
|
* function.
|
|
*
|
|
* The cyclic_callback is used when app_utils_cyclic_data_poll()
|
|
* is called. Typically on the tick event in the main task.
|
|
* The \a tag parameter is passed with the cyclic_callback and
|
|
* is typically a handle to a submodule on application.
|
|
*/
|
|
typedef struct app_subslot
|
|
{
|
|
/** True when the position in the subslot array is occupied */
|
|
bool used;
|
|
|
|
/** True when the subslot is plugged */
|
|
bool plugged;
|
|
|
|
uint16_t slot_nbr;
|
|
uint16_t subslot_nbr;
|
|
uint32_t submodule_id;
|
|
const char * submodule_name;
|
|
pnet_data_cfg_t data_cfg;
|
|
|
|
/** Status indicator from PLC */
|
|
uint8_t indata_iocs;
|
|
|
|
/** Status indicator from PLC */
|
|
uint8_t outdata_iops;
|
|
|
|
/** Callback for cyclic input- or output data, or NULL if not implemented */
|
|
app_utils_cyclic_callback cyclic_callback;
|
|
void * tag;
|
|
} app_subslot_t;
|
|
|
|
/**
|
|
* Information of module plugged into a slot,
|
|
* and array of subslots for admin of submodules.
|
|
*/
|
|
typedef struct app_slot
|
|
{
|
|
bool plugged;
|
|
uint32_t module_id;
|
|
const char * name; /** Module name */
|
|
|
|
/** Subslots. Use a separate index, as the subslot number might be large.
|
|
* For example the subslot for DAP port 1 has number 0x8001 */
|
|
app_subslot_t subslots[PNET_MAX_SUBSLOTS];
|
|
} app_slot_t;
|
|
|
|
/**
|
|
* Profinet API state for application
|
|
*
|
|
* Used to manage plugged modules into slots (and submodules into subslots).
|
|
*/
|
|
typedef struct app_api_t
|
|
{
|
|
uint32_t api_id;
|
|
uint32_t arep;
|
|
|
|
/** Slots. Use slot number as index */
|
|
app_slot_t slots[PNET_MAX_SLOTS];
|
|
} app_api_t;
|
|
|
|
/**
|
|
* Convert IP address to string
|
|
* @param ip In: IP address
|
|
* @param outputstring Out: Resulting string buffer. Should have size
|
|
* PNAL_INET_ADDRSTR_SIZE.
|
|
*/
|
|
void app_utils_ip_to_string (pnal_ipaddr_t ip, char * outputstring);
|
|
|
|
/**
|
|
* Get string description of data direction
|
|
* @param direction In: Submodule data direction
|
|
* @return String represention of data direction
|
|
*/
|
|
const char * app_utils_submod_dir_to_string (pnet_submodule_dir_t direction);
|
|
|
|
/**
|
|
* Get string description of PNIO producer or consumer status
|
|
* @param ioxs In: Producer or consumer status (IOPS/IOCS)
|
|
* @return String represention of ioxs (IOPS/IOCS)
|
|
*/
|
|
const char * app_utils_ioxs_to_string (pnet_ioxs_values_t ioxs);
|
|
|
|
/**
|
|
* Convert MAC address to string
|
|
* @param mac In: MAC address
|
|
* @param outputstring Out: Resulting string buffer. Should have size
|
|
* PNAL_ETH_ADDRSTR_SIZE.
|
|
*/
|
|
void app_utils_mac_to_string (pnet_ethaddr_t mac, char * outputstring);
|
|
|
|
/**
|
|
* Convert error code to string format
|
|
* Only common error codes supported.
|
|
* Todo: Add rest of error codes.
|
|
*
|
|
* @param err_cls In: The error class. See PNET_ERROR_CODE_1_*
|
|
* @param err_code In: The error code. See PNET_ERROR_CODE_2_*
|
|
* @param err_cls_str Out: The error class string
|
|
* @param err_code_str Out: The error code string
|
|
*/
|
|
void app_utils_get_error_code_strings (
|
|
uint16_t err_cls,
|
|
uint16_t err_code,
|
|
const char ** err_cls_str,
|
|
const char ** err_code_str);
|
|
|
|
/**
|
|
* Copy an IP address (as an integer) to a struct
|
|
* @param destination_struct Out: Destination
|
|
* @param ip In: IP address
|
|
*/
|
|
void app_utils_copy_ip_to_struct (
|
|
pnet_cfg_ip_addr_t * destination_struct,
|
|
pnal_ipaddr_t ip);
|
|
|
|
/**
|
|
* Return a string representation of
|
|
* the given dcontrol command.
|
|
* @param event In: control_command
|
|
* @return A string representing the command
|
|
*/
|
|
const char * app_utils_dcontrol_cmd_to_string (
|
|
pnet_control_command_t control_command);
|
|
|
|
/**
|
|
* Return a string representation of the given event.
|
|
* @param event In: event
|
|
* @return A string representing the event
|
|
*/
|
|
const char * app_utils_event_to_string (pnet_event_values_t event);
|
|
|
|
/**
|
|
* Update network configuration from a string
|
|
* defining a list of network interfaces examples:
|
|
* "eth0" or "br0,eth0,eth1"
|
|
*
|
|
* Read IP, netmask etc from operating system.
|
|
*
|
|
* @param netif_list_str In: Comma separated string of network ifs
|
|
* @param if_list Out: Array of network ifs
|
|
* @param number_of_ports Out: Number of ports
|
|
* @param if_cfg Out: P-Net network configuration to be updated
|
|
* @return 0 on success, -1 on error
|
|
*/
|
|
int app_utils_pnet_cfg_init_netifs (
|
|
const char * netif_list_str,
|
|
app_utils_netif_namelist_t * if_list,
|
|
uint16_t * number_of_ports,
|
|
pnet_if_cfg_t * if_cfg);
|
|
|
|
/**
|
|
* Parse a comma separated list of network interfaces and check
|
|
* that the number of interfaces match the PNET_MAX_PHYSICAL_PORTS
|
|
* configuration.
|
|
*
|
|
* For a single Ethernet interface, the \a arg_str should consist of
|
|
* one name. For two Ethernet interfaces, the \a arg_str should consist of
|
|
* three names, as we also need a bridge interface.
|
|
*
|
|
* Does only consider the number of comma separated names. No check of the
|
|
* names themselves are done.
|
|
*
|
|
* Examples:
|
|
* arg_str num_ports
|
|
* "eth0" 1
|
|
* "eth0,eth1" error (We need a bridge as well)
|
|
* "br0,eth0,eth1" 2
|
|
*
|
|
* @param arg_str In: Network interface list as comma separated,
|
|
* terminated string. For example "eth0" or
|
|
* "br0,eth0,eth1".
|
|
* @param max_port In: PNET_MAX_PHYSICAL_PORTS, passed as argument to
|
|
* allow test.
|
|
* @param p_if_list Out: List of network interfaces
|
|
* @param p_num_ports Out: Resulting number of physical ports
|
|
* @return 0 on success
|
|
* -1 on error
|
|
*/
|
|
int app_utils_get_netif_namelist (
|
|
const char * arg_str,
|
|
uint16_t max_port,
|
|
app_utils_netif_namelist_t * p_if_list,
|
|
uint16_t * p_num_ports);
|
|
|
|
/**
|
|
* Print network configuration using APP_LOG_INFO().
|
|
*
|
|
* @param if_cfg In: Network configuration
|
|
* @param number_of_ports In: Number of used ports
|
|
*/
|
|
void app_utils_print_network_config (
|
|
pnet_if_cfg_t * if_cfg,
|
|
uint16_t number_of_ports);
|
|
|
|
/**
|
|
* Print message if IOXS has changed.
|
|
*
|
|
* Uses APP_LOG_INFO()
|
|
*
|
|
* @param subslot In: Subslot
|
|
* @param ioxs_str In: String description Producer or Consumer
|
|
* @param ioxs_current In: Current status
|
|
* @param ioxs_new In: New status
|
|
*/
|
|
void app_utils_print_ioxs_change (
|
|
const app_subslot_t * subslot,
|
|
const char * ioxs_str,
|
|
uint8_t ioxs_current,
|
|
uint8_t ioxs_new);
|
|
|
|
/**
|
|
* Init the p-net configuration to default values.
|
|
*
|
|
* Most values are picked from app_gsdml.h
|
|
*
|
|
* Network configuration not initialized.
|
|
* This means that \a '.if_cfg' must be set by application.
|
|
*
|
|
* Use this function to init P-Net configuration before
|
|
* before passing config to app_init().
|
|
*
|
|
* @param pnet_cfg Out: Configuration for use by p-net
|
|
* @return 0 if the operation succeeded.
|
|
* -1 if an error occurred.
|
|
*/
|
|
int app_utils_pnet_cfg_init_default (pnet_cfg_t * pnet_cfg);
|
|
|
|
/**
|
|
* Plug application module
|
|
*
|
|
* This is for the application to remember which slots are
|
|
* populated in the p-net stack.
|
|
*
|
|
* @param p_api InOut: API
|
|
* @param slot_nbr In: Slot number
|
|
* @param id In: Module identity
|
|
* @param name In: Module name
|
|
* @return 0 on success, -1 on error
|
|
*/
|
|
int app_utils_plug_module (
|
|
app_api_t * p_api,
|
|
uint16_t slot_nbr,
|
|
uint32_t id,
|
|
const char * name);
|
|
|
|
/**
|
|
* Pull any application module in given slot.
|
|
*
|
|
* This is for the application to remember which slots are
|
|
* populated in the p-net stack.
|
|
*
|
|
* @param p_api InOut: API
|
|
* @param slot_nbr In: Slot number
|
|
* @return 0 on success, -1 on error
|
|
*/
|
|
int app_utils_pull_module (app_api_t * p_api, uint16_t slot_nbr);
|
|
|
|
/**
|
|
* Plug application submodule.
|
|
*
|
|
* This is for the application to remember which subslots are
|
|
* populated in the p-net stack.
|
|
*
|
|
* @param p_api InOut: API
|
|
* @param slot_nbr In: Slot number
|
|
* @param subslot_nbr In: Subslot number
|
|
* @param submodule_id In: Submodule identity
|
|
* @param p_data_cfg In: Data configuration,
|
|
* direction, in and out sizes
|
|
* @param submodule_name In: Submodule name
|
|
* @param cyclic_callback In: Submodule data callback
|
|
* @param tag In: Tag passed in cyclic callback
|
|
* Typically application or
|
|
* submodule handle
|
|
* @return Reference to allocated subslot,
|
|
* NULL if no free subslot is available. This should
|
|
* never happen if application is aligned with p-net state.
|
|
*/
|
|
app_subslot_t * app_utils_plug_submodule (
|
|
app_api_t * p_api,
|
|
uint16_t slot_nbr,
|
|
uint16_t subslot_nbr,
|
|
uint32_t submodule_id,
|
|
const pnet_data_cfg_t * p_data_cfg,
|
|
const char * submodule_name,
|
|
app_utils_cyclic_callback cyclic_callback,
|
|
void * tag);
|
|
|
|
/**
|
|
* Unplug any application submodule from given subslot.
|
|
*
|
|
* This is for the application to remember which subslots are
|
|
* populated in the p-net stack.
|
|
*
|
|
* @param p_api InOut: API
|
|
* @param slot_nbr In: Slot number
|
|
* @param subslot_nbr In: Subslot number
|
|
* @return 0 on success, -1 on error.
|
|
*/
|
|
int app_utils_pull_submodule (
|
|
app_api_t * p_api,
|
|
uint16_t slot_nbr,
|
|
uint16_t subslot_nbr);
|
|
|
|
/**
|
|
* Trigger data callback for all plugged submodules in all slots.
|
|
*
|
|
* The callbacks given in \a app_utils_plug_submodule() are used.
|
|
*
|
|
* @param p_api In: API
|
|
*/
|
|
void app_utils_cyclic_data_poll (app_api_t * p_api);
|
|
|
|
/**
|
|
* Get subslot application information.
|
|
*
|
|
* @param p_appdata InOut: Application state.
|
|
* @param slot_nbr In: Slot number.
|
|
* @param subslot_nbr In: Subslot number. Range 0 - 0x9FFF.
|
|
* @return Reference to application subslot,
|
|
* NULL if subslot is not found/plugged.
|
|
*/
|
|
app_subslot_t * app_utils_subslot_get (
|
|
app_api_t * p_api,
|
|
uint16_t slot_nbr,
|
|
uint16_t subslot_nbr);
|
|
|
|
/**
|
|
* Return true if subslot is input.
|
|
*
|
|
* @param p_subslot In: Reference to subslot.
|
|
* @return true if subslot is input or input/output.
|
|
* false if not.
|
|
*/
|
|
bool app_utils_subslot_is_input (const app_subslot_t * p_subslot);
|
|
|
|
/**
|
|
* Return true if subslot is neither input or output.
|
|
*
|
|
* This is applies for DAP submodules/slots
|
|
*
|
|
* @param p_subslot In: Reference to subslot.
|
|
* @return true if subslot is input or input/output.
|
|
* false if not.
|
|
*/
|
|
bool app_utils_subslot_is_no_io (const app_subslot_t * p_subslot);
|
|
|
|
/**
|
|
* Return true if subslot is output.
|
|
*
|
|
* @param p_subslot In: Reference to subslot.
|
|
* @return true if subslot is output or input/output,
|
|
* false if not.
|
|
*/
|
|
bool app_utils_subslot_is_output (const app_subslot_t * p_subslot);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* APP_UTILS_H */
|