summaryrefslogtreecommitdiffstats
path: root/apps/demo/main.c
blob: d74a2d3085b91a4af1bb04dc693410d208d6f0bf (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/* 
 * 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);
}