Topic : malloc.c

Forum : 8051

Original Post
Post Information Post
January 23, 2007 - 11:34am
Guest

can you post a simple tutorial about using RC51's "malloc" function ?
thanks
M.Marolda

Replies
Post Information Post
+1
0
-1
January 23, 2007 - 4:08pm
Guest

Hopefully not.

get your head out of the bush, the '51 is NOT a PC

Using malloc in a '51 application is forcing the code to go through major hoops simply because the architecture of the '51 is not designed for such.

If you want to code "for a PC" code the PC, do not apply such to the '51, if you believe that "C is C" I have some swampland in Florida to sell.

If you 'refuse' to get knowledge of the underlying hardware, you will end up with a miserable product.

Erik

+1
0
-1
January 24, 2007 - 3:30pm
Guest

The library malloc() works (I tried it on the simulator). However you sound like you're new to MCU's. Don't use it; if you knew enough to use it on an 8051, you wouldn't have posted this request.

Steven Pruzina

+1
0
-1
January 25, 2007 - 10:03am
Guest

during time you were speaking about politics reasons, I succeded using the malloc.c library with the "poor" 8051.
Please consider that using dynamic RAM is simply the MOST EFFICIENT way to implement (for example) a stack of records ( fifo, lifo ecc.).
For your information I'm not a dummy! I have a computer science degree, and I have designed my hardware completely from scratch, so I know it as myself.
If you want go on programming as my grandfather did, it's your choice.

have a good luck
M.Marolda

+1
0
-1
January 25, 2007 - 3:22pm
Guest

I have a computer science degree

That is the problem, for small embedded you will have to unlearn a lot.

"computer science" is totally geared towards the behemots with Mega and Giga, when you work with the '51 you work with kilo.

what is "simply the MOST EFFICIENT" may be so in your eyes, since the mantra of computer science is "if you are not happy, buy a faster machine".

I suggest, that if you have no interest in considering the overhead using "simply the MOST EFFICIENT" generates, you stay out of embedded.

What "simply the MOST EFFICIENT" is in computer science can be (and often is) totally false in 'small embedded' such as the '51.

This has nothing to do with "programming as my grandfather did" is is a simple matter of considering the fact that in small embedded "simply the MOST EFFICIENT" is what is best for the provcessor, not what is best for the programmer.

I am, by no means, saying that all lerned in computer science is irrelevant to small embedded, just that the mindset permeating that discipline does not apply.

Erik, who, very likely know, at least, as much computer science as you.

+1
0
-1
January 25, 2007 - 4:02pm
Guest

Your answer makes clear to me that you have not idea of what a computer science deegre is.
The "if you are not happy, buy a faster machine" rule is valid maybe in television advertisement, but for sure not at University.
Many projects required to pass examinations have to works with very small hardware, and the first book I have bought was about Zailog 8000 MCU that is even less powerfull than a 8051.

My considerations about an efficient way to implement a STACK is valid for any MCU because the definition of "efficiency of an alghoritm" is INDEPENDENT from the real machine where it will run.

But I think that this concept is too hard for you.
Please, get a good book, and start to study.

+1
0
-1
January 25, 2007 - 5:41pm
Guest

Hello Massimo

Yes, the efficiency of an algorithm is independent of the machine on which it runs. However the efficiency of the machine itself is depends particular code used to implement the algorithm.

As you know, standard 'C' heap pairs the heap memory with a doubly linked pointer linked. Pointer manipulation and access is very inefficient in an 8051 because it has a single dedicated memory pointer (DPTR). At each use, DPTR must be set to fetch a heap node and either dereference it (another DPTR operation) or traverse to the next heap node. When executing code with multiple pointers, such as heap manipulation, an 8051 speeds a lot of time just manipulating DPTR. That's very slow. The code is also large.

So, a conventional heap is slow on an 8051. If that's OK then use it. Otherwise a fixed block heap, either tagged or indexed, is faster. If you can avoid using a heap at all, that's best.

Behind the flames above, Erik's point remains valid: if you wish to program embedded systems efficiently, you must understand the operation and limitations of the microcontroller you are using and tailor the 'C' code accordingly.

regards Steven Puzina

+1
0
-1
January 25, 2007 - 5:43pm
Guest

OK.

Now I suggest we stop insulting each other and try to behave like adults for a change. :)

This forum is about the Raisonance tools, and on this the discussion is over because the malloc function works and nobody denies this.

Now, if you want to argue on whether it is a good thing to use it, please do it calmly or somewhere else.

If you choose to do it calmly and here, then I suggest a contest. I'll define the specs for a FIFO library and a test program using it. Then, each of you can implement the library using malloc or not and we'll compare memory usage, and execution speed and decide who the winner is. And then we can include all this as examples in RIDE... :)

What do you think?

Best Regards,

Vincent

+1
0
-1
January 25, 2007 - 5:44pm
Guest

Sorry, Steven, your last post was not already there when I send my last one.

Thank you for pouring water on the flames...

Vincent

+1
0
-1
January 25, 2007 - 5:59pm
Guest

Thank you Vincent, it's a good idea.
Please, consider that for my application I need something more complicated than a FIFO.
I need a stack of records, where I can put and remove items in a random order in any position.
This is the reason why I'm thinking to a linked list ( maybe the upsd3434's double data pointer)

regards
Massimo

+1
0
-1
January 25, 2007 - 9:42pm
Guest

This is not a flame, it is emphasizing that the issue is "thinking small embedded" not "thinking PC" when coding for the '51.

A "PC thinking" person will automatically go for things like malloc etc since there is no "hardware concern" when coding for the PC and "ease of coding" thus becomes more important than "ease of execution". One aspect of going by "ease of coding" is that there is no (need for) thinking about the consequences of taking whatever route (as long as it lead to the correct result).

The reaction "programming as my grandfather did" is typical for those that refuse to understand that in small embedded "hardware concerns" are essential. Since most "computer scientists" can not be concerned with mundane things like hardware but insist that the 'elegance' of some code is much more important than the execution speed and memory requirements (oh yes, I have been there).

I have a blatant example from the past where i were called in to assist 3 "computer scientists" with implementing code banking (they had run out of memory at 64k) and, instead threw out their code, redid the job and had it fully functional in less than 8k. That, of course required that I did know the consequences of coding decisions.

To Massimo: the "efficiency of an alghoritm" is INDEPENDENT from the real machine where it will run. true, but that is irrelevant. What matters is that the "efficiency of the implementation of an alghoritm" is totally6 dependent the real machine where it will run. just as an example, try looking of sorting, say, 20 5 byte strings in DATA, IDATA or XDATA, you will be amazed.

Erik

+1
0
-1
January 25, 2007 - 9:45pm
Guest

Last paragraph corrected as to highlight

To Massimo: the "efficiency of an alghoritm" is INDEPENDENT from the real machine where it will run. true, but that is irrelevant. What matters is that the "efficiency of the implementation of an alghoritm" is totally dependent the real machine where it will run. just as an example, try looking at the efficiency of sorting, say, 20 5 byte strings in DATA, IDATA or XDATA, you will be amazed.

Erik

To Vincent: can we have a preview button, please

+1
0
-1
January 26, 2007 - 11:03am
Guest

Hi,

I think we all agree on "coding for embedded must be done with more care and, generally, different techniques than coding for PC". And that this rules out malloc most of the time.

But still, there are people who will insist that there exists some very specific applications that are particularly suited for dynamic allocation, and for which the loss in memory and CPU time for using malloc will not be so significant compared to the gain in implementation time.

For my part I'm doubtfull, and that's why I suggested a contest. (Are you taking it?) It might be interesting to have the same application written both ways, even if just to prove your point without pages of (enraged) argument the next time this question arises. Because it will, I'd bet on that. :)

Here is a first draft of application that could be used for the contest, if you decide to try it:
ftp://www.raisonance.com/temp/malloc_contest/malloc_contest.txt

