Pumpkin, Inc.

Pumpkin User Forums

Idea for new construction - OSWaitBinKey()

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

Idea for new construction - OSWaitBinKey()

Postby luben » Wed Dec 20, 2000 9:07 am

Hello,

Because I used to make multitasking (or something like that) on many processors with bigger RAM, I would like to share one of my constructions, that I don't find in Salvo. It should be named (if we want to keep the style of Salvo) OSWaitBinKey().

The idea is comming from the door locks and keys. You have a door lock (and you wait there to be opened) and you wait until the right key is comming. If you have a key, but only a part of it don't match to the lock - you can't open the door, right? Until all parts of the key becomes desired value you have to wait. A mask is defined to scope some bits of the key or the whole key. And Salvo construction OSWaitBinSem() is just a case of this KEY construction.

In more details - OSWaitKey(OSTypeID Key_Name, mask,OsTypeDelay Timeout, label);

The task waits until (mask & ~(mask & KeyName)))== 0 - all bits of the key match the mask (become 1) or timeout occurs. For example if the mask is 0b00010011 - you have to wait until the corresponding bits in KeyName variable becomes 1 - 0bxxx1xx11.

Of course to keep the stype of Salvo we should add OSSetKey(name,mask) and OSResetKey(name,mask). In the first case we should make OR with the <mask> and <name> (result in >name> ) and in second case - AND with <~mask> and <key>. And of course you can define the lenght of the construction via OS_BYTES_OF_KEY FOR 1,2,3,4 bytes.

With such powerful construction you can make very complicated logical switching.

The checking of the match key is making into Scheduler.

After the key matches, the user should manually clear the corresponding bits in varable with OSSetKey() or OSResetKey().

With up to now moment construction of Salvo it is difficult to do such switching.

As you see, OSWaitBinSem() is just a case of this construction (when you watch one bit). Trust me, if Salvo has similar construction like OSWaitKey() it will become more powerful. Immagine that you have to watch for appearing of 5 events that could be simply define as some codes into <key_name>.

I use such construction in my "table" switch projects. I have one big table with many keys and corresponding to them reactions, jumps, etc. The program starts from the beginning of the table. If key matches - you do something, if not - other thing (for example you can goto the same line). The idea of the tables is that they are very close to Petry's net descriptions - the pure algorithm of any program (in addition there is really good theory about all questions with Petry's net - transformations, reducing, etc). And if you build once the table, interpretator could very easy change the behavior of the whole program simply changing the content of the table (it could be made even with text editor and without any C compilers if the table resides in EEPROM).

My idea is to use Salvo to manage such tables - so I can run simultaneously 2 or more tables. Such table constructions are very usful in automatic - for controlling processes. Imagine that you have simple machine that has 5 motors, 10 end-switches. In one table is very easy to describe the behaviour of such system. And will be very good if it's possible to start not one, but 2 or 3 and more tables - that means - you can implement 2 or more totally different algorythms into one uP.

Think about it.

Regards
Luben

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

Re: Idea for new construction - OSWaitBinKey()

Postby aek » Wed Dec 20, 2000 9:24 am

Hi Luben.

What you describe is definitely very useful -- it's another way of describing what are event flags, and Salvo v2.1 does not support event flags very well.

We've been thinking about how to implement something like this, in a powerful manner. Your explanation has given us some good ideas ... :-)

Just to make sure we understand this correctly -- is it correct to say that in an application that uses these keys, there will be several places where OSSetBinKey() is called from for each OS_WaitBinKey()? Each one will set a couple (but not all) of the bits in the key. Only when all of the bits have been set and match the mask does the "door open."

Also, in keeping with Salvo and how binary semaphores are handled, when OS_WaitBinKey() succeeds then all the bits in the mask will be cleared automatically. Is that in keeping with your idea?

The integration you describe with Petry nets should be very easy with this functionality -- some Salvo users are already embedding state machines into Salvo tasks for similar purposes.

[This message has been edited by aek (edited December 20, 2000).]

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

Re: Idea for new construction - OSWaitBinKey()

Postby aek » Wed Dec 20, 2000 9:35 am

