Hmmmm... After messing some hours with that error message, I finally found this ticket - and yes, the solution is suggested in the title.
So the module, inputs, outputs were working OK, just this stupid message in the PLC Log.
Seems like, in order to implement ICmpIoDrv one have to say something about Module Mapping. Looking at the Parameters for the call, I assume It has stg to do with the possible mapping of parameters to different tasks... Has stg to do with this:
As all this was working OK, I assume (maybe incorrectly) that it is not necessary to do anything in this call, unless you really want to do so... So, - assuming again - that these things were taken care of already somewhere high in the IoDrv, I just set the status to ERR_OK in the call.
This seems to fix the issue. Let me know if I am wrong...
Meanwhile I understood the meaning of this call. At least I think I did. Roughly:
PLEASE FEEL FREE TO CORRECT ME IF I AM WRONG, I AM STILL JUST EXPLORING
IoDrvUpdateMapping is not needed, if you take care all of your input / output parameters at IoDrvUpdateConfigurtion, by providing a memory location, where the IoDrv should read/write the parameters from.
This is done by assigning a pointer to memory location, probably to a variable instance with the proper type and size the parameter.dwDriverSpecific value. This is the value, what the default IoDrvReadInputs / IoDrvWriteOutputs are looking for.
For a practical reason there is no built in safety in these calls - so you just get an Exception - access violation, when the RT / IoDrv finds a blank value here. This happens, if you have defined Input/Output parameters in the XML Device Description, but you did not set their .dwDriverSpecific member to a valid pointer. It's actually very practical for a developer... Naturally, can go around and avoid the Exception:
Maybe, this small additional code explains a little bit better, what is IoDrvBase doing for us, and how IoDrvReadInputs / IoDrvWriteOutputs are actually working: They look for for dwDriverSpecific, as a default "mapping", and if they don't find, just throw up.
This is not the end of the World, you can just implement these calls according to your needs. But... be careful, there are many tricky things are taken care of in the background: especially when it comes to tasks, multicore, memory allocation, etc....
(By the way, it would be nice someone could react, what might be an issue with the above modification ... - because I see some :) )
IoDrvUpdateMapping can be practical, if you don't want to bind the input / output process data to a pre-determined, fixed, hard-coded variable. For example, you would like to "map" the process data of all your modules ("sub devices") in a continuous memory area... for some reason... maybe package them for network transfer? Or you just don't want to implement a special function block for each of your modules? Who knows... Life is dangerous.
The big advantage is, that at the point when this call is initiated, all connectors are already initialized and configured, so you can traverse the complete device tree... Like:
But once again - it is not necessary to set all the .dwDriverSpecific pointers. Just deal with the consequences.
One example is, if you prepare a driver for a modular device - you can not predict the number of inputs / outputs, not even the structure of the configuration data - all this happens ad-hoc, when the station is assembled and configured in the device editor...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hmmmm... After messing some hours with that error message, I finally found this ticket - and yes, the solution is suggested in the title.
So the module, inputs, outputs were working OK, just this stupid message in the PLC Log.
Seems like, in order to implement ICmpIoDrv one have to say something about Module Mapping. Looking at the Parameters for the call, I assume It has stg to do with the possible mapping of parameters to different tasks... Has stg to do with this:
As all this was working OK, I assume (maybe incorrectly) that it is not necessary to do anything in this call, unless you really want to do so... So, - assuming again - that these things were taken care of already somewhere high in the IoDrv, I just set the status to ERR_OK in the call.
This seems to fix the issue. Let me know if I am wrong...
Last edit: Strucc.c 2024-11-10
Update:
Meanwhile I understood the meaning of this call. At least I think I did. Roughly:
PLEASE FEEL FREE TO CORRECT ME IF I AM WRONG, I AM STILL JUST EXPLORING
IoDrvUpdateMapping is not needed, if you take care all of your input / output parameters at IoDrvUpdateConfigurtion, by providing a memory location, where the IoDrv should read/write the parameters from.
This is done by assigning a pointer to memory location, probably to a variable instance with the proper type and size the parameter.dwDriverSpecific value. This is the value, what the default IoDrvReadInputs / IoDrvWriteOutputs are looking for.
For a practical reason there is no built in safety in these calls - so you just get an Exception - access violation, when the RT / IoDrv finds a blank value here. This happens, if you have defined Input/Output parameters in the XML Device Description, but you did not set their .dwDriverSpecific member to a valid pointer. It's actually very practical for a developer... Naturally, can go around and avoid the Exception:
Maybe, this small additional code explains a little bit better, what is IoDrvBase doing for us, and how IoDrvReadInputs / IoDrvWriteOutputs are actually working: They look for for dwDriverSpecific, as a default "mapping", and if they don't find, just throw up.
This is not the end of the World, you can just implement these calls according to your needs. But... be careful, there are many tricky things are taken care of in the background: especially when it comes to tasks, multicore, memory allocation, etc....
(By the way, it would be nice someone could react, what might be an issue with the above modification ... - because I see some :) )
IoDrvUpdateMapping can be practical, if you don't want to bind the input / output process data to a pre-determined, fixed, hard-coded variable. For example, you would like to "map" the process data of all your modules ("sub devices") in a continuous memory area... for some reason... maybe package them for network transfer? Or you just don't want to implement a special function block for each of your modules? Who knows... Life is dangerous.
The big advantage is, that at the point when this call is initiated, all connectors are already initialized and configured, so you can traverse the complete device tree... Like:
But once again - it is not necessary to set all the .dwDriverSpecific pointers. Just deal with the consequences.
One example is, if you prepare a driver for a modular device - you can not predict the number of inputs / outputs, not even the structure of the configuration data - all this happens ad-hoc, when the station is assembled and configured in the device editor...