Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Sequence of code blocks

Posted by gerhardkreuzer on January 21, 2016

Hi, I have to go thtough a list of functions, but there is a rule. Start the next function after the previous function has done .. and this takes time. Such a function (logically not programmatically) consists of some steps.

func1() startTimer func2 BLOCK until timer expires func3 func4 startTimer BLOCK until timer expires .... .....

Other tasks should run during a BLOCK phase How can I do this efficiently within freeRTOS?

With best tegards

Gerhard


Sequence of code blocks

Posted by rtel on January 21, 2016

The most efficient way would be to have the task use a direct to task notification when it needs to block, and have the timer send the notification to the task when it expires (unblocking the task). See the example code on the following page: http://www.freertos.org/RTOSTaskNotificationAsCounting_Semaphore.html

Depending on your requirements, the timer could be either a one shot software timer, or a hardware (peripheral) timer. If it is a software timer then a callback will execute when the timer expires - and the callback function will send the notification to the task to unblock the task. If it is a hardware timer then an interrupt service routine will execute when it expires, and the service routine will send the notification to the task to unblock the task.

You will need to make sure the task does not already have a notification pending before it start the timer - otherwise it will not block when it attempts to wait for a notification, because one is already pending.

Regards.


Sequence of code blocks

Posted by gerhardkreuzer on January 21, 2016

Thanks. Will look into that sample. Unfortunately have an older version without notification and Atmel didn't integrate the new version in her IDE .... Maybe you can tell me how to migrate within Atmel Studio 6

With best regards

Gerhard


Sequence of code blocks

Posted by rtel on January 21, 2016

Just use a binary semaphore instead of the task notification - as per your other post. It is less efficient, but functionally equivalent.


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Thanks, ok, this means, semaphores only working between different tasks. As I have a list of steps I cant do this:

step1(); step2(); step3(); ==> starting only when a recursive mutex taken in step1 and step 2 is given by timers used by step1 and step 2. And it isnt important which timer expires first.

Is it true I have to seperate step3(), running in a different task to wait for this semaphore?

With best regards

Gerhard


Sequence of code blocks

Posted by rtel on January 22, 2016

No, it can be the same task. In fact, with mutexes, it would be normal for the same task to both take and then give back the mutex. Different semaphores are used in different scenarios.

Note if you are using a recursive mutex you will have to use a software timer rather than an interrupt. Other types of semaphore can be given from an interrupt, but mutexes (recursive or not) cannot as they include a priority inheritance mechanism (which works on task priorities, and gets confused if its an interrupt using the mutex).

Regards.


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

What exactly is the terminus 'owner of the semaphore' ? As both tasks have to know the semaphore, or have a pointer to it, the semaphore has to be declared somewhere outside. The system hardly can know which tasks owns the semaphore, right? When I call a API function ..Take.. within a task loop, than the system knows somehow that this task currently owns the semaphore? There is no parameter to define that. The owner can do whatever he want, take, give no blocking take place, right? All other tasks, which didn't own the semaphore were blocked during a take, right?

The ownership of a semaphore could be changing during system lifetime?

If another task takes the semaphore first he will be the owner until he gives the semaphore, right?

If two tasks want to use a shared resource, one tries first so it is the owner until he is done, afterwards the other task owns the semaphore probably until he is done, right?

But always needed, it only works between different tasks, right?

With best regards

Gerhard


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Ah. Ok, I tried to use a recursive mutex, and a software timer. I called my steps, here the mutex is taken and the timer is started, which also restarts the timer if it was running. In the timer callback I gave the mutex. But the system halts indefinetly long on that line for what reason ever.

So I start reading again and found the ownership clause and now I think I am wrong.

Ok, any idea whats wrong with my idea?

stepX() carry out functionallity. If timer is running, just restart if timer is not running, take the recursive mutex and start timer step3() blocks until he can take the mutex.

All code running in one task.

I attached my code of one of this steps.

With best regards

Gerhard

Attachments

InputMux.c (4668 bytes)

Sequence of code blocks

Posted by rtel on January 22, 2016

Semaphore ownership doesn't really have a meaning unless you are using a semaphore type mutex, in which case the semaphore is intended to be used to guard a resource. If you want to access the resource first you must successfully 'obtain' the mutex, and as long as you have the mutex, no other task can successfully obtain it - and as only the mutex owner can legitimately access the resource, the resource is protected. Once you have finished with the resource you give the mutex back - at which point other tasks that want to access the same resource have an opportunity to obtain the mutex.

In your case, you are not using the semaphore in this way, so I was guessing the only reason you were using a recursive mutex was so you could 'take' it multiple times, but from you latest post I'm wondering if that is what is causing you the problem. With a recursive mutex you must 'give' it back the same number of times as you have [recursively] taken it before it becomes available again.

When you say "If the timer is running, just restart it. if the timer is not running, take the recursive mutex", it sounds you are going to take the mutex the same number of times as the timer callback function is going to give it - because you are only taking the mutex again if the timer has actually expired. However, you may get into race conditions here - for example, if the timer were to expire between your task determining it had not expired and your task restarting the timer.

I don't want to confuse things, as you seem to have gone down this route quite some way, and I don't fully understand your use case, but perhaps an event group would be a more appropriate object to use than a mutex.

