[freertos - Open Discussion and Support] Intertask Communication and resource

26 views
Skip to first unread message

SourceForge.net

unread,
Nov 21, 2011, 3:53:53 PM11/21/11
to SourceForge.net

Read and respond to this message at:
https://sourceforge.net/projects/freertos/forums/forum/382005/topic/4831645
By: tekkkon

Hi All,

I am doing a test program on LPC2292 processor.

There are three tasks running. TaskA and TaskB may want to read/write data on
another device through I2C interfaces at some point. The two tasks can call
my I2CRead and I2CWrite functions and then call the callback functions after
the I2C network transaction is done. When TaskA and TaskB individually call
the I2C functions, everything works OK. But when TaskA is keep reading slave
device register every second, TaskB trying to write one byte to the slave device
may blow up the processor.

I tried to use the resource management API(xSemaphoreCreateCounting), but it
didn't help. I am thinking probably because something goes wrong when TaskB
try to write a byte while the I2C read is not finished in TaskA. TaskB has a
higher priority than TaskA.

Do I need a semaphore in I2C ISR when the I2CRead is finished, to inform the
task?

Could it solve the problem if I use xSemaphoreTake and xSemaphoreGive in TaskA/TaskB
before calling I2CRead and I2Cwrite?

Is a third task, like I2CTask needed? So every time when TaskA/TaskB want to
get access to the I2C interface it will wake up the I2CTask and let the I2CTask
do its job.

Thanks in advance!

-Tekkon


_____________________________________________________________________________________
You are receiving this email because you elected to monitor this topic or entire forum.
To stop monitoring this topic visit:
https://sourceforge.net/projects/freertos/forums/forum/382005/topic/4831645/unmonitor
To stop monitoring this forum visit:
https://sourceforge.net/projects/freertos/forums/forum/382005/unmonitor

SourceForge.net

unread,
Nov 21, 2011, 4:31:14 PM11/21/11
to SourceForge.net
By: edwards3

I don't know enough about your library code, but would think a mutex was what
you need. Don't use a mutex in an interrupt through!

something like:

xMutexTake( I2CMutex, portMAX_DELAY );
I2CWrite()
xMutexGive( I2CMutex );

Then the same for read.

You should not give the mutex back until the I2C comms has finished. So you
can poll the I2C and only return from I2CWrite when all the data is transmitted.
Or if you are using interrupt, have the interrupt give a semaphore, to say the
write is complete. Then you code would be something like


xMutexTake( I2CMutex, portMAX_DELAY );
I2CWrite()
xSemaphoreTake( xI2CFinishedSemaphore, portMAX_DELAY );
/* Now you know the mutex can be released. */
xMutexGive( I2CMutex );

and the I2C interrupt calls xSemaphoreGiveFromISR() on xI2CFinishedSemaphore.

SourceForge.net

unread,
Nov 21, 2011, 4:48:19 PM11/21/11
to SourceForge.net
By: tekkkon

Thank you so much edward, this is really helpful!!!

I don't have xMutexTake and xMutexGive API in my library.
Can I use xSemaphoreCreateMutex, xSemaphoreTake and xSemaphoreGive instead of
xMutexTake and xMutexGive? I think they probably do the same thing.

Thanks!

SourceForge.net

unread,
Nov 21, 2011, 4:50:43 PM11/21/11
to SourceForge.net
By: edwards3

Yes. My mistake. You would think I would know the API functions by now. You
are exactly right.

SourceForge.net

unread,
Nov 22, 2011, 10:36:48 AM11/22/11
to SourceForge.net
By: tekkkon

Here is another question. How to do a fast context switch?

For example. In the mid of TaskA or TaskB, they need send data to slave and
receive data back. So the TaskA/TaskB send out a message to the I2C task to
wake it up, the I2C task finish all the read/write transactions as soon as possible
and send data back to TaskA/TaskB. Then TaskA/TaskB keep running from where
the scheduler switched to I2C task.

I think the above is possible. I know how to send message through the queue
to wake the I2C task up. But how to send the processed message back to TaskA/TaskB?
Another queue? This may happened frequently when the scheduler start running,
so is there an optimal inter-task communication mechanism to use?

The I2C task read/write 16 bytes generally cost 2.8ms. Is there anything I need
to pay special attention to? Like the size of the queue(used to communication
between TaskA/TaskB and I2CTask)? And the timing issue?

Thank you for your help!

-Tekkon

SourceForge.net

unread,
Nov 22, 2011, 12:18:22 PM11/22/11
to SourceForge.net
By: richard_damon

First, in FreeRTOS all task switches take the same time, so there are not "fast"
switches. If you need to send "data" between tasks, the simplest thing to use
is a queue. If you just need to send a "done" signal than a semaphore may be
sufficient (which is really just a queue without a data area).

If you are sending 16 byte messages than it probably makes sense to have the
queue be at least 16 bytes long so the task can queue up the message and then
resume processing (unless it needs to wait for a response). An alternate option
would be rather than send all the characters via the queue, to send a buffer
address, and the receiving task just uses the data where it was, and somehow
lets the sending task know the buffer is free again to reuse.

An alternative method, which is what I have been using, is to NOT make a special
I2C task, but have a library that any task that wants to send a message out
via I2C call, which first interlocks with a mutex so only a given task has "control"
over the I2C when it is active, and then it queues up the data for an ISR, and
then kick starts the hardware. The ISR then continues to send the data from
the queue. If the operation is a read, then the library waits on another queue
where the ISR puts the return data. Since there isn't much to do on each interrupt,
it doesn't make much sense to actually drop down to a task to do that level
of I/O.

Reply all
Reply to author
Forward
0 new messages