ProfinetConnector/profinet_test/sample_app/app_data.c
svad05 c9fe825657 dev(UML-981): Автоматизация сборки
1. Добавил скрипт build.sh - собирает библиотеку pnet и группирует
получившиеся файлы в папку install, туда же помещает библиотеку osal.
Теперь все библиотеки и их заголовки в одном месте, а не распизаны по
папкам в папке build.
2. Добавил проект sample_app в папку profinet_test. Он отвязан от
процесса сборки pnet и использует уже собранную библиотеку из папки
install.
2022-07-12 15:59:03 +02:00

316 lines
8.2 KiB
C

/*********************************************************************
* _ _ _
* _ __ | |_ _ | | __ _ | |__ ___
* | '__|| __|(_)| | / _` || '_ \ / __|
* | | | |_ _ | || (_| || |_) |\__ \
* |_| \__|(_)|_| \__,_||_.__/ |___/
*
* www.rt-labs.com
* Copyright 2021 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.
********************************************************************/
#include "app_data.h"
#include "app_utils.h"
#include "app_gsdml.h"
#include "app_log.h"
#include "sampleapp_common.h"
#include "osal.h"
#include "pnal.h"
#include <pnet_api.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define APP_DATA_DEFAULT_OUTPUT_DATA 0
/* Parameter data for digital submodules
* The stored value is shared between all digital submodules in this example.
*
* Todo: Data is always in pnio data format. Add conversion to uint32_t.
*/
static uint32_t app_param_1 = 0; /* Network endianness */
static uint32_t app_param_2 = 0; /* Network endianness */
/* Parameter data for echo submodules
* The stored value is shared between all echo submodules in this example.
*
* Todo: Data is always in pnio data format. Add conversion to uint32_t.
*/
static uint32_t app_param_echo_gain = 1; /* Network endianness */
/* Digital submodule process data
* The stored value is shared between all digital submodules in this example. */
static uint8_t inputdata[APP_GSDML_INPUT_DATA_DIGITAL_SIZE] = {0};
static uint8_t outputdata[APP_GSDML_OUTPUT_DATA_DIGITAL_SIZE] = {0};
static uint8_t counter = 0;
/* Network endianness */
static uint8_t echo_inputdata[APP_GSDML_INPUT_DATA_ECHO_SIZE] = {0};
static uint8_t echo_outputdata[APP_GSDML_OUTPUT_DATA_ECHO_SIZE] = {0};
CC_PACKED_BEGIN
typedef struct CC_PACKED app_echo_data
{
/* Network endianness.
Used as a float, but we model it as a 4-byte integer to easily
do endianness conversion */
uint32_t echo_float_bytes;
/* Network endianness */
uint32_t echo_int;
} app_echo_data_t;
CC_PACKED_END
CC_STATIC_ASSERT (sizeof (app_echo_data_t) == APP_GSDML_INPUT_DATA_ECHO_SIZE);
CC_STATIC_ASSERT (sizeof (app_echo_data_t) == APP_GSDML_OUTPUT_DATA_ECHO_SIZE);
/**
* Set LED state.
*
* Compares new state with previous state, to minimize system calls.
*
* Uses the hardware specific app_set_led() function.
*
* @param led_state In: New LED state
*/
static void app_handle_data_led_state (bool led_state)
{
static bool previous_led_state = false;
if (led_state != previous_led_state)
{
app_set_led (APP_DATA_LED_ID, led_state);
}
previous_led_state = led_state;
}
uint8_t * app_data_get_input_data (
uint16_t slot_nbr,
uint16_t subslot_nbr,
uint32_t submodule_id,
bool button_pressed,
uint16_t * size,
uint8_t * iops)
{
float inputfloat;
float outputfloat;
uint32_t hostorder_inputfloat_bytes;
uint32_t hostorder_outputfloat_bytes;
app_echo_data_t * p_echo_inputdata = (app_echo_data_t *)&echo_inputdata;
app_echo_data_t * p_echo_outputdata = (app_echo_data_t *)&echo_outputdata;
if (size == NULL || iops == NULL)
{
return NULL;
}
if (
submodule_id == APP_GSDML_SUBMOD_ID_DIGITAL_IN ||
submodule_id == APP_GSDML_SUBMOD_ID_DIGITAL_IN_OUT)
{
/* Prepare digital input data
* Lowest 7 bits: Counter Most significant bit: Button
*/
inputdata[0] = counter++;
if (button_pressed)
{
inputdata[0] |= 0x80;
}
else
{
inputdata[0] &= 0x7F;
}
*size = APP_GSDML_INPUT_DATA_DIGITAL_SIZE;
*iops = PNET_IOXS_GOOD;
return inputdata;
}
if (submodule_id == APP_GSDML_SUBMOD_ID_ECHO)
{
/* Calculate echodata input (to the PLC)
* by multiplying the output (from the PLC) with a gain factor
*/
/* Integer */
p_echo_inputdata->echo_int = CC_TO_BE32 (
CC_FROM_BE32 (p_echo_outputdata->echo_int) *
CC_FROM_BE32 (app_param_echo_gain));
/* Float */
/* Use memcopy to avoid strict-aliasing rule warnings */
hostorder_outputfloat_bytes =
CC_FROM_BE32 (p_echo_outputdata->echo_float_bytes);
memcpy (&outputfloat, &hostorder_outputfloat_bytes, sizeof (outputfloat));
inputfloat = outputfloat * CC_FROM_BE32 (app_param_echo_gain);
memcpy (&hostorder_inputfloat_bytes, &inputfloat, sizeof (outputfloat));
p_echo_inputdata->echo_float_bytes =
CC_TO_BE32 (hostorder_inputfloat_bytes);
*size = APP_GSDML_INPUT_DATA_ECHO_SIZE;
*iops = PNET_IOXS_GOOD;
return echo_inputdata;
}
/* Automated RT Tester scenario 2 - unsupported (sub)module */
return NULL;
}
int app_data_set_output_data (
uint16_t slot_nbr,
uint16_t subslot_nbr,
uint32_t submodule_id,
uint8_t * data,
uint16_t size)
{
bool led_state;
if (data == NULL)
{
return -1;
}
if (
submodule_id == APP_GSDML_SUBMOD_ID_DIGITAL_OUT ||
submodule_id == APP_GSDML_SUBMOD_ID_DIGITAL_IN_OUT)
{
if (size == APP_GSDML_OUTPUT_DATA_DIGITAL_SIZE)
{
memcpy (outputdata, data, size);
/* Most significant bit: LED */
led_state = (outputdata[0] & 0x80) > 0;
app_handle_data_led_state (led_state);
return 0;
}
}
else if (submodule_id == APP_GSDML_SUBMOD_ID_ECHO)
{
if (size == APP_GSDML_OUTPUT_DATA_ECHO_SIZE)
{
memcpy (echo_outputdata, data, size);
return 0;
}
}
return -1;
}
int app_data_set_default_outputs (void)
{
outputdata[0] = APP_DATA_DEFAULT_OUTPUT_DATA;
app_handle_data_led_state (false);
return 0;
}
int app_data_write_parameter (
uint16_t slot_nbr,
uint16_t subslot_nbr,
uint32_t submodule_id,
uint32_t index,
const uint8_t * data,
uint16_t length)
{
const app_gsdml_param_t * par_cfg;
par_cfg = app_gsdml_get_parameter_cfg (submodule_id, index);
if (par_cfg == NULL)
{
APP_LOG_WARNING (
"PLC write request unsupported submodule/parameter. "
"Submodule id: %u Index: %u\n",
(unsigned)submodule_id,
(unsigned)index);
return -1;
}
if (length != par_cfg->length)
{
APP_LOG_WARNING (
"PLC write request unsupported length. "
"Index: %u Length: %u Expected length: %u\n",
(unsigned)index,
(unsigned)length,
par_cfg->length);
return -1;
}
if (index == APP_GSDML_PARAMETER_1_IDX)
{
memcpy (&app_param_1, data, length);
}
else if (index == APP_GSDML_PARAMETER_2_IDX)
{
memcpy (&app_param_2, data, length);
}
else if (index == APP_GSDML_PARAMETER_ECHO_IDX)
{
memcpy (&app_param_echo_gain, data, length);
}
APP_LOG_DEBUG (" Writing parameter \"%s\"\n", par_cfg->name);
app_log_print_bytes (APP_LOG_LEVEL_DEBUG, data, length);
return 0;
}
int app_data_read_parameter (
uint16_t slot_nbr,
uint16_t subslot_nbr,
uint32_t submodule_id,
uint32_t index,
uint8_t ** data,
uint16_t * length)
{
const app_gsdml_param_t * par_cfg;
par_cfg = app_gsdml_get_parameter_cfg (submodule_id, index);
if (par_cfg == NULL)
{
APP_LOG_WARNING (
"PLC read request unsupported submodule/parameter. "
"Submodule id: %u Index: %u\n",
(unsigned)submodule_id,
(unsigned)index);
return -1;
}
if (*length < par_cfg->length)
{
APP_LOG_WARNING (
"PLC read request unsupported length. "
"Index: %u Length: %u Expected length: %u\n",
(unsigned)index,
(unsigned)*length,
par_cfg->length);
return -1;
}
APP_LOG_DEBUG (" Reading \"%s\"\n", par_cfg->name);
if (index == APP_GSDML_PARAMETER_1_IDX)
{
*data = (uint8_t *)&app_param_1;
*length = sizeof (app_param_1);
}
else if (index == APP_GSDML_PARAMETER_2_IDX)
{
*data = (uint8_t *)&app_param_2;
*length = sizeof (app_param_2);
}
else if (index == APP_GSDML_PARAMETER_ECHO_IDX)
{
*data = (uint8_t *)&app_param_echo_gain;
*length = sizeof (app_param_echo_gain);
}
app_log_print_bytes (APP_LOG_LEVEL_DEBUG, *data, *length);
return 0;
}