I'll refine it if there is more than one declared contestant. :)
(You'd be allowed to modify the part that I wrote, so long as the whole thing does the same in the end.)

Vincent

Erik: we won't add a preview button to this forum because we are in the process of changing the whole thing. the new one will be much better, with faster search, categories, better protection against spam, and hopefully a preview button or the possibility to edit your posts. should come very soon.

+1
0
-1
January 26, 2007 - 12:37pm
Guest

It's not my intention to go on reading this thread, I'm really bored.

To Erik:

of course I know very well differences about DATA, IDATA, XDATA.
Usually I implement kernel part of my code in ASSEMBLY.
Please STOP saying that i'm "thinking PC", and STOP trying to teach me things that I already know.

The simple reasons because I use malloc are:

- this part of code is NOT time critical
- I have to manage many STACKS, but I can not use a FIXED size for each stack, because the size will depend on the CUSTOMER application.
So, in my opinion, the best thing to do is dynamic allocation (with a carefull code), in this way the varius stacks will contend the ram in the best way.

I think that a good programmer must have the ability of using differents programming style for differents parts of the project.
Please Erik, open your mind.

Best regards to you all.

+1
0
-1
January 26, 2007 - 3:57pm
Guest

to Vincent: the link blew up, can uou provide another (preferebly http)

To Massimo: you do whatever you want, if you do not want my advice, do not take it, but I believe that it is you that need to "open your mind". Again, if you do not want my advice, do not take it, but there should br no need to insult me with 'I think that this concept is too hard for you" and such.

Erik

+1
0
-1
January 26, 2007 - 4:30pm
Guest

Here it is...

Note it's only a draft, or I should say a spec, written in 10 minutes just to get the general idea.
I don't think it even compiles as is.

Best Regards,

Vincent

And here is the file:

/*
purpose:
We are receiving messages from different captors through a stream. (UART for ex)
A message consists of a priority and some text, up to MAX_MESSAGE_SIZE chars.
(usually just a few bytes, but occasionnally, more)
We have to sort them according to priority firstly and order of reception secondly.
When we receive the "READ" message from the master (priority 0), then we have to
send it the oldest message of the highest priority.
When we receive the "FLUSH" message from the master (priority 0), then we have to
clear the whole list and start again.
If we receive more messages than we can handle, then we should drop the lowest priority first,
the oldest if tie on priority.
*/

#define MAX_MESSAGE_SIZE 0x80
#define MESSAGE_END_CHAR (0x0A)

//function for adding a message in the list
void ListAddMessage(unsigned char MessagePriority, unsigned int MessageNumber, char *MessageText)
{
//TODO (that's what the contestants should write)
}

//function for retrieving the highest priority message, the oldest if tie on priority.
void ListGetHighestIndexMessage(char *MessageText)
{
//TODO (that's what the contestants should write)
}

//function for flushing all the messages
void ListFlushAllMessages()
{
//TODO (that's what the contestants should write)
}

#if _8051
#include
#endif

#if WINDOWS
#include
#include
FILE *Fin=0;
FILE *Fout=0;
FILE *Flog=0;
#endif

//function for reading from the stream
//target-dependent
unsigned char mygetchar()
{
#if _8051
return getchar();
#endif
#if WINDOWS
if(!Fin)
F=fopen("inputmessagesfile.txt", "rb");
return fgetc(Fin);
#endif
}

//function for sending messages to the master
//target-dependent
myputs(char *msg)
{
#if _8051
puts(msg);
#endif
#if WINDOWS
if(!Fout)
Fout=fopen("outputmessagesfile.txt", "wb");
fputs(Fout, msg);
#endif
}

//function for toggling IOs, for measuring exec time with scope
//target-dependent
void SetPinState(unsigned char newstate, unsigned char pinnumber)
{
#if _8051
//TODO (will depend on derivative and board)
#endif
#if WINDOWS
if(!Flog)
Flog=fopen("logfile.txt", "wb");
fprintf(Flog, "time: %d, setting pin %d to state %d", time(), pinnumber, newstate);
#endif
}

//variables for handling the current message
char CurrentMessagePriority;
unsigned int CurrentMessageNumber;
char CurrentMessageText[MAX_MESSAGE_SIZE];

//master messages
const char *OutputMessage = "READn";
const char *FlushMessage = "FLUSHn";

//function for comparing the messages against the master's messages
unsigned char msgcmp(unsigned char *msg1, unsigned char *msg2)
{
unsigned int i=0;
while(msg1[i]==msg2[i])
{
if(msg1[i]==MESSAGE_END_CHAR )
return 0; //messages are identical
}
return (-1); //messages are different
}

#define STATE_WAITINGFORSTARTOFMESSAGE 0
#define STATE_GETTINGMESSAGETEXT 1

char state;
char c;
char *msgptr;

//main function
void main()
{
CurrentMessageNumber=0;
state=STATE_WAITINGFORSTARTOFMESSAGE;
SetPinState(0,0);
SetPinState(0,1);
SetPinState(0,2);

while(1)
{
c=mygetchar();

if(state==STATE_WAITINGFORSTARTOFMESSAGE)
{
//the first char is the priority of the message
CurrentMessagePriority = (unsigned char)(c);
state = STATE_GETTINGMESSAGETEXT ;
msgptr=CurrentMessageText;
}
else
{
//now we're reading the message
*(msgptr++)=c;

//check for end of message
if(c==MESSAGE_END_CHAR)
{ //end of message reached
state=STATE_WAITINGFORSTARTOFMESSAGE;

//check for message from master
if(!CurrentMessagePriority)
{
if(!msgcmp(CurrentMessageText, OutputMessage))
{
//master wants highest priority message for handling it
SetPinState(1,0);
ListGetHighestIndexMessage(CurrentMessageText);
SetPinState(0,0);
puts(CurrentMessageText);
}
else
{
if(!msgcmp(CurrentMessageText, FlushMessage))
{
//master says to forget all memorized messages
SetPinState(1,1);
ListFlushAllMessages();
SetPinState(0,1);
CurrentMessageNumber=0;
}
}
}
else
{
//the message is not from the master. store it in the list.
SetPinState(1,2);
ListAddMessage(CurrentMessagePriority, CurrentMessageNumber, CurrentMessageText);
SetPinState(0,2);
CurrentMessageNumber++;
}
}
else
{
//message continuing. check for overflow
if( msgptr-CurrentMessageText > MAX_MESSAGE_SIZE )
{
msgptr = CurrentMessageText;
state=STATE_WAITINGFORSTARTOFMESSAGE;
}
}
}
}
}