Hi Luben.

I've given it some more thought -- in order to support bit masks greater than 8 bits, it will have to be like Salvo's message queues, where an external structure (a bit mask control block) will be required. This means that it's a little extra work to declare them properly.

For 8-bit keys, we can fit them into the event control blocks directly.

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

Re: Idea for new construction - OSWaitBinKey()

Postby aek » Wed Dec 20, 2000 9:42 am

Hi Luben.

One more thing -- in keeping with Salvo's current inner workings, the mask would have to be defined in OSCreateBinKey(), like this:

code:
OSCreateBinKey(BINKEY1, mask);

and therefore to wait on the key would look like

code:
OS_WaitBinKey(BINKEY1, timeout, _label);

Is that acceptable? I.e. have one mask for a binkey? I suspect not -- I suspect you want to be able to wait with multiple, different masks on a single binkey. That's not so simple, because it would require an exhaustive search of all instances of OS_WaitBinKey() on a particular key from within OSSignalBinKey(). And exhaustive searches lead to non-constant-time / non-deterministic execution, etc.

Please provide an example with more than one OS_WaitBinKey(). See the BB's FAQ on how to format code using UBB codes for legibility.

Regards,

[This message has been edited by aek (edited December 20, 2000).]

[This message has been edited by aek (edited December 20, 2000).]

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

Re: Idea for new construction - OSWaitBinKey()

Postby luben » Wed Dec 20, 2000 10:27 am

Hello,

1. it's not good to clear automatically the corresponding bits in mask. It could be made with OSResetKey() or OSSetKey(). The automatic clearing is only particular case ot this and limits the possibilities fo this structure. From my own experience it's good to manage by myself the flags.

2. From my real projects I can tell that it's not very often when I had to use masks longer then 8 bits and 2 and more masks together. But this could be made very easy with merging the checking from several OS_WaitKey() with some flag. It's hard to explain now, because I'm hurry to the office, but will try to tell you how. It's a flag, that is transmited from one OS_WaitKey to the next one.

Talk to you soon. Seems that Salvo is very nice area for exercises of my brain :-)

Regards
Luben

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

Re: Idea for new construction - OSWaitBinKey()

Postby luben » Thu Dec 21, 2000 1:03 am

Hello,

On the way to my office I received clear vision of how the OS_WaitKey() should look like.

-It’s not good idea for Salvo to manage all these masks and keys, variables and so on. As you told me this will be first difficult to implement and second – will bring some limitations. There is no sense to put limitation for the length of the maks and variables, their number or where they reside. You have to agree, that this only decreases the power of such construction. The only one thing that Salvo should do is to check one expression for FALSE/TRUE. Just one simple expression.

So, the idea is :

OS_WaitKey(<expression>,timeout,label); - simple and clear, right?
Well, the idea of the key and the lock is not very visible, but still alive. Just the key is transformed into one expression. So with the same success the construction could be named like OS_WaitEvent(), if you like it more.

The expression is checked into scheduler for TRUE and if it’s TRUE the event occures. If not – check for timeout occurrence.

Now, to make easier the working of such construction and to implement the idea of the masks and keys you should add some macros, like:

#define OSPosKey(var,mask) ((mask & ~(mask & var)) == 0) // this will check is the mask fits the key (variable) – all bits in var, that presense like 1 in mask should be 1 too. Example var = 0b1110000010000000 mask = 0b0b1110000010000001 will not fit until bit 0 of the var becomes 1.

#define OSNegKey(var,mask) ((mask & ~(mask & ~var)) ==0) // check if all bits in mask, that are 1 have corresponding 0 in the var.

#define OSExactlyKey(var,value,mask) (~(~(var ^ value) & mask) == 0) // check if the mask exactly to variable, but for bits marked in mask

Some feature, that will increase the power is to check for toggle of 0->1 or 1->0 of the bits. This will need additional registers to remember the old value. Don’t forget that in more of the cases (like buttons pressed) you don’t the value of the variable, but the toggle from one state to other.

#define OSToggPosKey(var,mask) (~(~old_var & var) & mask == 0 ) // in corresponding bits you wait for toggle 0->1 of the variable

#define OSToggNegKey(var,mask) (~(old_var & ~var) & mask == 0 ) // in corresponding bits you wait for toggle 1->0 of the variable

In last two macros you need to make refresh of the old_var every time you enter sheduler like
old_var = var;
var = read/refresh value …… I’m afraid that this is taugh (at least for me  ….
This could be made if you have special declaration like
OSVarWatch(var); - this will create a new variable with the same size and type like <var>, caleed <oldvar> and should say to Salvo to refresh every time when sheduler started var -> oldvar. And when checking the toggle of the bits you can call the value of <oldvar>.


With two words – what you add more to Salvo with new construction OS_WaitKey();
1. You can directly watch pin on the port, flags into memory, exactly value of some register.
2. You can add as much as you want expressions , connecting them with &&. So, you can watch in one moment unlimited number of events and keys (depend on the compiler)
3. You don’t need to manage the variables and masks – you just check is the expression TRUE or FALSE, nothing more. Don’t try to reset or set flags – it could be made with powerful macros. So, after expression becomes TRUE you have two choices – to clear/set some bits in the variables (with or without macros) or to drop them to be the same. In last case you bring possibility to other tasks to use the same bits, until you don’t especially clear/set them. This is very useful if you watch a pin on the uP.
4. The OS_WaitBinSem() is just a case of this construction, well, with some convenient feature – to clear the used flag. But this could be made easy with OsWaitKey() and one additional command. Because in OS_WaitKey() is calculating expression of variables, declared from the user, they could be set/reset in any part of the program without any problems (but you should care for interrups – not to change the value when checking the expression).

I think is no problem to write some macros to reset var like

#define OSClearBits(var,mask) var &= ~mask;
#define OSSetBits(var,mask) var |= mask;

You have to agree that the new construction is similar to the constructions used in Salvo in this moment, it’s the same “fasion style”. But it has very powerrful option – to watch events and variables, pin from the ports, flags in the special registers, user defined flags.

I’m afraid that it’s hard to me to explain all these ideas (at least english is not my native language), but if you have interest or if you don’t understand what I said – just ask me. But for people who made so complicated stuff like Salvo will be no problem to understand from half word, right? I was some time in Japan (for learning management and quality control in big firms like Matsushita, Sony, Sumitomo) and from there I learned – try to simplify the things, try to make them better with removing unnessary things and adding quality.

The other way is to improve the menshend construction OS_WaitKey(var,mask,timeout,label) if you like it more. You can merge them if you transfere some flag between them, like:

OSReadKey(Idnumber,var1,mask1);
OSReadKey(Idnumber,var2,mask2);
OSReadKey(Idnumber,var3,mask3);
OSReadKey(Idnumber,var4,mask4);
OSReadKey(Idnumber,var5,mask5);
OS_WaitKey(Idnumber,timeout,label);

The new construction is OSReadKey() – it only calculates the expression ((mask & ~(mask & var)) == 0) - are all bits in var= 1 that have corresponding 1 in the mask? Of course you can make additional construction (menshened before). But you have to note that this expressions are calculating into the scheduler, not in the task.

With two words– the other way is to separate the calculating of the value and the taking the decision. So you will see two construction OS_WaitKey() and OSReadKey(). If you ask me this is not “clear” method, and will destroy the style of Salvo.

So, it’s your turn 

Regards
Luben

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

Re: Idea for new construction - OSWaitBinKey()

Postby aek » Thu Dec 21, 2000 1:35 am

Hi Luben.

Here's the problem ... this we can do very easily:

code:
OSCreateBinKey(BINKEY1);
OSCreateBinKey(BINKEY2);
...
OSSignalBinKey(BINKEY1, _mask1, OSANY_BITS);
...
OSSignalBinKey(BINKEY2, _mask2, OSALL_BITS);
...
void TaskA (void)
{
for (;;) {
/* task proceeds when any bits in _mask1 */
/* are set */
OS_WaitBinKey(BINKEY1);
...
}
}

void TaskB (void)
{
for (;;) {
/* task proceeds when all bits in _mask2 */
/* are set */
OS_WaitBinKey(BINKEY2);
...
}
}


What you are asking for (and I understand and appreciate the utility) is something rather different. Here's why that's a problem:

Remember, Salvo is event-driven. What this means is that all the "action" occurs not in OS_WaitXyz(), but in OSSignalXyz(). Also, only one waiting task can be made active when an event is signaled. A task that waits an event becomes eligible if and only if it is the most eligible task waiting for the event, and the event is signaled.

The system you are proposing is no longer single-threaded, though you do appreciate / understand that this could all be resolved in the Scheduler before the current task is dispatched. Having multiple tasks wait on a single BinKey, using different masks, doesn't work because only the most eligible task can be made eligible when the event (BinKey) is signaled. Also, it's not possible to do any sort of "polled processing" in OS_WaitBinKey() because the task is waiting, i.e. the processor isn't spending even a single instruction on it -- that all happens when the event is signaled.

Now, if the PIC had lots and lots of memory, we could implement this easily with arrays and pointers and such. But we have extremely limited memory (3 bytes per event, normally) and so this isn't an option.

You see, you're trying to drive the BinKey operation from OS_WaitBinKey(). But events are driven from the signaling mechanism(s), not scanned in the scheduler. Having to scan vars and masks for a match in the scheduler kills all performance, because there's no predictability any more -- you could have one BinKey, or 15 BinKeys, each of which would have to be scanned in each call to OSSched().

Put another way, ** Salvo watches nothing ** in terms of events. Instead, events ** drive ** other actions. The only event that is processed in OSSched() is the timer tick event -- it is a single, predictable event, and by doing it in OSSched() (v2.2), it removes a lot of processing requirements from the timer ISR.

The idea of being able to specify an expression is appealing. Perhaps if we can sort out these other problems we can come up with a good Key system.

[This message has been edited by aek (edited December 21, 2000).]

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

Re: Idea for new construction - OSWaitBinKey()

Postby aek » Thu Dec 21, 2000 1:41 am

Hi Luben.

Another thing to consider would be some sort of "Key processor" that is used like this:

code:
main() {
...
for (;;) {
OSProcessKeys();
OSSched();
}
}

This would be an "extension" to Salvo, and would not represent event-driven event behavior, but rather a more polled behavior. Perhaps that would work for you.

This also shows how it's easy to add addtional functionality above and beyond Salvo.

[This message has been edited by aek (edited December 21, 2000).]

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

Re: Idea for new construction - OSWaitBinKey()

Postby luben » Thu Dec 21, 2000 9:06 am

Hello,

I understand what you're talking about. Sounds like the idea of OS_WaitKey() is a little bit not compatible with the conception of Salvo. It's true - using OS_WaitKey() will decrease the performance of the Scheduler, because you should calculate every time the expressions. And if more of the tasks don't need any "key event" procedures, they have to pay time for this too. Now Salvo doesn't calculate anything and this makes it fast kernel. And all tasks receive what they want - clear and simple. If one tasks need to know pins - let it know, but other tasks will not lose resources for this.

Sounds like Salvo is very good made machanism - you can't add or remove anything :-)

Maybe is better to implement my own fuction that cares for events and keys, then to destroy the working conception of Salvo.

But I don't give up - will think if it's possible to add this idea of WaitKey() somehow, without destroing the rules of Salvo. You have to agree that to watch one real pin status is big "extra" to any RTOS. The problem is that such real status functions will consume the time of all tasks - not good idea for one RTOS.

Regards
Luben


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

Re: Idea for new construction - OSWaitBinKey()

Postby aek » Thu Dec 21, 2000 9:09 am

I think we can fit OSCreateFlags(), OSSetFlags() and OS_WaitFlags(), with support for ANY or ALL masked bits in 8-bit or 16-bit flags, into the next release -- it's not too hard.

Perhaps you can play with them and propose some additions? Or if you have the full version, you could adapt them for your own needs ...

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

Next

Return to Feature Requests

Who is online

Users browsing this forum: No registered users and 1 guest

cron