Pumpkin, Inc.

Pumpkin User Forums

Messages

If you can't make Salvo do what you want it to do, post it here.

Messages

Postby aek » Thu Apr 11, 2002 12:42 am

You can improve on Task1() (reduce ROM) by restructuring it like this:
code:
void Task1( void ){  
OSCreateMsg(...);
OSCreateTask(Task2, ...);
...
OSSignalMsg(...);
for (;;) {
OS_WaitBinSem(...);
...
OSSignalMsg(...);
}
}

and if you need to, you can put the ...'s before OSSignalBinSem() in a called function.

Using PICC or PICC-18, OS_WaitXyz() is fairly expensive, ROM-wise (20? instructions), whereas OSSignalXyz() is much smaller. So removing an OS_WaitXyz() is a win-win situation.

------------------

[This message has been edited by aek (edited April 11, 2002).]

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: Messages

Postby Nado » Thu Apr 11, 2002 1:06 am

My goal is slightly different I think. Task 2 is higher priority, but I don't want it to run until after Task1 has run once. So I tried this:

code:
void Task1( void ){  
OSCreateMsg(...);
OSCreateTask(Task2, ...);
...
/*OSSignalMsg(...); - Leaving this out so that Task2 is blocked */

/*OS_WaitBinSem(...) - this is at the bottom of the task so it runs once before getting blocked */

for (;;) {
...
OSSignalMsg(...);
OS_WaitBinSem(...);
}
}

void Task2 ( void ){
for (;;) {
OS_WaitMsg(...);
...
OSSignalBinSem(...);
}
}


I'm still having the same problem. When I first yield in Task1, Task2 executes even though the message hasn't been sent yet. It should be halted at the OS_WaitMsg() and go back to Task1 (well, that's what I want it to do). I'm not sure what's going on. I'll keep working with it tomorrow. Thanks for your help.

[This message has been edited by aek (edited April 11, 2002).]

Nado
 
Posts: 14
Joined: Tue Apr 02, 2002 12:00 am
Location: Westlake, OH, USA

Re: Messages

Postby aek » Thu Apr 11, 2002 1:43 am

Hi Nado.

quote:
When I first yield in Task1, Task2 executes even though the message hasn't been sent yet.

But it has been sent. Task1() first yields at the OS_WaitBinSem() call (assuming you created the binSem with a value of 0). But OSSignalMsg() precedes it, so the message has been sent by the time Task1() yields. When Task1() yields, Task2() runs because the act of signaling the message has set the message pointer to a non-zero value, and task can continue running when it waits a message whose pointer is non-zero.

BTW, you are initializing the binSem, too, aren't you? Just checking ..., but without it, behavior is unpredictable. You could initialize it in Task1() if you want ...

If you were to swap the order of OSSignalMsg() and OS_WaitBinSem() in Task1(), then you'd get the behavior that you want (the first time 'round -- dunno if that's what you want on subsequent executions of the two tasks's loops).

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: Messages

Postby Nado » Thu Apr 11, 2002 7:27 am

Hello. I'm having a little problem getting messages to work the way that I want them to. What I'm trying to do is have two tasks communicate, Task1 is lower priority than Task2. Task2 will not run until Task1 sends a message. While Task2 is running, Task1 waits for a binary semaphore from Task2 before continuing. BUT, Task1 must run once before Task2 can start. Here is a rough snippet of code that I'm using:

code:
void Task1(void)	/* Priority of 10 */
{
OSCreateMsg(task1msg,...);
OSStartTask(task2label);
for(;;)
{
...

OSSignalMsg(task1msg,...);
OS_WaitBinSem(task2binsem,...);
}
}


void Task2(void) /* Priority of 8 */
{
OS_Stop(task2label);

for (;;)
{
OS_WaitMsg(task1msg, ...);

...

OSSignalBinSem(task2binsem,...);

}
}


The problem I am having is that when stepping through the code, after OSStartTask(task2label) is called in Task1, the program jumps to Task2, stops at OS_WaitMsg(task1msg,...) twice, and continues on executing before Task1 ever sends the message. After Task2 is finished, control is returned to Task1 via the semaphore, and everything behaves as it should from this point on. I have a feeling the problem has something to do with waiting for a message before it's created. I'm not really sure though.

In any case, what is the best way to code this? Thanks.

[This message has been edited by Salvo Tech Support (edited April 11, 2002).]

Nado
 
Posts: 14
Joined: Tue Apr 02, 2002 12:00 am
Location: Westlake, OH, USA

Re: Messages

Postby Salvo Tech Support » Thu Apr 11, 2002 8:04 am

Hi Nado.

A couple of things:

You are not using OSStartTask() correctly. The argument to OSStartTask() is a pointer (e.g. OSTCBP(2)), not a label (I figure that's just a typo -- in the future it's always best to cut-and-paste actual code when requesting technical support).

Also, unless you called

code:
OSCreateTask(Task2, OSTCBP(2), prio | OSDONT_START_TASK)

Task2() will automatically start and be up and running ... So, in your example Task2() will run first (it has the higher priority), and then stop immediately.

I would suggest something different (same priorities, but main only calls OSCreateTask(Task1(), ...)):

