summaryrefslogblamecommitdiffstats
path: root/apps/demo/main.c
blob: 800b0d01d5426c7314d74dcb0c5b042fb6a03370 (plain) (tree)
1
  





























                                                                         

                           










                                                                     












































































                                                                           










                                                     



























































                                                                     









            

                   
 




                                                                            
 




                                                                         
 


                                       
 
                   
 

                         


               
                                                         
















                                                                      



                                                                            
 
/*
 * This file is a simple example of an application that could be run
 * on top of the monitor.
 *
 * Cstart():
 * The Cstart() function depends on the setting of MONCOMPTR in config.h.
 * It demonstrates the use of monConnect and the first mon_XXX function
 * typically called by an application, mon_getargv().
 *
 * main():
 * The main() function demonstrates argument processing (thanks to
 * the call to mon_getargv() in start()), environment variables and
 * a simple use of TFS to dump the content of an ASCII file.
 * Also, if the first argument is "strace_demo", then the strace_demo()
 * function is called.  Refer to strace.c for details.
 */

#include <string.h>
#include <stdlib.h>
#include "monlib.h"
#include "tfs.h"
#include "cfg.h"
#include "timer.h"

unsigned long AppStack[APPSTACKSIZE/4];

extern void strace_demo(void);

void
hitakey(void)
{
    while(!mon_gotachar());
    mon_getchar();
}

/* timer_demo():
 * This function assumes that the underlying monitor has a relatively
 * new uMon API hook call mon_timer().
 * This demo shows how to do a few different elapsed timer operations
 * using the API.
 */
void
timer_demo(void)
{
    struct elapsed_tmr  tmr;
    unsigned long starttime, endtime;

    /* Here are a few different ways (using the uMon API) to wait for
     * three seconds...
     *
     * First make sure the underlying monitor has a Hardware-based
     * timer.  If it doesn't then this is worthless.
     */
    mon_timer(TIMER_QUERY,&tmr);
    if((HWRTMR_IS_ENABLED(&tmr)) == 0) {
        mon_printf("This monitor doesn't have INCLUDE_HWTMR configured\n");
        return;
    }

    mon_printf("Timer demo ready to start, hit a key to continue\n");
    hitakey();

    /*****************************************************************
     *
     * The first one, also the simplest, but least versatile is to just
     * use mon_delay().  The mon_delay function just takes the number
     * of milliseconds you want to wait, and uses the underlying hardware
     * to busy wait on that duration...
     */
    mon_printf("1. Wait for 3 seconds...\n");
    mon_delay(3000);
    mon_printf("1. Done, hit a key to continue\n");
    hitakey();

    /*****************************************************************
     *
     * The second one, allows the user to specify the elapsed time
     * (in milliseconds), then allows the user to poll waiting for that
     * time to expire.  Meanwhile, the application can do other things
     * while it waits.
     */
    mon_printf("2. Wait for 3 seconds...\n");
    tmr.start = 3000;
    mon_timer(TIMER_START,&tmr);
    while(mon_timer(TIMER_ELAPSED,&tmr) == 0) {
        /* Do whatever you like here. */
    }
    mon_printf("2. Done, hit a key to continue\n");
    hitakey();

    /*****************************************************************
     *
     * The third method, uses the granularity of the hardware clock
     * and the returned value of "ticks-per-millisecond".  It provides
     * the most versatility (without actually knowing the details of
     * the hardware clock), but requires the most work.  Note that we
     * have to deal with the possiblity of 32-bit timer value wrap.
     */
    mon_printf("3. Wait for 3 seconds...\n");
    mon_timer(TIMER_QUERY,&tmr);
    starttime = tmr.currenttmrval;
    endtime = starttime + 3000 * tmr.tpm;
    if(endtime < starttime) {
        do {
            mon_timer(TIMER_QUERY,&tmr);
        } while(tmr.currenttmrval > starttime);
        do {
            mon_timer(TIMER_QUERY,&tmr);
        } while(tmr.currenttmrval < endtime);
    } else {
        do {
            mon_timer(TIMER_QUERY,&tmr);
        } while((tmr.currenttmrval > starttime) &&
                (tmr.currenttmrval < endtime));
    }

    mon_printf("3. Done, hit a key to continue\n");
    while(!mon_gotachar());

    mon_printf("Timer demo done\n");
    mon_appexit(1);
}

/* Global variables added just to be able to use this
 * app to demonstrate hookup with gdb...
 */
int argtot;
long apprambase;

int
main(int argc,char *argv[])
{
    int     i, tfd;
    char    line[80], *ab, *filename;

    argtot = argc;

    /* If argument count is greater than one, then dump out the
     * set of CLI arguments...
     */
    if(argc > 1) {
        if((argc == 2) && (strcmp(argv[1],"strace_demo") == 0)) {
            strace_demo();
        }

        if((argc == 2) && (strcmp(argv[1],"timer") == 0)) {
            timer_demo();
        }

        mon_printf("Argument list...\n");
        for(i=0; i<argc; i++) {
            mon_printf("  arg[%d]: %s\n",i,argv[i]);
            if(strcmp(argv[i],"match") == 0) {
                mon_printf("got a match!\n");
            }
        }
    }

    /* Using the content of the shell variable APPRAMBASE, dump the
     * memory starting at that location...
     */
    ab = mon_getenv("APPRAMBASE");
    if(ab) {
        char *addr = (char *)strtoul(ab,0,0);
        apprambase = strtoul(ab,0,0);

        mon_printf("Dumping memory at 0x%lx...\n",addr);
        mon_printmem(addr,128,1);
    }

    filename = "monrc";

    /* If the 'monrc' file exists, the assume it is ASCII and dump it
     * line by line...
     */
    if(mon_tfsstat(filename)) {
        mon_printf("Dumping content of '%s'...\n",filename);

        tfd = mon_tfsopen(filename,TFS_RDONLY,0);
        if(tfd >= 0) {
            while(mon_tfsgetline(tfd,line,sizeof(line))) {
                mon_printf("%s",line);
            }
            mon_tfsclose(tfd,0);
        } else {
            mon_printf("TFS error: %s\n",
                       (char *)mon_tfsctrl(TFS_ERRMSG,tfd,0));
        }
    } else {
        mon_printf("File '%s' not found\n",filename);
    }
    return(0);
}

void
__gccmain()
{
}

int
Cstart(void)
{
    char    **argv;
    int     argc;

    /* Connect the application to the monitor.  This must be done
     * prior to the application making any other attempts to use the
     * "mon_" functions provided by the monitor.
     */
    monConnect((int(*)())(*(unsigned long *)MONCOMPTR),(void *)0,(void *)0);

    /* When the monitor starts up an application, it stores the argument
     * list internally.  The call to mon_getargv() retrieves the arg list
     * for use by this application...
     */
    mon_getargv(&argc,&argv);

    /* Call main, then exit to monitor.
     */
    main(argc,argv);

    mon_appexit(0);

    /* Won't get here. */
    return(0);
}

/* CstartAlt():
 * Demonstrates the use of the "call -a" command in uMon.
 * For example, if for some reason you wanted to do this...
 * Load the application then load the symtbl file using
 * "make TARGET_IP=1.2.3.4 sym", then issue these commands:
 *
 *  tfs -v ld app
 *  call -a %CstartAlt one two three
 *
 * The "call -a" command in uMon correctly sets up the function
 * call parameters so that the following function would see 4
 * arguments (including arg0), with argv[1] thru argv[3] being
 * pointers to each of the number strings (i.e. "one", "two", "three")
 * and argv[0] being the ascii-coded-hex address of the function
 * CstartAlt.
 */
int
CstartAlt(int argc, char *argv[])
{
    monConnect((int(*)())(*(unsigned long *)MONCOMPTR),(void *)0,(void *)0);
    main(argc,argv);
    mon_appexit(0);
    return(0);
}