Forum : 8051
Original Post
Post Information | Post |
---|---|
January 23, 2007 - 11:34am
|
can you post a simple tutorial about using RC51's "malloc" function ? |
Forum : 8051
Post Information | Post |
---|---|
January 23, 2007 - 11:34am
|
can you post a simple tutorial about using RC51's "malloc" function ? |
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
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
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
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.
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.
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
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
Sorry, Steven, your last post was not already there when I send my last one.
Thank you for pouring water on the flames...
Vincent
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
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
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
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.
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.
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
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;
}
}
}
}
}