i2c driver across multiple tasks

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i2c driver across multiple tasks

Jump to solution
3,862 Views
OldNick
Contributor IV

New to RTOS, but perfectly comfortable with bare metal and serial protocols in general.

 

But nervous about accessing a variety of slave devices on a single i2c channel, which are polled at different rates (or even sporadically "on demand".)  It makes sense to me to have different tasks for different parts of my system, even if they use a common i2c interface.

Anyway, I have converted MQX i2c driver into a thin layer of something a bit more sensible which maps to the bare metal for most slave devices.

 

_mqx_int i2cSendData (uint_8 address, uint_8 no_bytes,char *pData);  //start/ack/address/ack/datawrite.../stop sequence
_mqx_int i2cReadData (uint_8 address, uint_8 no_bytes,char *pData);  //start/ack/address/ack/dataread.../stop sequence
_mqx_int i2cReadDevice (uint_8 address, uint_8 Offs, uint_8 no_bytes,char *pData);  //start/ack/address/datawrite/rp_start/address/dataread/stop sequence

These work perfectly in a single thread. 

 

But these i2c transactions each use several MQX driver calls.  So how should I keep the transactions safe between threads?

 

Should I open and close the master every time I need it?

Wrap the api in CriticalSection? (not nice).

Or is there some better way?

0 Kudos
1 Solution
2,244 Views
OldNick
Contributor IV

CarlFST60L wrote:

The most simple way is to create your own read / write I2C function that is 'global' and protect it with a mutex i.e. all your threads  call a single read or write function which you pass all the required information to, it will lock the mutex and then do the read write as required with the mutex locked.

 

 


Carl,

thanks...that is helpful.

As I said, new to RTOS...taking your advice, I will wrap the i2cread/i2cwrite and i2creaddevice functions in a mutex.

I presume that will block any calling threads unti lthe i2c transaction is complete?

As a matter of curiosity, should I lock/unlock the mutex in the global function (while the function parameters are still on the stack) or is it safer to lock/unlock it in the calling thread after the i2c function returns, or doesn't it matter? 

It would probably be tidier to do it in the transaction hander than in the calling thread, as long as nothing gets porruupted.

View solution in original post

0 Kudos
8 Replies
2,244 Views
PetrM
Senior Contributor I

Hello,

 

you can't mix I2C read/writes from different tasks until the whole ongoing I2C transaction is finished (STOP_CONDITION). The MQX I2C driver provides just low level access with standardized API.

So you should add mutual exclusion (semaphore, mutex...) to the beginning and to the end of your functions mentioned above.

 

PetrM

 

0 Kudos
2,244 Views
OldNick
Contributor IV

Petr,

thankyou for confirming my original suspicions.

 

Please consider adding those mutexes to the i2c example code in MQX tower.  Otherwise your example code is not thread-safe.

 

Best Regards

0 Kudos
2,244 Views
OldNick
Contributor IV

bump.

I would really like to know what "old hands" would recommend.

 

Thanks

0 Kudos
2,244 Views
CarlFST60L
Senior Contributor II

The most simple way is to create your own read / write I2C function that is 'global' and protect it with a mutex i.e. all your threads  call a single read or write function which you pass all the required information to, it will lock the mutex and then do the read write as required with the mutex locked.

 

 

0 Kudos
2,244 Views
CarlFST60L
Senior Contributor II

As MQX is based on Posix threads, you can start with this (I have this book and it gave me an in site to Posix thread programming), its not specific to FSLMQX, but useful:

http://www.amazon.com/Programming-POSIX-Threads-David-Butenhof/dp/0201633922/ref=sr_1_1?s=books&ie=U...

 

Also search for books on "embedded real time" and "multithreaded embedded", just about all Multithreading systems are Posix based, or at least similar in most ways, enough so that if you are fimilar with one, the rest can be worked out from the examples/user guide etc.

0 Kudos
2,245 Views
OldNick
Contributor IV

CarlFST60L wrote:

The most simple way is to create your own read / write I2C function that is 'global' and protect it with a mutex i.e. all your threads  call a single read or write function which you pass all the required information to, it will lock the mutex and then do the read write as required with the mutex locked.

 

 


Carl,

thanks...that is helpful.

As I said, new to RTOS...taking your advice, I will wrap the i2cread/i2cwrite and i2creaddevice functions in a mutex.

I presume that will block any calling threads unti lthe i2c transaction is complete?

As a matter of curiosity, should I lock/unlock the mutex in the global function (while the function parameters are still on the stack) or is it safer to lock/unlock it in the calling thread after the i2c function returns, or doesn't it matter? 

It would probably be tidier to do it in the transaction hander than in the calling thread, as long as nothing gets porruupted.

0 Kudos
2,244 Views
CarlFST60L
Senior Contributor II

I would do it inside the wrapper. 

 

If you are after some research material that will help you with FSLMQX, search on "Embedded Real Time Multi Threaded Operating Systems", Amazon has a couple of good books. MQX is based on Posix 4.a threads, another topic to research. Hope this helps!

0 Kudos
2,244 Views
OldNick
Contributor IV

Carl,

couldn't get any hits from the amazonsearch, could you be a tiny bit more specific?

 

Anyway, I have added the mutex based on the worked examples and the code still works from a single thread.  Multithread yet to be tested.

 

If anybody wants the three functions i2cread, i2cwrite, and i2cread-device, I will post them

 

Cheers

0 Kudos