Synchronization between threads with RLP

Hello,
I am trying to sample an external signal with FezPanda2 at more than 1 KHZ rate. Managed code can’t help me and I have to use RLP.
I am using RLP and native code to:

  • intialize the ADC module on Usbizi
  • start a new thread for continuously sampling data and store it into a circular buffer
  • use a “getdata” function to be called outside native code to get all the samples available in the circular buffer.

I can’t understand from documentation if in the native side there is any mutex or sometihng similar that I can use to synchronize the sampling thread (native) and the external thread (from managed side) that calls the getdata function. Indeed, both access the same circular buffer…

Thank you in advance for your help

Welcome to the forum!

When RLP is running managed side is suspended.

You could schedule a RLP thread to run periodically, take an analog sample, notify the managed side via an event, and then reschedule the RLP thread. The managed side would only be suspended while the analog sampling was executing.

You will not be able to do continuous sampling.

Oh, welcome to the forum.

Wow!
thank you guys for your prompt replies! I am not sure to understand well.

My scenario is the following:

  1. the native thread do sampling and store data in a buffer, let’s call it nativeBuffer, than reschedule itself after 500 microseconds
  2. the managed thread call the native procedure getData.InvokeEx(managedBuffer). Inside the native function the samples stored in nativeBuffer are then copied to managedBuffer.

Basically, both threads read or write from/in the same nativeBuffer. Generally I would protect this acces with a mutex or sempahor or a lock statement if I am developing in C#.
Architect, if I understand well since managed side is suspended there is no possibility to have a concurrent access to the shared resources?

Anyway, my question remains: what about if I want to schedule on the native side two or more threads accessing the same resources? is there any mutex or semaphore or sometihing similar in the Native side that one can use to synchronize two or more native threads?

Correct. While native (RLP) code is running managed threads are suspended.

Ok. so I have not to worrie about it.

With regards to sycnhronizing two native threads that access the same shared resources? are mutex or semaphore available in your RLP?

have a look at lock(…) lock statement - synchronize thread access to a shared resource | Microsoft Learn

@ andre.m - Yeah, sorry i didn’t read properly

[quote=" i afraid its impossible to have threads within rlp but i am not sure[/quote"]

Premium supports threads.

yes indeed,

In my code I created two different threads with the following statements

/* Init task */
RLPext->Task.Initialize(&myTask1, MyTaskCallback, 0, RLP_TRUE);
RLPext->Task.Initialize(&myTask2, MyTaskCallback2, 0, RLP_TRUE);

/* start task */
RLPext->Task.Schedule(&myTask1);
RLPext->Task.Schedule(&myTask2);

then I have MyTaskCallback and MyTaskCallback2 both trying to acces the ADC for sampling the two different channels
I would like to protect the access to the ADC registers through some sort of semaphore mechanism, but I didn’t found anything about in the official documentation.

So my questionis: are there any semaphores available in RLP that I can use in such situations?

Thank you in advance for your help, guys!

the obvious question is why two threads to access the ADC?

there are no semaphores in RLP. but I believe they are not needed. a RLP thread runs to completion or rescheduling. there is not a sleep or wait function, and a running RLP thread will not be interrupted or suspended

Tasks never overlap so there is no need for locking mechanism.

Hi Mike,
The reason why I have two threads is just because I want to sample each channel at a different rate so in myTaskCallback and MyTaskCallback2 I basically reschedule the corresponding thread within a period of 500 microsecond and 2000 respectively:
for instance:

void MyTaskCallback2(void arg)
{
WORD reading = 0;
if (cbIsFull(&CircBuffer2) == FALSE)
{
reading = ADC0Read(channel2);
cbWrite(&CircBuffer2, &reading);
}
else
{
/
tbd send here an overflow event */
}

RLPext->Task.ScheduleTimeOffset(&myTask2, period_microseconds2);
}

In this way each channel is separated and work at its own sample rate.

500 is 1/4 of the 2000. Read both channels every 4th reading.

Ok maybe I catched it.

RLP scheduler is non-preemptive so there is no risk to be switched off and no need for mutex. is it right?

sorry but I am new to ghi products…

yes you maybe right here.
Thanks for your suggestion.

I tought to have two separate threads because I want to design a generic DLL that can be reusable in the future for other projects and other signals.
If I need to sample with different periods like 500 microseconds and 600 microseconds I should rewrite the code and compile each time…
With two threads I can just pass these values to the same initSampling function.

Whatever you end up doing, just remember – the moment you leave the CLR, you’re running on bare metal. The managed environment does not sit on top of some sort of RTOS or anything like that – just a very thick HAL/PAL. So, if you call a native function, it will execute and when it’s finished, it will return to the CLR.

If you’re feeling adventurous…
Personally, I prefer interops over RLP in almost every case, and in your project especially, it sounds like a perfect use for interop code. The idea is simple:
[ol]
Go ahead and create a managed C# class with all the methods you’ll be using. Pretend you’re going to write it all in C#.
Add a

 [MethodImpl(MethodImplOptions.InternalCall)]

before any function you need to run natively (just declare the function – don’t implement it)
Build your library in Visual Studio and copy the files in the \stubs folder to an appropriate place in the port. (Probably DeviceCode\Drivers if your code is processor-independent; otherwise, in the \DeviceCode\Targets folder for your processor).
Implement your function by editing the stub.
Add a reference to the project in the Solution.
Profit.[/ol]

This is trickier to do on the FEZ Panda, which isn’t an open-source board, however, if you’re not using any other GHI Premium features, you could grab the open-source NETMF port for it here: http://usbiziopen.codeplex.com/, set up the build environment, and develop your application using interops.

Whenever anyone starts talking about thread synchronization and semaphores, it’s a good sign that they’d rather get the job done right instead of hack something together. Getting the porting kit environment set up takes some time (and lots of reading), but once it’s set up, you’ll easily be able to develop interop assemblies that jump around between managed and native code.

There’s a good wiki tutorial here:

2 Likes