code:
void Task1( void )
{
OSCreateMsg(...);
OSCreateTask(Task2, ...);
...
OSSignalMsg(...);
OS_WaitBinSem(...);
for (;;) {
...
OSSignalMsg(...);
OS_WaitBinSem(...);
}
}

void Task2 ( void )
{
for (;;) {
OS_WaitMsg(...);
...
OSSignalBinSem(...);
}
}


A couple things to note: 1) Creating a task from within another task is fine. The created task can't run until the creating task context-switches. 2) You can call OS_Xyz outside of a task's infinite loop -- that's useful in a case like this.

There are, in fact, many ways you can do this. Remember that you can also "pre-load" a message or binSem with an initial value so that a waiting task can proceed before the event has been signaled again ... they key to intertask communications is to have a clear view of the mechanisms you will use, and the initial values of the events you're using.

Also, since you're just starting out, when you have problems with something not working correctly, it's useful to check the return codes from the Salvo services -- a non-zero (i.e. not OSNOERR) code probably means that it's not doing what you think it should be doing.

quote:
I have a feeling the problem has something to do with waiting for a message before it's created.
That's a no-no, and will have unpredictable results. The example above fixes that.

Hope this helps,

------------------
--------
Salvo Technical Support
Please request all tech support through the Forums.

[This message has been edited by Salvo Tech Support (edited April 11, 2002).]

--------
Salvo Technical Support
Please request all tech support through the Forums.
Salvo Tech Support
 
Posts: 173
Joined: Sun Nov 19, 2000 12:00 am

Re: Messages

Postby aek » Fri Apr 12, 2002 2:13 am

... (follow-up) ...

Nado emailed me his files, and I was able to locate the problem rather quickly. Turns out his call to OSCreateMsg() was incorrect. He wrote:

code:
void Task1(void)
{
...
OSCreateMsg(MSG_AVEADC, &ui_AveADC);
...
}

Any non-zero value used to initialize a message pointer is equivalent to have signaled the message.

So in Nado's case, the correct call to OSCreateMsg() is:

code:
OSCreateMsg(MSG_AVEADC, (OStypeMsgP) 0);

This creates an "empty" message. Anyway, everything's working fine on Nado's end now that he's changed the second argument (a message pointer) in OSCreateMsg().

Messages (and message queues) are probably the hardest Salvo component to learn, simply because they involve pointers and pointer operations. We advise users to study the examples in the manual and elsewhere (e.g. in salvo u6) and use those as a starting point.

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: Messages

Postby Nado » Fri Apr 12, 2002 5:25 am

Oh, I forgot to mention this, but in the "..." section of the Task1 code, there are a few OS_Yield()'s. This is where Task1 first yields to the scheduler. Task2 begins to execute at this point, instead of waiting for OSSignalMsg and OS_WaitBinSem(). (Also, the BinSem is created in main, and is initialized to 0).

It's kind of weird. I set up a bunch of breakpoints in MPLAB to check this. What happens is that Task2 is called at the first OS_Yield() in Task1, and stops at the breakpoint I placed at OS_WaitMsg() in Task2. But, instead of returning to Task1, it stops again at OS_WaitMsg(). Finally, the program does not return to Task1, but now continues executing Task2. Also, I have breakpoints at OSSignalMsg() and OS_WaitBinSem() in Task1, and neither of these execute before Task2 begins to run.

After Task2 finishes, and OSSignalBinSem() occurs, control returns to Task1, and now the program operates as I wanted it. It hits all my breakpoints as expected, and the problem is gone.

Do you want me to email you the source code?

Nado
 
Posts: 14
Joined: Tue Apr 02, 2002 12:00 am
Location: Westlake, OH, USA

Re: Messages

Postby aek » Fri Apr 12, 2002 7:12 am

Hi Nado.

quote:
Do you want me to email you the source code?

Yes, please do. ZIP up the whole project and email it to support@pumpkininc.com. Ideally, you should remove / comment out all of your own non-Salvo code, verify that it still has the same behavior, then send that project to us.

I'll have a look at it. Something's not quite right here.

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm

Re: Messages

Postby aek » Fri Apr 12, 2002 7:35 am

Hi Nado.

While I'm figuring out what the root of your problem is (and I may not get to it today), here's a simple way to get around it: Instead of counting on OS_WaitMsg() to stop Task2(), use OSCreateTask() and OSStartTask() to control when it starts. E.g.:

code:
void Task1(void)
{
OSCreateTask(Task2, OSTCBP(2), prio | OSDONT_START_TASK);
...
/* now Task1() has run once, and I'm ready for Task2() */
OSStartTask(OSTCBP(2));
...
}

You could use a simple boolean flag to ensure that OSStartTask() is called just once, and only after Task1() has run that first time.

Using OSDONT_START_TASK causes a task to be created in the stopped state, instead of the eligible styate, and it won't start running until it's made eligible by a call (from somewhere else) to OSStartTasp(p).

There's an example of this kind of task control in our App Note AN-8, though it uses OS_Stop() in the controlled task (your Task2()) and OSStartTask() in an ISR.

------------------

-------
aek
aek
 
Posts: 1888
Joined: Sat Aug 26, 2000 11:00 pm


Return to Coding

Who is online

Users browsing this forum: No registered users and 1 guest

cron