Suspended task activity

I currently programming on an Arduino Mega 3 . I have a loop running which prints out a message every second or so. From the loop I resume a task that I have previously created and suspended. From a input key stroke are resume the task and it runs just fine spitting out a ‘1’ on the terminal every 300ms or so. with another keystroke I suspend the task. No problem. I can restart and suspend over and over.
What is confusing to me is if I suspend it for any length of time and restart it. It spits out a stream of ‘1’ s before it continues it’s normal run.
What’s up with that?
Here’s the task but please note. I have a yield statement that probably does nothing. I was looking it to how to use it or if I need it at all.

void Task_2(void *pvParameters)
{
    TickType_t xLastWakeTime;
    const TickType_t xFrequency = 409;

    // Initialize the xLastWakeTime variable with the current time.
    xLastWakeTime = xTaskGetTickCount();

    for (;;)
    {
        // Wait for the next cycle.
        vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(xFrequency));
        yield();
        Serial.print("2");
    }
}

Thanks so much

VTaskDelayUntil is designed to keep a fixed repetitive rate, with catchup if the task falls behind. That is the purpose of the vLastWakeTime parameter. The function basically waits until the time gets to (or is past) the last value of vLastWakeTime + the specified delay, and updates vLastWakeTime to that value.

If you “go to sleep” for awhile , you need to reseed that variable with a new time mark.

And be aware that suspend/resuming a task might cause problems like race conditions.
Who knows what’s happening when supending the task right in middle of the Serial.print operation…
You should use an appropriate task synchronization mechanism (or a volatile flag at least) to stop/start the output (e.g. omitting the print and do a small xTaskDelay instead for testing purposes) on keystrokes.

Thank you so much! That certainly solved the problem

Thank you. You have certainly given me something to think about. Most likely only one task will be running from the main loop at a time with no Serial prints in the final build but there will be RS422 activity in the idle state where up to 30 bytes are transmitted and then received. There is a delay between the two but I now wonder if the task will cause problems with this operation.

I ran into this exact problem. I wasn’t aware at first that it held the execution of the task at the line that it stops. My task has to start at the beginning. So, rather than suspend the task I just delete it and then create it again when I need it again. That’s a viable way to handle it isn’t it?

That’s a question I was asking myself especially since I don’t know exactly how the RTOS heap is being managed. It seems to me that if you keep creating and deleting a task, the heap could get fragmented depending of course on other asynchronous memory activity that your or I could be doing.

I want to avoid this so I think I’ll just create tasks statically. In fact I started printing out the highWaterMark but not sure how to read it. I think it depends on how large the target processor is. I’m targeting an 8 bit processor so if I get a highwater mark of 96, I think that might be the bytes available that are not being used. I bet someone here could answer both of our questions better than I can. But I think you might consider usingthat benchmark. Thanks for your response. - Rick

I guess if you were doing this with multiple tasks over and over again. But if you’re only doing it with one, then wouldn’t it always end up using the same heap every time it was created? I guess it all depends on what else your program is doing really. I can say that my 2 systems that I’m doing this with have been running for 9 days and have over 50 create/delete cycles each and neither has rebooted or had a problem yet. But the program is VERY basic and the SOC has a lot of extra memory.

For your case, I think it’s fine especially after 9 days of runtime. It all depends on what you are doing. At this point I don’t know how complex the project I am working on will get.

Anyway, I think if you add more tasks later it on it might be safer to run your task in a loop. Let it suspend itself at the end (one time through) and just resume it when you need it. This way it will only be dynamically allocated one time rather than multiple times.

All the best - Rick

If you needed the task to restart from a known state, the only way to suspend it would be to allow it to suspend itself then though. Otherwise you have no idea what step within the function the task was performing when it was suspended.

You both are right that heap fragmentation might be an issue but is strongly dependent on the heap usage patterns and of course the heap implementation. However, most general purpose heap implementations might get affected by this issue. In addition the time needed for allocations is non deterministic and can vary greatly.
Especially in deeply embedded systems with very limited RAM resp. heap it’s good practice to allocate memory statically or only once during init also to avoid unexpected out-of-memory situations.
Hint: Don’t use suspend/resume for task synchronization. It’s a somewhat special functionality and sometimes I think it should be there at all :wink: because you might get trapped by subtle race conditions. Even the seemingly easy case resuming a self-suspending task can fail if resume is done but the task was not yet (self-)suspended.
Compare it for example with using a semaphore and why it was invented to provide (robust) task synchronization.

