On 14.05.2016 06:11, Philippe Leuba wrote:
Some updates with the latest release:
 > -  pdserv_parameter allows defining a callback to have a chance to
modify data before copying it, is the updated value  expected to be
reported back to Test Manager ?
We are able to do it by modifying the 'const src' parameter in the callback
Hmm, that may be possible, but was not intended to be used like that.

The intended use case is for example to change a scaling or an offset between the "outside world" (aka TestManager) and the cyclic task, albeit very rare.

Another use case is a set of dependent parameters that are parameterized by a single value. For example, if you have a many pole filter where you want to change a frequency using a single parameter and calculate the coefficients all in one go (otherwise your filter may explode).

The heaviest use case, however, is parameter locking, as explained below.


 > - pdserv_event_set allows setting and resetting an event, like a
state. How to deal with a punctual event, if we set it and reset it
immediately, it seems not to be sent ?
Both are now sent, but Test Manager displays both, the second one
without message.
See my previous reply.

- I did not like the change where the parameter callback is now called
from an other thread because this forces the realtime thread to use a
lock to access the parameter.
As from changeset 487:9b87a3c48ebd, parameter changes asynchronous to the real time task. That means that a parameter may change while it is being used.

You are obliged to supply a small helper function that is called when a parameter is changed. Inside the helper function you can lock a semaphore, copy data and unlock again. Although every parameter can store a unique helper function, the helper function may be generic in nature and shared by all parameters. A priv_data pointer, passed when registering the parameter, is supplied to the helper function during the call.

For example:

<code>
semaphore parameter_lock;   // in global scope

// Helper function
void copy_parameter(const struct pdvariable* param,
  void *dst, const void *src, size_t len,
  struct timespec *time, void *priv_data)
{
  sem_get((semaphore*)priv_data);   // or even sem_get(&paramter_lock)
  memcpy(dst, src, len);
  sem_put((semaphore*)priv_data);
}

void cyclic_task()
{
  while (true) {
     sem_get(&parameter_lock);  // lock parameters
     // calculations using registered parameters
     sem_put(&paramter_lock);   // unlock parameters

     pdserv_update(...);
     sleep(delay);
  }
}

void init()
{
 // ...
 pdserv_parameter(pdserv, "/parameter/path1", 0666, pd_double_T,
   &parameter1, 1, 0, copy_parameter, &parameter_lock);
 pdserv_parameter(pdserv, "/parameter/path2", 0666, pd_double_T,
   &parameter2, 1, 0, copy_parameter, &parameter_lock);
 // ...
}
</code>


Supplying NULL for write_parameter_t is possible but not recommended!

A similar helper function is recommended for signals!

Philippe Leuba

- Richard
_______________________________________________
etherlab-dev mailing list
etherlab-dev@etherlab.org
http://lists.etherlab.org/mailman/listinfo/etherlab-dev

Reply via email to