Axioline F Hot Reload

Hey All,

Understand its not electrically supported, but we would like to automatically reload our C++ runtime whenever the modules on an Axioline F are swapped.

I'm currently looking at https://api.plcnext.help/api_docs_2020-3/classArp_1_1Io_1_1Axioline_1_1Services_1_1IAxioMasterService.html as the class that we will need to use to perform this.

Our current CPP code is more or less:

- ArpPlcGds_BeginRead for Arp.Io.AxlC/AXIO_DIAG_STATUS_REG
- Check If it equals 0xE010 (i.e. F_BD_BIT - Bus Different) is set (This will be fleshed out more past proof of concept)
- If it does, then call
 axioMasterService->ResetMaster();
 axioMasterService->CreateConfiguration(0x0001);
 axioMasterService->ActivateConfiguration(0x0001);

This currently produces logging like such (Noting endianess of what I'm logging is inverted from what the manual indicates):
13.12.21 06:44:09.995 root                      INFO    - AXIO Status Changed from FFFF to E000 <-- Initialised & working
13.12.21 06:45:35.016 root                      INFO    - AXIO Status Changed from E000 to C400 <-- Remove a DI16 module
13.12.21 06:45:46.019 root                      INFO    - AXIO Status Changed from C400 to C410 <--- Remove another DI16 module
13.12.21 06:45:49.521 root                      INFO    - AXIO Status Changed from C410 to E010 <--- Swap position of two removed modules (in an SE6)
13.12.21 06:45:49.521 root                      INFO    - AXIO Status indicates a different bus configuration, hot reloading
13.12.21 06:45:49.814 root                      INFO    - AXIO Status reload successful <-- Written after the reset/create/activate code above
13.12.21 06:45:50.314 root                      INFO    - AXIO Status Changed from E010 to C000 <--- Result after code above

Some of this code is gathered from the plcNext Bus Conductor example, however, I am sure I am just missing some crucial final step. We are essentially trying to automate "sudo /etc/init.d/plcnext restart" whenever the bus configuration changes (As currently, if I "hot-swap" two modules and run the restart it works perfectly). Please note that the module types are not changing here, purely for replacement if a module dies.

Cheers,

Joseph

Hello Joseph,

[b]please note that the module types are not changing here, purely for replacement if a module dies.[/b]
if you do not introduce new modules and only replace faulty modules with identical modules.
I do not understand what the purpose of the application is.
The PLC should automatically accept those modules already,
without any manual AxioMasterService implementation.

What exactly is unsatisfactory in your usecase with the current implementation?

kind regards,
Oliver

Hey Oliver,

Site scenario is:
PLC is running, fully powered up
Say a DI16 module in an SE6 fails
Without removing power, swap faulty DI16 with a new DI16, whilst SE6 remains fully powered
After performing this swap, the SE6 LED's indicate solid green on all sub-modules except for the one that is swapped, which remains flashing green
A check of the diagnostic register at this point indicates that F_BD_BIT is set
IO at this point can be read/written to all SE6 modules except for the one that has been interchanged
A restart of the PLC C++ application via `sudo /etc/init.d/plcnext restart` at this point will result in it coming back online and the F_BD_BIT clearing and data can then be read/written to the swapped module as if no swap had occurred.

In our test environment, we are simulating this "site fault" by swapping two modules around (Both DI16) rather than removing a single module and replacing with a new module.

The issue we are trying to avoid is the restart of the entire PLC runtime, as numerous things start up and this means the reload time after swapping a module is potentially on the order of 1 minute. Whereas if we can re-initialise the entire Axioline F bus from within the C++ runtime on its own, we are hoping to achieve something closer to the sub-10 second region.

Cheers, 

Joseph

Managed to get it working, having a more careful read through the BusConductor C++ example. Below was the implementation used to successfully (Sub 1 second) hot reload when swapping two identical DI16 modules.

[code]
if (axioStatus == 0xE010) {
    Log::Info("AXIO Status indicates a different bus configuration, hot reloading");
    // Reset driver
    //axioMasterService->ResetMaster(); ???
    send[0] = 0x1703;
    send[1] = 0x0000;
    uint16_t response =axioMasterService->AxioControl(send, receive);
    if (response != 0) {
        Log::Error("AXIO reset failed");
    } else {
        Log::Info("AXIO reset successful");
    }

    // Create configuration
    //axioMasterService->CreateConfiguration(0x0001); ???
    send[0] = 0x0710;
    send[1] = 0x0001;
    send[2] = 0x0001;
    response =axioMasterService->AxioControl(send, receive);
    if (response != 0) {
        Log::Error("AXIO configuration create failed");
    } else {
        Log::Info("AXIO configuration create successful");
    }

    // Read configuration
    //axioMasterService->ReadConfiguration(); ???
    send[0] = 0x030B;
    send[1] = 0x0001;
    send[2] = 0x0003;
    response =axioMasterService->AxioControl(send, receive);
    if (response != 0) {
        Log::Error("AXIO configuration read failed");
    } else {
        Log::Info("AXIO configuration read successful");
    }

    // Start local IO?
    //axioMasterService->ActivateConfiguration(0x0001); ???
    send[0] = 0x0728;
    send[1] = 0x0004;
    send[2] = 0x3000;
    send[3] = 0x0001;
    send[4] = 0x0021;
    send[5] = 0x0000;
    receive.clear();
    response = axioMasterService->AxioControl(send, receive);
    if (response != 0) {
        Log::Error("AXIO configuration load failed");
    } else {
        Log::Info("AXIO configuration load successful");
    }

    // Start data transfer
    //axioMasterService->????(); ???
    send[0] = 0x0701;
    send[1] = 0x0001;
    send[2] = 0x0001;
    send[3] = 0x0001;
    send[4] = 0x0021;
    send[5] = 0x0000;
    receive.clear();
    response = axioMasterService->AxioControl(send, receive);
    if (response != 0) {
        Log::Error("AXIO data output enable failed");
    } else {
        Log::Info("AXIO data output enable successful");
    }
}
[/code]

[code]
14.12.21 03:48:58.258 root                      INFO    - AXIO Status Changed from E000 to C400
14.12.21 03:49:11.261 root                      INFO    - AXIO Status Changed from C400 to C410
14.12.21 03:49:18.763 root                      INFO    - AXIO Status Changed from C410 to E010
14.12.21 03:49:18.880 root                      INFO    - AXIO Status indicates a different bus configuration, hot reloading
14.12.21 03:49:18.909 root                      INFO    - AXIO reset successful
14.12.21 03:49:19.143 root                      INFO    - AXIO configuration create successful
14.12.21 03:49:19.172 root                      INFO    - AXIO configuration read successful
14.12.21 03:49:19.188 root                      INFO    - AXIO configuration load successful
14.12.21 03:49:19.192 root                      INFO    - AXIO data output enable successful
14.12.21 03:49:19.693 root                      INFO    - AXIO Status Changed from E010 to E000
[/code]

Only potential request would be that the "random" hex codes I've used be more publicly documented (Current ones there are pulled "magically" from the BusConductor file") and/or that the functions above be confirmed and/or added to IAxioMasterService as a single (or set of) named commands as this is likely a very useful bit of functionality for people to utilise.

A note on my previous posts, I incorrectly identified it as the F_BD_BIT, however, it is in fact the F_PARA_REQ (Module requesting parameters) that is set, which makes more sense, since the bus is probably the same, however the modules are requesting initialisation, which is what I am doing in my code above.