I am implementing SW update routine for my application and I use the example code provided for libuavcan. However I experience that .Read service call result sometimes fails. Below is a modified version of the response handler for the read_client. I have implemented retries to get around the problem until I figure out the root cause.
So, when it happens, result.isSuccessful() is FALSE, e.g. result.getStatus() != Success.
When looking in GUI tool to see the frames, all look good and the messages are complete without errors, but the SW update reading routing stops due to above fault. Hence my retry code fix below.
My conclusion so far is that the service call timed out, but I am not sure why. Best guess is that the response was not processed by stack in time, or that some frame got lost on the way from bus to lib.
I am calling .spin(…) periodically, with 250ms blocking time. My applications does stuff in between calls, but nothing that blocks. My node subscribes many broadcasts so I guess some time is needed to process them during spin(). The read_client call has a timeout of 1000ms.
void handleReadResponse(const uavcan::ServiceCallResult<uavcan::protocol::file::Read> &result)
{
static uint8_t retry = 0;
if (result.isSuccessful() && result.getResponse().error.value == 0)
{
auto &data = result.getResponse().data;
retry = 0;
image_.insert(image_.end(), data.begin(), data.end());
if (data.size() < data.capacity())
{ // Termination condition
status_ = Status::Success;
uavcan::TimerBase::stop();
DEBUG_OUT(DEBUG_LVL_2, "Finished!");
}
}
else
{
retry++;
DEBUG_OUT(DEBUG_LVL_2, "Read fail, status = " << result.getStatus());
if(retry > 3)
{
status_ = Status::Failure;
uavcan::TimerBase::stop();
DEBUG_OUT(DEBUG_LVL_2, "STOP");
retry = 0;
}
else
{
DEBUG_OUT(DEBUG_LVL_2, "Retry " << unsigned(retry));
}
}
}
The above approach seams to solve the problem, however I am keen on making my application multithreaded with subnode(s) as per example provided here https://uavcan.org/Implementations/Libuavcan/Tutorials/12._Multithreading/
to let some uavcan functionalities such as sw update run in main thread, and other application functions run in sub node.
Can this be a more controlled way of handling this type of problems?
Are there more examples for linux and socketCan on the Multithreading topic?
Kind regards