Hello,
How are You Pavel ? I have one question maybe You or someone could help me. Just finishing my small gimbal motor control project and left to do publisher and subsciber services. Problem are how to nicely safeguard parameters service, where parameters must be read and write by multiple freertos threads. At some point code crashes.
At this time I am using legacy libuavcan library with stm32 drivers.
- So, first of all I have created Parameter service which work normally.
- I am reading parameters to the structure from EEPROM, which executes before param service initialization.
uint8_t pos[31]={0};
myEEPROM.readData(pos, 0x04, 31);
if (osSemaphoreWait(Param_completeID, 1000) == osOK)
{
configuration.PowerOn = pos[0];
configuration.ControlType = pos[1];
num[0].bytes[0] = pos[2];
num[0].bytes[1] = pos[3];
num[0].bytes[2] = pos[4];
num[0].bytes[3] = pos[5];
configuration.ControlValue = num[0].number;
configuration.Calibrate = pos[6];
configuration.PoleNumber = pos[7];
configuration.FOCModulation = pos[8];
num[1].bytes[0] = pos[9];
num[1].bytes[1] = pos[10];
num[1].bytes[2] = pos[11];
num[1].bytes[3] = pos[12];
configuration.VEL_P = num[1].number ;
num[2].bytes[0] = pos[13];
num[2].bytes[1] = pos[14];
num[2].bytes[2] = pos[15];
num[2].bytes[3] = pos[16];
configuration.VEL_I = num[2].number;
num[3].bytes[0] = pos[17];
num[3].bytes[1] = pos[18];
num[3].bytes[2] = pos[19];
num[3].bytes[3] = pos[20] ;
configuration.VEL_U_RAMP = num[3].number;
num[4].bytes[0] = pos[21];
num[4].bytes[1] = pos[22];
num[4].bytes[2] = pos[23];
num[4].bytes[3] = pos[24];
configuration.VEL_FILTER_Tf = num[4].number;
num[5].bytes[0] = pos[25];
num[5].bytes[1] = pos[26];
num[5].bytes[2] = pos[27];
num[5].bytes[3] = pos[28];
configuration.Angle = num[5].number;
configuration.Orientation = pos[29];
configuration.NodeID = pos[30];
osSemaphoreRelease(Param_completeID);
}
- Reading param values in param class without safe guards
void readParamValue(const Name& name, Value& out_value) const override {
if (name == "Power On/Off")
out_value.to<uavcan::protocol::param::Value::Tag::boolean_value>() = configuration.PowerOn;
else if (name == "Control Type")
out_value.to<uavcan::protocol::param::Value::Tag::integer_value>() = configuration.ControlType;
else if (name == "Control Value")
out_value.to<uavcan::protocol::param::Value::Tag::real_value>() = configuration.ControlValue;
else if (name == "Calibrate On/Off")
out_value.to<uavcan::protocol::param::Value::Tag::boolean_value>() = configuration.Calibrate;
else if (name == "Pole Number")
out_value.to<uavcan::protocol::param::Value::Tag::integer_value>() = configuration.PoleNumber;
else if (name == "FOC Modulation")
out_value.to<uavcan::protocol::param::Value::Tag::integer_value>() = configuration.FOCModulation;
else if (name == "Velocity PID P")
out_value.to<uavcan::protocol::param::Value::Tag::real_value>() = configuration.VEL_P;
else if (name == "Velocity PID I")
out_value.to<uavcan::protocol::param::Value::Tag::real_value>() = configuration.VEL_I;
else if (name == "Velocity U Ramp")
out_value.to<uavcan::protocol::param::Value::Tag::real_value>() = configuration.VEL_U_RAMP;
else if (name == "Velocity Filter Tf")
out_value.to<uavcan::protocol::param::Value::Tag::real_value>() = configuration.VEL_FILTER_Tf;
else if (name == "Primary angle")
out_value.to<uavcan::protocol::param::Value::Tag::real_value>() = configuration.Angle;
else if (name == "Motor Pitch/Roll/Yaw")
out_value.to<uavcan::protocol::param::Value::Tag::integer_value>() = configuration.Orientation;
else if (name == "Node ID")
out_value.to<uavcan::protocol::param::Value::Tag::integer_value>() = configuration.NodeID;
else
if (DEBUG_MAIN == 1) printf("Can't read parameter. Check if type is correct\r\n");
}
So first question do I need to have additional safe guards in parameter class ?
- Saving new parametrs. Here without safeguards
int saveAllParams() override {
if (DEBUG_MAIN == 1) printf("Save - this implementation does not require any action\r\n");
uint8_t pos[31]={0};
pos[0] = configuration.PowerOn;
pos[1] = configuration.ControlType;
num[0].number = configuration.ControlValue;
pos[2] = num[0].bytes[0];
pos[3] = num[0].bytes[1];
pos[4] = num[0].bytes[2];
pos[5] = num[0].bytes[3];
pos[6] = configuration.Calibrate;
pos[7] = configuration.PoleNumber;
pos[8] = configuration.FOCModulation;
num[1].number = configuration.VEL_P;
pos[9] = num[1].bytes[0];
pos[10] = num[1].bytes[1];
pos[11] = num[1].bytes[2];
pos[12] = num[1].bytes[3];
num[2].number = configuration.VEL_I;
pos[13] = num[2].bytes[0];
pos[14] = num[2].bytes[1];
pos[15] = num[2].bytes[2];
pos[16] = num[2].bytes[3];
num[3].number = configuration.VEL_U_RAMP;
pos[17] = num[3].bytes[0];
pos[18] = num[3].bytes[1];
pos[19] = num[3].bytes[2];
pos[20] = num[3].bytes[3];
num[4].number = configuration.VEL_FILTER_Tf;
pos[21] = num[4].bytes[0];
pos[22] = num[4].bytes[1];
pos[23] = num[4].bytes[2];
pos[24] = num[4].bytes[3];
num[5].number = configuration.Angle;
pos[25] = num[5].bytes[0];
pos[26] = num[5].bytes[1];
pos[27] = num[5].bytes[2];
pos[28] = num[5].bytes[3];
pos[29] = configuration.Orientation;
pos[30] = configuration.NodeID;
/**
* @brief Write data from EEPROM
* @param pos - array or variable where readed data will be pushed
* @param start - start address in the momory in HEX format
* @param size - Size of data to read sequentally
*/
myEEPROM.writeData(pos, 0x04, 31);
osDelay(100);
return 0; // Zero means that everything is fine.
}
- And now I want to access in some thread one of the parameters
foo(configuration.value);
if I put here safeguard practical it crashes imidiatelly. If using without safeguard it could crash in different time period.
Maybe soem ideas how to solve it ?
How variables is handeld by param service and how it sfaeguard and how correctlly safeguard this variables in structures from different threads and do not influence param service handler ?