You reminded me of the other problem I encountered when using suspend/resume. A mutex got locked inside of a suspended task and another function could never get it. I agree, suspend/resume seems to be a much more “niche” case than it first appears to be. I understand why it’s there but it seems easy to get pulled in that it will solve your problems when it creates so many more.

Thanks Harmut, I will switch to using a binary semaphore. It’s only been 15 years since I worked with an RTOS (vxWorks and Win32 API) so I’m relearning albeit slowly. Thanks so much for your input.
Best,

Rick

Hi Harmut, Using semaphores for inter task signaling works great, thanks. Unfortunately I need to wake up a task from a idle loop. I could not signal a task from the idle loop. Only from another running task. So Task suspends and resumes work fine for this but after reading your response I am curious to hear if there is a better way. I could explore semaphores from irq’s but not sure if this would work either.
Thanks
Rick

Unfortunately I need to wake up a task from an idle loop.

Do you mean the Idle task? There is no problem signaling a semaphore from the Idle task, you just need to use a 0 block time, as the Idle task isn’t allowed to block.

I have a different kind of situation. It’s not the idle task but a loop where I am trying to start a task by giving the semaphore. The task then would run and then wait on the semaphore at the top of a while loop.
( Why am I doing this? It’s a long story that Id rather not get into - thanks) .
In any case I have no problem resuming a task from the loop where upon the task completes, it suspends itself. And of course, I can run it over and over from the loop with task resume calls.
Most likely there will only be one task running at a time so this may work but I thought a semaphore would be better but it looks like they are only for task to task .
Any advice here is much appreciated.
Thanks,
Rick

I don’t fully understand what you mean with idle loop. It’s another task controlling the other task(s), right ? There are only tasks after the scheduler was started :thinking:
However, there should be no problem to signal a semaphore (or use a lean task notification/ xTaskNotify) instead of using vTaskResume to wake up the worker tasks.

Having a “busy loop” just running and detecting when to do things sounds like you are doing something that isn’t “RTOS Friendly”. Note, this loop will HAVE to be in a task, as the only code that runs at all is either Tasks or the contents of ISRs.

Under an RTOS, all tasks should be BLOCKING on something until something happens that starts them up, then they do their work, and go back a block again.

Sometimes you do have an “Idle” priority task (or several using round robin scheduling) that sweep up unused cycles to handle totally non-time critical functions. These tasks might never block (But can, and should if they don’t have anything to do, only the System Idle task can’t block), but just get switched out while the system does the Round Robin Sceduling of the tasks

Hi Richard, I beg to differ.
I’m a contractor that has come into a late situation and time critical as far as release is concerned.
Further, it’s based on Arduino libraries.
Arduino uses a loop() to run things.
I decided that some of the things that need to be done in this loop are somewhat time critical. For instance certain things need to get done after 100ms, then 1500ms and finally after another 100ms. Although these times are slow and could be accomplished in a loop(), I thought to spin of a RTOS task to accomplish it since the loop is performing so much other stuff. (all of it non blocking)
So although I would rather use an RTOS for the whole project, management is nervous and has dictated that I do not. I totally disagree with them but their concern is justified and they are good people.
So in fact, I am running a task (actually 4 for test purposes) from the loop and I see no problems. I’m printing out the high water mark (which I still don’t understand) and getting numbers ranging from 41 to 96. It ran all night so I think I’m good but trying to see if there is a better way to accomplish running a task without suspends and resumes from the loop.
Your probably right about not being RTOS friendly but if it’s going to work for this first release, I plan to convince the authorities to convert fully to an RTOS and freeRTOS appears to me to be very robust.
Thanks so much for your input.

Rick

You need to understand that after the scheduler starts, ONLY FreeRTOS tasks run. The following is the general structure of a FreeRTOS application (showing only FreeRTOS related stuff)-

int main( void )
{
    1. Create FeeRTOS objects (tasks, queues, semaphores etc.).
    2. Start the scheduler by calling vTaskStartScheduler.
    /* If the scheduler is successfully started, the control never reaches here
     * and ONLY FreeRTOS tasks run after this point. */
}

Assuming that you are using this library, the loop function that you mentioned is called from the IDLE task - https://github.com/feilipu/Arduino_FreeRTOS_Library/blob/master/src/variantHooks.cpp#L76

Can you elaborate on what you mean by you could not signal a task from the idle loop? Does the function call succeed or not? Is it possible for you to share code snippets?