This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Runtime / Simulation Specific Code

Hello everyone,

So, I am working with an 8051W core processor (with OTP, once again, that's a whole other discussion) and I'm pretty maxed out on code space and looking to trim it down a bit. I need to check the functionality of some of my interrupts so I've had to create code that looks like this:

void main (void)
{
        DiagMode = 0;

        /* Loop for standard/hardware diagnostics mode */
        if ((DiagMode == 0) || (DiagMode == 2))
        {
                while (1)
                {
                        // Insert code here
                }; /* Loop forever */
        }
        /* Loop for simulation/software diagnostic mode */
        else if (DiagMode == 1)
        {
                while(1)
                {
                        decimator2_ISR();
                        // Insert code here
                };      /* Loop forever */
        }

}

So if I wanted to use the code in simulation mode, I set DiagMode = 1. When I go to burn the chip, I set it equal to 0 (or 2 if I'm doing some hardware diagnostics, I have various case statements throughout the code that run only if DiagMode = 1 or 2).

Currently, if I want to cut down the code I have, I can comment out any unnecessary code portions (anything with DiagMode = 1, etc). I was wondering if there was a way to set my code to build the code differently if it is being used in simulation mode and when I compile it to hex (or set DiagMode to 0), the portions in code with DiagMode set to 1 are not built into the hex code, saving space.

I apologize if what I'm asking for is confusing. Realistically, it probably isn't possible but I figure if anyone would know how to do something along these lines (or has a better alternative), this would be the place to go.

Let me know when you get the chance. Thanks!

Parents
  • So, I updated my code to look like this:

    void main (void)
    {
            DiagMode = 0;
    
            /* Loop for standard/hardware diagnostics mode */
            #if ((DiagMode == 0) || (DiagMode == 2))
            {
                    while (1)
                    {
                            // Insert code here
                    }; /* Loop forever */
            }
            /* Loop for simulation/software diagnostic mode */
            #else //if (DiagMode == 1)
            {
                    while(1)
                    {
                            decimator2_ISR();
                            // Insert code here
                    };      /* Loop forever */
            }
            #endif
    }
    

    It appears that it's working as it's supposed to (my code dropped by 50 bytes, so that's good) but I did get the following warnings:

    warning C322: unknown identifier
    warning C322: unknown identifier

    It might still work but I'd feel a lot more comfortable making those warnings go away, in case I'm doing something wrong.

    If I was to guesstimate the problem, I'm guessing it's referring to DiagMode twice. Is this because I need to do some sort of #declare statement or something to that effect (#declare DiagMode = 0, possibly?)? Or set it as a constant? Or do I need to include some sort of library I'm missing?

    Also, I wasn't able to get a #elseif statement working. I got the following error when I tried

    #elseif (DiagMode == 1)
    

    :

    warning C315: unknown #directive 'elseif'

    Did I screw something else up or is there a Keil specific way to do this?

Reply
  • So, I updated my code to look like this:

    void main (void)
    {
            DiagMode = 0;
    
            /* Loop for standard/hardware diagnostics mode */
            #if ((DiagMode == 0) || (DiagMode == 2))
            {
                    while (1)
                    {
                            // Insert code here
                    }; /* Loop forever */
            }
            /* Loop for simulation/software diagnostic mode */
            #else //if (DiagMode == 1)
            {
                    while(1)
                    {
                            decimator2_ISR();
                            // Insert code here
                    };      /* Loop forever */
            }
            #endif
    }
    

    It appears that it's working as it's supposed to (my code dropped by 50 bytes, so that's good) but I did get the following warnings:

    warning C322: unknown identifier
    warning C322: unknown identifier

    It might still work but I'd feel a lot more comfortable making those warnings go away, in case I'm doing something wrong.

    If I was to guesstimate the problem, I'm guessing it's referring to DiagMode twice. Is this because I need to do some sort of #declare statement or something to that effect (#declare DiagMode = 0, possibly?)? Or set it as a constant? Or do I need to include some sort of library I'm missing?

    Also, I wasn't able to get a #elseif statement working. I got the following error when I tried

    #elseif (DiagMode == 1)
    

    :

    warning C315: unknown #directive 'elseif'

    Did I screw something else up or is there a Keil specific way to do this?

Children
  • ... when you do not relate warnings to sourcelines

    but my guess is that you are #if ing on things that are not #defined

    BTW look onto #ifdef

    Erik

  • Sorry about that, I meant to actually tell you that that line pointed to the following line but it looks like I left out that very important bit of information:

    if ((DiagMode == 0) || (DiagMode == 2))
    

    I added the line:

    #define DiagMode 0
    

    That seemed to fix the errors and removed all the unnecessary code in this .C file. Unfortunately, I have a number of .C files and it's not doing the same thing in all of those. Is there a place I can place that #define code that would reach all .C files? For instance, in my vars.c or VARS.H file (since all my .c files have:

    #include "vars.h"?
    

    at the top?)

    I currently have diagmode defined in my vars.C code as:

    unsigned char idata DiagMode = 0;
    

    and my VARS.H file as:

    extern unsigned char idata DiagMode;
    

    Is there a way I can incorporate this #define statement into my VARS.H? I tried placing it at the top but it is giving me issues because, I'm assuming, that variable is not defined yet (and it won't allow me to add the define statement after the declaration statement without additional errors or warnings).

    Any direction you can give me would be appreciated. Thanks again!

  • the preprocessor, which handles the #... thingies do NOT look at char, int etc.

    thus if you have
    #ifdef RALPH

    RALPH must be a #define

    the ussual way to do this is in xxx.h to have something like
    //#define BUILD1 //uncomment this line for build1

    Erik

  • So you're saying I would just need to change all my:

    if(DiagMode==1)
    

    statements to

    #if(BUILD1)
    

    Is that correct? I just want to make sure before I change my whole program.

    Thanks, Erik!

  • Note that #if BUILD1 tests if the preprocessor symbol BUILD1 is nonzero.
    #if defined(BUILD1) (or the older #ifdef BUILD1) just tests if it is defined.

    #define BUILD1 // just defines this symbol
    #define BUILD1 1 // also gives it a value

    if you give the define a value, you can also do

    #define BUILD_TYPE 2
    
    #if BUILD_TYPE==0
        ...
    #elif BUILD_TYPE==1
        ...
    #elif BUILD_TYPE==2
        ...
    #else
        #error "Unsupported build type."
    #endif
    

  • Well, found the issue with the errors with

    #define DiagMode 0
    

    in my VARS.H file. Turns out, I just need to comment out:

    unsigned char idata DiagMode = 0;
    extern unsigned char idata DiagMode;
    

    Now I don't have to change anything (which is convenient). Thanks!

  • Well remember that #define does symbol replacement.

    So your

    unsigned char idata DiagMode = 0;
    


    will look like

    unsigned char idata 0 = 0;
    


    and the compiler is not impressed by that.

  • So you're saying I would just need to change all my:

    if(DiagMode==1)
    statements to

    #if(BUILD1)
    Is that correct? I just want to make sure before I change my whole program.

    of course not, Names in an example are just that

    Erik

  • Ok, now I'm confused. What is it you guys are proposing me to do at this point?

    Originally, I had:

    VARS.H

    #ifndef _D4_VARS_H
    #define _D4_VARS_H
    
    extern unsigned char idata DiagMode;
    

    vars.c

    #include "VARS.H"
    unsigned char idata DiagMode = 0;
    

    main.c

    #include "VARS.H"
    void main (void)
    {
            DiagMode = 0;
    
            /* Loop for standard/hardware diagnostics mode */
            if ((DiagMode == 0) || (DiagMode == 2))
            {
                    while (1)
                    {
                            // Insert code here
                    }; /* Loop forever */
            }
            /* Loop for simulation/software diagnostic mode */
            else if (DiagMode == 1)
            {
                    while(1)
                    {
                            decimator2_ISR();
                            // Insert code here
                    };      /* Loop forever */
            }
    
    }
    

    I have now changed it to:

    VARS.H

    #ifndef _D4_VARS_H
    #define _D4_VARS_H
    
    //extern unsigned char idata DiagMode;
    #define DiagMode 0
    

    vars.c

    #include "VARS.H"
    //unsigned char idata DiagMode = 0;
    

    main.c

    #include "VARS.H"
    void main (void)
    {
            DiagMode = 0;
    
            /* Loop for standard/hardware diagnostics mode */
            if ((DiagMode == 0) || (DiagMode == 2))
            {
                    while (1)
                    {
                            // Insert code here
                    }; /* Loop forever */
            }
            /* Loop for simulation/software diagnostic mode */
            else if (DiagMode == 1)
            {
                    while(1)
                    {
                            decimator2_ISR();
                            // Insert code here
                    };      /* Loop forever */
            }
    
    }
    

    This appears to work as I can change the Diagmode = 0 to 1 and it gives me a different code size, which I assume means it's working (maybe I'm wrong). Am I doing this right or are you suggesting I need to do it a bit differently?

    I understand that you guys generally want to give guidance without giving sample code but at this point, I think you're losing me with what it is you're suggesting. Can you give me a quick code example for what you think I should be doing because, if I'm doing something incorrectly right now, I really don't understand what it is you are suggesting.

  • I have a question for you. So, if you look at my last post, you can see what I did and it seemed to work without updating any of my if statements to #if statements. Is this because Keil fixed the issue for me with the compiler (which probably means I am still doing it incorrectly, regardless of how Keil fixes it for me) or is what I did actually correct?

    I found an area that had an if/else diagmode statement and changed them to #if and #else and noticed no change in code size (ie the code I had was executing correctly with my fixes) so it appears to be doing what I wanted it to do correctly.

    I just want to know if my procedure is incorrect and, for best practices or when using other compilers (or even changing optimization levels, possibly), I need to implement it differently or if my coding is correct.

    Let me know if my wording is confusing and I can try and explain it again. Thanks!

  • you are mixing precompiler and compiler directive

    THIS IS AN EXAMPLE VARIABLE NAMES ARE FICTIONAL

    common.h

    //#define OMIT1 //uncomment if certain code is to be omitted
    //#define OMIT2 //uncomment if certain other code is to be omitted
    

    whatever.c

    #include common.h
    
    code
    #ifndef OMIT1
    code that is to be excluded if omit 1
    #endif
    code
    #ifndef OMIT2
    code that is to be excluded if omit 2
    #endif
    code
    #ifndef OMIT1
    more code that is to be excluded if omit 1
    #endif
    code
    

  • Ok, I understand.

    Out of curiosity, is it really easier to create your own examples from scratch rather than to simply demonstrate by correcting code that is incorrect (such as my examples)? Could save a few posts.

  • Oh, and for the record, I don't want to come off as ungrateful because I do appreciate the help I'm getting.

    And so you know, I used "BUILD1" for reference purpose, not because I thought BUILD1 was the required variable (I understand you weren't being literal with that name). So that part wasn't lost on me, in case I gave you the impression I didn't know how variables worked . . . :p

  • The compiler is smart. If it see C code that is unreachable, it can remove it.

    So:

    int charlie=1
    if (charlie == 1) {
        ...
    } else {
        ...
    }
    


    the compiler can throw away the code inside the else statement.

    If the code instead looks like:

    void my_function(int charlie) {
        if (charlie == 1) {
            ...
        } else {
            ...
        }
    }
    


    Then the compiler can't throw away any code.

    But when using #ifdef x or #if defined(x) or #if x == y then the preprocessor will filter away non-matching code and the compiler don't need to worry about what can be resolved at compile time and what needs to be resolved at runtime.