Hi, I am using calloc in a function to allocate memory to my array. This function writes to the array different number of elements each time the function is called. Here is my problem. Say for the first time function writes to all the 3 locations and next time it writes to only first 2 locations. After the second call, the 3rd memory locations still contains the value written by the first function call. I understand that is the way it works.But I want to know if there is a way to erase all the locations before calling the function again? Is there any built-in function available? Also when I print the values of array initially it doesn't print zeroes. I have read that calloc initializes the memory fields to 0's. Following is the function code.
function write_to_array(int value) { int xdata *ascii_value,i; ascii_value = calloc(3, sizeof (int)); for(i=0;value!=0;i++) { mod = value%10; c = mod+'0'; ascii_value[i] = toascii(c); value/=10; } }
I cant understand your problem. If the number of items in calloc call is fixed and it is only '3' then why cant you do it your self? some thing like:
ascii_value[0] = 0; ascii_value[1] = 0; ascii_value[2] = 0;
If the number of items in calloc call is fixed and it is only '3' then why cant you do it your self? Because calloc is supposed to return a memory block that is initialized with zeros. If it doesn't do that, something is wrong.
You should become an evangelist Eric ;-)
I am using free() at the end of the function code. Somehow I missed to copy that line of code. And I am also manually setting the locations to '0' to make my code work for now. I was just willing to know if there is another way of doing it. But the whole point here is my 'calloc' code line not working fine. As quoted by one of you, I have not used init_mempool(). I will try including this command. Thank you Ramya
Hi all, I have just included init_mempool() in my function and it worked fine. Thanks for all your valuable replies. Ramya
You're welcome. It's probably a common mistake because the C library reference manual entry for malloc and calloc do not mention the need to call init_mempool. As others have said though, calloc really isn't suited here. Why not a simple array
int ascii_value[3] = {0,0,0};
The reason I preferred calloc is that, for now am using 3 locations but as my project extends I might end up using more locations. Thank you Ramya
for now am using 3 locations but as my project extends I might end up using more locations what on earth does that have to do with (ab)using calloc? Erik
Hi Eric, Sorry it took so long to reply. At first I was using an array. But then realized that the number of elemetns of the array are not constant each time the function is called. So I wanted some way to create a dynamic array. Using calloc and realloc I thought I could satisfy my need. The maximum array size known , I can first use calloc to allocate maximum number of memory fields. Then depending on array length I can use realloc. This is the idea I have. Guide me if I am not making proper use of calloc Thank you Ramya
The maximum array size known , I can first use calloc to allocate maximum number of memory fields. Then depending on array length I can use realloc. This is the idea I have. see below Guide me if I am not making proper use of calloc in the '51 there is NO SUCH THONG as "proper use of calloc" your array: U8 a; ... U8 z; just change it to U8 used_length; U8 a; ... U8 z; Erik
I am sorry I do not understand your sample code. Can you make it clear?
Ramya,
From your initial post, I can understand that you are writing a function which reads a number in decimal form and stores it in the ASCII form in the XRAM.
I can't understand why are you trying to use calloc and all. Any way your array index does not exceed 5 because the input parameter for the function is 'int'. Then why can you constantly allocate some array with size 5 and clear them by just assigning it to 0?
If you call the calloc to allocate a sum of 5 bytes, I think this is not necessory.Why do you want to let the controller to go through such linked list and all? This will increase your code size and decrease your execution speed. Think over it.
But then realized that the number of elemetns of the array are not constant each time the function is called. So I wanted some way to create a dynamic array.
Bad reasoning. Just because the array size isn't the same each time a function is used doesn't justify dynamic data structures. Certainly not in an 8051-based system, and generally not in any system without swap space.
Using calloc and realloc I thought I could satisfy my need.
You could satisfy that need much more easily by just using an array of the maximal size you're actually going to need.
Rule-of-thumb: functions like malloc() and calloc() may have some sense in an small embedded system (i.e. if you have different boards with different amounts of memory, but the same software) --- but realloc() and free() are too dangerous to be allowable.
Generally, an embedded system has to guarantee performance for a certain number of elements. Thus, you have to have memory available for the worst-case table size. Given that you have a guarantee, there's little reason to dynamically allocate that memory from a heap.
Dynamic allocation is only useful when two or more functions share the same resource, and the sum of the max consumption of each function exceeds the total resources available. If you just malloc() and free() and expect the arbitration to happen at run time, then you run the risk of being unable to operate at run time. Many embedded systems, unlike desktop apps, can't tolerate this sort of sudden and unpredictable failure, even if it's rare.
It's often useful to partition system resources between two functions depending on the application. Perhaps your system can support up to 32 widgets, or up to 16 gadgets, or any combination where a gadget takes twice the memory of a widget, say 16 widgets and 8 gadgets. You might use malloc() to chop up this heap into two pieces once at configuration time. This system would never call free() until it was reconfigured. So, the system is adjustable without recompiling, but still can guarantee performance of its configuration.
I also find it very common to dynamically allocate individual items from a particular pool -- say, message buffers. This is not a general malloc() function, though; there are many individual pools for particular purposes. Most often, the maximum size of such a pool is statically allocated, and items are of fixed size (meaning much less tracking overhead and time). But the usage of these pools is limited to a particular function of the code. There's no possibility that using a lot of items from one pool affects another. malloc() shares exactly one pool of memory between multiple functions, which is where the problems begin to creep in.
As far as linked lists and such are concerned, the 8051 has a pretty small address space. And, the architecture is poorly suited to handling pointers. Often, you'll be better off using a 8-bit or even 16-bit index into a table as the pointer in your lists, rather than an actual C pointer, which is to say memory address. It will often consume less storage, and also produce smaller and faster code than a textbook "struct MyStruct* next" implementation.
A mark/release concept is more appropriate for small embedded systems than 'alloc/free. Mr. Payson has an overview here (my apologies in advance regarding the link as this forum is having some difficulties with URLs lately):
www.htsoft.com/.../23148
Thank you all for making it very clear when to go for dynamic allocation. As most of you have said, I have changed my code to use an array of max size. Thank you Ramya
"Dynamic allocation is only useful when two or more functions share the same resource, and the sum of the max consumption of each function exceeds the total resources available."
Another case where dynamic allocation is useful is where the available resource is unknown at build time. This is quite rare in embedded systems, but very common indeed on PCs and the like.
Because standard 'C' textbooks tend to be written with general-purpose computer targets in mind (PCs, etc), they tend to take dynamic allocation as read
This is quite rare in embedded systems, but very common indeed on PCs and the like.
This contains another lesson about dynamic allocation:
It should only be used in cases where the program has a sensible option if the allocation fails. Your PC can bark "Not enough memory, stoopid." at you and exit the program. Your uC most likely can't.
I noticed a comment or two about portablilty and embedded systems. I've been doing embedded systems for 20 years, both in assembly and C. I can assure you that Portability in an embedded system is both important and desirable, but very difficult to obtain.
As an example, I have had to port the same program now from a silabs F320 to a F310 to an F342 and now to an F040.
Each of these required slightly different code, most of which was abstracted by the use of headers for the machine specific portions. The code however, still has processor dependant sections. I wrote the code in such a way, that the processor dependent sections (such as initialization, powerup, powerdown, and port I/O are contained in single simple modules.
The code is however highly dependent on the Silabs 8051 architecture. It specifically is based around the PCA array. porting to another 8051 with a PCA array would be pretty easy. Porting to another processor would not be to hard (basically 5 short routines and one long one (the PCA handler) would have to be re-written, but 80% of the code will work untouched (with the use of some judicial defines).
So portablilty needs to be cast in terms of same architecture vs different architecture. Portablitly is necessary and desirable if you are doing the same general CPU/arch.
I have to weigh in on the side of Dynamic allocation has no place in embedded system (especially 8051's), along with Java and the rest of the abortions that people try to cram into embedded systems.
As for the arguement about char, unsigned char and signed char, from the compiler point of view they are all distinct types. From the functional point of view they are vastly different.
I do a lot of communication protocols. Some are 8 bit binary, some are not. You learn really quickly to explicitly use unsigned vs signed. Just as an example, suppose you have an 8 bit data stream. you define something like
unsigned int cksum=0; char c; c=input_from_port(); cksum+=C;
vs unsigned int cksum=0; unsigned char c; c=input_from_port(); cksum+=C; and I guarantee you that you will get the wrong checksum in one of these cases, because the compiler will treat C as a signed addition, rather than an unsigned one.
Chars are defined in an 8 bit world to be 8 bits, but subsequent expressions may sign extend characters that are not explicitly defined as unsigned char .
Some compilers treat signed char and char as signed number, while others treat unsigned char and char as unsigned numbers.
Cheers
As an example, I have had to port the same program now from a silabs F320 to a F310 to an F342 and now to an F040. ... The code is however highly dependent on the Silabs 8051 architecture. the 040 is standard '51 architecture the f3x is "Silabs architecture" aka the deviates.
So portablilty needs to be cast in terms of same architecture vs different architecture. Portablitly is necessary and desirable if you are doing the same general CPU/arch. portability is a joke. There are so many differences between the various uCs that while 'reuse of code' is valid, 'portability' is not. I have seen code that needed an enormous helping of tomato sauce just because it had been written 'portable'
I have migrated code from one '51 processor to another and if anyone told me that I 'ported' the code, I would call him a liar. Did i reuse a lot of code? of course, but ported - no way. If I had 'ported' I would have lost the advantages the processor I changed to had over its predecessor. I have seen 'ported' code that bit-banged IIC on processors with HW IIC, is that in any way reasomable - absolutely not. When asked, the so called programmer answered "If I use the HW IIC it is not portablr" baloney, that is putting a premium on something unlikely (porting to a 'dumber' uC).
As for the arguement about char, unsigned char and signed char, from the compiler point of view they are all distinct types. From the functional point of view they are vastly different. I vote for outlawing 'char', the only legal should be unsigned and signed, and that has the GLORIOUS side effect of making it impossible to use most of the library routines that all, because they were developed for 'full size' machines, really do not have a place in a '51.
Erik
<amateurish code bodging nonsense snipped>
I vote for outlawing 'char', the only legal should be unsigned and signed...
Look, you've already demonstrated your poor knowledge of standard 'C' and refused to try and educate yourself by reading the one document that might help - the 'C' standard - so please, would you try and refrain from posting rubbish on the topic you know so little about?
standard 'C' ... so please, would you try and refrain from posting rubbish on the topic you know so little about?
There is NOTHING in my post about "standard C" I do not know why you bring that up. Only about "C and its application in small embedded". If you are a proponent of the stupid "C is C wherever it is applied" I feel sorry for you.
I do not have ANY 'char' 'int' 'short' or so in ANY of my code everything is either signed or unsigned.
If you have a beef with that post "my coding style is different" not some blabber about 'standard C'.
You keep referring to me as an 'amateur', I have written C for small embedded 15+ years and heve developed a host of methods for EFFICIENT C for small embedded not STUIPID "standard C for small embedded"
Good lord man, ignoring The Standard's distinction between 'plain' char, "signed char", and "unsigned char", why do you even bother with C at all? Profound ignorance (intolerance, indifference, etc.) of the language/standard is no excuse! Just do it in assembly language if that's the case. No questions asked or answered -- simple, done, no discussion, "Kirk out".
I have written C for small embedded 15+ years
No. 'C' is defined by the ANSI standard, what you have written is something that looks a bit like 'C'.
You keep referring to me as an 'amateur'
If you were a professional we wouldn't be having this discussion in the first place.
Good lord man, ignoring The Standard's distinction between 'plain' char, "signed char", and "unsigned char", who said ANYTHING about "ignoring The Standard". The fact is that plain 'char' is ambigouous and in small embedded C is not needed. i had, some years ago, a problem with a compiler that was not consistent in which side of the ambiguity it leaned towards and the simple way to avoid ambiguity is to avoid what is ambighous.
what you have written is something that looks a bit like 'C'. so you adhere to the same mantra as the only guy I ever fired who said when told to make some code more efficient "then it will not be real C".
If you were a professional we wouldn't be having this discussion in the first place. correct if it is required to be a blabbering idiot (C is C wherevere it is used) to be considered a 'professional'.
It may be that you are a "professional in C", but based on your total refusal of acknowledging the facts of working in 'small embedded' you are definitely not a professional re C51
The Cidiots that insist on totally ignoring that using a small micro makes ther beloved 'C standard' too inclusive should go back to their beloved PC where everything the 'C standard' states may be proper practice.
Going by what you guys state you should require Keil to include fopen() etc in C51 since that is part of "the C standard". Or is it that YOU, not whichever user, is to decide what parts of the "C standard" apply to the '51 and C51
<usual incomprehensible rant snipped>
Going by what you guys state you should require Keil to include fopen() etc in C51 since that is part of "the C standard".
Oh dear, wrong again. Time you read the standard.
"who said ANYTHING about "ignoring The Standard"
Nobody did. You left off the "'s distinction ...". Quoting the original complaint:
"... ignoring The Standard's distinction between 'plain' char, "signed char", and "unsigned char", ... "
The point (I think) is that there are three char types, all equally valid in small embedded C, but you have to understand the distinction between the three types and use them appropriately, regardless whether the target is "small embedded" or not.
"The fact is that plain 'char' is ambigouous and in small embedded C is not needed."
'Plain' char also has its place in "small embedded" systems.
Excerpts from The Standard's section 6.2.5 paragraphs 3-6 making the distinction between the three char types:
(3) "An object declared as type char is large enough to store any member of the basic execution character set. If a member of the basic execution character set is stored in a char object, its value is guaranteed to be nonnegative. If any other character is stored in a char object, the resulting value is implementation-defined but shall be within the range of values that can be represented in that type."
(4) "There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. ..."
(5) "An object declared as type signed char occupies the same amount of storage as a 'plain' char object. ..."
(6) "For each of the signed integer types, there is a corresponding (but different) unsigned integer type (designated with the keyword unsigned) that uses the same amount of storage (including sign information) and has the same alignment requirements. ..."
From those excerpts, we see that 'plain' char is intended for values from the basic execution character set, that those values are nonnegative, and storing any other value is implementation-defined (i.e., your implementation disambiguates it). So, simply put, for small embedded systems that deal with text-y things (e.g., an LCD message), 'plain' char is a perfectly valid, innocuous, and useful type.
From those excerpts, we also see that there are two char-sized integer types, "signed char" and "unsigned char", to be used when one wants to use an integer type other than the signed and unsigned varieties of short, int, long, and long long. These second and third char types, just like 'plain' char are useful and have their place in systems, "small embedded" or otherwise.
Don't use 'plain' char when you want do to signed integer arithmetic on char-sized objects; use signed char.
Don't use 'plain' char when you want do to unsigned integer arithmetic on char-sized objects; use unsigned char.
Do use 'plain' char when you are dealing with character set functionality.
"Going by what you guys state you should require Keil to include fopen() etc in C51 since that is part of "the C standard"."
Who guys? We already discussed above that fopen() wouldn't be required in a freestanding implementation.
Do use 'plain' char when you are dealing with character set functionality Please give me an example of "character set functionality" ONLY for a char in small embedded. Since small embedded rarely (never?) have a character e.g. ASCII on which no arithmetic is performed, using 'just' char there makes the ambiguity shine through.
Please give me an example of where you need to use 'just' char in a small embedded system. Please do not suggest to use the libraries which, since specified for 'full size', are way too 'comprehensive' and thus too large for small embedded.
DO NOTE, my suggestion 'outlaw char' was in relation to 'portability' (which I do not think apply to small embedded) but in reuse of code (which I do think apply to small embedded) the ambiguity may bite you.
what we are discussing is not 'C' but design philosophy.
I have yet to find two persons that can agree fully in that area.
My philiosophy is 'efficiency' (whatever the cost) and I gather that your philiosophy is 'purity' (whatever the cost).
so you take the high road and I take the low road but I'll be in Scotland before ye (i.e. faster code)
"Please give me an example of "character set functionality" ONLY for a char in small embedded."
Is this really necessary? It's pretty basic stuff and I already did -- "... an LCD message ..." (i.e., a character string literal).
"... I gather that your philiosophy is 'purity' (whatever the cost)."
Pure efficiency with the lowest cost possible.
View all questions in Keil forum