Lets say you have three timers, the timers are started at different times, and at some point your task wants to wait until all three timers have expired. That might not be the actual case, but perhaps close enough to your actual case to use as an example.

You can assign different bits in the event group to three different timers:

#define TIMER_1 ( 0x01 << 0 )
#define TIMER_2 ( 0x01 << 1 )
#define TIMER_3 ( 0x01 << 2 )

Before you start any timers you ensure all the bits are clear.

The callback function for timer 1 then sets bit TIMER1 in the event group. The callback function for timer 2 sets bit TIMER2 in the event group. The callback function for timer 3 sets bit TIMER_3 in the event group (the same timer callback function could be used for all the timers, but lets keep it simple now, and assume these are three separate callback functions for three separate timers).

Once your code has started all three timers, and gets to the point where it needs to wait for all three to expire, it has to wait for all three bits to get set in the event group:

~~~~ xEventGroupWaitBits( xEventGroup, // Handle of the event group ( TIMER1 | TIMER2 | TIMER_3 ), // Bits to wait for pdTRUE, // Clear the bits back to zero before returning pdTRUE, // Wait for all three bits to be set BlockTime ); // However long you want to wai ~~~~

Is this close to what you want to achieve?


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Hmm, somehow, but: Atmel uses freeRTOS 7.3.0, as I can see here, so there is no event group available, isn't it?

How can I update, I use a ARM 4 based MCU, sam4n by Atmel.

I posted my code, maybe something is wrong and I just didn't see it.

Race condition, ok, but I tried it more than once, so race conditions only appear sometimes, or I am wrong?

With best regards

Gerhard


Sequence of code blocks

Posted by rtel on January 22, 2016

I think event groups were added in version 8. In theory you should be able to take the latest version of FreeRTOS and drop the source files over the top of the ones you are using. I say that is the 'theory', so make sure you have a back up of your existing files first.


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Ok, will give it a try.

I attached an altered code snippet, cause I still not understand how this recursive mutex can know whats wanted in the moment ...

The InputMux_setPort function is the one we discuss ..

Attachments

InputMux.c (5018 bytes)

Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

.. what does this mean for the idea to just copy the V8.x files over the V7.3 files?

Software timers and FreeRTOS-MPU The software timer API is not yet included in the official distribution of FreeRTOS/source/include/mpu_wrappers.h.

With best regards

Gerhard


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Hi,

ok, done, but not working out:

1.) Copied file per file from new version over original version supplied by Atmel. There is a folder /portable/gcc/sam and here I take the CM4F files. Unfortunately I get an error that a floating point option has to be set somewhere ... 2..) Next I tried out the CM3 files, as the original uses the CM3, but again, I get lot of errors, telling me, that MCU_... is missing. 3.) I just reied the original files, and now I get lot of errors cause something is declared double ...

Seems, that Atmel didn't work with V8.2

With best regards

Gerhard


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Ok, after switch to V8 didn't worked out I start checking why it hangs in the timer callback and I get nice result, see screenshot. The system told me that I cant give the mutex, cause I am not the holder, aha ..

So, this pattern would not work out but why?

With best regards

Gerhard

Attachments


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Hi, so is this an explaination for that behaviour?

In the manual I get this info:

Mutexes must always given back by the owner.

Ok. I take the mutex in the context of my shell task, which decodes command line input and calls the function under discussion. The software timer is run by another task, which is the timer service by freeRTOS. The timer callback is running in the context of this task and so for the mutex can't be given by the callback function ..... And that is exactly the situation I see here during debugging.

Ok, but how can I carry out the function I needed (using FreeRTOS 7.3, thanks to Atmel, grr).

It is somehow common when hardware programming is in the focus. I want to execute a code block kicking off some hardware action, like switching a relay.. Than I want to continue down the code until I reach a point, where the hardware response must be finished. During executing more code, the hardware, here a relay takes his time to finish switching (bouncing effects ...).

Which kind of synchronisation/blocking can I use to archive this?

Mutex isnt that good.

Ok, semaphore maybe, but what if I have two or more such situations. Preparing different pieces of hardware and after all has setteled I start some other code block.

???

With best regards

Gerhard

PS: Would be a nice sample in the new upcoming book, cause I think it is common enough and it isn't a task to task sync, it is more than a gate function. Gate can only be passed, if some processes outside the system (relays ...) entering a stable state.


Sequence of code blocks

Posted by edwards3 on January 22, 2016

Mutexes are used to for mutual exclusion, where the taker has to be the giver to relinquish a resource. Binary semaphores are used for synchronization, why not use one of those? Counting semaphores might be useful too.


Sequence of code blocks

Posted by gerhardkreuzer on January 22, 2016

Hi, the problem is, that I have to call the function more than once, and couldnt know in advance how often. It could be between 0 and 4. There were other functions also setting something in HW and after all that I have to wait until all is settled. So I discovered the recursive mutex. Counting semaphore do odd things. Counting events, ok, but I don't know how often the functions were calles, so this is of little use. Maybe the new Event Group will be a nice thing, but I am not able to use FreeRTOS v8, Atmel didnt provide any infos √°bout migration and just copy the fils around fails ...

With best regards

Gerhard


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS