Discussion and help about my framework

Go To Last Post
18 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi to all!
I have done an actor based framework in c++. My intent is to use it to programming the avr microcontrollers and in general to programm the embedded systems.
Actually, i have tested it on an Arduino Mega2560 and it seem to work, but i have some proble and i need some other tests.
I have some problems and some doubts about this framework. Let me tell you about my problem.

This framework use a message exchange system to communicate between the actors, so in the message class i have a property that I called data.
I have choose to use a void pointer type for this class property. The problem is that when i put some data in a message (example a unsigned char), 
the actor that receive this message doesn't read correctly this data. For example if i put a unsigned char of value of 5, the actor that receive the message read a value of 33.
I think to use correctly the semantic of the void type, but i don't know why the actor receive a wrong value. Can suggest me some solution or test about this problem? Arduino framework can play a role about this error?

 

The second problem is that i have organized the code in some folders. Now if i would to use my framework, i have to do a copy of this folders in every project.
I have read about the static library, so i have create a solution in Atmel Studio 7 to make a static library. I'm able to compile this solution and i obtain a .a file.
The problem is that i'm unable to use this static library in a new project. I think that i import this file correctly in the Atmel studio 7, but when i try to compile the solution i obtain an error.
I don't know if this error is due to linker that don't find the file .a or if the error is due to my mistake to include this library in my file.
I have tryed to import the library using #include "ClassHeader.h", #include"folderStructure/ClassHeader.h" but i'm not was lucky. 
Can you suggest me the correct procedure on how i make a static library and how i include it in a new project?

 

What do you thinks about this framework? Is this a correct framework to work with the embedded system? Can you suggest me some alternative or some other solution like this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

luca80 wrote:
I have choose to use a void pointer type for this class property. The problem is that when i put some data in a message (example a unsigned char), 

the actor that receive this message doesn't read correctly this data. For example if i put a unsigned char of value of 5, the actor that receive the message read a value of 33.

 

If you use a pointer, then the pointed-to data must remain available and unchanged after the message is sent - at least until the receiver has finished with it.

 

This means that you must not send pointers to automatic (ie, local, non-static) variables ... !

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Let's see some code. If you know win16/win32 and the lparam and wparam then you will know that two pretty general parameters can be used for passing all kinds of data either holding actual values directly or being used to pass pointers to more complex data objects.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi awneil, thank you so much for the reply!
I think I've solved this problem!! :)
Now i use a reference (operator &x) to the data in the message object and i send the message. In the receiver side, using the static_cast operator, 
first I cast the reference to pointer and after I deference (operator *x)  it to obtain the value. 
When I print the message, the result It is consistent with the data that I sent. This solution work well now, but is correct this solution?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

Let's see some code. If you know win16/win32 and the lparam and wparam then you will know that two pretty general parameters can be used for passing all kinds of data either holding actual values directly or being used to pass pointers to more complex data objects.
 

I'm sorry, clawson but i don't understand what do you mean. Please can you help me to understand?
Now, i have solved the problem of passing the data between the actors, but it is in my interest to improve this type of mechanism.
What code do you want to see? The framework that i have done it has many classes.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was just saying that the way Windows (generally) works is all driven by a message queue. As things happen in the system messages are posted into that queue to be delivered to one/some/all the running applications. There are messages for all kinds of things: keys being pressed, mouse moves being made, windows getting focus, windows being obscured or told to repaint. All these messages are delivered with 2 parameters to the message handling function in each app. For something like a keyboard it might be that just one of the parameters is used and holds a code to identify the key that was pressed. For mouse moves perhaps one param has the new X/Y together in one parameter and some control bits in the other. For a window repaint one parm may contain a pointer to a window repainting context and so on.

 

I was just citing it as a fairly well known example of reusing general parameters for a multitude of different functions which seemed to be what you were talking about doing.

 

If you don't know Windows programming just ignore me.

 

As to the "lets see some code" I meant you were asking a question about passing valued into functions and then how you access the passed data. I was suggesting that until you show us some of the code you have a problem with then it would be very difficult for anyone here to simply guess what you might be doing wrong.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you for clarifing clawons,

in effect i don't know Windows programming, but i know what you tell me.

I have studied Java at the university, so I know this as event programming.

An object generate an event (like mouse click), and another object (the listener associate at the click event) have a handle method to manage this kind of event.

My framework is derived/adapted from another framework that I have studied at the university, and this it was written in Java.

In my case, i can't use the full power of OOP because the avr enviroment don't permit all OOP functionalities, so i have do some work to traslate from Java to C++,

but the concept remain the same (I hope! :) )

 

You are rigth about to show the code when i have a problem. I remember this advice form the next time! ;)

In any case this is that i have done:

class Message {
public:
    ...
    
    inline void* getData(){return data;}
    inline void setData(void* d){ data = d; }
    
private:
    ...
    void* data;
};

this is the header file for the class Message. The next code snippet show the handle method of the application class. This class is derived from Actor (the base class) and it manage the message. In practice, I have done a tipical Hello world application. I have two actor and they exchange some message. In this case the HelloActor send a message with a data to the AnotherHelloActor. The AnotherHelloActor receive the message send from HelloActor, print the message, and then reply to HelloActor:

void 
HelloActor::handler(Message& m) {
    switch (currentStatus()) {
        case helloMessage:
        {
            if (m.checkId(HELLO_MESSAGE_ID)) {
                cout << ("Hello World! I'm an hello actor!..") << endl;
                cout << "..and now i send a message to another actor!!" << endl;
            
                Message tmp(ANOTHER_HELLO_MESSAGE_ID);
                tmp.setSender(*this);
                unsigned char c = 'a';
                tmp.setData(&c);
                anotherHelloActor->sendToScheduler(tmp);
                become(waitForReply);
            }
        }
            break;
        case waitForReply:
        {
            cout << ("Hello World! I'm an hello actor!") << endl;
            cout << "..and now i have received a reply message!" << endl;
        }
            break;
    }
}

void
AnotherHelloActor::handler(Message& m) {
    if (m.checkId(ANOTHER_HELLO_MESSAGE_ID)) {
        unsigned char* c = static_cast<unsigned char*> (m.getData());
        
        cout << ("Hello World! I'm an another actor!") << endl;
        cout << ("..the sender send me a number -> ") << *c <<endl;
        cout << ("..and now i reply to sender!!") << endl;

        Actor_ptr sender = m.getSender();
        Message tmp(REPLY_ANOTHER_HELLO_MESSAGE_ID);
        sender->sendToScheduler(tmp);
    }
}

This is very similar to the Java code. The main difference is the use of the method checkId, that is not present in the Java version.

The Java framework use the keyword "istanceof"instead of the method checkId, in C++ the dual is the dynamic_cast keyword, but this is computionally heavvy and however it use the RTTI functionalities that is not active in the avr enviroment.

 

However, can you tell me some advice on how i use a static library or similar thing, and more serius, is this kind of framework suitable for programming the embedded system?

I have see that there are some framework that use the actor to program the embedded system (es Quantum Leap, http://www.state-machine.com/), but i would to know some alternative if they exisist.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Given that pointers in AVR are 16 bit what happens when the sender wants to send something like "uint32_t mylong = 0xFEEDF00D" ?

 

I'd make the "container" the widest possible size. Either an array of N bytes or at the very least a uint64_t (8 bytes) that would cater for pretty much anything you might want to pass back and forth.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Great point of view clawson! 
I thought that the use of void pointer haven't this kind of memory "overflow" problem, so i used it.
However i understand what you means and you are right. Your solution look like simple and efficiently for the embedded systems. 
In reality, at this stage i'm aware about the data exchanged between the actors, so for now I have deliberately neglect this aspect.
At this moment i would to make a simple application to test the overload due to the framework, so this isn't the final version of the framework.
However i have planned to use a template class for the message data parameter. 
In the OOP world i think that the template class solve correctly (in the OOP sense) the problem that you have pointed me but honestly, your solution is a valid and simple alternative. Thank you!

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's amazing how many posts we see here from people who have odd ideas about what "void *" and "size_t" are.

 

As far as void * goes I'm not sure why anyone would ever actually create a variable of that type. It is generally used while passing pointers around so that no limit is imposed on the type of the memory that the pointer holds the address of.

 

It's true that templates are probably the real solution for what you are trying to achieve as you can write generic code that then applies to a particular instantiated type.
 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In effect, it create a bit of confusion.

I think that void* is a more general and raw form of the size_t.

I'm not an expert using both this kind of types, so far I never had the need to use them.

However i used the void* type because i have used the avr eeprom library.

In this library there are some methods that use the void* type. In the methods description there is written that this kind of type is used to pass any kind of data.

Reading your post, now i think that in the eeprom case, the use of the void* type doen't create memory problem because is responsibility of the programmer allocate correctly the memory size, or i'm wrong?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

void * has nothing to do with size_t. I was simply citing them both as examples of C concepts a lot of users don't appear to have grasped. void * is not some kind of magically infinite variable and nor is size_t. In AVR they are both 2 byte variables.

 

As I say void * has one main use and that is to say "here is a pointer to 'something', I'm not entirely sure what it is but I know there are some bytes at this address - you choose to interpret them in whatever way you choose because C is gracious enough to let you turn this anonymous pointer into a pointer to any kind of data you choose to interpret it as". Perhaps the classic example is the return value from malloc(). It says "here are N bytes, use them however you like".

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Mmm, maybe I understand what you're trying to tell me!
There are N bytes allocates somewhere in the memory, so the malloc return a void ptr to the memory start point of the N bytes, 
the void ptr in this case is a (only ?) way to transform the N bytes in any kind of data type. This use is different, from the use the void ptr to store directly any kind of type, right?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What I'd saying is this. malloc() has the classic definition:

void* malloc (size_t size);

Not only does it take a size_t parameter as input but it returns a void * as output. That's basically "here is a pointer - I don't care how you use it". So you can use:

int * pInt;
char * pChar;
long * pLong;

pInt = malloc(5 * sizeof(int));
pChar = malloc(8 * sizeof(char));
pLong = malloc(3 * sizeof(long));

pInt[3] = 12345;
pChar[2] = 'X';
pLong[0] = 0xBABEFACE;

I'm able to assign this to pointers of three different types because "void *" says "use this for what you like". On the other hand if I did this:

char * newmalloc(size_t n) {
    return (char *)malloc(n);
}

then replace those calls to malloc with newmalloc():

pInt = newmalloc(5 * sizeof(int));
pChar = newmalloc(8 * sizeof(char));
pLong = newmalloc(3 * sizeof(long));

then I get:

test4.c:14:6: warning: assignment from incompatible pointer type [enabled by default]
test4.c:16:7: warning: assignment from incompatible pointer type [enabled by default]

for two of the three calls as only assigning the return value to "char *" makes sense.

 

This is why malloc() uses "void *" to mean "use this for anything - I don't care"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I understand clawson, the key is "here is a pointer - I don't care how you use it"!

This make clear to me, the difference between void* and size_t. Thank you!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawons, i have another question for you.

What happens at the data property of the Message class if I need to send some data from an ISR to an actor?
Make sense declare the data member variable as volatile?

 

Last Edited: Fri. Jun 17, 2016 - 10:06 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ISR() are C functions so to pass data out of them you need to write to globals (that are also volatile). 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you so much clawon!  :)