Commit 970b5281 authored by Marcus Nordenberg's avatar Marcus Nordenberg Committed by Esteban Blanc

profinet: propagate state on stack shutdown

(cherry picked from commit 9497f8a92eed8c75f9c90d459a91ec693939b21f)
parent e7b8508a
...@@ -301,7 +301,7 @@ static pwr_tStatus IoAgentWrite(io_tCtx ctx, io_sAgent* ap) ...@@ -301,7 +301,7 @@ static pwr_tStatus IoAgentWrite(io_tCtx ctx, io_sAgent* ap)
pack_write_req(&local->service_req_res, pack_write_req(&local->service_req_res,
local->device_data[ii]->device_ref, &sp->WriteReq); local->device_data[ii]->device_ref, &sp->WriteReq);
sts = pnak_send_service_req_res(0, &local->service_req_res); sts = pnak_send_service_req_res(0, &local->service_req_res);
errh_Info("Profinet - Asynch write, dev: %d", errh_Info("PROFINET: Async write, dev: %d",
local->device_data[ii]->device_ref); local->device_data[ii]->device_ref);
break; break;
} }
...@@ -329,48 +329,59 @@ static pwr_tStatus IoAgentClose(io_tCtx ctx, io_sAgent* ap) ...@@ -329,48 +329,59 @@ static pwr_tStatus IoAgentClose(io_tCtx ctx, io_sAgent* ap)
io_sAgentLocal* local; io_sAgentLocal* local;
int *exitcodep; int *exitcodep;
int error; int error;
pwr_tStatus sts = PB__NOTINIT;
local = (io_sAgentLocal*)ap->Local; local = (io_sAgentLocal*)ap->Local;
if (ctx->Node->EmergBreakTrue == 1)
errh_Fatal("Emergency break detected shutting down PROFINET");
/* Stop profistack */
// Stop the supervision thread before shutting down PROFINET. // Stop the supervision thread before shutting down PROFINET.
local = (io_sAgentLocal*)ap->Local; local = (io_sAgentLocal*)ap->Local;
if (!local) return IO__SUCCESS; if (!local) return IO__SUCCESS;
if ((error = pthread_cancel(local->handle_events))) // Start taking the stack down. A PNAK_WAIT_OBJECT_CHANNEL_CLOSED event will
errh_Warning("Unsuccessful cancelation of PROFINET supervision thread"); // be emitted and the supervision thread will exit
else pnak_stop_stack(0);
errh_Info("Canceled PROFINET supervision thread");
// Wait for the thread to exit // Wait for the thread to exit
if ((error = pthread_join(local->handle_events, (void**)&exitcodep))) if ((error = pthread_join(local->handle_events, (void**)&exitcodep)))
errh_Warning("Unable to wait for PROFINET thread! Might cause undefined behaviour..."); errh_Warning("PROFINET: Unable to wait for supervision thread!");
else else
errh_Info("PROFINET supervision thread has exited. Stopping PROFINET..."); errh_Info("PROFINET: Supervision thread has exited. PROFINET stopped...");
sts = pnak_stop_stack(0);
pnak_term();
free(local); free(local);
local = NULL; local = NULL;
/* Clean data areas .... */ /* Clean data areas .... */
return sts; return IO__SUCCESS;
} }
static pwr_tStatus IoAgentSwap(io_tCtx ctx, io_sAgent* ap, io_eEvent event) static pwr_tStatus IoAgentSwap(io_tCtx ctx, io_sAgent* ap, io_eEvent event)
{ {
switch (event) { switch (event)
{
// For now we just shut down regardless of what EmergBreakSelect says...safety
// first :)
case io_eEvent_EmergencyBreak: case io_eEvent_EmergencyBreak:
case io_eEvent_IoCommEmergencyBreak: errh_Fatal("PROFINET: Emergency break detected! Shutting down PROFINET!");
IoAgentClose(ctx, ap); IoAgentClose(ctx, ap);
// TODO We need a complete overhaul of EmergencyBreakTrue / EmergBreakSelect
// / IOReadWriteFlag
// switch (ctx->Node->EmergBreakSelect)
// {
// case pwr_eEmergBreakSelectEnum_StopIO:
// case pwr_eEmergBreakSelectEnum_Reboot:
// errh_Fatal("PROFINET: Emergency break action (StopIO/Reboot) shutting
// down PROFINET"); IoAgentClose(ctx, ap); break;
// case pwr_eEmergBreakSelectEnum_NoAction:
// errh_Warning("PROFINET: Emergency break action (NoAction).
// Continuing..."); break;
// case pwr_eEmergBreakSelectEnum_FixedOutputValues:
// errh_Warning("PROFINET: Behaviour of FixedOutputValues should be
// configured on device level"); errh_Fatal("PROFINET: Emergency break
// action (Fixed Output Values)."); break;
// }
break;
case io_eEvent_IoCommEmergencyBreak:
break; break;
default: default:
break; break;
......
...@@ -64,7 +64,7 @@ static pwr_tStatus IoRackInit(io_tCtx ctx, io_sAgent* ap, io_sRack* rp) ...@@ -64,7 +64,7 @@ static pwr_tStatus IoRackInit(io_tCtx ctx, io_sAgent* ap, io_sRack* rp)
pwr_sClass_ChanIo* chan_io; pwr_sClass_ChanIo* chan_io;
sts = gdh_ObjidToName(rp->Objid, (char*)&name, sizeof(name), cdh_mNName); sts = gdh_ObjidToName(rp->Objid, (char*)&name, sizeof(name), cdh_mNName);
errh_Info("Init of Profinet Device and Modules %s", name); errh_Info("PROFINET: Init of device and modules %s", name);
op = (pwr_sClass_PnDevice*)rp->op; op = (pwr_sClass_PnDevice*)rp->op;
local = (io_sPnRackLocal*)rp->Local; local = (io_sPnRackLocal*)rp->Local;
...@@ -255,14 +255,17 @@ static pwr_tStatus IoRackRead(io_tCtx ctx, io_sAgent* ap, io_sRack* rp) ...@@ -255,14 +255,17 @@ static pwr_tStatus IoRackRead(io_tCtx ctx, io_sAgent* ap, io_sRack* rp)
sp->ErrorCount++; sp->ErrorCount++;
} }
if (sp->ErrorCount == sp->ErrorHardLimit) { if (sp->ErrorCount == sp->ErrorHardLimit)
errh_Error("IO Error hard limit reached on card '%s', stall action %d", {
errh_Error("PROFINET: IO Error hard limit reached on device '%s', stall action %d",
rp->Name, sp->StallAction); rp->Name, sp->StallAction);
ctx->IOHandler->CardErrorHardLimit = 1; ctx->IOHandler->CardErrorHardLimit = 1;
ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref(rp->Objid); ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref(rp->Objid);
sp->ErrorCount++; sp->ErrorCount++;
} else if (sp->ErrorCount == sp->ErrorSoftLimit) { }
errh_Error("IO Error soft limit reached on card '%s'", rp->Name); else if (sp->ErrorCount == sp->ErrorSoftLimit)
{
errh_Error("PROFINET: IO Error soft limit reached on device '%s'", rp->Name);
ctx->IOHandler->CardErrorSoftLimit = 1; ctx->IOHandler->CardErrorSoftLimit = 1;
ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref(rp->Objid); ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref(rp->Objid);
sp->ErrorCount++; sp->ErrorCount++;
...@@ -297,14 +300,17 @@ static pwr_tStatus IoRackWrite(io_tCtx ctx, io_sAgent* ap, io_sRack* rp) ...@@ -297,14 +300,17 @@ static pwr_tStatus IoRackWrite(io_tCtx ctx, io_sAgent* ap, io_sRack* rp)
sp->ErrorCount++; sp->ErrorCount++;
} }
if (sp->ErrorCount == sp->ErrorHardLimit) { if (sp->ErrorCount == sp->ErrorHardLimit)
errh_Error("IO Error hard limit reached on card '%s', stall action %d", {
errh_Error("PROFINET: IO Error hard limit reached on device '%s', stall action %d",
rp->Name, sp->StallAction); rp->Name, sp->StallAction);
ctx->IOHandler->CardErrorHardLimit = 1; ctx->IOHandler->CardErrorHardLimit = 1;
ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref(rp->Objid); ctx->IOHandler->ErrorHardLimitObject = cdh_ObjidToAref(rp->Objid);
sp->ErrorCount++; sp->ErrorCount++;
} else if (sp->ErrorCount == sp->ErrorSoftLimit) { }
errh_Error("IO Error soft limit reached on card '%s'", rp->Name); else if (sp->ErrorCount == sp->ErrorSoftLimit)
{
errh_Error("PROFINET: IO Error soft limit reached on device '%s'", rp->Name);
ctx->IOHandler->CardErrorSoftLimit = 1; ctx->IOHandler->CardErrorSoftLimit = 1;
ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref(rp->Objid); ctx->IOHandler->ErrorSoftLimitObject = cdh_ObjidToAref(rp->Objid);
sp->ErrorCount++; sp->ErrorCount++;
......
...@@ -1852,7 +1852,7 @@ void handle_device_state_changed(io_sAgentLocal* local, io_sAgent* ap) ...@@ -1852,7 +1852,7 @@ void handle_device_state_changed(io_sAgentLocal* local, io_sAgent* ap)
else else
dev->Status = PB__NOCONN; dev->Status = PB__NOCONN;
errh_Info("Profinet - New device state, dev: %s, state: %d", errh_Info("PROFINET: New device state, dev: %s, state: %d",
slave_list->Name, dev->State); slave_list->Name, dev->State);
} }
} }
...@@ -1969,7 +1969,7 @@ void* handle_events(void* ptr) ...@@ -1969,7 +1969,7 @@ void* handle_events(void* ptr)
/* Initialize interface */ /* Initialize interface */
errh_Info("Initializing interface for Profinet IO Master %s", ap->Name); errh_Info("PROFINET: Initializing interface for controller %s", ap->Name);
/* Add master as a device */ /* Add master as a device */
...@@ -2092,7 +2092,7 @@ void* handle_events(void* ptr) ...@@ -2092,7 +2092,7 @@ void* handle_events(void* ptr)
if (sts != PNAK_OK) if (sts != PNAK_OK)
{ {
op->Status = PB__INITFAIL; op->Status = PB__INITFAIL;
errh_Error("Starting profistack returned with error code: %d", sts); errh_Error("PROFINET: Start of stack returned with error code: %d", sts);
// return IO__ERRINIDEVICE; // return IO__ERRINIDEVICE;
} }
...@@ -2156,7 +2156,7 @@ void* handle_events(void* ptr) ...@@ -2156,7 +2156,7 @@ void* handle_events(void* ptr)
} }
else else
{ {
errh_Error("Download of Profinet Device configuration failed for: %s", errh_Error("PROFINET: Download of device configuration failed for: %s",
device_vect[ii]->device_name); device_vect[ii]->device_name);
/* Setup a dummy i/o area. Depending on exisiting channels this area /* Setup a dummy i/o area. Depending on exisiting channels this area
* needs to exist */ * needs to exist */
...@@ -2221,7 +2221,7 @@ void* handle_events(void* ptr) ...@@ -2221,7 +2221,7 @@ void* handle_events(void* ptr)
if (sts != PNAK_OK) if (sts != PNAK_OK)
{ {
op->Status = PB__INITFAIL; op->Status = PB__INITFAIL;
errh_Error("Profistack unable to go online, errcode: %d", sts); errh_Error("PROFINET: Unable to go online, error code: %d", sts);
// return IO__ERRINIDEVICE; // return IO__ERRINIDEVICE;
} }
...@@ -2242,7 +2242,7 @@ void* handle_events(void* ptr) ...@@ -2242,7 +2242,7 @@ void* handle_events(void* ptr)
if (sts != PNAK_OK) if (sts != PNAK_OK)
{ {
op->Status = PB__INITFAIL; op->Status = PB__INITFAIL;
errh_Error("Profistack unable to set state online, errcode: %d", sts); errh_Error("PROFINET: Unable to set state online, error code: %d", sts);
// return IO__ERRINIDEVICE; // return IO__ERRINIDEVICE;
} }
} }
...@@ -2267,7 +2267,7 @@ void* handle_events(void* ptr) ...@@ -2267,7 +2267,7 @@ void* handle_events(void* ptr)
if (sts != PNAK_OK) if (sts != PNAK_OK)
{ {
op->Status = PB__INITFAIL; op->Status = PB__INITFAIL;
errh_Error("Profistack unable to activate devices, errcode: %d", sts); errh_Error("PROFINET: Unable to activate devices, error code: %d", sts);
// return IO__ERRINIDEVICE; // return IO__ERRINIDEVICE;
} }
...@@ -2290,83 +2290,83 @@ void* handle_events(void* ptr) ...@@ -2290,83 +2290,83 @@ void* handle_events(void* ptr)
pthread_cond_signal(&local->cond); pthread_cond_signal(&local->cond);
pthread_mutex_unlock(&local->mutex); pthread_mutex_unlock(&local->mutex);
/* Do forever ... */ /* Do until we close the channel and break out */
while (1) while (1)
{ {
// wait_object = PNAK_WAIT_OBJECTS_EVENT_IND | PNAK_WAIT_OBJECTS_OTHER /* Other states available:
// | PNAK_WAIT_OBJECT_SERVICE_CON; PNAK_WAIT_OBJECT_ETHERNET_STATE_CHANGED
wait_object = PNAK_WAIT_OBJECTS_ALL & PNAK_WAIT_OBJECT_INTERRUPTED
~(PNAK_WAIT_OBJECT_PROVIDER_DATA_UPDATED | PNAK_WAIT_OBJECTS_EVENT_IND
PNAK_WAIT_OBJECT_CONSUMER_DATA_CHANGED); PNAK_WAIT_OBJECTS_OTHER
PNAK_WAIT_OBJECT_SERVICE_CON
*/
// pthread_mutex_lock(&local->mutex); wait_object =
PNAK_WAIT_OBJECTS_ALL & ~(PNAK_WAIT_OBJECT_PROVIDER_DATA_UPDATED |
PNAK_WAIT_OBJECT_CONSUMER_DATA_CHANGED);
sts = sts =
pnak_wait_for_multiple_objects(0, &wait_object, PNAK_INFINITE_TIMEOUT); pnak_wait_for_multiple_objects(0, &wait_object, PNAK_INFINITE_TIMEOUT);
if (sts == PNAK_OK) if (sts == PNAK_OK)
{ {
if (wait_object & PNAK_WAIT_OBJECT_EXCEPTION) if (wait_object & PNAK_WAIT_OBJECT_CHANNEL_CLOSED)
{
errh_Info("PROFINET: Stack received channel closed event!");
// Iterate through all devices and propagate stopped state to all children
if (ap)
{
((pwr_sClass_PnControllerSoftingPNAK*)ap->op)->Status = PB__STOPPED;
io_sRack* device;
io_sCard* module;
pwr_sClass_PnDevice *dev;
pwr_sClass_PnModule *mod;
for (device = ap->racklist; device != NULL; device = device->next)
{
dev = (pwr_sClass_PnDevice*)device->op;
dev->Status = PB__STOPPED;
for (module = device->cardlist; module != NULL; module = module->next)
{
mod = (pwr_sClass_PnModule*)module->op;
mod->Status = PB__STOPPED;
}
}
}
break;
}
else if (wait_object & PNAK_WAIT_OBJECT_EXCEPTION)
{ {
// printf("Exception !!\n");
handle_exception(local); handle_exception(local);
} }
else if (wait_object & PNAK_WAIT_OBJECT_STATE_CHANGED) else if (wait_object & PNAK_WAIT_OBJECT_STATE_CHANGED)
{ {
// printf("State changed !!\n");
handle_state_changed(local); handle_state_changed(local);
} }
else if (wait_object & PNAK_WAIT_OBJECT_DEVICE_STATE_CHANGED) else if (wait_object & PNAK_WAIT_OBJECT_DEVICE_STATE_CHANGED)
{ {
// printf("Device state changed !!\n");
handle_device_state_changed(local, ap); handle_device_state_changed(local, ap);
} }
else if (wait_object & PNAK_WAIT_OBJECT_ALARM) else if (wait_object & PNAK_WAIT_OBJECT_ALARM)
{ {
// printf("Alarm !!\n");
handle_alarm_indication(local, ap); handle_alarm_indication(local, ap);
} }
// else if (wait_object & PNAK_WAIT_OBJECT_CHANNEL_CLOSED) {
// // printf("Channel closed !!");
// // What to do if channel closes ???;
// }
// else if (wait_object & PNAK_WAIT_OBJECT_ETHERNET_STATE_CHANGED) {
// // printf("Ethernet state changed !!");
// // What to do if ethernet state changes ???;
// }
// else if (wait_object & PNAK_WAIT_OBJECT_INTERRUPTED) {
// // printf("Interrupted !!");
// // What to do if interrupted ???;
// }
else if (wait_object & PNAK_WAIT_OBJECT_SERVICE_CON) else if (wait_object & PNAK_WAIT_OBJECT_SERVICE_CON)
{ {
// printf("Service con !!\n");
sts = handle_service_con(local, ap); sts = handle_service_con(local, ap);
} }
// else
// {
// printf("Unhandled status!! 0x%02X\n", wait_object);
// }
}
else if ((sts == PNAK_ERR_FATAL_ERROR) || (sts == PNAK_EXCEPTION_THROWN))
{
printf("Err Fatal / Exception !!\n");
// user_handle_exception (ChannelId);
} }
else else
{ {
printf("Running == NOT !!\n"); errh_Fatal("PROFINET: Fatal exception occured. Stopping PROFINET!");
// pThisSmObject->Running = PN_FALSE; pnak_stop_stack(0);
} }
// pthread_mutex_unlock(&local->mutex);
} }
pnak_term();
return 0;
} }
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