Sending enums as messages in a uCos OSQue

Discussion to talk about software related topics only.
Post Reply
barttech
Posts: 135
Joined: Fri Feb 20, 2009 12:59 pm

Sending enums as messages in a uCos OSQue

Post by barttech »

The queue examples that I've seen send strings as messages. Can I send integers or enums instead?
I have an enum called 'commands', I'd like to have several tasks send 'commands' to UserMain(). I've tried this:

enum commands{ SETUP_FOV_CMD, SETUP_FOCUS_CMD, SETUP_MIRROR_CMD, SETUP_PADDLE_CMD, ...

A task:
void TouchScreenServer(void*){
iprintf( "Starting TouchScreenServer.\r\n" );
commands TSCommand = NOTHING_CMD;
while (true){
char key = TS.Key();
if (WFOVButton.Hit(key)){
TSCommand = WIDE_CMD;
...

OSQPost(&CommandQueue, (void *)TSCommand);
}
} // end of TouchScreenServer

in UserMain :
...
commands Command = NARROW_CMD;
iprintf("Ready...\n");
while(true){
commands* pc = (commands *)OSQPend(&CommandQueue, 0, &QueueError);
Command = *pc;
iprintf("Working...");
switch (Command) {
// FOV commands follow
case WIDE_CMD :

...

This will compile, but hangs when the OSQPend unblocks (never prints "Working ..."). The hardware needs a hard reset to respond to the ID after this. I suspect I've gotten my pointers tangled up.
I think I'm missing something fundamental here, does anyone have an example of passing a non-char* message in a uCos OSQue?

Netburner MFC5234. Eclipse
Thanks,
Sam
User avatar
yevgenit
Posts: 84
Joined: Fri Apr 25, 2008 12:47 am
Contact:

Re: Sending enums as messages in a uCos OSQue

Post by yevgenit »

The error is mixing enum with pointer to enum.

The sent value is enum:
enum commands{ SETUP_FOV_CMD, SETUP_FOCUS_CMD, SETUP_MIRROR_CMD, SETUP_PADDLE_CMD, ...
...
commands TSCommand = NOTHING_CMD;
...
OSQPost(&CommandQueue, (void *)TSCommand);

but the received value is pointer to enum:
commands* pc = (commands *)OSQPend(&CommandQueue, 0, &QueueError);

Try to replace above line with
commands pc = (commands)OSQPend(&CommandQueue, 0, &QueueError);
________________
barttech wrote:The queue examples that I've seen send strings as messages. Can I send integers or enums instead?
I have an enum called 'commands', I'd like to have several tasks send 'commands' to UserMain(). I've tried this:

enum commands{ SETUP_FOV_CMD, SETUP_FOCUS_CMD, SETUP_MIRROR_CMD, SETUP_PADDLE_CMD, ...

A task:
void TouchScreenServer(void*){
iprintf( "Starting TouchScreenServer.\r\n" );
commands TSCommand = NOTHING_CMD;
while (true){
char key = TS.Key();
if (WFOVButton.Hit(key)){
TSCommand = WIDE_CMD;
...

OSQPost(&CommandQueue, (void *)TSCommand);
}
} // end of TouchScreenServer

in UserMain :
...
commands Command = NARROW_CMD;
iprintf("Ready...\n");
while(true){
commands* pc = (commands *)OSQPend(&CommandQueue, 0, &QueueError);
Command = *pc;
iprintf("Working...");
switch (Command) {
// FOV commands follow
case WIDE_CMD :

...

This will compile, but hangs when the OSQPend unblocks (never prints "Working ..."). The hardware needs a hard reset to respond to the ID after this. I suspect I've gotten my pointers tangled up.
I think I'm missing something fundamental here, does anyone have an example of passing a non-char* message in a uCos OSQue?

Netburner MFC5234. Eclipse
Thanks,
Sam
Yevgeni Tunik
Embedded/RealTime software engineer
https://www.linkedin.com/in/yevgenitunik/
________________________
barttech
Posts: 135
Joined: Fri Feb 20, 2009 12:59 pm

Re: Sending enums as messages in a uCos OSQue

Post by barttech »

Thanks yevgenit,
The uCos OS_Q is a queue of void pointers, so OSQPend returns a void pointer,
void * OSQPend( OS_Q * pq, WORD timeout, BYTE * err );

so when I tried your suggestion I get:
error: invalid cast from type 'void*' to type 'commands'

I think where I'm confused is what it is that the queue holds. It holds pointers to "messages", but do these messages always have to be strings? When I "post an enum to the queue", I am really posting it's pointer, I post (void *)TSCommand to the queue. If I try to just put the TSCommand in, I get a compile error, "can't convert type 'commands' to type 'void*'".

So are the queue elements pointers to TSCommand, (or whatever other 'commands' type variable I have placed in the queue)?
How do I get the value of TSCommands that was placed in the queue back out?

The Post/Pend aspect of the queue is working nicely for me, the main task blocks until I post to the queue. If I just make TSCommands global I can access it from any task, but then I only get the current value, there is no queueing of the values.

Thanks?
Sam
User avatar
yevgenit
Posts: 84
Joined: Fri Apr 25, 2008 12:47 am
Contact:

Re: Sending enums as messages in a uCos OSQue

Post by yevgenit »

The following tested example shows using message with integer value.
The identical integer representation of both integer and any pointer is assumed.
Such assumption is true for most(?) 32-bit architectures.

______ Start of example____
// Modified example of "NetBurner's uC/OS RTOS Library - 2.18 OSQInit".

#include "predef.h"
#include <stdio.h>
#include <ctype.h>
#include <startnet.h>
#include <autoupdate.h>
#include <smarttrap.h>
#include <taskmon.h>
#include <NetworkDebug.h>

extern "C" {
void UserMain(void * pd);
}

const char * AppName="post_integer";

OS_Q MyQueue;

void task_dst(void*)
{
BYTE err;
iprintf("Ready to receive messages...\n");
while(true)
{
void * pData = OSQPend( &MyQueue, 0, &err );
iprintf("Received message: %d\n", (int)pData );
}
}

const int NUM_ELEMENTS = 3;
void * MyQueueStorage[NUM_ELEMENTS];

void UserMain(void * pd)
{
InitializeStack();
OSChangePrio(MAIN_PRIO);
EnableAutoUpdate();
EnableTaskMonitor();

#ifndef _DEBUG
EnableSmartTraps();
#endif

#ifdef _DEBUG
InitializeNetworkGDB_and_Wait();
#endif

iprintf("Application started\n");

OSQInit( &MyQueue, MyQueueStorage, NUM_ELEMENTS );
static int count;
OSSimpleTaskCreate( task_dst, MAIN_PRIO+10 );
OSTimeDly(1*TICKS_PER_SECOND);
iprintf( "Starting to send messages.\n" );

while (1)
{
OSTimeDly(2*TICKS_PER_SECOND);
for( int i=0; i<NUM_ELEMENTS; i++)
{
iprintf("Sent message: %d\n", count );
OSQPost( &MyQueue, (void *)count );
count++;
}
}
}

______ End of example____

barttech wrote:Thanks yevgenit,
The uCos OS_Q is a queue of void pointers, so OSQPend returns a void pointer,
void * OSQPend( OS_Q * pq, WORD timeout, BYTE * err );

so when I tried your suggestion I get:
error: invalid cast from type 'void*' to type 'commands'

I think where I'm confused is what it is that the queue holds. It holds pointers to "messages", but do these messages always have to be strings? When I "post an enum to the queue", I am really posting it's pointer, I post (void *)TSCommand to the queue. If I try to just put the TSCommand in, I get a compile error, "can't convert type 'commands' to type 'void*'".

So are the queue elements pointers to TSCommand, (or whatever other 'commands' type variable I have placed in the queue)?
How do I get the value of TSCommands that was placed in the queue back out?

The Post/Pend aspect of the queue is working nicely for me, the main task blocks until I post to the queue. If I just make TSCommands global I can access it from any task, but then I only get the current value, there is no queueing of the values.

Thanks?
Sam
Yevgeni Tunik
Embedded/RealTime software engineer
https://www.linkedin.com/in/yevgenitunik/
________________________
User avatar
pbreed
Posts: 1088
Joined: Thu Apr 24, 2008 3:58 pm

Re: Sending enums as messages in a uCos OSQue

Post by pbreed »

void * is the compiler way of saying I'm reserving a 32 bit block of stuff, I have no idea what you are going to put in there.


So with proper casting any int or enum can be conveted to/from a void *.

enum an_enum {A,B,C};

void * pV;
an_enum x;

x=A;

//Cast to void *
pV=(void *)x;

//Cast back to enum.
x=(an_enum)pV;
barttech
Posts: 135
Joined: Fri Feb 20, 2009 12:59 pm

Re: Sending enums as messages in a uCos OSQue

Post by barttech »

Thanks pbreed,

Maybe this a compiler issue. When I try your suggestion, which was what yevgenit said also, I get:
error: invalid cast from type 'void*' to type 'commands'

If I first cast to int, then cast to my enum 'commands', it works (ie compiles AND behaves) fine:

int *pc = (int*)OSQPend(&CommandQueue, 0, &QueueError);
Command = (commands)(int)pc;

The error messages I've been getting make it look like the compiler treats enums as pointers, not like the ints I expected.
I think of enums as a subset of ints, so this compiler behavior seems odd to me.
I think this is as clean as I'm going to get it w/o making a Queue for enums myself.
Sam
barttech
Posts: 135
Joined: Fri Feb 20, 2009 12:59 pm

Re: Sending enums as messages in a uCos OSQue

Post by barttech »

Thanks yevgenit,
Your example got me over the hump. I'm not sure why, but if I cast to int first, then cast to my enum 'commnds', I get the desired operation from the OSQueue:

int *pc = (int*)OSQPend(&CommandQueue, 0, &QueueError);
Command = (commands)(int)pc;

Thanks for your comprehensive example!
Sam
Post Reply