Commit dcb32a3b authored by Robert Karlsson's avatar Robert Karlsson

Profibus/Profinet fixes, added rt_elog_dump utility

parent 95ad1973
......@@ -52,3 +52,7 @@
120615 cs profinet Profinet configurator, sorting of moduletypes and iodata length settings
120813 cs profibus Profibus configurator in xtt, bugfix in errorhandling for empty gsd-file (refs #112)
120813 cs profibus Profibus device Janitza umg961 added
120829 rk profinet IO offset caclulation bugfix for modules with both in- and output.
121130 rk profibus Handling of large prm data areas.
121130 rk profibus Moved event handling to separate thread. Not dependant on io-read cycle time.
......@@ -72,6 +72,11 @@
#include "rt_io_profiboard.h"
typedef struct _agent_args {
void *local;
io_sAgent *ap;
} agent_args;
typedef struct {
int hServiceReadDevice; // Handle for Service device
int hServiceWriteDevice; // Handle for Service device
......@@ -81,6 +86,9 @@ typedef struct {
unsigned char CurrentBoardNumber;
int slave_diag_requested;
int hDpsBoardDevice; // Handle for DP-Slave Output-Data device
pthread_t events;
pthread_mutex_t mutex;
agent_args args;
} io_sAgentLocal;
#define DP_MAX_SERVICE_RETRY 10
......@@ -441,6 +449,94 @@ static void dp_get_slave_diag_con(T_DP_GET_SLAVE_DIAG_CON * get_slave_diag_con_p
} /* diag_data_len */
}
/*----------------------------------------------------------------------------*\
Starts download sequence of prm data to one slave
\*----------------------------------------------------------------------------*/
static pwr_tStatus start_download_seq (
T_PROFI_DEVICE_HANDLE *hDevice,
pwr_sClass_Pb_DP_Slave *op
)
{
T_PROFI_SERVICE_DESCR sdb;
T_DP_START_SEQ_REQ ssrp;
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
USIGN16 timeout = 400;
T_PROFI_SERVICE_DESCR con_ind_sdb;
INT16 result; /* !!! local result variable !!! */
sdb.comm_ref = 0;
sdb.layer = DP;
sdb.service = DP_START_SEQ_LOC;
sdb.primitive = REQ;
sdb.invoke_id = 0;
sdb.result = 0;
ssrp.rem_add = 0;
ssrp.area_code = op->SlaveAddress;
ssrp.timeout = timeout;
profi_snd_req_res(hDevice, &sdb, &ssrp, PB_FALSE);
try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result);
if ((con_ind_sdb.service == DP_START_SEQ_LOC) &&
(con_ind_sdb.primitive == CON ) &&
(con_ind_sdb.result == POS )) {
op->Status = PB__NOCONN;
return (PB_TRUE);
}
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
/*----------------------------------------------------------------------------*\
Starts download sequence of prm data to one slave
\*----------------------------------------------------------------------------*/
static pwr_tStatus end_download_seq (
T_PROFI_DEVICE_HANDLE *hDevice,
pwr_sClass_Pb_DP_Slave *op
)
{
T_PROFI_SERVICE_DESCR sdb;
T_DP_END_SEQ_REQ esrp;
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
T_PROFI_SERVICE_DESCR con_ind_sdb;
INT16 result; /* !!! local result variable !!! */
sdb.comm_ref = 0;
sdb.layer = DP;
sdb.service = DP_END_SEQ_LOC;
sdb.primitive = REQ;
sdb.invoke_id = 0;
sdb.result = 0;
esrp.rem_add = 0;
esrp.dummy = 0;
profi_snd_req_res(hDevice, &sdb, &esrp, PB_FALSE);
try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result);
if ((con_ind_sdb.service == DP_END_SEQ_LOC) &&
(con_ind_sdb.primitive == CON ) &&
(con_ind_sdb.result == POS )) {
op->Status = PB__NOCONN;
return (PB_TRUE);
}
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
/*----------------------------------------------------------------------------*\
Initializes one DP slave in the master card
\*----------------------------------------------------------------------------*/
......@@ -457,12 +553,15 @@ static pwr_tStatus dp_download_slave (
unsigned char param[512];
} slave_data;
char *send_buf;
T_DP_SLAVE_PARA_SET prm_head;
T_DP_PRM_DATA prm_data;
T_DP_AAT_DATA aat_data;
T_DP_SLAVE_USER_DATA user_data;
USIGN16 download_data_size;
USIGN16 data_len;
pwr_tBoolean failure = FALSE;
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
......@@ -475,7 +574,7 @@ static pwr_tStatus dp_download_slave (
op->PrmUserDataLen + op->ConfigDataLen +
sizeof(aat_data) + sizeof(user_data);
data_len = sizeof(slave_data.drp) + download_data_size;
data_len = download_data_size;
sdb.comm_ref = 0;
sdb.layer = DP;
......@@ -484,11 +583,6 @@ static pwr_tStatus dp_download_slave (
sdb.invoke_id = 0;
sdb.result = 0;
slave_data.drp.data_len = download_data_size;
slave_data.drp.rem_add = 0;
slave_data.drp.area_code = op->SlaveAddress;
slave_data.drp.add_offset = 0;
prm_head.slave_para_len = swap16(download_data_size);
prm_head.sl_flag = DP_SL_NEW_PRM | DP_SL_ACTIVE;
prm_head.slave_type = DP_SLAVE_TYPE_DP;
......@@ -529,20 +623,58 @@ static pwr_tStatus dp_download_slave (
memcpy(&slave_data.param[i], &user_data, sizeof(user_data));
i += sizeof(user_data);
slave_data.drp.rem_add = 0;
slave_data.drp.area_code = op->SlaveAddress;
slave_data.drp.add_offset = 0;
send_buf = (char *) slave_data.param;
if (data_len > DP_MAX_DOWNLOAD_DATA_LEN) {
if (!start_download_seq(hDevice, op)) {
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
}
while (download_data_size > 0) {
slave_data.drp.data_len = MIN(download_data_size, DP_MAX_DOWNLOAD_DATA_LEN);
profi_snd_req_res(hDevice, &sdb, &slave_data, PB_FALSE);
try_profi_rcv_con_ind(hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len, &result);
if ((con_ind_sdb.service == DP_DOWNLOAD_LOC) &&
(con_ind_sdb.primitive == CON ) &&
if (con_ind_sdb.service == DP_DOWNLOAD_LOC) {
if ((con_ind_sdb.primitive == CON ) &&
(con_ind_sdb.result == POS )) {
op->Status = PB__NOCONN;
return (PB_TRUE);
} else {
op->Status = PB__INITFAIL;
failure = TRUE;
break;
}
}
if (download_data_size > DP_MAX_DOWNLOAD_DATA_LEN) {
download_data_size -= DP_MAX_DOWNLOAD_DATA_LEN;
slave_data.drp.add_offset += DP_MAX_DOWNLOAD_DATA_LEN;
send_buf += DP_MAX_DOWNLOAD_DATA_LEN;
memcpy(slave_data.param, send_buf, MIN(download_data_size, DP_MAX_DOWNLOAD_DATA_LEN));
}
else
download_data_size = 0;
}
if (data_len > DP_MAX_DOWNLOAD_DATA_LEN) {
if (!end_download_seq(hDevice, op)) {
op->Status = PB__INITFAIL;
return (PB_FALSE);
}
}
if (failure)
return (PB_FALSE);
else
return (PB_TRUE);
}
......@@ -601,6 +733,215 @@ static pwr_tStatus dp_io_offsets (
return (PB_FALSE);
}
/* Supervision thread */
void *handle_events(void *ptr) {
agent_args *args;
io_sAgentLocal *local;
io_sAgent *ap;
short sts;
T_PROFI_DEVICE_HANDLE *hDevice;
pwr_sClass_Pb_Profiboard *op;
char s [128];
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
T_PROFI_SERVICE_DESCR con_ind_sdb;
T_DP_GET_SLAVE_DIAG_CON *get_slave_diag_con_ptr;
struct timespec rqtp = {0, 10000000}; // 10 ms
args = (agent_args *) ptr;
local = (io_sAgentLocal *) args->local;
ap = args->ap;
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
op = (pwr_sClass_Pb_Profiboard *) ap->op;
/* If everything is fine we should be in state OPERATE
Make a poll to see if there are diagnostics, the answer also tell us
if there are any hardware faults. In that case, make a reset and a new init. */
while (1) {
if (op->DisableBus) exit(0);
pthread_mutex_lock(&local->mutex);
con_ind_buffer_len = 256;
sts = profi_rcv_con_ind ( hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len);
if (sts == CON_IND_RECEIVED) {
if (con_ind_sdb.primitive == CON) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
if (op->Status == PB__NOTINIT) {
op->Status = PB__STOPPED;
errh_Info( "Profibus DP Master %s to state STOPPED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (op->Status == PB__STOPPED) {
op->Status = PB__CLEARED;
errh_Info( "Profibus DP Master %s to state CLEARED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_OPERATE);
}
else if (op->Status == PB__CLEARED) {
errh_Info( "Profibus DP Master %s to state OPERATE", ap->Name);
op->Status = PB__NORMAL;
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
op->Diag[2]++;
local->slave_diag_requested = op->Diag[3] = PB_FALSE;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if (get_slave_diag_con_ptr->diag_entries) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
dp_get_slave_diag (hDevice);
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %x neg con rec", ap->Name, *((unsigned short *) con_ind_buffer) );
} /* else POS */
} /* if CON */
else if (con_ind_sdb.primitive == IND) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
case FMB_FM2_EVENT: {
switch (((T_FMB_FM2_EVENT_IND FAR*) con_ind_buffer)->reason) {
case FM2_FAULT_ADDRESS : sprintf (s, "Duplicate address recognized"); break;
case FM2_FAULT_PHY : sprintf (s, "Phys.layer is malfunctioning"); break;
case FM2_FAULT_TTO : sprintf (s, "Time out on bus detected "); break;
case FM2_FAULT_SYN : sprintf (s, "No receiver synchronization "); break;
case FM2_FAULT_OUT_OF_RING : sprintf (s, "Station out of ring "); break;
case FM2_GAP_EVENT : sprintf (s, "New station in ring "); break;
default : sprintf (s, "Unknown reason code received");
} /* switch reason */
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
break;
} /* case FMB_FM2_EVENT */
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
USIGN8 usif_state;
usif_state = ((T_DP_ACT_PARAM_IND FAR*) con_ind_buffer)->activate;
switch (usif_state) {
case DP_OP_MODE_STOP : {
op->Status = PB__STOPPED;
sprintf (s, "Mode changed to STOP");
break;
}
case DP_OP_MODE_CLEAR : {
op->Status = PB__CLEARED;
sprintf (s, "Mode changed to CLEAR");
break;
}
case DP_OP_MODE_OPERATE: {
op->Status = PB__NORMAL;
sprintf (s, "Mode changed to OPERATE");
break;
}
}
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
if (usif_state == DP_OP_MODE_STOP) {
usif_state = DP_OP_MODE_CLEAR;
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (usif_state == DP_OP_MODE_CLEAR) {
usif_state = DP_OP_MODE_OPERATE;
dp_act_param_loc (hDevice, DP_OP_MODE_OPERATE);
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
op->Diag[0]++;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if ( (get_slave_diag_con_ptr->diag_entries) &&
(! local->slave_diag_requested ) ) {
if (dp_get_slave_diag(hDevice)) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
} else {
errh_Warning( "Profibus - Request for diag failed.");
}
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %x neg ind rec", ap->Name, *((unsigned short *) con_ind_buffer) );
} /* else POS */
} /* if IND */
} else if (sts != NO_CON_IND_RECEIVED) {
op->Status = PB__NOTINIT;
} else {
if (local->slave_diag_requested) {
errh_Info( "Profibus - Diag re-request");
dp_get_slave_diag(hDevice);
}
}
pthread_mutex_unlock(&local->mutex);
nanosleep(&rqtp, NULL);
}
}
/*----------------------------------------------------------------------------*\
Init method for the Pb_profiboard agent
\*----------------------------------------------------------------------------*/
......@@ -613,6 +954,8 @@ static pwr_tStatus IoAgentInit (
pwr_tUInt16 sts;
pwr_tStatus status;
T_PROFI_DEVICE_HANDLE *hDevice;
io_sAgentLocal *local;
char ok;
pwr_tObjid slave_objid;
......@@ -635,6 +978,9 @@ static pwr_tStatus IoAgentInit (
}
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
local = (io_sAgentLocal *) ap->Local;
op = (pwr_sClass_Pb_Profiboard *) ap->op;
op->Status = PB__NOTINIT;
......@@ -775,6 +1121,21 @@ static pwr_tStatus IoAgentInit (
return IO__ERRINIDEVICE;
}
} */
/* Active supervision thread */
pthread_attr_t attr;
pthread_mutexattr_t mutexattr;
local->args.local = local;
local->args.ap = ap;
pthread_mutexattr_init(&mutexattr);
pthread_mutex_init(&local->mutex, &mutexattr);
pthread_mutexattr_destroy(&mutexattr);
pthread_attr_init(&attr);
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
pthread_create(&local->events, &attr, handle_events, &local->args);
}
else
op->Status = PB__DISABLED;
......@@ -846,13 +1207,6 @@ static pwr_tStatus IoAgentRead (
T_PROFI_DEVICE_HANDLE *hDevice;
pwr_sClass_Pb_Profiboard *op;
pwr_tUInt16 sts;
static int count;
char s [128];
USIGN8 con_ind_buffer [256];
USIGN16 con_ind_buffer_len = 256;
T_PROFI_SERVICE_DESCR con_ind_sdb;
T_DP_GET_SLAVE_DIAG_CON FAR *get_slave_diag_con_ptr;
pwr_sClass_Pb_Profiboard *mp;
pwr_sClass_Pb_DP_Slave *sp;
......@@ -863,6 +1217,8 @@ static pwr_tStatus IoAgentRead (
local = (io_sAgentLocal *) ap->Local;
op = (pwr_sClass_Pb_Profiboard *) ap->op;
pthread_mutex_lock(&local->mutex);
/* Iterate over the slaves. */
for (slave_list = ap->racklist; slave_list != NULL;
slave_list = slave_list->next) {
......@@ -879,202 +1235,7 @@ static pwr_tStatus IoAgentRead (
}
/* If everything is fine we should be in state OPERATE
Make a poll to see if there are diagnostics, the answer also tell us
if there are any hardware faults. In that case, make a reset and a new init. */
count++;
if ((op->Process & io_mProcess_Profibus) && (ctx->Process != io_mProcess_Profibus))
return IO__SUCCESS;
if (op->DisableBus != 1) {
switch (op->Status) {
case PB__NORMAL:
case PB__STOPPED:
case PB__CLEARED:
case PB__NOTINIT:
sts = profi_rcv_con_ind ( hDevice, &con_ind_sdb, con_ind_buffer, &con_ind_buffer_len);
if (sts == CON_IND_RECEIVED) {
if (con_ind_sdb.primitive == CON) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
if (op->Status == PB__NOTINIT) {
op->Status = PB__STOPPED;
errh_Info( "Profibus DP Master %s to state STOPPED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (op->Status == PB__STOPPED) {
op->Status = PB__CLEARED;
errh_Info( "Profibus DP Master %s to state CLEARED", ap->Name);
dp_act_param_loc(hDevice, DP_OP_MODE_OPERATE);
}
else if (op->Status == PB__CLEARED) {
errh_Info( "Profibus DP Master %s to state OPERATE", ap->Name);
op->Status = PB__NORMAL;
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[0]);
op->Diag[2]++;
local->slave_diag_requested = op->Diag[3] = PB_FALSE;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if (get_slave_diag_con_ptr->diag_entries) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
dp_get_slave_diag (hDevice);
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %d neg con rec", ap->Name, count );
} /* else POS */
} /* if CON */
else if (con_ind_sdb.primitive == IND) {
if (con_ind_sdb.result == POS) {
switch (con_ind_sdb.service) {
case FMB_FM2_EVENT: {
switch (((T_FMB_FM2_EVENT_IND FAR*) con_ind_buffer)->reason) {
case FM2_FAULT_ADDRESS : sprintf (s, "Duplicate address recognized"); break;
case FM2_FAULT_PHY : sprintf (s, "Phys.layer is malfunctioning"); break;
case FM2_FAULT_TTO : sprintf (s, "Time out on bus detected "); break;
case FM2_FAULT_SYN : sprintf (s, "No receiver synchronization "); break;
case FM2_FAULT_OUT_OF_RING : sprintf (s, "Station out of ring "); break;
case FM2_GAP_EVENT : sprintf (s, "New station in ring "); break;
default : sprintf (s, "Unknown reason code received");
} /* switch reason */
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
break;
} /* case FMB_FM2_EVENT */
/*--------------------------------------------------------------*/
case DP_ACT_PARAM_LOC: {
USIGN8 usif_state;
usif_state = ((T_DP_ACT_PARAM_IND FAR*) con_ind_buffer)->activate;
switch (usif_state) {
case DP_OP_MODE_STOP : {
op->Status = PB__STOPPED;
sprintf (s, "Mode changed to STOP");
break;
}
case DP_OP_MODE_CLEAR : {
op->Status = PB__CLEARED;
sprintf (s, "Mode changed to CLEAR");
break;
}
case DP_OP_MODE_OPERATE: {
op->Status = PB__NORMAL;
sprintf (s, "Mode changed to OPERATE");
break;
}
}
errh_Info( "Profibus DP Master %s - %s", ap->Name, s );
if (usif_state == DP_OP_MODE_STOP) {
usif_state = DP_OP_MODE_CLEAR;
dp_act_param_loc(hDevice, DP_OP_MODE_CLEAR);
}
else if (usif_state == DP_OP_MODE_CLEAR) {
usif_state = DP_OP_MODE_OPERATE;
dp_act_param_loc (hDevice, DP_OP_MODE_OPERATE);
}
break;
} /* case DP_ACT_PARAM_LOC */
/*--------------------------------------------------------------*/
case DP_GET_SLAVE_DIAG: {
get_slave_diag_con_ptr = (T_DP_GET_SLAVE_DIAG_CON FAR*) con_ind_buffer;
dp_get_slave_diag_con (get_slave_diag_con_ptr, ap->racklist, op->Diag[1]);
op->Diag[0]++;
if (get_slave_diag_con_ptr->diag_entries < 0) {
errh_Warning( "Profibus - diagnostic circular buffer owerflow.");
}
if ( (get_slave_diag_con_ptr->diag_entries) &&
(! local->slave_diag_requested ) ) {
if (dp_get_slave_diag(hDevice)) {
local->slave_diag_requested = op->Diag[3] = PB_TRUE;
} else {
errh_Warning( "Profibus - Request for diag failed.");
}
}
break;
} /* case DP_GET_SLAVE_DIAG */
/*--------------------------------------------------------------*/
default: {
break;
} /* deafult service */
} /* switch */
} /* if POS */
else {
op->Status = PB__NOTINIT;
errh_Error( "Profibus DP Master %s - %d neg ind rec", ap->Name, count );
} /* else POS */
} /* if IND */
} else if (sts != NO_CON_IND_RECEIVED) {
op->Status = PB__NOTINIT;
} else {
if (local->slave_diag_requested) {
errh_Info( "Profibus - Diag re-request");
dp_get_slave_diag(hDevice);
}
}
break;
default:
op->Status = PB__NOTINIT;
errh_Error( "Reconfig of Profibus DP Master %s - %d", ap->Name, count );
IoAgentClose(ctx, ap);
IoAgentInit(ctx, ap);
break;
}
}
pthread_mutex_unlock(&local->mutex);
return IO__SUCCESS;
}
......@@ -1088,6 +1249,7 @@ static pwr_tStatus IoAgentWrite (
io_sAgent *ap
)
{
io_sAgentLocal *local;
T_PROFI_DEVICE_HANDLE *hDevice;
pwr_tUInt16 sts;
......@@ -1096,6 +1258,9 @@ static pwr_tStatus IoAgentWrite (
io_sRack *slave_list;
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
local = (io_sAgentLocal *) ap->Local;
pthread_mutex_lock(&local->mutex);
/* Iterate over the slaves. */
for (slave_list = ap->racklist; slave_list != NULL;
......@@ -1119,6 +1284,8 @@ static pwr_tStatus IoAgentWrite (
}
pthread_mutex_unlock(&local->mutex);
return IO__SUCCESS;
}
......@@ -1145,6 +1312,10 @@ static pwr_tStatus IoAgentClose (
local = (io_sAgentLocal *) ap->Local;
if ( !local) return IO__SUCCESS;
pthread_cancel(local->events);
pthread_mutex_lock(&local->mutex);
hDevice = (T_PROFI_DEVICE_HANDLE *) ap->Local;
sdb.comm_ref = 0;
sdb.layer = DP;
......@@ -1170,6 +1341,8 @@ static pwr_tStatus IoAgentClose (
close(local->hDpsOutputDataDevice);
close(local->hDpsBoardDevice);
pthread_mutex_unlock(&local->mutex);
free( (char *)local);
return sts;
......
......@@ -276,20 +276,20 @@ static pwr_tStatus IoAgentInit (
for (ll = 0; ll < local->device_data[ii]->module_data[kk]->submodule_data.size(); ll++) {
PnSubmoduleData *submodule;
submodule = local->device_data[ii]->module_data[kk]->submodule_data[ll];
if (submodule->type & type) {
if ((submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT) ||
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT)) {
if ((type == PROFINET_IO_CR_TYPE_INPUT) &&
((submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT) ||
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT))) {
submodule->offset_clean_io_in = offset_inputs;
offset_inputs += submodule->io_in_data_length;
}
if ((submodule->type == PROFINET_IO_SUBMODULE_TYPE_OUTPUT) ||
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT)) {
else if ((type == PROFINET_IO_CR_TYPE_OUTPUT) &&
((submodule->type == PROFINET_IO_SUBMODULE_TYPE_OUTPUT) ||
(submodule->type == PROFINET_IO_SUBMODULE_TYPE_INPUT_AND_OUTPUT))) {
submodule->offset_clean_io_out = offset_outputs;
offset_outputs += submodule->io_out_data_length;
}
}
}
}
local->device_data[ii]->iocr_data[jj]->clean_io_data = (unsigned char *) calloc(1, offset_inputs + offset_outputs);
local->device_data[ii]->iocr_data[jj]->clean_io_data_length = offset_inputs + offset_outputs;
}
......
......@@ -221,3 +221,5 @@
120823 cs plc Plc, serveral processes, handling of error log and process status
120824 cs plc Plc, several plc processes, signal handling with rt_ini at start and restart
120926 cs neth Size check in subscription client message to avoid rt_neth crash at bad network
121203 rk elog Added executable rt_elog_dump that will dump historical event log to text-file.
ifndef link_rule_mk
link_rule_mk := 1
link = $(ld) $(linkflags) $(domap) -o $(export_exe) \
$(export_obj) $(objects) $(rt_msg_objs) \
$(pwr_obj)/rt_io_user.o \
$(pwre_conf_libdir) $(pwre_conf_libpwrrt) $(pwre_conf_lib)
endif
/* rt_elog_dump.c -- <short description>
Author Jonas Nylund.
Dumps the rt_eventlog.db to a file.
If the eventlog doesn't exist a errormess will appear.
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <db.h>
#include "co_time.h"
#include "rt_mh_def.h"
#include "co_dcli.h"
#include "rt_elog.h"
void ReadFromDBAndPutInFile(FILE *outFile);
void Init(char *fname);
void WriteColumnNames(FILE *outFile);
int Write(sEvent *sp, FILE *outFile);
void printMess(sEvent *sp, FILE *outFile);
void printAck(sEvent *sp, FILE *outFile);
void printRet(sEvent *sp, FILE *outFile);
void printBlock(sEvent *sp, FILE *outFile);
void printMsgInfo(mh_sMsgInfo *mp, FILE *outFile);
void printEventFlags(FILE *outFile, int flags);
void convertEventType(int type, char *ret);
void convertEventPrio(int prio, char *ret);
DB *dataBaseP = NULL;
int
main (int argc, char *argv[])
{
FILE *outFile;
pwr_tInt32 ret;
if(argc == 3)
{
if(argv[2] != NULL)
outFile = fopen(argv[2], "w");
}
else
outFile = fopen(DUMPFILE, "w");
if(outFile == NULL)
{
printf("kunde ej skapa fil, avslutar");
exit(1);
}
if(argc > 1)
Init(argv[1]);
else
Init(DATABASE);
ReadFromDBAndPutInFile(outFile);
fclose(outFile);
if((ret = dataBaseP->close(dataBaseP,0) != 0))
{
printf("error db_close: %s\n", db_strerror(ret));
}
if(argc == 3)
printf("Programmet klart resultatet finns i filen %s\n", argv[2]);
else
printf("Programmet klart resultatet finns i filen %s\n", DUMPFILE);
return 0;
}
void
Init (char *fname)
{
pwr_tInt32 ret;
char dbName[200];
dcli_translate_filename( dbName, fname);
/*create the database if it's not already created*/
if((ret = db_create(&dataBaseP, NULL, 0)) != 0)
{
/*error creating db-handle send the mess to errh, then exit*/
printf("error db_create: %s\n", db_strerror(ret));
printf(" Fel vid skapande av databashandtag avslutar\n");
exit(1);
}
#if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
ret = dataBaseP->open(dataBaseP, NULL, dbName, NULL, DATABASETYPE, DB_RDONLY, 0);
#else
ret = dataBaseP->open(dataBaseP, dbName, NULL, DATABASETYPE, DB_RDONLY, 0);
#endif
if(ret != 0)
{
/*error opening/creating db send the mess to errh, then exit*/
printf("error db_open: %s\n", db_strerror(ret));
exit(1);
}
}
void ReadFromDBAndPutInFile(FILE *outFile)
{
pwr_tInt32 ret, sts;
pwr_tUInt32 nrOfEvents = 0;
sEvent *eventp;
DBT data, key;
DBC *dbcp;
WriteColumnNames(outFile);
/* Acquire a cursor for the database. */
if ((ret = dataBaseP->cursor(dataBaseP, NULL, &dbcp, 0)) != 0)
{
printf("error dataBaseP->cursor: %s\n", db_strerror(ret));
exit(1);
}
/* Initialize the key/data return pair. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
if((ret = dbcp->c_get(dbcp, &key, &data, DB_FIRST)) == 0)
{
eventp = data.data;
sts = Write(eventp, outFile);
nrOfEvents++;
}
while((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
{
eventp = data.data;
sts = Write(eventp, outFile);
nrOfEvents++;
}
if(ret != DB_NOTFOUND)
{
printf("error dbcp->c_get: %s\n", db_strerror(ret));
printf("Fel vid frsk att lsa post nr %u, avslutar\n", nrOfEvents);
exit(1);
}
printf("Antal hndelser skrivna till fil: %u\n", nrOfEvents);
/*Close the cursor*/
if((ret = dbcp->c_close(dbcp)) != 0)
{
printf("Error dbcp->c_close(): %s\n", db_strerror(ret));
}
}
void WriteColumnNames(FILE *outFile)
{
fprintf(outFile, "Nid\t");
fprintf(outFile, "BirthTime\t");
fprintf(outFile, "Idx\t");
fprintf(outFile, "EventFlags\t");
fprintf(outFile, "EventTime\t");
fprintf(outFile, "EventName\t");
fprintf(outFile, "EventType\t");
fprintf(outFile, "EventPrio\t");
fprintf(outFile, "EventText\t");
//fprintf(outFile, "Status\t");
fprintf(outFile, "TargetIdx\t");
fprintf(outFile, "DetectTime\t");
fprintf(outFile, "AValue\t");
fprintf(outFile, "CtrlLimit\t");
fprintf(outFile, "Hysteres\t");
fprintf(outFile, "Unit\t");
fprintf(outFile, "DValue\t");
fprintf(outFile, "High\t");
fprintf(outFile, "\n");
}
int
Write (
sEvent *sp,
FILE *outFile
)
{
switch (sp->EventType) {
case mh_eEvent_Alarm:
case mh_eEvent_Info:
printMess(sp, outFile);
break;
case mh_eEvent_Ack:
printAck(sp, outFile);
break;
case mh_eEvent_Cancel:
case mh_eEvent_Return:
printRet(sp, outFile);
break;
case mh_eEvent_Block:
case mh_eEvent_Unblock:
case mh_eEvent_Reblock:
case mh_eEvent_CancelBlock:
printBlock(sp, outFile);
break;
default:
printf("rt_elog_dump: Error in Write unknown EventType");
break;
}
fprintf(outFile, "\n");
return 1;
}
void
printMess (
sEvent *sp,
FILE *outFile
)
{
printMsgInfo(&(sp->Mess.message.Info), outFile);
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile, "%s\t", sp->Mess.message.EventText);
fprintf(outFile,"\t");
fprintf(outFile,"\t");
switch (sp->Mess.message.SupInfo.SupType) {
case mh_eSupType_Analog:
fprintf(outFile, "%.2f\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.ActualValue);
fprintf(outFile, "%.2f\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.CtrlLimit);
fprintf(outFile, "%.2f\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.Hysteres);
fprintf(outFile, "%s\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.Unit);
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.A.High);
break;
case mh_eSupType_Digital:
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.D.ActualValue);
fprintf(outFile, "%u\t", sp->Mess.message.SupInfo.mh_uSupInfo_u.D.High);
break;
case mh_eSupType__:
case mh_eSupType_None:
case mh_eSupType_Link:
case mh_eSupType_:
break;
}
}
void
printAck (
sEvent *sp,
FILE *outFile
)
{
char time_str[40];
pwr_tTime event_time;
printMsgInfo(&(sp->Mess.ack.Info), outFile);
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ack.TargetId.Idx);
event_time = net_NetTimeToTime(&(sp->Mess.ack.DetectTime));
time_AtoAscii(&event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
switch (sp->Mess.ack.SupInfo.SupType) {
case mh_eSupType_Analog:
fprintf(outFile, "%.2f\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.ActualValue);
fprintf(outFile, "%.2f\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.CtrlLimit);
fprintf(outFile, "%.2f\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.Hysteres);
fprintf(outFile, "%s\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.Unit);
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.A.High);
break;
case mh_eSupType_Digital:
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.D.ActualValue);
fprintf(outFile, "%u\t", sp->Mess.ack.SupInfo.mh_uSupInfo_u.D.High);
break;
case mh_eSupType__:
case mh_eSupType_None:
case mh_eSupType_Link:
case mh_eSupType_:
break;
}
}
void
printRet (
sEvent *sp,
FILE *outFile
)
{
char time_str[40];
printMsgInfo(&(sp->Mess.ret.Info), outFile);
pwr_tTime event_time;
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile, "%s\t", sp->Mess.ret.EventText);
fprintf(outFile, "%u\t", sp->Mess.ret.TargetId.Idx);
event_time = net_NetTimeToTime(&(sp->Mess.ret.DetectTime));
time_AtoAscii( &event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
switch (sp->Mess.ret.SupInfo.SupType) {
case mh_eSupType_Analog:
fprintf(outFile, "%.2f\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.ActualValue);
fprintf(outFile, "%.2f\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.CtrlLimit);
fprintf(outFile, "%.2f\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.Hysteres);
fprintf(outFile, "%s\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.Unit);
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.A.High);
break;
case mh_eSupType_Digital:
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.D.ActualValue);
fprintf(outFile, "%u\t", sp->Mess.ret.SupInfo.mh_uSupInfo_u.D.High);
break;
case mh_eSupType__:
case mh_eSupType_None:
case mh_eSupType_Link:
case mh_eSupType_:
break;
}
}
void
printBlock (
sEvent *sp,
FILE *outFile
)
{
char time_str[40];
pwr_tTime event_time;
printMsgInfo(&(sp->Mess.block.Info), outFile);
//EventText
//Status
//TargetIdx
//DetectTime
//AValue
//CtrlLimit
//Hysteres
//Unit
//DValue
//High
fprintf(outFile,"\t");
fprintf(outFile, "%u\t", sp->Mess.block.TargetId.Idx);
event_time = net_NetTimeToTime( &(sp->Mess.block.DetectTime));
time_AtoAscii(&event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
fprintf(outFile,"\t");
}
void
printMsgInfo (
mh_sMsgInfo *mp,
FILE *outFile
)
{
char time_str[40];
pwr_tTime event_time;
fprintf(outFile, "%d\t", mp->Id.Nix);
event_time = net_NetTimeToTime(&(mp->Id.BirthTime));
time_AtoAscii(&event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
fprintf(outFile, "%d\t",mp->Id.Idx);
/*
sp->Object
sp->SupObject
*/
printEventFlags(outFile, mp->EventFlags);
fprintf(outFile, "\t");
event_time = net_NetTimeToTime(&(mp->EventTime));
time_AtoAscii( &event_time, time_eFormat_ComprDateAndTime, time_str, sizeof(time_str));
fprintf(outFile, "%s\t", time_str);
fprintf(outFile, "%s\t",mp->EventName_V3);
convertEventType(mp->EventType, time_str);
fprintf(outFile, "%s\t", time_str);
convertEventPrio(mp->EventPrio, time_str);
fprintf(outFile, "%s\t",time_str);
}
void printEventFlags(FILE *outFile, int flags)
{
if(flags & mh_mEventFlags_Return)
{
fprintf(outFile,"Return/");
}
if(flags & mh_mEventFlags_Ack)
{
fprintf(outFile,"Ack/");
}
if(flags & mh_mEventFlags_Bell)
{
fprintf(outFile,"Bell/");
}
if(flags & mh_mEventFlags_Force)
{
fprintf(outFile,"Force/");
}
if(flags & mh_mEventFlags_InfoWindow)
{
fprintf(outFile,"InfoWind");
}
if(flags & mh_mEventFlags_Returned)
{
fprintf(outFile,"Returned/");
}
if(flags & mh_mEventFlags_NoObject)
{
fprintf(outFile,"NoObject");
}
}
void convertEventType(int type, char *ret)
{
switch (type) {
case mh_eEvent_Alarm:
strcpy(ret, "Alarm");
break;
case mh_eEvent_Info:
strcpy(ret, "Info");
break;
case mh_eEvent_Ack:
strcpy(ret, "Ack");
break;
case mh_eEvent_Cancel:
strcpy(ret, "Cancel");
break;
case mh_eEvent_Return:
strcpy(ret, "Return");
break;
case mh_eEvent_Block:
strcpy(ret, "Block");
break;
case mh_eEvent_Unblock:
strcpy(ret, "Unblock");
break;
case mh_eEvent_Reblock:
strcpy(ret, "Reblock");
break;
case mh_eEvent_CancelBlock:
strcpy(ret, "CancelBlock");
break;
default:
strcpy(ret, " ");
break;
}
}
void convertEventPrio(int prio, char *ret)
{
switch (prio) {
case mh_eEventPrio_A:
strcpy(ret, "A");
break;
case mh_eEventPrio_B:
strcpy(ret, "B");
break;
case mh_eEventPrio_C:
strcpy(ret, "C");
break;
case mh_eEventPrio_D:
strcpy(ret, "D");
break;
default:
strcpy(ret, " ");
break;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment