Hello everyone,
I have used freemaster succesfully so far, but now I have a problem with a PACKED struct pointers. Freemaster shown values are not correct.
The struct is the following where MinasOutput* and MinasInput* are two pointers to PACKED structs:
typedef struct
{
uint16 slaveNum; /*<! Numero dello slave del motore. */
MBDLT25BF_STATE state; /*<! Stato attuale del motore. */
MinasOutput* mbdlt25bfOut; /*<! Puntatore alla struct dei RxPDO. */
MinasInput* mbdlt25bfIn; /*<! Puntatore alla struct dei TxPDO. */
osal_timert tself; /*<! Timer utilizzato per controllare la buona riuscita di un'operazione. */
int acc, dec, max, duration;
DIRECTION direction;
int counter;
}tMbdlt25bf;
On freemaster_cfg.c I did:
FMSTR_TSA_RO_VAR(mbdlt25bf, FMSTR_TSA_USERTYPE(tMbdlt25bf))
FMSTR_TSA_STRUCT(tMbdlt25bf)
FMSTR_TSA_MEMBER(tMbdlt25bf, state, FMSTR_TSA_USERTYPE(MBDLT25BF_STATE))
FMSTR_TSA_MEMBER(tMbdlt25bf, acc, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(tMbdlt25bf, dec, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(tMbdlt25bf, duration, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(tMbdlt25bf, max, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(tMbdlt25bf, counter, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfOut, FMSTR_TSA_USERTYPE(MinasOutput))
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfIn, FMSTR_TSA_USERTYPE(MinasInput))
FMSTR_TSA_STRUCT(MinasOutput)
FMSTR_TSA_MEMBER(MinasOutput, controlword, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasOutput, operation_mode, FMSTR_TSA_SINT8)
FMSTR_TSA_MEMBER(MinasOutput, target_torque, FMSTR_TSA_SINT16)
FMSTR_TSA_MEMBER(MinasOutput, max_torque, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasOutput, target_position, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasOutput, max_motor_speed, FMSTR_TSA_UINT32)
FMSTR_TSA_MEMBER(MinasOutput, touch_probe_function, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasOutput, target_velocity, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasOutput, position_offset, FMSTR_TSA_SINT32)
Is there an alternative solution instead of coping struct field values to some variables and share the latters with freemaster tool ?
Thank you.
Regards,
Davidino
Solved! Go to Solution.
Hello Davidino,
with TSA, the FreeMASTER driver in the MCU actively monitors any access and it denies reading or writing to a memory which is not "described" by at least one TSA entry. It also protects a write access to memory locations marked in TSA as RO (Read-only).
You can turn this protection off (set FMSTR_USE_TSA_SAFETY to 0). This will keep the TSA basic functionality, but will disable the memory access checks.
I think this is the reason for the question mark. If not, let me know and we will investigate further.
Regards,
Michal
Dear Davidino,
the problem is not is the packed structures, but in the fact that you only have pointers to them. You should treat this type as FMSTR_TSA_POINTER which is in fact just a 32bit number.
If you indeed need to read/write the structure members, it would be best to include them directly into the top level structure (not via pointers) or at least give them a fixed (static/global) addresses and access them individually.
There is also a solution for you to access the two child structures indirectly and without a fixed pointers, but this is more complex and will require some small JavaScript support. Let me know if this is needed, I can guide you through necessary steps.
Regards,
Michal
Hello @MichalH ,
thank you very much for your answer. Among the several solution that you proposed me I'd go with the simpler (the one using FMSTR_TSA_POINTER I think) as I don't need to write the fields, only reading is requested.
I cannot make them as structs, as the struct memory locations are shared through an union to an array; and I cannot change that part.
CAn you provide me an example about the simpler approach?
Thank you.
Davidino
Hello,
the simpler way without JavaScript involved:
Now you can access e.g. the "mbdlt25bf.mbdlt25bfOut->controlword" member:
Harder, but more effective way with JavaScript. JavaScript is able to programmatically retrieve an address of the mbdlt25bf.mbdlt25bfOut pointer and define a new symbol properly typed as a pointer to MinasOutput. The members of the referenced structure than appear automatically in the FreeMASTER symbols list:
<!DOCTYPE html>
<html>
<head>
</head>
<body onload="main()">
<OBJECT id="pcm" height="0" width="0" classid="clsid:48A185F1-FFDB-11D3-80E3-00C04F176153">
</OBJECT>
<script>
function main()
{
if(pcm.ReadUIntVariable("mbdlt25bf.mbdlt25bfOut", 4))
{
if(pcm.DefineSymbol("mbdlt25bf.mbdlt25bfOut_ptr", pcm.LastVariable_vValue, "MinasOutput*", 4))
console.log("mbdlt25bf.mbdlt25bfOut_ptr symbol defined at address" + pcm.LastVariable_vValue);
else
console.log("Error defining the mbdlt25bf.mbdlt25bfOut_ptr");
}
else
{
console.log("Error reading mbdlt25bf.mbdlt25bfOut");
}
}
</script>
</body>
</html>
Hello @MichalH ,
thank you for your answer. I searched for some piece of code that uses FMSTR_TSA_POINTER but it doesn't exist, neither in SDK Freemaster example nor in documentation. How do I substitute
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfOut, FMSTR_TSA_USERTYPE(MinasOutput))
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfIn, FMSTR_TSA_USERTYPE(MinasInput))
with FMSTR_TSA_POINTER considering that its definition is
"extern FMSTR_TSA_CDECL char FMSTR_TSA_POINTER[]"?
Thank you.
Regards,
Davidino
Hello,
it should be a simply:
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfOut, FMSTR_TSA_POINTER)
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfIn, FMSTR_TSA_POINTER)
or you could also replace it with just FMSTR_TSA_UINT32 as the pointer is 4 bytes long and our intent is just to read the pointer value.
Regards,
Michal
Hello @MichalH ,
thank you for your message. I did as you showed me and FMSTR_TSA_POINTER is ok.
Now I have a problem with:
valueof(mbdlt25bf.mbdlt25bfOut) + offsetof(MinasOutput, controlword)
I didn't find any info about that on internet except that it's a new feature of Freemaster version 3.1.4. I can't find out how to implement it. Besides searching for the functions offsetof and valueof in the code, I couldn't find them.
Could you explain me?
Thank you for your cooperation.
Davidino
Hello,
both valueof and offsetof operators can be used when defining a FreeMASTER variable object. Each FreeMASTER variable needs to know the address (in target MCU memory space) from where the FreeMASTER could read the required value. Normally, you specify either a direct numeric address or you can use a C-language symbol obtained by reading application’s ELF file. In more advanced way, the TSA-defined symbols can be used – but in any case, such symbol resolves to a single constant numeric address.
In your case, the address of the mbdlt25bf.mbdlt25bfOut->controlword is not statically available in ELF file nor in the TSA because the mbdlt25bfOut is a pointer whose value can be dynamically changed in the application. This is why you need to define the address using the expression:
valueof(mbdlt25bf.mbdlt25bfOut) + offsetof(MinasOutput, controlword)
The valueof operator reads a value of the given FreeMASTER variable (which must exist in FreeMASTER project, it can be sampled “once” as we assume the pointer will not change).
The offsetof operator returns an offset of a given member withing a structure type.
All together, this expression returns an address of mbdlt25bf.mbdlt25bfOut->controlword.
In FreeMASTER, there is a hint describing the operators:
Regards,
Michal
Hello @MichalH,
thank you for your patience and support. I installed the new freemaster version 3.2 so that it's possible to define expression for the variable addresses. My freemaster_cfg.c now looks like this:
FMSTR_TSA_STRUCT(tMbdlt25bf)
FMSTR_TSA_MEMBER(tMbdlt25bf, state, FMSTR_TSA_USERTYPE(MBDLT25BF_STATE))
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfOut, FMSTR_TSA_POINTER)
FMSTR_TSA_MEMBER(tMbdlt25bf, mbdlt25bfIn, FMSTR_TSA_POINTER)
FMSTR_TSA_STRUCT(MinasOutput)
FMSTR_TSA_MEMBER(MinasOutput, controlword, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasOutput, operation_mode, FMSTR_TSA_SINT8)
FMSTR_TSA_MEMBER(MinasOutput, target_torque, FMSTR_TSA_SINT16)
FMSTR_TSA_MEMBER(MinasOutput, max_torque, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasOutput, target_position, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasOutput, max_motor_speed, FMSTR_TSA_UINT32)
FMSTR_TSA_MEMBER(MinasOutput, touch_probe_function, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasOutput, target_velocity, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasOutput, position_offset, FMSTR_TSA_SINT32)
FMSTR_TSA_STRUCT(MinasInput)
FMSTR_TSA_MEMBER(MinasInput, error_code, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasInput, statusword, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasInput, operation_mode, FMSTR_TSA_USERTYPE(PDS_OPERATION))
FMSTR_TSA_MEMBER(MinasInput, position_actual_value, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasInput, velocity_actual_value, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasInput, torque_actual_value, FMSTR_TSA_SINT16)
FMSTR_TSA_MEMBER(MinasInput, touch_probe_status, FMSTR_TSA_UINT16)
FMSTR_TSA_MEMBER(MinasInput, touch_probe_posl_pos_value, FMSTR_TSA_SINT32)
FMSTR_TSA_MEMBER(MinasInput, digital_inputs, FMSTR_TSA_UINT32)
One thing that I didn't tell you is that my mbdlt25bf struct is actually an array of struct:
tMbdlt25bf mbdlt25bf[ARRAY_SIZE_MOTORS];
I've one more issue where I'm trying to get the value stored in the variable mbdlt25bf[7].mbdlt25bfOut->controlWord.
The address that I wrote is: valueof(mbdlt25bf[7].mbdlt25bfOut) + offsetof(MinasOutput, controlword), as shown in the picture.
As you can see the value doesn't get updated. Can you advise me?
Thank you again for your cooperation.
Davidino
Hello,
you should first make sure that the FreeMASTER determines the address of mbdlt25bf[7].mbdlt25bfOut member correctly. One way of verifying that would be to examine this member in a debugger or print it to console by the MCU application. In any case, the address of this element should match what FreeMASTER prints in the Variable definition dialog (in my example it prints an address of variable named "var16").
If mbdlt25bf is really an array, the FreeMASTER should understand it and calculate a correct address. Basically, to access the mbdlt25bf[7].mbdlt25bfOut member, the FreeMASTER calculates something like:
mbdlt25bf + 7*sizeof(tMbdlt25bf) + offsetof(tMbdlt25bf, mbdlt25bfOut)
This is a fixed address (not runtime) so FreeMASTER should be able to show it to you in the Variable definition dialog. You should be able to see the address just like I see it for my "var16" above.
When you are sure the above is correct, define a FreeMASTER variable named mbdlt25bf[7].mbdlt25bfOut with the same address specification and size=4 bytes. You should be able to put this variable into a Watch and see the value of the mbdlt25bfOut pointer.
Last, you will be able to define a new FreeMASTER variable named mbdlt25bf[7].mbdlt25bfOut->controlword with address defined by the runtime expression as we discussed earlier:
valueof(mbdlt25bf[7].mbdlt25bfOut) + offsetof(MinasOutput, controlword)
This address is calculated in run-time, because FreeMASTER must first read the mbdlt25bf[7].mbdlt25bfOut variable and add the fixed controlword member offset to the obtained value.
_____________________________
As you can see, dealing with pointers in FreeMASTER is tricky. I would advise again not to declare the mbdlt25bfOut member as a pointer to a MinasOutput structure, but to include the full structure directly. This will enable FreeMASTER to calculate address of mbdlt25bf[7].mbdlt25bfOut.controlword statically and access the controlword member directly.
Regards,
Michal
Hello @MichalH ,
thanks for your detailed answer. I can confirm you that the address stored in mbdlt25bf[7].mbdlt25bfOut is correct (green box in the picture) as it is confirmed in MCUXpresso with the debugger. However, the address valueof(mbdlt25bf[7].mbdlt25bfOut) isn't computed correctly as it shows the question mark (red box in the picture). I don't understand why this happens.
P.S. In case this method doesn't work, I'll create copy of mbdlt25bfOut and mbdlt25bfIn structs and ciclically update the values for the solely purpose of seeing them on Freemaster.
Giving up on struct pointers would affect my program performances.
Thank you again.
Davidino
Hello Davidino,
with TSA, the FreeMASTER driver in the MCU actively monitors any access and it denies reading or writing to a memory which is not "described" by at least one TSA entry. It also protects a write access to memory locations marked in TSA as RO (Read-only).
You can turn this protection off (set FMSTR_USE_TSA_SAFETY to 0). This will keep the TSA basic functionality, but will disable the memory access checks.
I think this is the reason for the question mark. If not, let me know and we will investigate further.
Regards,
Michal