2
\$\begingroup\$

I am working on a Project that will requires using an MCU to receive frame packets with unknown frame length on reception, but each reception has an octet from which you can deduce the number of frames left to receive and hence calculate the length of the entire frame.

In other to avoid allocating a fixed memory for the receiving frame which might not be used up (if the receive frame length is less that the Max frame length to receive), I am of the opinion to dynamically allocate a memory for the remaining frame to be received.

For example. If we assume a packets of 20 octets and the 3rd octets tells you the number of the remaining octets left to be received (which could be 2, 3, even 17 octets max). Rather than creating a register of size 17, which might not be used up, how can I dynamically allocate this memory especially for an embedded application, so that if the 3rd octets revels that there are 6 octets to be receive, then I simply allocate a register with size 6 for the rest of the frame, with out using the "malloc".

Programming language is C.

I hope my question is clear enough. Please share your views as I need to best possible approach on this.

Thanks.

\$\endgroup\$
7
  • 1
    \$\begingroup\$ Any reason why you don't want to use malloc? \$\endgroup\$ – Bruno Ferreira Aug 14 '12 at 22:57
  • 3
    \$\begingroup\$ What advantage does not using up the extra memory gain you? You still have to size the MCU to have enough RAM for the largest packet you can receive. \$\endgroup\$ – markrages Aug 14 '12 at 23:00
  • \$\begingroup\$ @Bruno, Would you advice the use of malloc for an embedded applicaiton, of a RAM size of about 2K, and thinking of the fact that the memory are conjugated. \$\endgroup\$ – Paul A. Aug 14 '12 at 23:11
  • 2
    \$\begingroup\$ What are you going to do with the remaining? You must be ready for the maximum packet size to come in, no? \$\endgroup\$ – markrages Aug 14 '12 at 23:15
  • 1
    \$\begingroup\$ You should elaborate on what you mean by "an MCU". If you're talking about a tiny little embedded processor that's not doing anything else, the answer is, commit all your memory to the job, don't worry about dynamic allocation. If it's a 32 bit ARM running linux and there are lots of other things using memory, then yes, go dynamic. How much memory is in the system, and what else is using it? \$\endgroup\$ – JustJeff Aug 15 '12 at 0:32
5
\$\begingroup\$

In this case I would say the best approach is probably just to allocate the maximum memory size, and reuse it for as many other things as possible too.
Some compilers have an option for variables to share memory space providing they are not active at the same time. For example, the (now replaced by HI-Tech C) PIC18 C compiler has an overlay attribute that can be used with variables to do this.
It can also handle variable size arrays which would be perfect for what you wish to do (less overhead than malloc) I would check if your compiler can do this.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ @oil Glaser. Thanks for this point. I use the keil compiler and the Atmel studio 6. I do know if they have such features! \$\endgroup\$ – Paul A. Aug 15 '12 at 9:01
  • 1
    \$\begingroup\$ Agreed, this seems like a poor case for dynamic allocation, especially on an embedded platform; dynamic allocation is most useful when you literally don't know how much memory will be needed, i.e. user interaction provokes memory allocation. Unless I'm missing something it sounds like you need enough headroom for a worst case maximum number of maximum-size packets, so why not allocate that much memory instead of overengineering a solution? Besides, if you go the dynamic route on a memory-constrained platform and aren't careful you get bit by dynamic allocation's grumpy friend, Fragmentation. \$\endgroup\$ – Suboptimus Aug 15 '12 at 23:45
3
\$\begingroup\$

On many microcontroller systems, compilers and linkers allocate data from the bottom and/or top of RAM; unused RAM will usually be in a contiguous area, and it's generally possible to convince the linker to make the addresses of the start and end of that area available to the programmer (e.g. one could ask the linker to place a one-byte variable as the very last thing before the free area, and another as the very first thing following; the addresses of those variables would delineate the free space).

Although a lot of system offer a malloc() function, it's more complicated than necessary in a lot of scenarios. For example, if one will need to allocate objects based upon information received at run-time, but objects will always be freed in the reverse order of allocation, one may simply keep a pointer to "next available space". To allocate an object, copy that pointer add the size of the new object to it, and return the copied pointer. To free an object (and everything allocated after it), simply set the "next available space" pointer to the start of that object.

Some scenarios are a little more complex than would be allowed with that approach, but still not need a full "malloc/free" approach. For example, in some scenarios, one may have two groups of objects which obey the last-in-first-out rule among themselves, but objects in one group may outlive those in the other. To deal with that situation, use a "next available space" pointer which starts at the bottom of free space, and a "previous available space" pointer which starts at the top. Allocate things in the first group as before. For those in the second group, subtract the size of the new object from the "previous available space" pointer and return the result. To free an object in the second group (and all second-group objects allocated after it), add the size of the object to its address and store the result to the "previous available space" pointer.

Note that malloc and free are designed so that it's possible for objects in the middle of memory to be freed, while objects before and after remain valid. While this can at times be useful, it can also lead to memory fragmentation. If one's objects will not fit with a last-in-first-out model, it may be a good idea to make objects relocatable. For example, one might hold a queue of variable-sized objects which get stored consecutively in memory as long as there's room. When memory gets full (or at some convenient time before that), one would copy the first object that hadn't yet been read to the start of the queue, the next object that hadn't been read immediately following it, etc. until all objects had been copied, consolidating the free space that had been at the start of the queue, to the end. One must be careful when moving any data to ensure that pointers to that data are updated accordingly, but that's often not too difficult. Moving memory around may take more CPU cycles than managing discontinuous areas of free space, but the behavior of the moving-memory approach may be more predictable.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.