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

User defined functions in uVision3

Has anyone ever seen an authoritative document on using
debug functions in uVision3?  It could be a powerful tool if
I knew how to use it, but what little information I have
come across is scattered across 2 hardcopy manuals, a bit
more in the help file system, and smatterings in the Keil
Knowledgebase.

Here are clues, not documented anywhere, that I have
discovered by trial and error:
  - If the last line of a .ini file containing function
    definitions does not end in a CR/LF, you get a "syntax
    error".
  - The "Breakpoint Set (BS), and "Go" (GO) commands may be
    executed from the command line, but not inside a
    function.
  - If you access program variables from the function, you
    must halt execution at a point in the program where
    they are all in scope before you load the function with
    an "include" command.  Otherwise you get another "syntax
    error."
  - When you define and/or when you invoke a function, you
    must terminate its name with a pair of parentheses.
    When you "kill" the function, you must omit the
    parentheses. Otherwise, you get another one of those
    ubiquitous "syntax errors".
  - It could be that everything is a syntax error in this
    domain.  The messages are that useful.              :-}

Perhaps if we all pool our insights, we will have a running
start on a manual.
============================================================
Gary Lynch           |   To send mail, no$pam in domain name
lynchg@no$pam.com    |   must be changed to stacoenergy.

Parents
    1. User-defined functions are subject to several more "eccentricities":
      • The last line of a command file must end with a CR/LF, else you will get a "syntax error."
      • Never declare an automatic variable within a user- defined function and forget to use it. You will get a "syntax error."
      • User-defined functions may not use arrays, structures, pointers, or global variables from the target application.
      • All automatics of the target application referenced by your function must be in-scope both at the time the command file is read, and when the function is invoked. I generally pick a single break point from which I can do both. Know what you get if you forget this? Hint: "syntax error"

      You can work around the 3rd item by creating a function inside your target application, declare a bunch of automatics, and copy all globals of interest to one of the automatics before you hit the breakpoint from which you define your function:

            int glob1, glob2;
      
            void main(void) {
      
              int lclMn1, lclMn2;
      
              uV3Break(lclMn1, lclMn2);
            }
      
            void uV3Break(int parm1, int parm2);
              int glbuV1, glbuV2;
              int dummy;
      
              glbuV1 = glob1;
              glbuV2 = glob2
      
              dummy = 0;
              return;
            }
      

      At this point: parm1, parm2, glbuV1, glbuV2 are all in scope and can be used by a user-defined function.

      Here the statement "dummy = 1" gives me a place to set a breakpoint, from which to launch my command file.

    2. You can create the moral equivalent of a global from a command file with the #define command, but you must encapsulate a #define command inside an exec() command:
      exec("#define NO_OF_SAMPLES 12");
      
    3. You read the command file in from the 'Output Window- Command' page, using the INCLUDE command:
      include dumpIoPorts.ini
      
    4. If your command file is long and errors occur early in the read, the diagnostics may scroll up beyond the top of the window so quickly you do not notice. A quick way to verify that a function definition took is the
      DIR UFUNC
      

      command. If your function does not appear in the list, it failed.

    5. You invoke the function directly from the 'Output Window-Command' page:
      dumpIoPorts();
      

      You may invoke it from inside a command file, too, but I haven't found that particularly useful.

    6. If your function definition succeeded, but has logic errors, you must first delete it:
      KILL FUNC dumpIoPorts
      

      before you can read the next version back in.

      Note that in the definition and invocation of my function, I have adhered to strict C syntax for the function name, including parentheses that surround a parameter list (even if you use no parameters), and the terminating semi-colon. Note also that I DO NOT use the latter 2 elements with the KILL command. Try that and you run afoul of the infamous ....

      <drum roll>

      Aw, never mind. You know the routine by now.

    7. If the foregoing seems a little tedious, there is a vastly superior alternative. It is mentioned in my Getting Started manual, pp. 127-128, but is very easy to miss. It is called the "Debug-Function Editor", and is accessed from the "Debug/Function Editor (open .Ini file) ..." drop-down menu (in debug mode only). With this single dialog box you can:
      • Create,
      • Edit,
      • Save,
      • Read into your application ("Compile")
      • Change and overwrite old version in one operation;

      and I recommend it over the manual methods.

    8. It would be extremely useful to be able to start and stop execution of the target under script control, but I have never been able to master this art. I have developed a powerful work-around, and will publish it under its own thread, should anyone have a need.

    ============================================================
    Gary Lynch           |   To send mail, no$pam in domain name
    lynchg@no$pam.com    |   must be changed to stacoenergy.
    

Reply
    1. User-defined functions are subject to several more "eccentricities":
      • The last line of a command file must end with a CR/LF, else you will get a "syntax error."
      • Never declare an automatic variable within a user- defined function and forget to use it. You will get a "syntax error."
      • User-defined functions may not use arrays, structures, pointers, or global variables from the target application.
      • All automatics of the target application referenced by your function must be in-scope both at the time the command file is read, and when the function is invoked. I generally pick a single break point from which I can do both. Know what you get if you forget this? Hint: "syntax error"

      You can work around the 3rd item by creating a function inside your target application, declare a bunch of automatics, and copy all globals of interest to one of the automatics before you hit the breakpoint from which you define your function:

            int glob1, glob2;
      
            void main(void) {
      
              int lclMn1, lclMn2;
      
              uV3Break(lclMn1, lclMn2);
            }
      
            void uV3Break(int parm1, int parm2);
              int glbuV1, glbuV2;
              int dummy;
      
              glbuV1 = glob1;
              glbuV2 = glob2
      
              dummy = 0;
              return;
            }
      

      At this point: parm1, parm2, glbuV1, glbuV2 are all in scope and can be used by a user-defined function.

      Here the statement "dummy = 1" gives me a place to set a breakpoint, from which to launch my command file.

    2. You can create the moral equivalent of a global from a command file with the #define command, but you must encapsulate a #define command inside an exec() command:
      exec("#define NO_OF_SAMPLES 12");
      
    3. You read the command file in from the 'Output Window- Command' page, using the INCLUDE command:
      include dumpIoPorts.ini
      
    4. If your command file is long and errors occur early in the read, the diagnostics may scroll up beyond the top of the window so quickly you do not notice. A quick way to verify that a function definition took is the
      DIR UFUNC
      

      command. If your function does not appear in the list, it failed.

    5. You invoke the function directly from the 'Output Window-Command' page:
      dumpIoPorts();
      

      You may invoke it from inside a command file, too, but I haven't found that particularly useful.

    6. If your function definition succeeded, but has logic errors, you must first delete it:
      KILL FUNC dumpIoPorts
      

      before you can read the next version back in.

      Note that in the definition and invocation of my function, I have adhered to strict C syntax for the function name, including parentheses that surround a parameter list (even if you use no parameters), and the terminating semi-colon. Note also that I DO NOT use the latter 2 elements with the KILL command. Try that and you run afoul of the infamous ....

      <drum roll>

      Aw, never mind. You know the routine by now.

    7. If the foregoing seems a little tedious, there is a vastly superior alternative. It is mentioned in my Getting Started manual, pp. 127-128, but is very easy to miss. It is called the "Debug-Function Editor", and is accessed from the "Debug/Function Editor (open .Ini file) ..." drop-down menu (in debug mode only). With this single dialog box you can:
      • Create,
      • Edit,
      • Save,
      • Read into your application ("Compile")
      • Change and overwrite old version in one operation;

      and I recommend it over the manual methods.

    8. It would be extremely useful to be able to start and stop execution of the target under script control, but I have never been able to master this art. I have developed a powerful work-around, and will publish it under its own thread, should anyone have a need.

    ============================================================
    Gary Lynch           |   To send mail, no$pam in domain name
    lynchg@no$pam.com    |   must be changed to stacoenergy.
    

Children
No data