This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

very general question on memory usage

I have very-general question on when I code for MSP430.

Should I create less subroutine in code for uC like MSP430
in terms of memory usage?

For example, I create code like CASE-A and CASE-B.

//----------------------------
// CASE-A
static void routineA(void)
{
     bool res1;
     bool res2;

     res1 = do_procA();
     if (res) {
          res2 = do_procB();
          do_procC(res2);
     } else {
          res2 = do_procD();
          do_procE(res2);
     }
    
     res1 = do_procG();
     if (res) {
          res2 = do_procH();
          do_procI(res2);
     } else {
          res2 = do_procJ();
          do_procK(res2);
     }
}
//----------------------------

or
// CASE-B
static void doingAtoE(void)
{
     bool res1;
     bool res2;

     res1 = do_procA();
     if (res1) {
          res2 = do_procB();
          do_procC(res2);
     } else {
          res2 = do_procD();
          do_procE(res2);
     }
}
static void doingGtoK(void)
{    
     bool res1;
     bool res2;
    
     res1 = do_procG();
     if (res1) {
          res2 = do_procH();
          do_procI(res2);
     } else {
          res2 = do_procJ();
          do_procK(res2);
     }
}
static void routineA(void)
{
     doingAtoE();
     doingGtoK();
}

//----------------------------

In CASE-B, two routines are called from routineA. In the
two routines, only auto-variables (res1 and res2) are used. 
So the memory used for the auto-variables is freed after 
the routine-exit. But will this cause memory-fragmentation 
resulting in problem in long-duration operation?

For the readability (maintanability) of the code, I prefer CASE-B.
But if the subroutine should be created less, I stay with CASE-A.
  • I'll give you some instructions and I'd like you to share your results. 

    1. Compile the project using case A. 
    2. In the debug folder copy the .map file and rename the copy to caseA.map. 
    3. Then compile with case B. 
    4. Copy this map file and rename the copy to caseB.map. 
    5, Zip these two files and insert the zip file into a reply post to this thread.

  • Thank you Jason Work.

    I attached the file.

    3806.mapFile.zip

  • OKY said:
    Should I create less subroutine in code for uC like MSP430 in terms of memory usage?

    The question is entirely general - not specific to MSP430.

    The answer is, "It Depends"!

    Remember that two things consume "memory":

    1. Code;
       
    2. Data - your variables, etc.

    In a microcontroller, Code is likely to be in Flash, and Data in RAM - but they are still both "memory"

    Using subroutines adds some overhead for the calling & return, but can save code space use by reducing the amount of repeated code.

    OKY said:
    In the two routines, only auto-variables (res1 and res2) are used.  So the memory used for the auto-variables is freed after the routine-exit

    This is true provided the functions are not called simultaneously (eg, nested); so, yes - it can be a way to save memory.

    But you do have to consider the overhead of passing parameters...

    OKY said:
    will this cause memory-fragmentation 

    No.

    Automatic variables go on the Stack - this doesn't suffer from fragmentation.

    Dynamic allocation (from the Heap) is where you risk fragmentation...

    OKY said:
    For the readability (maintanability) of the code

    That is really a separate issue from minimising memory usage!

    Typically, "optimisation" and "maintainability" are in conflict.

     

  • Andy Neil said:

    For the readability (maintanability) of the code

    That is really a separate issue from minimising memory usage![/quote]

    Gathering repeated code into subroutines is a case that can help both maintainability and reducing code size!

    The potential code size reduction has already been described.

    It helps maintainability because, when a change is required, it only has to be made in one place.

  • OKY said:

    For the readability (maintanability) of the code, I prefer CASE-B.  

    But if the subroutine should be created less, I stay with CASE-A.

    CASE-A
    286 bytes of CODE memory  
    80 bytes of DATA memory (+ 2 absolute )

    CASE-B
    290 bytes of CODE memory  
    80 bytes of DATA memory (+ 2 absolute )

  • CASE-B is more readable and maybe easier to maintain (it depends on what the two parts are doing - related or unrelated things).

    However, CASE-B adds a nestign level. That means at least aone mro ereturn address is stored on stack. Also, the compiler cannot optimize code across separate functions. In CASE_A, the compile rmay rearrange the whole code to get an optimum result. In CASE_B this can only be done for each subroutine separately.

    Imagine that both subroutines require a certain calculation. In CASE-A, the compiler might just do it once, keep the result in a processor register and use it more than once. IOn CASE-B, the calculation must be done for each function - or done inthe main function and passed as parameter (requires additional coding). Things liek that happen more often than one might think. And are not always obvious.

    Finally, it may be that the compiler notices that both subroutines are only used once and inlines them into the main function. Then the generated code for the main function might be identical for both cases. If the subroutines are short, the compiler might decide that the overhead for a funciton call is bigger than the funciton code itself (especially with the then possible optimization). It's faster in any case.

    But since the function might be called from outside (different .c file), the compiler will in this case keep a copy of the separate functions, even if not cylled by the main function. This may result in even bigger code for CASE-B.

    Even worse: the results may be totally different when you switch to a different compiler (e.g. IAR and CCS or MSPGCC) or even between different revisions of the same compiler.

    Only one thing is for sure: there is no fragmentation due to local variables. Local variables are stored on the stack. And objects are stored ont eh stack when necesary, and removed in the opposite order when no longer needed. So when you return from a function, the size of the stack is the same as it was when entering the function. Everything that has been put on it has been removed. (if not, the CPU would crash, as the return address is one of these objects)
    That's why it is called 'stack'.

  • Thank you very much for all of you.

    I have made mistake about the "fragmentation". I recognized from your replies that auto variables are stored in to the STACK not causing the fragmentation.


    Andy Neil Wrote:
    >It helps maintainability because, when a change is required, it only has to be made in one place.

    I agree with you.

    ---

    I was thinking to make code which is more maintanable. So I asked this question.

    From your replies, whether the optimization works depends on various condition such as compiler, right?

    I will make code considering your advices, paying attention to CODE size, DATA size and overhead, etc.

    Best regards

**Attention** This is a public forum