Pumpkin, Inc.

Pumpkin User Forums

Contex switch from subroutines? OS__Yield() and OS__Delay()

Have an idea on how to make Salvo better? Post it here!

Contex switch from subroutines? OS__Yield() and OS__Delay()

Postby luben » Sat Jul 27, 2002 8:38 am

Hello,

If talking about the "wish list" - what SALVO have to make, I'm sure that there are not so many important, basic things in this list (except SALVOCFG.H Wizard, speed up the kernel as possible, etc.).

But there is one issue, that right now is impossible in SALVO (due to the limited RAM in PICs and impossibility to read directly the stack) - to call OS_WaitXYZ or OS_Delay from subroutines.

Let's think about is it OK to have such possibility? Of course I can create in now moment a task and can add to it an message, bin semaphore or something like that. In short - I can fake the subroutine with other task. But this is "fake" subroutine, not real one - means - slowlier response, bigger code and more resources. If we are speaking about slowly processes - it's OK.

Imagine that you need to output strings to RS232. What I'm doing now is to make a task responsible for RS232 output , to create a messge to it and binsem, showing that the task is idle (this is the perfect situation, binsem could be skipped in some cases, or by using some variable like flag).

In C language the functions responsible to output data is printf() and putch(). With current SALVO I can't use such functions, because I have to do context switch into subroutines. What I'm doing now is: I do sprintf() to some data buffer and then send the address of the buffer like message to the RS232 task, or send the address of the string, kept in ROM like message.

My issue is : Is it possible to add some new functions, allowing the user to call contex switch function from subroutines.

Imagine we have OS__Yield(Task_ID, Label), OS__Delay(time, TASK_ID, Label) /note that I used 2 sequential underlines, showing that this is "within subroutine" contex switch/. In fact what we need is usually OS_Yield and OS_Delay functionality - they are the basic "cells" for more complicated user services like OS_WaitXYZ.

When calling such "within subroutine" user service we decrease the depth of the stack by one. So, this service could be dangerous if both the user and SALVO don't track the situation.

In fact, it's my own experience, but after I started using SALVO my programs became much simplier and what's more important - due to the structure of SALVO, they don't occupy deep stack. I mean, before I used SALVO I had many cases, when the stack was not enough to hold many subroutines. Right now I can't imagine how I can reach the boundary of the stack (I don't speak about old 12 bit kernel of PICs).

So, one of the results of using SALVO is that the user has more free stack for subroutine calls. BTW I didn't saw this note into SALVO manual, despite that it's important and dramatical change - SALVO reduces the usage of stack, decreases its depth (it should be menshened more frequently in the manual).

Knowing that SALVO free some stack space, we could implement such OS__Yield() and OS__Delay() functions - it's possible. The kernel should keep track of two things:

- only one such function could be called at time - before it finish, no other task could issue such functions. The user have to check before entering into subroutine, where OS__Yield() or OS__Delay() exists, some global flag - OSOCCUPIED (imagine a bathroom share resources :-). If the flag is SET , he has to wait with OS_Yield, OS_Delay or OS_WaitXYZ. If the flag is free he enters the subroutine and immediately sets the flag OSOCCUPIED to SET, protecting the subroutine.

- the real moment status of stack depth. This will need two new functions OSEnterSUB() and OSExitSUB() - enter and exit subroutines - they will increase/decrease some variable that will track the moment status of stack depth. And if the stack became unstable to bring some information to the user that it's dangerous to call OS__... finctions. Of course the user could set some OSMAX_STACKDEPTH into salvocfg.h.

Because OS__Yield and OS__Delay bring to the kernel information from which task is called the subroutine, there is no problem of the kernel to apply priorities and all other attributes

So, imagine that we already have such functions - then the RS232 output will look like:

while (OSOCCUPIED)
OS_Yield(Label);

OSOCCUPIED = TRUE; // disable access for other tasks
var_task = TASK_ID; // current task ID
printf("message%....%...., var1, var2); // output data to serial
OSOCCUPIED = FALSE; // enable access for other tasks

with some putch() that contains OS__Yield() and OS__Delay() , that takes the var_task
.... OS__Yield(var_task, LABEL);

(ouch, I cant' imagine how to add OSEnter and OSExit into printf())


It's just and an idea ......


In short :
What about calling contex switch from subroutines? Even only one possible exception from the main rule (NO CONTEX SWITCH WITHIN SUBROUTINES) will bring tremendous power and flexibility. Don't forget that some processors have more stack then PIC and could read the stack, so they could allow multiple tasks to call simultaneously several such "exceptions".

Best regards and have you a nice weekend
Luben

luben
 
Posts: 324
Joined: Sun Nov 19, 2000 12:00 am
Location: Sofia, Bulgaria

Re: Contex switch from subroutines? OS__Yield() and OS__Delay()

Postby aek » Sun Jul 28, 2002 8:31 am

Hi Luben.

There are ways around the issue of encapsulation, which crops up most in the use of printf(). You can search the forums for some ideas. The best idea seems to be to have a "printf() task" which waits on messages from other tasks and sends out the string as putchar() processes the chars.

There are two main problems with extending Salvo's context switches to be allowable from anywhere -- the memory required, and the means to manipulate the stack.

Memory requirements vary -- on a stackless processor like a PIC16, technically one would only only need to preserve the calling stack so as to be able to return "up the call tree". I'm also not certain if PICC and PICC-18 would handle the auto variable and argument overlays for multiple call trees -- I suspect not. On a stack-based implementation (e.g. MSP430) it's only a matter of saving the complete stack frame for the call tree (it can be very large, if lots of auto variables and arguments are used).

Vis-a-vis the stack, the problem is that on the PIC16 the stack is completely inaccessible, i.e. there is no way to figure out what the return tree is for a given function. You would have to have a completely synthetic call...return mechanism using jumps (a la PIC12 + PICC) to pull this off. The overhead would be substantial, and the memory requirements would probably double, and the performance would suffer.

Realistically speaking, the ability to context-switch from any level requires a conventional stack stack and stack pointer, and a lot more than the 256-2048 bytes of RAM that typical Salvo targets have.

If you can solve your "printf()-context-switch" dilemma elegantly using a task and messages, etc., I'd be happy to incorporate it into an App Note.

Regards,

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

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

Re: Contex switch from subroutines? OS__Yield() and OS__Delay()

Postby luben » Sun Jul 28, 2002 10:04 am

Hello,

As I told you I already solved my problem using sprintf() command - it's absolutely equvalent of printf(), except that it requires a RAM buffer. I use, like you suggested, a task that waits a message and then sends this message out.

Because you're much closer to the SALVO problems, I agree, that trying to make SALVO contex switch into subroutines will need big resources of RAM and ROM.

My idea was to make some putch() that is totally compatible with ANSI C and in the same time implements the SALVO multitasking. Usually putch() doesn't return the control until the character is sent.

In fact there are not so many functions like printf() in C that are "uncompatible" with SALVO.

But if you can somehow make SALVO to contex switch into subroutines, it will make possible for example to devide some complicated routines like SIN(), EXP() into shorter pieces, allowing other tasks to "take breath". And of course to make putch().

I'll think more about how to make one elegant SALVO putch().

Regards
Luben

luben
 
Posts: 324
Joined: Sun Nov 19, 2000 12:00 am
Location: Sofia, Bulgaria


Return to Feature Requests

Who is online

Users browsing this forum: No registered users and 1 guest