Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Select TRACE functions based on both a variable and a #define?

Select TRACE functions based on both a variable and a #define?

Scheduled Pinned Locked Moved C / C++ / MFC
tutorialcomhardwaredebugging
8 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    arnold_w
    wrote on last edited by
    #1

    I'm working on an embedded ARM-project (STM32F) and I'm programming in C programming language and compiling with Eclipse/GCC. In the project there is TRACE functionality implemented that, if enabled, logs various things over UART using queues and DMA:

    #define TRACE(grp, lvl, ...) traceToPrintStream(grp, __FILE__, __FUNCTION__, __LINE__, lvl, __VA_ARGS__)

    It can be used, e.g. like this:

    TRACE("regCallbacks", T_D, "The user pressed the button");
    TRACE("regCallbacks", T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

    I need a different trace that is not queued, does not use DMA and does not include the file name, function name and line number, but the other persons in this project do not agree to throw out the existing TRACE, so I need to make something in parallel. I want to be able to enable my TRACE in two ways, either by #defines:

    #define ENABLE_USER_EVENTS_LOGGING
    #define ENABLE_COMMUNICATOIN_BUS_LOGGING

    or by setting a varible during runtime:

    Bool_t enableCommunicationBusLogging;
    Bool_t enableUserEventsLogging;

    I need a different grouping (the grp parameter) than the others, so the example TRACEings above would have to be augmented with my grouping as well:

    TRACE_EX("regCallbacks", USER_EVENTS, T_D, "The user pressed the button");
    TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

    The rules I would like to apply are: 1. If my TRACE is enabled using the macros (hardcode enabled), then the other TRACE can not be used (hardcode disabled). 2. If my TRACE is not enabled using the macros, then both TRACEs can be enabled/disabled during runtime independently of each other. However, they are enabled per groups! Does anybody know how I can solve this? I found a great website (C Preprocessor tricks, tips, and idioms · pfultz2/Cloak Wiki · GitHub[^]) that shows some really neat macro-tricks, but I'm not sure how to apply it my case.

    L 1 Reply Last reply
    0
    • A arnold_w

      I'm working on an embedded ARM-project (STM32F) and I'm programming in C programming language and compiling with Eclipse/GCC. In the project there is TRACE functionality implemented that, if enabled, logs various things over UART using queues and DMA:

      #define TRACE(grp, lvl, ...) traceToPrintStream(grp, __FILE__, __FUNCTION__, __LINE__, lvl, __VA_ARGS__)

      It can be used, e.g. like this:

      TRACE("regCallbacks", T_D, "The user pressed the button");
      TRACE("regCallbacks", T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

      I need a different trace that is not queued, does not use DMA and does not include the file name, function name and line number, but the other persons in this project do not agree to throw out the existing TRACE, so I need to make something in parallel. I want to be able to enable my TRACE in two ways, either by #defines:

      #define ENABLE_USER_EVENTS_LOGGING
      #define ENABLE_COMMUNICATOIN_BUS_LOGGING

      or by setting a varible during runtime:

      Bool_t enableCommunicationBusLogging;
      Bool_t enableUserEventsLogging;

      I need a different grouping (the grp parameter) than the others, so the example TRACEings above would have to be augmented with my grouping as well:

      TRACE_EX("regCallbacks", USER_EVENTS, T_D, "The user pressed the button");
      TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

      The rules I would like to apply are: 1. If my TRACE is enabled using the macros (hardcode enabled), then the other TRACE can not be used (hardcode disabled). 2. If my TRACE is not enabled using the macros, then both TRACEs can be enabled/disabled during runtime independently of each other. However, they are enabled per groups! Does anybody know how I can solve this? I found a great website (C Preprocessor tricks, tips, and idioms · pfultz2/Cloak Wiki · GitHub[^]) that shows some really neat macro-tricks, but I'm not sure how to apply it my case.

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      As I understand it (assuming the traceToPrintStream function is fixed) you need a slightly different macro for your TRACE_EX, something like:

      #define TRACE_EX(grp, lvl, ...) traceToPrintStream(grp, "", "", 0, lvl, __VA_ARGS__)

      If you want to enable the traces at runtime then you need them always enabled at compile time, otherwise you will need to rebuild the code every time. So to allow the traces to be based on switches you need something like:

      #define TRACE_EX(switch, grp, lvl, ...) \
      if (switch) \
      { \
      traceToPrintStream(grp, "", "", 0, lvl, __VA_ARGS) \
      }

      where switch is the name of the boolean that controls the tracing.

      A 1 Reply Last reply
      0
      • L Lost User

        As I understand it (assuming the traceToPrintStream function is fixed) you need a slightly different macro for your TRACE_EX, something like:

        #define TRACE_EX(grp, lvl, ...) traceToPrintStream(grp, "", "", 0, lvl, __VA_ARGS__)

        If you want to enable the traces at runtime then you need them always enabled at compile time, otherwise you will need to rebuild the code every time. So to allow the traces to be based on switches you need something like:

        #define TRACE_EX(switch, grp, lvl, ...) \
        if (switch) \
        { \
        traceToPrintStream(grp, "", "", 0, lvl, __VA_ARGS) \
        }

        where switch is the name of the boolean that controls the tracing.

        A Offline
        A Offline
        arnold_w
        wrote on last edited by
        #3

        Ok, so this is what I have now:

        #define USER_EVENTS_LOGGING 0x00000001
        #define COMMUNICATOIN_BUS_LOGGING 0x00000002
        uint32_t enabledMyGrpBitFlags = 0;

        #if defined(ENABLE_USER_EVENTS_LOGGING)
        #define TRACE_EX(grp, myGrp, lvl, ...) if (myGrp & USER_EVENTS_LOGGING) printf_(__VA_ARGS__)
        #elif defined(ENABLE_COMMUNICATOIN_BUS_LOGGING)
        #define TRACE_EX(grp, myGrp, lvl, ...) if (myGrp & COMMUNICATOIN_BUS_LOGGING) printf_(__VA_ARGS__)
        #else
        #define TRACE_EX(grp, myGrp, lvl, ...) \
        do { \
        if (myGrp & enabledMyGrpBitFlags) { \
        printf_(__VA_ARGS__); \
        } \
        traceToPrintStream(grp, __FILE__, __FUNCTION__, __LINE__, lvl, __VA_ARGS__); \
        } while (0)
        #endif

        Is it possible to remove the run-time checks:

        if (myGrp & USER_EVENTS_LOGGING)
        if (myGrp & COMMUNICATOIN_BUS_LOGGING)

        so that the TRACE_EX macro would become empty when the myGrop isn't matching? In other words, let's say only ENABLE_USER_EVENTS_LOGGING (not ENABLE_COMMUNICATOIN_BUS_LOGGING) is defined, then I would like the following line to "disappear" after the preprocessor is finished:

        TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

        Is that possible somehow?

        L 1 Reply Last reply
        0
        • A arnold_w

          Ok, so this is what I have now:

          #define USER_EVENTS_LOGGING 0x00000001
          #define COMMUNICATOIN_BUS_LOGGING 0x00000002
          uint32_t enabledMyGrpBitFlags = 0;

          #if defined(ENABLE_USER_EVENTS_LOGGING)
          #define TRACE_EX(grp, myGrp, lvl, ...) if (myGrp & USER_EVENTS_LOGGING) printf_(__VA_ARGS__)
          #elif defined(ENABLE_COMMUNICATOIN_BUS_LOGGING)
          #define TRACE_EX(grp, myGrp, lvl, ...) if (myGrp & COMMUNICATOIN_BUS_LOGGING) printf_(__VA_ARGS__)
          #else
          #define TRACE_EX(grp, myGrp, lvl, ...) \
          do { \
          if (myGrp & enabledMyGrpBitFlags) { \
          printf_(__VA_ARGS__); \
          } \
          traceToPrintStream(grp, __FILE__, __FUNCTION__, __LINE__, lvl, __VA_ARGS__); \
          } while (0)
          #endif

          Is it possible to remove the run-time checks:

          if (myGrp & USER_EVENTS_LOGGING)
          if (myGrp & COMMUNICATOIN_BUS_LOGGING)

          so that the TRACE_EX macro would become empty when the myGrop isn't matching? In other words, let's say only ENABLE_USER_EVENTS_LOGGING (not ENABLE_COMMUNICATOIN_BUS_LOGGING) is defined, then I would like the following line to "disappear" after the preprocessor is finished:

          TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

          Is that possible somehow?

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          The run time checks are only effective at the time the code runs, so there is no way that the macro can be changed at that point. And the macro itself is evaluated, and its code generated in the preprocessor, long before the code is running.

          A 1 Reply Last reply
          0
          • L Lost User

            The run time checks are only effective at the time the code runs, so there is no way that the macro can be changed at that point. And the macro itself is evaluated, and its code generated in the preprocessor, long before the code is running.

            A Offline
            A Offline
            arnold_w
            wrote on last edited by
            #5

            I want to be able to compile in 2 different modes: 1. Normal mode: The 2 types of TRACE can be enabled/disabled during runtime independently of each other. 2. Hardcoded my TRACE only mode: Only my TRACE is enabled (1 or more myGrp TRACE groups), it's impossible to enable/disable anything TRACE related during runtime. So, when compiling in mode 2 above, it should be possible for the macro to evaluate the passed myGrp parameter to determine how the TRACE_EX should be expanded. So if we only enable

            #define ENABLE_USER_EVENTS_LOGGING

            then the preprocessor should be able to determine that this line should be removed:

            TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

            L 1 Reply Last reply
            0
            • A arnold_w

              I want to be able to compile in 2 different modes: 1. Normal mode: The 2 types of TRACE can be enabled/disabled during runtime independently of each other. 2. Hardcoded my TRACE only mode: Only my TRACE is enabled (1 or more myGrp TRACE groups), it's impossible to enable/disable anything TRACE related during runtime. So, when compiling in mode 2 above, it should be possible for the macro to evaluate the passed myGrp parameter to determine how the TRACE_EX should be expanded. So if we only enable

              #define ENABLE_USER_EVENTS_LOGGING

              then the preprocessor should be able to determine that this line should be removed:

              TRACE_EX("regCallbacks", COMMUNICATION_BUS, T_D, "Write to reg %d. First written byte: 0x%X", regAddr, regValues[0]);

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              I have tried what I think you are asking for but the preprocessor rejects it. As far as I know you can only do it the way I already suggested.

              A 1 Reply Last reply
              0
              • L Lost User

                I have tried what I think you are asking for but the preprocessor rejects it. As far as I know you can only do it the way I already suggested.

                A Offline
                A Offline
                arnold_w
                wrote on last edited by
                #7

                On the following webpage C Preprocessor tricks, tips, and idioms · pfultz2/Cloak Wiki · GitHub[^] it is shown how an IIF (immediate if) statement for macros can be implemented. But as soon as I pass an expression, as oppose to either 0 or 1, to it, I can't get it to compile either:

                #define USER_EVENTS_LOGGING 0x00000001
                #define COMMUNICATION_BUS_LOGGING 0x00000002

                #if defined(ENABLE_USER_EVENTS_LOGGING) && defined(ENABLE_COMMUNICATION_BUS_LOGGING)
                #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (USER_EVENTS_LOGGING | COMMUNICATION_BUS_LOGGING)
                #elif !defined(ENABLE_USER_EVENTS_LOGGING) && defined(ENABLE_COMMUNICATION_BUS_LOGGING)
                #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (COMMUNICATION_BUS_LOGGING)
                #elif defined(ENABLE_USER_EVENTS_LOGGING) && !defined(ENABLE_COMMUNICATION_BUS_LOGGING)
                #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (USER_EVENTS_LOGGING)
                #else
                #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (0)
                #endif

                IIF(1)(true, false) // Compiles fine
                IIF((0 < (HARDCODE_ENABLED_MY_GRP_BIT_FLAGS & USER_EVENTS_LOGGING)))(true, false) // Doesn't compile!

                L 1 Reply Last reply
                0
                • A arnold_w

                  On the following webpage C Preprocessor tricks, tips, and idioms · pfultz2/Cloak Wiki · GitHub[^] it is shown how an IIF (immediate if) statement for macros can be implemented. But as soon as I pass an expression, as oppose to either 0 or 1, to it, I can't get it to compile either:

                  #define USER_EVENTS_LOGGING 0x00000001
                  #define COMMUNICATION_BUS_LOGGING 0x00000002

                  #if defined(ENABLE_USER_EVENTS_LOGGING) && defined(ENABLE_COMMUNICATION_BUS_LOGGING)
                  #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (USER_EVENTS_LOGGING | COMMUNICATION_BUS_LOGGING)
                  #elif !defined(ENABLE_USER_EVENTS_LOGGING) && defined(ENABLE_COMMUNICATION_BUS_LOGGING)
                  #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (COMMUNICATION_BUS_LOGGING)
                  #elif defined(ENABLE_USER_EVENTS_LOGGING) && !defined(ENABLE_COMMUNICATION_BUS_LOGGING)
                  #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (USER_EVENTS_LOGGING)
                  #else
                  #define HARDCODE_ENABLED_MY_GRP_BIT_FLAGS (0)
                  #endif

                  IIF(1)(true, false) // Compiles fine
                  IIF((0 < (HARDCODE_ENABLED_MY_GRP_BIT_FLAGS & USER_EVENTS_LOGGING)))(true, false) // Doesn't compile!

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  Sorry, that is something I have never seen before. To be honest I think you are in danger of making things far more difficult than you need. The original spec I suggested where you can generate (or not) the macro that includes a runtime check, is the simplest way of doing it.

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups