changing circuitry to disable RTC, update initialization to match
[fw/openalt] / monitor / monitor.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <fcntl.h>
7 #include <time.h>
8 #include <errno.h>
9 #include <malloc.h>
10 #include <sys/time.h>
11 #include <sys/times.h>
12
13 #include "FreeRTOS.h"
14 #include "task.h"
15
16 #include "args.h"
17 #include "../fatfs/diskio.h"
18 #include "../fatfs/ff.h"
19 #include "../fiq/fiq.h"
20 #include "../gps/gps.h"
21 #include "../i2c/eeprom.h"
22 #include "../i2c/i2c.h"
23 #include "../i2c/lm75.h"
24 #include "../iap/iap.h"
25 #include "../main.h"
26 #include "../rtc/rtc.h"
27 #include "../sensors/sensors.h"
28 #include "../swi/swi.h"
29 #include "monitor.h"
30
31 //
32 //
33 //
34 typedef enum
35 {
36   CMDTYPE_CMDLIST = 0,
37   CMDTYPE_FUNCTION
38 }
39 cmdType_e;
40
41 typedef struct abortDat_s
42 {
43   unsigned int dummy;
44   unsigned int sigil;
45   unsigned int count;
46   unsigned int type;
47   unsigned int pc;
48   unsigned int opcode;
49   unsigned int cpsr;
50   unsigned int lr;
51   unsigned int sp;
52   unsigned int r0;
53   unsigned int r1;
54   unsigned int r2;
55   unsigned int r3;
56   unsigned int r4;
57   unsigned int r5;
58   unsigned int r6;
59   unsigned int r7;
60   unsigned int r8;
61   unsigned int r9;
62   unsigned int r10;
63   unsigned int r11;
64   unsigned int r12;
65   unsigned int stack [8];
66 }
67 __attribute__ ((packed)) abortDat_t;
68
69 typedef struct commandList_s
70 {
71   const portCHAR *command;
72   portCHAR minArgs;
73   portCHAR maxArgs;
74   cmdType_e cmdType;
75   union
76   {
77     void *trickGCC;
78     int (*handler) (int argc, portCHAR **argv);
79     struct commandList_s *commandList;
80   };
81   const portCHAR *description;
82   const portCHAR *parameters;
83 }
84 commandList_t;
85
86 //
87 //  Prototypes
88 //
89 static int monitorHelp (int argc, portCHAR **argv);
90 static int monitorDiskInit (int argc, portCHAR **argv);
91 static int monitorDiskMount (int argc, portCHAR **argv);
92 static int monitorFileMkfs (int argc, portCHAR **argv);
93 static int monitorFileDf (int argc, portCHAR **argv);
94 static int monitorFileLs (int argc, portCHAR **argv);
95 static int monitorFileMkdir (int argc, portCHAR **argv);
96 static int monitorFileRmdir (int argc, portCHAR **argv);
97 static int monitorFileRm (int argc, portCHAR **argv);
98 static int monitorFileMv (int argc, portCHAR **argv);
99 static int monitorFileCp (int argc, portCHAR **argv);
100 static int monitorFileCpCon (int argc, portCHAR **argv);
101 static int monitorFileChmod (int argc, portCHAR **argv);
102 static int monitorFileSync (int argc, portCHAR **argv);
103 static int monitorFileThruPut (int argc, portCHAR **argv);
104 static int monitorGPS (int argc, portCHAR **argv);
105 static int monitorSensors (int argc, portCHAR **argv);
106 static int monitorMd (int argc, portCHAR **argv);
107 static int monitorAbortRegs (int argc, portCHAR **argv);
108 static int monitorAbortClear (int argc, portCHAR **argv);
109 static int monitorAbortDirty (int argc, portCHAR **argv);
110 static int monitorAbortUndef (int argc, portCHAR **argv);
111 static int monitorAbortPabort (int argc, portCHAR **argv);
112 static int monitorAbortDabort (int argc, portCHAR **argv);
113 static int monitorEEAddr (int argc, portCHAR **argv);
114 static int monitorEERead (int argc, portCHAR **argv);
115 static int monitorEEReadAddr (int argc, portCHAR **argv);
116 static int monitorEEWrite (int argc, portCHAR **argv);
117 static int monitorEEWriteAddr (int argc, portCHAR **argv);
118 static int monitorEEFillAddr (int argc, portCHAR **argv);
119 static int monitorFIQOn (int argc, portCHAR **argv);
120 static int monitorFIQOff (int argc, portCHAR **argv);
121 static int monitorFIQCount (int argc, portCHAR **argv);
122 static int monitorFIQClear (int argc, portCHAR **argv);
123 static int monitorI2CRead (int argc, portCHAR **argv);
124 static int monitorI2CWrite (int argc, portCHAR **argv);
125 static int monitorI2CWriteRead (int argc, portCHAR **argv);
126 static int monitorI2CDump (int argc, portCHAR **argv);
127 static int monitorI2CErrno (int argc, portCHAR **argv);
128 static int monitorIAPFSS (int argc, portCHAR **argv);
129 static int monitorIAPSTOA (int argc, portCHAR **argv);
130 static int monitorIAPFill (int argc, portCHAR **argv);
131 static int monitorIAPErase (int argc, portCHAR **argv);
132 static int monitorIAPBlank (int argc, portCHAR **argv);
133 static int monitorIAPID (int argc, portCHAR **argv);
134 static int monitorIAPVer(int argc, portCHAR **argv);
135 static int monitorIAPISP (int argc, portCHAR **argv);
136 static int monitorLM75Init (int argc, portCHAR **argv);
137 static int monitorLM75Mode (int argc, portCHAR **argv);
138 static int monitorLM75Addr (int argc, portCHAR **argv);
139 static int monitorLM75ReRead (int argc, portCHAR **argv);
140 static int monitorLM75Temp (int argc, portCHAR **argv);
141 static int monitorLM75Config (int argc, portCHAR **argv);
142 static int monitorLM75Thyst (int argc, portCHAR **argv);
143 static int monitorLM75Tos (int argc, portCHAR **argv);
144 static int monitorMemTask (int argc, portCHAR **argv);
145 static int monitorMemMap (int argc, portCHAR **argv);
146 static int monitorMemAlloc (int argc, portCHAR **argv);
147 static int monitorMemRealloc (int argc, portCHAR **argv);
148 static int monitorMemFree (int argc, portCHAR **argv);
149 static int monitorMemList (int argc, portCHAR **argv);
150 static int monitorMiscSizeof (int argc, portCHAR **argv);
151 static int monitorRTCGet (int argc, portCHAR **argv);
152 static int monitorRTCSet (int argc, portCHAR **argv);
153 static int monitorRTCAlarm (int argc, portCHAR **argv);
154 static int monitorRTCPeriodic (int argc, portCHAR **argv);
155 static int monitorSWISetAsm (int argc, portCHAR **argv);
156 static int monitorSWIOnAsm (int argc, portCHAR **argv);
157 static int monitorSWIOffAsm (int argc, portCHAR **argv);
158 static int monitorSWIToggleAsm (int argc, portCHAR **argv);
159 static int monitorSWISetC (int argc, portCHAR **argv);
160 static int monitorSWIOnC (int argc, portCHAR **argv);
161 static int monitorSWIOffC (int argc, portCHAR **argv);
162 static int monitorSWIToggleC (int argc, portCHAR **argv);
163 static int monitorWDTTest (int argc, portCHAR **argv);
164 static int monitorWDTStatus (int argc, portCHAR **argv);
165 static int monitorWDTClear (int argc, portCHAR **argv);
166 static int monitorVersion (int argc, portCHAR **argv);
167
168 //
169 //  Ye olde globals
170 //
171 static commandList_t commandListAbort [] =
172 {
173   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
174   { "regs",     0,  0, CMDTYPE_FUNCTION,  { monitorAbortRegs   }, "Print abort registers",        "'regs' has no parameters" },
175   { "clear",    0,  0, CMDTYPE_FUNCTION,  { monitorAbortClear  }, "Clear abort registers",        "'clear' has no parameters" },
176   { "dirty",    0,  0, CMDTYPE_FUNCTION,  { monitorAbortDirty  }, "Dirty sigil flag",             "'dirty' has no parameters" },
177   { "undef",    0,  0, CMDTYPE_FUNCTION,  { monitorAbortUndef  }, "Execute undefined instruction","'undef' has no parameters" },
178   { "pabort",   0,  0, CMDTYPE_FUNCTION,  { monitorAbortPabort }, "Cause prefetch abort",         "'pabort' has no parameters" },
179   { "dabort",   0,  0, CMDTYPE_FUNCTION,  { monitorAbortDabort }, "Cause data abort",             "'dabort' has no parameters" },
180   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
181 };
182
183 static commandList_t commandListEE [] =
184 {
185   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
186   { "a",        1,  1, CMDTYPE_FUNCTION,  { monitorEEAddr      }, "Set eeprom r/w address",       "'ee <address>'" },
187   { "r",        0,  1, CMDTYPE_FUNCTION,  { monitorEERead      }, "Read from current address",    "'r <# bytes>'" },
188   { "ra",       1,  2, CMDTYPE_FUNCTION,  { monitorEEReadAddr  }, "Read EEPROM",                  "'ra <address> <# bytes>'" },
189   { "w",        1, 16, CMDTYPE_FUNCTION,  { monitorEEWrite     }, "Write to current address",     "'w <byte> [<byte> [...<byte>]]'" },
190   { "wa",       2, 17, CMDTYPE_FUNCTION,  { monitorEEWriteAddr }, "Write EEPOM",                  "'wa <address> <byte> [<byte> [...<byte>]]'" },
191   { "fa",       3,  3, CMDTYPE_FUNCTION,  { monitorEEFillAddr  }, "Fill EEPOM",                   "'fa <address> <len> <byte>'" },
192   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
193 };
194
195 static commandList_t commandListFIQ [] =
196 {
197   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",                 "'help' has no parameters" },
198   { "on",       0,  0, CMDTYPE_FUNCTION,  { monitorFIQOn       }, "Enable FIQ interrupt",           "'on' has no parameters" },
199   { "off",      0,  0, CMDTYPE_FUNCTION,  { monitorFIQOff      }, "Disable FIQ interrupt",          "'off' has no parameters" },
200   { "count",    0,  0, CMDTYPE_FUNCTION,  { monitorFIQCount    }, "Show number of FIQ interrupts",  "'show' has no parameters" },
201   { "clear",    0,  0, CMDTYPE_FUNCTION,  { monitorFIQClear    }, "Clear FIQ interrupt counter",    "'clear' has no parameters" },
202   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                             NULL },
203 };
204
205 static commandList_t commandListI2C [] =
206 {
207   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",                     "'help' has no parameters" },
208   { "r",        2,  2, CMDTYPE_FUNCTION,  { monitorI2CRead     }, "Read from I2C device",               "'r <address> <# bytes>'" },
209   { "w",        2, 17, CMDTYPE_FUNCTION,  { monitorI2CWrite    }, "Write to I2C device",                "'w <address> <byte> [<byte> [...<byte>]]'" },
210   { "wr",       2, 18, CMDTYPE_FUNCTION,  { monitorI2CWriteRead}, "Write to then read from I2C device", "'wr <address> <byte> [<byte> [...<byte>]] <# bytes to read>'" },
211   { "dump",     0,  0, CMDTYPE_FUNCTION,  { monitorI2CDump     }, "Dump I2C Debug Buffer",              "'dump' has no parameters" },
212   { "errno",    0,  0, CMDTYPE_FUNCTION,  { monitorI2CErrno    }, "Display i2cErrno value",             "'errno' has no parameters" },
213   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                                 NULL },
214 };
215
216 static commandList_t commandListIAP [] =
217 {
218   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",                     "'help' has no parameters" },
219   { "fss",      0,  0, CMDTYPE_FUNCTION,  { monitorIAPFSS      }, "Find safe sector",                   "'fss' has no parameters" },
220   { "stoa",     1,  1, CMDTYPE_FUNCTION,  { monitorIAPSTOA     }, "Convert sector to address for 'md'", "'fss' has no parameters" },
221   { "fill",     2,  2, CMDTYPE_FUNCTION,  { monitorIAPFill     }, "Fill sector with byte",              "'fill <sector> <byte>'" },
222   { "erase",    1,  1, CMDTYPE_FUNCTION,  { monitorIAPErase    }, "Erase sector",                       "'erase <sector>'" },
223   { "blank",    1,  1, CMDTYPE_FUNCTION,  { monitorIAPBlank    }, "Blank check sector",                 "'blank <sector>'" },
224   { "id",       0,  0, CMDTYPE_FUNCTION,  { monitorIAPID       }, "Read part ID",                       "'id' has no parameters" },
225   { "ver",      0,  0, CMDTYPE_FUNCTION,  { monitorIAPVer      }, "Read boot loader version",           "'ver' has no parameters" },
226   { "isp",      0,  0, CMDTYPE_FUNCTION,  { monitorIAPISP      }, "Restart into ISP bootloader",        "'isp' has no parameters" },
227   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                                 NULL },
228 };
229
230 static commandList_t commandListLM75 [] =
231 {
232   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
233   { "init",     0,  0, CMDTYPE_FUNCTION,  { monitorLM75Init    }, "Initialize LM75",              "'init' has no parameters" },
234   { "mode",     1,  1, CMDTYPE_FUNCTION,  { monitorLM75Mode    }, "Set LM75 mode",                "'mode <value>'" },
235   { "addr",     1,  1, CMDTYPE_FUNCTION,  { monitorLM75Addr    }, "Set LM75 address",             "'addr <value>'" },
236   { "reread",   0,  0, CMDTYPE_FUNCTION,  { monitorLM75ReRead  }, "Re-read last register",        "'reread' has no parameters" },
237   { "temp",     0,  0, CMDTYPE_FUNCTION,  { monitorLM75Temp    }, "Read LM75 temperature",        "'temp' has no parameters" },
238   { "config",   0,  1, CMDTYPE_FUNCTION,  { monitorLM75Config  }, "Read part ID",                 "'id' has no parameters" },
239   { "thyst",    0,  1, CMDTYPE_FUNCTION,  { monitorLM75Thyst   }, "Read or set THYST register",   "'thyst [value]'" },
240   { "tos",      0,  1, CMDTYPE_FUNCTION,  { monitorLM75Tos     }, "Read or set TOS register",     "'tos [value]'" },
241   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
242 };
243
244 static commandList_t commandListMem [] =
245 {
246   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
247   { "task",     0,  0, CMDTYPE_FUNCTION,  { monitorMemTask     }, "Show FreeRTOS task memory",    "'task' has no parameters" },
248   { "map",      0,  0, CMDTYPE_FUNCTION,  { monitorMemMap      }, "Show various addresses",       "'map' has no parameters" },
249   { "alloc",    2,  2, CMDTYPE_FUNCTION,  { monitorMemAlloc    }, "Allocate memory",              "'alloc <slot> <size>'" },
250   { "realloc",  2,  2, CMDTYPE_FUNCTION,  { monitorMemRealloc  }, "Reallocate memory",            "'realloc <slot> <size>'" },
251   { "free",     1,  1, CMDTYPE_FUNCTION,  { monitorMemFree     }, "Free memory",                  "'free <slot>'" },
252   { "list",     0,  0, CMDTYPE_FUNCTION,  { monitorMemList     }, "List memory",                  "'list' has no parameters" },
253   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
254 };
255
256 static commandList_t commandListMisc [] =
257 {
258   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
259   { "sizeof",   0,  0, CMDTYPE_FUNCTION,  { monitorMiscSizeof  }, "Sizeof() variable data types", "'sizeof' has no parameters" },
260   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
261 };
262
263 static commandList_t commandListRTC [] =
264 {
265   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
266   { "get",      0,  0, CMDTYPE_FUNCTION,  { monitorRTCGet      }, "Display system date/time",     "'get' has no parameters" },
267   { "set",      1,  2, CMDTYPE_FUNCTION,  { monitorRTCSet      }, "Set system date/time",         "'set <gps|YYYY/MM/DD HH:MM:SS>'" },
268   { "alarm",    0,  2, CMDTYPE_FUNCTION,  { monitorRTCAlarm    }, "Set date/time for alarm",      "'alarm <off|YYYY/MM/DD HH:MM:SS>'" },
269   { "periodic", 0,  1, CMDTYPE_FUNCTION,  { monitorRTCPeriodic }, "Alarm every minute change",    "'periodic <on|off>'" },
270   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
271 };
272
273 static commandList_t commandListSWI [] =
274 {
275   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
276   { "aset",     1,  1, CMDTYPE_FUNCTION,  { monitorSWISetAsm   }, "Set LED2 state (asm)",         "'aset <on|of>'" },
277   { "aon",      0,  0, CMDTYPE_FUNCTION,  { monitorSWIOnAsm    }, "Turn LED2 on (asm)",           "'aon' has no parameters" },
278   { "aoff",     0,  0, CMDTYPE_FUNCTION,  { monitorSWIOffAsm   }, "Turn LED2 off (asm)",          "'aoff' has no parameters" },
279   { "atoggle",  0,  0, CMDTYPE_FUNCTION,  { monitorSWIToggleAsm}, "Toggle LED2 state (asm)",      "'atoggle' has no parameters" },
280   { "cset",     1,  1, CMDTYPE_FUNCTION,  { monitorSWISetC     }, "Set LED2 state (C)",           "'cset <on|off>'" },
281   { "con",      0,  0, CMDTYPE_FUNCTION,  { monitorSWIOnC      }, "Turn LED2 on (C)",             "'con' has no parameters" },
282   { "coff",     0,  0, CMDTYPE_FUNCTION,  { monitorSWIOffC     }, "Turn LED2 off (C)",            "'coff' has no parameters" },
283   { "ctoggle",  0,  0, CMDTYPE_FUNCTION,  { monitorSWIToggleC  }, "Toggle LED2 state (C)",        "'ctoggle' has no parameters" },
284   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
285 };
286
287 static commandList_t commandListWDT [] =
288 {
289   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
290   { "test",     0,  0, CMDTYPE_FUNCTION,  { monitorWDTTest     }, "Test watchdog",                "'test' has no parameters" },
291   { "status",   0,  0, CMDTYPE_FUNCTION,  { monitorWDTStatus   }, "Display RSIR register",        "'status' has no parameters" },
292   { "clear",    0,  0, CMDTYPE_FUNCTION,  { monitorWDTClear    }, "Clear RSIR status",            "'rsir' has no parameters" },
293   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
294 };
295
296 static commandList_t commandList [] =
297 {
298   { "help",     0,  0, CMDTYPE_FUNCTION,  { monitorHelp        }, "This help list",               "'help' has no parameters" },
299   { "init",     0,  0, CMDTYPE_FUNCTION,  { monitorDiskInit    }, "Initialize disk subsystem",    "'init' has no parameters" },
300   { "mount",    0,  0, CMDTYPE_FUNCTION,  { monitorDiskMount   }, "Mount disk",                   "'mount' has no parameters" },
301   { "mkfs",     0,  0, CMDTYPE_FUNCTION,  { monitorFileMkfs    }, "Create a FAT filesystem",      "'mkfs' has no parameters" },
302   { "df",       0,  0, CMDTYPE_FUNCTION,  { monitorFileDf      }, "File system status & info",    "'fd' has no parameters" },
303   { "ls",       0,  1, CMDTYPE_FUNCTION,  { monitorFileLs      }, "Display directory",            "'ls [optional path]'" },
304   { "mkdir",    1,  1, CMDTYPE_FUNCTION,  { monitorFileMkdir   }, "Create directory",             "'mkdir <[path]directory'" },
305   { "rmdir",    1,  1, CMDTYPE_FUNCTION,  { monitorFileRmdir   }, "Delete directory",             "'rmdir <[path]directory>'" },
306   { "rm",       1,  1, CMDTYPE_FUNCTION,  { monitorFileRm      }, "Delete file",                  "'rm <[path]filename>'" },
307   { "mv",       2,  2, CMDTYPE_FUNCTION,  { monitorFileMv      }, "Rename a file or directory",   "'mv <[path]old_filename> <[path]new_filename>'" },
308   { "cp",       1,  2, CMDTYPE_FUNCTION,  { monitorFileCp      }, "Copy a file",                  "'mv <[path]old_filename> <[path]new_filename>'" },
309   { "cpcon",    1,  1, CMDTYPE_FUNCTION,  { monitorFileCpCon   }, "Copy console input to file",   "'cp <[path]filename>' (ctrl-d exits and saves)" },
310   { "chmod",    2,  2, CMDTYPE_FUNCTION,  { monitorFileChmod   }, "Change file mode",             "'chmod <+w|-w> <[path]filename>'" },
311   { "sync",     0,  0, CMDTYPE_FUNCTION,  { monitorFileSync    }, "Sync filesystem",              "'sync' has no parameters" },
312   { "thruput",  1,  1, CMDTYPE_FUNCTION,  { monitorFileThruPut }, "Measure MMC/SD throughput",    "'thruput <normal|noints|high|suspendall>'" },
313   { "gps",      0,  0, CMDTYPE_FUNCTION,  { monitorGPS         }, "Display GPS data",             "'gps' has no parameters" },
314   { "sensors",  0,  0, CMDTYPE_FUNCTION,  { monitorSensors     }, "Display sensor data",          "'sensors' has no parameters" },
315   { "md",       0,  2, CMDTYPE_FUNCTION,  { monitorMd          }, "Display memory",               "'md [address [length]]'" },
316
317   { "abort",    1,  0, CMDTYPE_CMDLIST,   { commandListAbort   }, "Read/clear abort registers",   "'abort help' for help list" },
318   { "ee",       1,  0, CMDTYPE_CMDLIST,   { commandListEE      }, "Read/write I2C EEPROM",        "'ee help' for help list" },
319   { "fiq",      1,  0, CMDTYPE_CMDLIST,   { commandListFIQ     }, "Demonstrate FIQ functions",    "'fiq help' for help list" },
320   { "i2c",      1,  0, CMDTYPE_CMDLIST,   { commandListI2C     }, "Perform I2C commands",         "'i2c help' for help list" },
321   { "iap",      1,  0, CMDTYPE_CMDLIST,   { commandListIAP     }, "Perform IAP commands",         "'iap help' for help list" },
322   { "lm75",     1,  0, CMDTYPE_CMDLIST,   { commandListLM75    }, "Read/set LM75 temp sensor",    "'lm75 help' for help list" },
323   { "mem",      1,  0, CMDTYPE_CMDLIST,   { commandListMem     }, "Various memory functions",     "'mem help' for help list" },
324   { "misc",     1,  0, CMDTYPE_CMDLIST,   { commandListMisc    }, "Miscellaneous stuff",          "'misc help' for help list" },
325   { "rtc",      1,  0, CMDTYPE_CMDLIST,   { commandListRTC     }, "Demonstrate RTC functions",    "'rtc help' for help list" },
326   { "swi",      1,  0, CMDTYPE_CMDLIST,   { commandListSWI     }, "Demonstrate SWI functions",    "'swi help' for help list" },
327   { "wdt",      1,  0, CMDTYPE_CMDLIST,   { commandListWDT     }, "Manipulate watchdog timer",    "'wdt help' for help list" },
328   { "version",  0,  0, CMDTYPE_FUNCTION,  { monitorVersion     }, "Display version information",  "'version' has no parameters" },
329   { NULL,       0,  0, CMDTYPE_FUNCTION,  { NULL               }, NULL,                           NULL },
330 };
331
332 static FATFS fatfs;
333 static FILINFO fileInfo;
334 commandList_t *activeCommandList = NULL;
335
336 //
337 //  External variables
338 //
339 extern unsigned int __abort_dat;
340 extern unsigned long __start_of_text__;
341 extern unsigned long __end_of_text__;
342 extern unsigned long __start_of_startup__;
343 extern unsigned long __end_of_startup__;
344 extern unsigned long __start_of_prog__;
345 extern unsigned long __end_of_prog__;
346 extern unsigned long __start_of_rodata__;
347 extern unsigned long __end_of_rodata__;
348 extern unsigned long __start_of_glue7__;
349 extern unsigned long __end_of_glue7__;
350 extern unsigned long __data_beg__;
351 extern unsigned long __data_end__;
352 extern unsigned long __bss_beg__;
353 extern unsigned long __bss_end__;
354 extern unsigned long __heap_max;
355 extern unsigned long __heap_beg;
356 extern unsigned long __heap_end;
357 extern unsigned long __stack_end__;
358 extern unsigned long __stack_beg_und;
359 extern unsigned long __stack_end_und;
360 extern unsigned long __stack_beg_abt;
361 extern unsigned long __stack_end_abt;
362 extern unsigned long __stack_beg_fiq;
363 extern unsigned long __stack_end_fiq;
364 extern unsigned long __stack_beg_irq;
365 extern unsigned long __stack_end_irq;
366 extern unsigned long __stack_beg_svc;
367 extern unsigned long __stack_end_svc;
368 extern unsigned long __stack_beg_sys;
369 extern unsigned long __stack_end_sys;
370
371
372 //
373 //  Recursion is our friend...  fileInfo is global to avoid eating stack space
374 //
375 static FRESULT scan_files_ex (char *path, int *total_size, int *total_files, int *total_dirs)
376 {
377   DIR dirs;
378   FRESULT res;
379
380   if ((res = f_opendir (&dirs, path)) == FR_OK) 
381   {
382     int i = strlen (path);
383
384     while (((res = f_readdir (&dirs, &fileInfo)) == FR_OK) && fileInfo.fname [0]) 
385     {
386       if (fileInfo.fattrib & AM_DIR) 
387       {
388         *total_dirs += 1;
389         *(path + i) = '/'; 
390         strcpy (path + i + 1, &fileInfo.fname [0]);
391         res = scan_files_ex (path, total_size, total_files, total_dirs);
392         *(path + i) = '\0';
393
394         if (res != FR_OK) 
395           return res;
396       } 
397       else 
398       {
399         *total_files += 1;
400         *total_size += fileInfo.fsize;
401       }
402     }
403   }
404
405   return res;
406 }
407
408 static FRESULT scan_files (char *path, int *total_size, int *total_files, int *total_dirs)
409 {
410   *total_size = 0;
411   *total_files = 0;
412   *total_dirs = 0;
413
414   return scan_files_ex (path, total_size, total_files, total_dirs);
415 }
416
417 //
418 //  These two really ought to be in the FatFS code
419 //
420 U32 get_fattime ()
421 {
422   U32 tmr;
423   time_t now;
424   struct tm tm;
425
426   now = time (NULL);
427   localtime_r (&now, &tm);
428
429   tmr = 0
430     | ((tm.tm_year - 80) << 25)
431     | ((tm.tm_mon + 1)   << 21)
432     | (tm.tm_mday        << 16)
433     | (tm.tm_hour        << 11)
434     | (tm.tm_min         << 5)
435     | (tm.tm_sec         >> 1);
436
437   return tmr;
438 }
439
440 //
441 //  Functions newlib doesn't know about (but should)
442 //
443 void _sync  (void);
444 int  _mkdir (const char *path, mode_t mode);
445 int  _chmod (const char *path, mode_t mode);
446
447 void sync  (void);
448 int  chmod (const char *path, mode_t mode);
449
450 void sync (void)
451 {
452   _sync ();
453 }
454
455 int mkdir (const char *path, mode_t mode)
456 {
457   return _mkdir (path, mode);
458 }
459
460 int chmod (const char *path, mode_t mode)
461 {
462   return _chmod (path, mode);
463 }
464
465 //
466 //
467 //
468 static int getNumber (char *s, unsigned int *result)
469 {
470   unsigned int value;
471   unsigned int mustBeHex = FALSE;
472   int sgn = 1;
473   const unsigned char hexToDec [] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15};
474
475   if (!s)
476     return 0;
477
478   if ((strlen (s) > 2) && (!strncmp (s, "0x", 2) || !strncmp (s, "0X", 2)))
479   {
480     mustBeHex = TRUE;
481     s += 2;
482   }
483
484   if (!mustBeHex && *s && (*s == '-'))
485   {
486     sgn = -1;
487     s++;
488   }
489
490   for (value = 0; *s; s++)
491   {
492     if (mustBeHex && isxdigit (*s))
493       value = (value << 4) | hexToDec [toupper (*s) - '0'];
494     else if (isdigit (*s))
495       value = (value * 10) + (*s - '0');
496     else
497     {
498       printf ("Malformed number.  Must be decimal number, or hex value preceeded by '0x'\n");
499       return 0;
500     }
501   }
502
503   if (!mustBeHex)
504     value *= sgn;
505
506   *result = value;
507
508   return 1;
509 }
510
511 static int monitorDumpMemory (unsigned int displayAddress, unsigned int address, int length)
512 {
513   unsigned char *buffer;
514   int i;
515
516   if (!length)
517   {
518     printf ("Error: monitorDumpMemory() passed 0 for length\n");
519     return address;
520   }
521
522   for (buffer = (unsigned char *) address, i = 0; i < length; i += 16)
523   {
524     unsigned int l;
525     unsigned int j;
526
527     if (i)
528       printf ("\n");
529
530     printf ("%08x: ", displayAddress + i);
531
532     if ((length - i) < 16)
533       l = length & 15;
534     else
535       l = 16;
536
537     for (j = 0; j < 16; j++)
538     {
539       if (j < l)
540         printf ("%02x ", buffer [i+j]);
541       else
542         printf ("   ");
543     }
544
545     printf ("  ");
546
547     for (j = 0; j < l; j++)
548     {
549       unsigned char c = buffer [i+j];
550
551       if (c < 32 || c > 127)
552         c = '.';
553
554       printf ("%c", c);
555     }
556   }
557
558   printf ("\n");
559
560   address += length;
561
562   return address;
563 }
564
565 //
566 //
567 //
568 static int monitorHelp (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
569 {
570   unsigned int i;
571   int t;
572   int longestCmd;
573   portCHAR spaces [32];
574
575   memset (spaces, ' ', sizeof (spaces));
576
577   for (longestCmd = 0, i = 0; activeCommandList [i].command; i++)
578     if ((t = strlen (activeCommandList [i].command)) > longestCmd)
579       longestCmd = t;
580
581   spaces [longestCmd] = '\0';
582
583   for (i = 0; activeCommandList [i].command; i++)
584   {
585     const commandList_t *cl = &activeCommandList [i];
586
587     printf ("%s%s -- %s\n", cl->command, &spaces [strlen (cl->command)], cl->description);
588   }
589
590   printf ("\nUse '<command> ?' for details on parameters to command\n");
591
592   return 0;
593 }
594
595 //
596 //
597 //
598 static int monitorDiskInit (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
599 {
600   printf ("RRC=%d\n", diskInitialize (0));
601
602   return 0;
603 }
604
605 static int monitorDiskMount (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
606 {
607   f_printerror (f_mount (0, &fatfs));
608
609   return 0;
610 }
611
612 static int monitorFileMkfs (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
613 {
614   f_printerror (f_mkfs (0, 0, 64));
615
616   return 0;
617 }
618
619 static int monitorFileDf (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
620 {
621   U32 p2;
622   FATFS *fs;
623   char buffer [100];
624   FRESULT res;
625   int acc_size;
626   int acc_files;
627   int acc_dirs;
628
629   if ((res = f_getfree ("", (U32 *) &p2, &fs)))
630   { 
631     f_printerror (res); 
632     return 0;
633   }
634
635   printf ("FAT type = %u\nBytes/Cluster = %u\nNumber of FATs = %u\n"
636       "Root DIR entries = %u\nSectors/FAT = %u\nNumber of clusters = %u\n"
637       "FAT start (lba) = %u\nDIR start (lba,clustor) = %u\nData start (lba) = %u\n",
638       fs->fs_type, fs->sects_clust * 512, fs->n_fats,
639       fs->n_rootdir, fs->sects_fat, fs->max_clust - 2,
640       fs->fatbase, fs->dirbase, fs->database
641       );
642
643   acc_size = acc_files = acc_dirs = 0;
644
645   buffer [0] = '\0';
646
647   if ((res = scan_files (buffer, &acc_size, &acc_files, &acc_dirs)))
648   { 
649     f_printerror (res); 
650     return 0;
651   }
652
653   printf ("\n%u files, %u bytes.\n%u folders.\n"
654       "%u bytes total disk space.\n%u bytes available\n",
655       acc_files, acc_size, acc_dirs,
656       (fs->max_clust - 2) * fs->sects_clust * 512, p2 * fs->sects_clust * 512
657       );
658
659   return 0;
660 }
661
662 static int monitorFileLs (int argc, portCHAR **argv)
663 {
664   DIR dir;
665   FRESULT res;
666   U32 size;
667   U16 files;
668   U16 dirs;
669   FATFS *fs;
670   char *path;
671
672   path = argc ? argv [0] : "";
673
674   if ((res = f_opendir (&dir, path)))
675   { 
676     f_printerror (res); 
677     return 0;
678   }
679
680   for (size = files = dirs = 0;;)
681   {
682     if (((res = f_readdir (&dir, &fileInfo)) != FR_OK) || !fileInfo.fname [0]) 
683       break;
684
685     if (fileInfo.fattrib & AM_DIR) 
686       dirs++;
687     else 
688     {
689       files++; 
690       size += fileInfo.fsize;
691     }
692
693     printf ("\n%c%c%c%c%c %u/%02u/%02u %02u:%02u %9u  %s",
694         (fileInfo.fattrib & AM_DIR) ? 'D' : '-',
695         (fileInfo.fattrib & AM_RDO) ? 'R' : '-',
696         (fileInfo.fattrib & AM_HID) ? 'H' : '-',
697         (fileInfo.fattrib & AM_SYS) ? 'S' : '-',
698         (fileInfo.fattrib & AM_ARC) ? 'A' : '-',
699         (fileInfo.fdate >> 9) + 1980, (fileInfo.fdate >> 5) & 15, fileInfo.fdate & 31,
700         (fileInfo.ftime >> 11), (fileInfo.ftime >> 5) & 63,
701         fileInfo.fsize, &(fileInfo.fname [0]));
702   }
703
704   printf ("\n%4u File(s),%10u bytes\n%4u Dir(s)", files, size, dirs);
705
706   if (f_getfree (path, (U32 *) &size, &fs) == FR_OK)
707     printf (", %10uK bytes free", size * fs->sects_clust / 2);
708
709   printf ("\n");
710
711   return 0;
712 }
713
714 static int monitorFileMkdir (int argc __attribute__ ((unused)), portCHAR **argv)
715 {
716   f_printerror (f_mkdir (argv [0]));
717
718   return 0;
719 }
720
721 static int monitorFileRmCommon (char *path, int mode)
722 {
723   FRESULT f;
724
725   if ((f = f_stat (path, &fileInfo)) != FR_OK)
726   {
727     f_printerror (f);
728     return 0;
729   }
730
731   if (mode == AM_DIR)
732   {
733     if (!(fileInfo.fattrib & AM_DIR))
734       printf ("Not a directory\n");
735     else
736       f_printerror (f_unlink (path));
737   }
738   else
739   {
740     if (fileInfo.fattrib & AM_DIR)
741       printf ("Not a regular file\n");
742     else
743       f_printerror (f_unlink (path));
744   }
745
746   return 0;
747 }
748
749 static int monitorFileRmdir (int argc __attribute__ ((unused)), portCHAR **argv)
750 {
751   return monitorFileRmCommon (argv [0], AM_DIR);
752 }
753
754 static int monitorFileRm (int argc __attribute__ ((unused)), portCHAR **argv)
755 {
756   return monitorFileRmCommon (argv [0], 0);
757 }
758
759 static int monitorFileMv (int argc __attribute__ ((unused)), portCHAR **argv)
760 {
761   if (rename (argv [0], argv [1]) == -1)
762     printf ("rename failed, errno=%d/%s\n", errno, strerror (errno));
763
764   return 0;
765 }
766
767 static int monitorFileCp (int argc __attribute__ ((unused)), portCHAR **argv)
768 {
769   int fdIn;
770   int fdOut;
771   int l;
772   char buffer [128];
773
774   if ((fdIn = open (argv [0], O_RDONLY)) == -1)
775   {
776     printf ("Cannot open input file \"%s\", errno=%d/%s\n", argv [0], errno, strerror (errno));
777     return 0;
778   }
779
780   if (argc == 1)
781   {
782     fdOut = fileno (stdout);
783     fflush (stdout);
784   }
785   else if ((fdOut = open (argv [1], O_CREAT | O_TRUNC | O_WRONLY)) == -1)
786   {
787     printf ("Cannot open output file \"%s\", errno=%d/%s\n", argv [1], errno, strerror (errno));
788     close (fdIn);
789     return 0;
790   }
791
792   while ((l = read (fdIn, buffer, sizeof (buffer))))
793   {
794     if (write (fdOut, buffer, l) != l)
795     {
796       printf ("write() returned error %d/%s (l=%d)\n", errno, strerror (errno), l);
797       break;
798     }
799   }
800
801   close (fdIn);
802
803   if (fdOut != fileno (stdout))
804     close (fdOut);
805
806   return 0;
807 }
808
809 static int monitorFileSync (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
810 {
811   sync ();
812
813   return 0;
814 }
815
816 int monitorTimevalSubtract (struct timeval *result, struct timeval *x, struct timeval *y);
817 int monitorTimevalSubtract (struct timeval *result, struct timeval *x, struct timeval *y)
818 {
819   if (x->tv_usec < y->tv_usec)
820   {
821     int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
822     y->tv_usec -= 1000000 * nsec;
823     y->tv_sec += nsec;
824   }
825
826   if (x->tv_usec - y->tv_usec > 1000000)
827   {
828     int nsec = (x->tv_usec - y->tv_usec) / 1000000;
829     y->tv_usec += 1000000 * nsec;
830     y->tv_sec -= nsec;
831   }
832
833   result->tv_sec = x->tv_sec - y->tv_sec;
834   result->tv_usec = x->tv_usec - y->tv_usec;
835
836   return x->tv_sec < y->tv_sec;
837 }
838
839 typedef enum
840 {
841   MODE_NORMAL = 0,
842   MODE_NOINTS,
843   MODE_SUSPENDALL,
844   MODE_HIGH
845 }
846 mode_e;
847
848 static int monitorFileThruPut (int argc __attribute__ ((unused)), portCHAR **argv)
849 {
850   unsigned int i;
851   mode_e mode;
852   int fileSizes [] = { 1*1024, 8*1024, 16*1024, 64*1024, 128*1024, 512*1024, 1024*1024, 2048*1024 };
853
854   if (!strcmp (argv [0], "normal"))
855     mode = MODE_NORMAL;
856   else if (!strcmp (argv [0], "noints"))
857     mode = MODE_NOINTS;
858   else if (!strcmp (argv [0], "suspendall"))
859     mode = MODE_SUSPENDALL;
860   else if (!strcmp (argv [0], "high"))
861     mode = MODE_HIGH;
862   else
863   {
864     printf ("arguments must be 'normal', 'noints', 'suspendall', or 'high'\n");
865     return 0;
866   }
867
868   printf ("%lu tests, with ", arrsizeof (fileSizes));
869
870   switch (mode)
871   {
872     case MODE_NORMAL     : printf ("interrupts enabled, no tasks suspended, default priority\n\n"); break;
873     case MODE_NOINTS     : printf ("interrupts disabled (no tasking)\n\n"); break;
874     case MODE_SUSPENDALL : printf ("interrupts enabled, all tasks suspended\n\n"); break;
875     case MODE_HIGH       : printf ("interrupts enabled, this task promoted to highest priority\n\n");
876   }
877
878   for (i = 0; i < arrsizeof (fileSizes); i++)
879   {
880     int j;
881
882     for (j = 0; j < 2; j++)
883     {
884       int fd;
885       int k;
886       char buffer [512];
887       struct timeval tv_start;
888       struct timeval tv_end;
889       struct timeval tv_diff;
890       unsigned long ticks10ms;
891       unsigned portBASE_TYPE taskPriority = 0;
892
893       if ((fd = open ("testfile.bin", !j ? (O_TRUNC | O_CREAT | O_WRONLY) : (O_RDONLY))) == -1)
894       {
895         printf ("Cannot open \"testfile.bin\", errno=%d/%s\n", errno, strerror (errno));
896         return 0;
897       }
898
899       if (!j)
900         memset (buffer, 0xe5, sizeof (buffer));
901
902
903       switch (mode)
904       {
905         case MODE_NORMAL     : break;
906         case MODE_NOINTS     : portENTER_CRITICAL (); break;
907         case MODE_SUSPENDALL : vTaskSuspendAll (); break;
908         case MODE_HIGH       : taskPriority = uxTaskPriorityGet (NULL); vTaskPrioritySet (NULL, (configMAX_PRIORITIES - 1)); break;
909       }
910
911       gettimeofday (&tv_start, NULL);
912
913       if (!j)
914       {
915         for (k = fileSizes [i]; k > 0; k -= sizeof (buffer))
916         {
917           if (write (fd, buffer, sizeof (buffer)) != sizeof (buffer))
918           {
919             printf ("write() failed, errno=%d/%s\n", errno, strerror (errno));
920             close (fd);
921             return 0;
922           }
923         }
924       }
925       else
926       {
927         for (k = fileSizes [i]; k > 0; k -= sizeof (buffer))
928         {
929           if (read (fd, buffer, sizeof (buffer)) != sizeof (buffer))
930           {
931             printf ("read() failed, errno=%d/%s\n", errno, strerror (errno));
932             close (fd);
933             return 0;
934           }
935         }
936       }
937
938       gettimeofday (&tv_end, NULL);
939
940       switch (mode)
941       {
942         case MODE_NORMAL     : break;
943         case MODE_NOINTS     : portEXIT_CRITICAL (); break;
944         case MODE_SUSPENDALL : xTaskResumeAll (); break;
945         case MODE_HIGH       : vTaskPrioritySet (NULL, taskPriority); break;
946       }
947
948       if (close (fd) == -1)
949       {
950         printf ("close() failed, errno=%d/%s\n", errno, strerror (errno));
951         return 0;
952       }
953
954       {
955         struct timeval tempStart = tv_start;
956         struct timeval tempEnd = tv_end;
957
958         monitorTimevalSubtract (&tv_diff, &tv_end, &tv_start);
959         ticks10ms = (tv_diff.tv_sec * 100) + (tv_diff.tv_usec / 10000);
960
961         printf ("%5s: %9u bytes, %7lu milliseconds (%4ld seconds), %7lu bytes/sec\n", 
962             !j ? "Write" : "Read", 
963             fileSizes [i], 
964             ticks10ms * 10,
965             ticks10ms / 100,
966             (fileSizes [i] * 100) / ticks10ms);
967
968         if (ticks10ms > 10000)
969         {
970           printf ("tv_start = %ld, %ld\n", tempStart.tv_sec, tempStart.tv_usec);
971           printf ("tv_end   = %ld, %ld\n", tempEnd.tv_sec, tempEnd.tv_usec);
972           printf ("tv_diff  = %ld, %ld\n", tv_diff.tv_sec, tv_diff.tv_usec);
973         }
974       }
975
976       if (j && unlink ("testfile.bin") == -1)
977       {
978         printf ("unlink() failed, errno=%d/%s\n", errno, strerror (errno));
979         return 0;
980       }
981     }
982   }
983
984   printf ("\nDone\n");
985
986   return 0;
987 }
988
989 static int monitorFileCpCon (int argc __attribute__ ((unused)), portCHAR **argv)
990 {
991   int fdOut;
992   char c;
993
994   if ((fdOut = open (argv [0], O_CREAT | O_TRUNC | O_WRONLY)) == -1)
995   {
996     printf ("Cannot open output file \"%s\", errno=%d/%s\n", argv [0], errno, strerror (errno));
997     return 0;
998   }
999
1000   while (read (fileno (stdin), &c, sizeof (c)))
1001   {
1002     if (c == 0x04)
1003       break;
1004
1005     if (c == '\r')
1006       c = '\n';
1007
1008     if (write (fdOut, &c, sizeof (c)) != sizeof (c))
1009     {
1010       printf ("write() returned error %d/%s\n", errno, strerror (errno));
1011       break;
1012     }
1013
1014     printf ("%c", c);
1015     fflush (stdout);
1016   }
1017
1018   if (close (fdOut) == -1)
1019     printf ("close() returned error %d/%s\n", errno, strerror (errno));
1020
1021   return 0;
1022 }
1023
1024 static int monitorFileChmod (int argc __attribute__ ((unused)), portCHAR **argv)
1025 {
1026   mode_t mode;
1027
1028   if (!strcmp (argv [0], "-w"))
1029     mode = 0;
1030   else if (!strcmp (argv [0], "+w"))
1031     mode = S_IWUSR;
1032   else
1033   {
1034     printf ("mode must be +w (writable) or -w (not writable)\n");
1035     return 0;
1036   }
1037
1038   if (chmod (argv [1], mode) == -1)
1039     printf ("chmod() failed, errno=%d/%s\n", errno, strerror (errno));
1040
1041   return 0;
1042 }
1043
1044 //
1045 //
1046 //
1047 static int monitorGPS (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1048 {
1049   gpsData_t gpsData;
1050
1051   if (gpsCopyData (&gpsData))
1052   {
1053     printf ("Valid ...... : %d\n", gpsData.valid);
1054     printf ("Date ....... : %04d/%02d/%02d\n", gpsData.utcYear, gpsData.utcMonth, gpsData.utcDay);
1055     printf ("Time ....... : %02d:%02d:%02d\n", gpsData.utcHours, gpsData.utcMinutes, gpsData.utcSeconds);
1056     printf ("Speed ...... : %f\n", gpsData.groundSpeed);
1057     printf ("Heading .... : %f\n", gpsData.trueCourse);
1058     printf ("Altitude ... : %f\n", gpsData.height);
1059     printf ("Latitude ... : %f\n", gpsData.latitude);
1060     printf ("Longitude .. : %f\n", gpsData.longitude);
1061     printf ("Restarts ... : %d\n", gpsData.restarts);
1062     printf ("Sizeof () .. : %ld\n", sizeof (gpsData));
1063   }
1064   else
1065     printf ("Unable to get GPS data\n");
1066
1067   return 0;
1068 }
1069
1070 //
1071 //
1072 //
1073 static int monitorSensors (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1074 {
1075   sensorData_t sensorData;
1076
1077   if (sensorsCopyData (&sensorData))
1078   {
1079     printf ("Sensor count .. : %d\n", sensorData.sensorCount);
1080     printf ("ADC changes ... : %d\n", sensorData.adcChanges);
1081   }
1082   else
1083     printf ("Unable to get sensor data\n");
1084
1085   return 0;
1086 }
1087
1088 static int monitorMd (int argc, portCHAR **argv)
1089 {
1090   static unsigned int address = 0x00000000;
1091   unsigned int length = 256;
1092
1093   if ((argc >= 1))
1094   {
1095     if (!getNumber (argv [0], &address))
1096       return 0;
1097
1098     if (argc == 2)
1099       if (!getNumber (argv [1], &length))
1100         return 0;
1101   }
1102
1103   address = monitorDumpMemory (address, address, length);
1104
1105   return 0;
1106 }
1107
1108 //
1109 //
1110 //
1111 static int monitorAbortRegs (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1112 {
1113   abortDat_t *ad = (abortDat_t *) &__abort_dat;
1114
1115   printf ("contents=%s, sigil=0x%08x, count=%d\n", (ad->sigil == 0xdeadc0de) ? "probable" : "invalid", ad->sigil, ad->count);
1116   printf ("abort type=%s\n", (ad->type == 0) ? "undefined instruction" : (ad->type == 1) ? "prefetch abort" : (ad->type == 2) ? "data abort" : "unknown");
1117   printf ("pc=0x%08x, opcode=0x%08x\n", ad->pc, ad->opcode);
1118   printf ("cpsr=0x%08x, sp=0x%08x, lr=0x%08x\n", ad->cpsr, ad->sp, ad->lr);
1119   printf ("r0=0x%08x, r1=0x%08x, r2=0x%08x, r3=0x%08x\n", ad->r0, ad->r1, ad->r2, ad->r3);
1120   printf ("r4=0x%08x, r5=0x%08x, r6=0x%08x, r7=0x%08x\n", ad->r4, ad->r5, ad->r6, ad->r7);
1121   printf ("r8=0x%08x, r9=0x%08x, r10=0x%08x, r11=0x%08x\n", ad->r8, ad->r9, ad->r10, ad->r11);
1122   printf ("r12=0x%08x\n", ad->r12);
1123   printf ("\n");
1124
1125   printf ("sp[0]=0x%08x, sp[1]=0x%08x, sp[2]=0x%08x, sp[3]=0x%08x\n", ad->stack [0], ad->stack [1], ad->stack [2], ad->stack [3]);
1126   printf ("sp[4]=0x%08x, sp[5]=0x%08x, sp[6]=0x%08x, sp[7]=0x%08x\n", ad->stack [4], ad->stack [5], ad->stack [6], ad->stack [7]);
1127
1128   return 0;
1129 }
1130
1131 static int monitorAbortClear (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1132 {
1133   abortDat_t *ad = (abortDat_t *) &__abort_dat;
1134
1135   memset (ad, 0, sizeof (* ad));
1136
1137   return 0;
1138 }
1139
1140 static int monitorAbortDirty (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1141 {
1142   abortDat_t *ad = (abortDat_t *) &__abort_dat;
1143
1144   ad->sigil = 0;
1145
1146   return 0;
1147 }
1148
1149 static int monitorAbortUndef (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1150 {
1151   asm volatile (" .word 0x06000010" : /* no output */ : /* no inputs */ );
1152
1153   return 0;
1154 }
1155
1156 static int monitorAbortPabort (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1157 {
1158   asm volatile (" ldr r0, =0x00080000" : /* no output */ : /* no inputs */ );
1159   asm volatile (" mov pc, r0" : /* no output */ : /* no inputs */ );
1160
1161   return 0;
1162 }
1163
1164 static int monitorAbortDabort (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1165 {
1166   unsigned char c;
1167   volatile unsigned char *ptr = (unsigned char *) 0x40008000;
1168
1169   c = *ptr;
1170
1171   return 0;
1172 }
1173
1174 //
1175 //
1176 //
1177 static int monitorEEAddr (int argc __attribute__ ((unused)), portCHAR **argv)
1178 {
1179   unsigned int address;
1180
1181   if (!getNumber (argv [0], &address))
1182     return 0;
1183
1184   if (eepromSetAddress (address))
1185   {
1186     printf ("Error: address out of range\n");
1187     eepromSetAddress (0);
1188   }
1189
1190   return 0;
1191 }
1192
1193 static int monitorEERead (int argc, portCHAR **argv)
1194 {
1195   unsigned int address;
1196   unsigned int length = 256;
1197   unsigned char buffer [64];
1198   unsigned int i;
1199
1200   if (argc && !getNumber (argv [0], &length))
1201     return 0;
1202
1203   for (address = eepromGetAddress(), i = 0; i < length; i += sizeof (buffer), address = (address + sizeof (buffer)) % EEPROM_SIZE)
1204   {
1205     unsigned int l;
1206
1207     if (!(l = i % sizeof (buffer)))
1208       l = MIN (length, sizeof (buffer));
1209
1210     if (eepromRead (buffer, l))
1211     {
1212       printf ("eepromRead() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1213       return 0;
1214     }
1215
1216     monitorDumpMemory (address, (unsigned int) buffer, l);
1217   }
1218
1219   return 0;
1220 }
1221
1222 static int monitorEEReadAddr (int argc, portCHAR **argv)
1223 {
1224   unsigned int address;
1225   
1226   if (!getNumber (argv [0], &address))
1227     return 0;
1228
1229   if (eepromSetAddress (address))
1230   {
1231     printf ("Error: address out of range\n");
1232     return 0;
1233   }
1234
1235   return monitorEERead (--argc, ++argv);
1236 }
1237
1238 static int monitorEEWriteCommon (int argc, portCHAR **argv, unsigned char *buffer, int bufferLength)
1239 {
1240   int i;
1241
1242   for (i = 0; i < argc; i++)
1243   {
1244     unsigned int n;
1245
1246     if (i >= bufferLength)
1247     {
1248       printf ("Error: buffer too small for number arguments\n");
1249       return -1;
1250     }
1251
1252     if (!getNumber (argv [i], &n))
1253       return 0;
1254
1255     if (n > 255)
1256     {
1257       printf ("Error: data must be 0x00..0xff (0..255)\n");
1258       return -1;
1259     }
1260
1261     buffer [i] = n;
1262   }
1263
1264   return 0;
1265 }
1266
1267 //
1268 //  Note the two reserved bytes at the beginning of the buffer.  These are
1269 //  reserved for the address we're writing to in the EEPROM.  They're populated
1270 //  by the eepromWrite() routine.  This feel hackish, but unlike the read
1271 //  routines, we can't send the address, then a repeated start bit to switch to
1272 //  write.
1273 //
1274 static int monitorEEWrite (int argc, portCHAR **argv)
1275 {
1276   unsigned char buffer [18];
1277
1278   if (monitorEEWriteCommon (argc, argv, &buffer [2], sizeof (buffer) - 2))
1279     return 0;
1280
1281   if (eepromWrite (buffer, argc))
1282     printf ("eepromWrite() returned %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1283
1284   return 0;
1285 }
1286
1287 static int monitorEEWriteAddr (int argc, portCHAR **argv)
1288 {
1289   unsigned int address;
1290
1291   if (!getNumber (argv [0], &address))
1292     return 0;
1293
1294   if (eepromSetAddress (address))
1295   {
1296     printf ("Error: address out of range\n");
1297     return 0;
1298   }
1299
1300   return monitorEEWrite (--argc, ++argv);
1301 }
1302
1303 static int monitorEEFillAddr (int argc __attribute__ ((unused)), portCHAR **argv)
1304 {
1305   unsigned int address;
1306   unsigned int length;
1307   unsigned int fillChar;
1308
1309   if (!getNumber (argv [0], &address) || !getNumber (argv [1], &length) || !getNumber (argv [2], &fillChar))
1310     return 0;
1311
1312   if (fillChar > 255)
1313     printf ("Error: fill value must be 0x00..0xff (0..255)\n");
1314   else if (eepromFillAddress (address, length, fillChar))
1315     printf ("eepromFillAddress() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1316
1317   return 0;
1318 }
1319
1320 //
1321 //
1322 //
1323 static int monitorFIQOn (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1324 {
1325   printf ("FIQ interrupts enabled, previous state was %s\n", fiqEnable () ? "enabled" : "disabled");
1326
1327   return 0;
1328 }
1329
1330 static int monitorFIQOff (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1331 {
1332   printf ("FIQ interrupts disabled, previous state was %s\n", fiqDisable () ? "enabled" : "disabled");
1333
1334   return 0;
1335 }
1336
1337 static int monitorFIQCount (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1338 {
1339   printf ("FIQ counter = %u\n", fiqGetCount ());
1340
1341   return 0;
1342 }
1343
1344 static int monitorFIQClear (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1345 {
1346   fiqClearCount ();
1347
1348   return 0;
1349 }
1350
1351 //
1352 //
1353 //
1354 int monitorI2CRead (int argc __attribute__ ((unused)), portCHAR **argv)
1355 {
1356   unsigned int address;
1357   unsigned int numBytes;
1358   unsigned char buffer [16];
1359   int r;
1360
1361   if (!getNumber (argv [0], &address))
1362     return 0;
1363   if (!getNumber (argv [1], &numBytes))
1364     return 0;
1365
1366   if (address > 255)
1367   {
1368     printf ("Error: address must be 0x00..0xff (0..255)\n");
1369     return 0;
1370   }
1371
1372   if ((numBytes < 1) || (numBytes > sizeof (buffer)))
1373   {
1374     printf ("Error: number of bytes must be 1..%ld\n", sizeof (buffer));
1375     return 0;
1376   }
1377
1378   r = i2cReadBuffer (address, buffer, numBytes);
1379
1380   printf ("i2cReadBuffer() returned %d/%s (%s)\n\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()), r ? "error" : "no error");
1381
1382   monitorDumpMemory (0, (unsigned int) buffer, (int) sizeof (buffer));
1383
1384   return 0;
1385 }
1386
1387 int monitorI2CWrite (int argc, portCHAR **argv)
1388 {
1389   unsigned int address;
1390   unsigned char buffer [16];
1391   int i;
1392
1393   if (!getNumber (argv [0], &address))
1394     return 0;
1395
1396   if (address > 255)
1397   {
1398     printf ("Error: address must be 0x00..0xff (0..255)\n");
1399     return 0;
1400   }
1401
1402   for (i = 0; i < argc - 1; i++)
1403   {
1404     unsigned int n;
1405
1406     if (!getNumber (argv [i + 1], &n))
1407       return 0;
1408
1409     if (n > 255)
1410     {
1411       printf ("Error: data must be 0x00..0xff (0..255)\n");
1412       return 0;
1413     }
1414
1415     buffer [i] = n;
1416   }
1417
1418   i = i2cWriteBuffer (address, buffer, argc - 1);
1419
1420   printf ("i2cWriteBuffer() returned %d/%s (%s)\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()), i ? "error" : "no error");
1421
1422   return 0;
1423 }
1424
1425 int monitorI2CWriteRead (int argc, portCHAR **argv)
1426 {
1427   unsigned int address;
1428   unsigned int bytesToWrite;
1429   unsigned int bytesToRead;
1430   unsigned char buffer [16];
1431   unsigned int i;
1432
1433   if (!getNumber (argv [0], &address))
1434     return 0;
1435
1436   if (address > 255)
1437   {
1438     printf ("Error: address must be 0x00..0xff (0..255)\n");
1439     return 0;
1440   }
1441
1442   for (bytesToWrite = argc - 2, i = 0; i < bytesToWrite; i++)
1443   {
1444     unsigned int n;
1445
1446     if (!getNumber (argv [i + 1], &n))
1447       return 0;
1448
1449     if (n > 255)
1450     {
1451       printf ("Error: data must be 0x00..0xff (0..255)\n");
1452       return 0;
1453     }
1454
1455     buffer [i] = n;
1456   }
1457
1458   if (!getNumber (argv [argc - 1], &bytesToRead))
1459     return 0;
1460
1461   if ((bytesToRead < 1) || (bytesToRead > sizeof (buffer)))
1462   {
1463     printf ("Error: number of bytes must be 1..%ld\n", sizeof (buffer));
1464     return 0;
1465   }
1466
1467   i2cWriteReadBuffer (address, buffer, bytesToWrite, bytesToRead);
1468
1469   printf ("i2cWriteReadBuffer() returned %d/%s\n\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1470
1471   monitorDumpMemory (0, (unsigned int) buffer, (int) sizeof (buffer));
1472
1473   return 0;
1474 }
1475
1476 int monitorI2CDump (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1477 {
1478   i2cDump ();
1479
1480   return 0;
1481 }
1482
1483 int monitorI2CErrno (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1484 {
1485   printf ("i2cErrno=%d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1486
1487   return 0;
1488 }
1489
1490 //
1491 //  Note that although the iapXXX calls can deal with multiple sectors, we only ever
1492 //  deal with one at a time.  This simplifies the user interface.
1493 //
1494 static int monitorIAPFSS (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1495 {
1496   int ss;
1497
1498   if ((ss = iapFindSafeSector ()) == -1)
1499     printf ("Can't find a safe sector!  All of flash in use?\n");
1500   else
1501     printf ("Sector number %d is safe for IAP operations (won't overwrite any code)\n", ss);
1502
1503   return 0;
1504 }
1505
1506 static int monitorIAPSTOA (int argc __attribute__ ((unused)), portCHAR **argv)
1507 {
1508   unsigned int sector;
1509   unsigned long address;
1510   int sectorSize;
1511
1512   if (!getNumber (argv [0], &sector))
1513     return 0;
1514
1515   if (iapSectorToAddress (sector, &address, &sectorSize) == -1)
1516     printf ("Sector number out of range\n");
1517   else
1518     printf ("Sector %d occupies address 0x%08lx for 0x%04x bytes\n", sector, address, sectorSize);
1519
1520   return 0;
1521 }
1522
1523 static int monitorIAPFill (int argc __attribute__ ((unused)), portCHAR **argv)
1524 {
1525   unsigned int sector;
1526   unsigned int byte;
1527
1528   if (!getNumber (argv [0], &sector))
1529     return 0;
1530   if (!getNumber (argv [1], &byte))
1531     return 0;
1532
1533   if (!iapIsSafeSector ((int) sector))
1534   {
1535     printf ("Sector number out of range or not in safe region\n");
1536     return 0;
1537   }
1538
1539   if (byte > 255)
1540   {
1541     printf ("Fill character must be 0x00..0xff (0..255)\n");
1542     return 0;
1543   }
1544
1545   if (iapFillSectors (sector, sector, byte) == -1)
1546     printf ("iapFillSectors returned error %d/%s\n", iapGetErrno (), iapStrerror (iapGetErrno ()));
1547   else
1548     printf ("Sector %d filled with 0x%02x\n", sector, byte);
1549
1550   return 0;
1551 }
1552
1553 static int monitorIAPErase (int argc __attribute__ ((unused)), portCHAR **argv)
1554 {
1555   unsigned int sector;
1556
1557   if (!getNumber (argv [0], &sector))
1558     return 0;
1559
1560   if (!iapIsSafeSector ((int) sector))
1561   {
1562     printf ("Sector number out of range or not in safe region\n");
1563     return 0;
1564   }
1565
1566   if (iapEraseSectors (sector, sector) == -1)
1567     printf ("iapEraseSectors returned error %d/%s\n", iapGetErrno (), iapStrerror (iapGetErrno ()));
1568   else
1569     printf ("Sector %d erased\n", sector);
1570
1571   return 0;
1572 }
1573
1574 static int monitorIAPBlank (int argc __attribute__ ((unused)), portCHAR **argv)
1575 {
1576   unsigned int sector;
1577
1578   if (!getNumber (argv [0], &sector))
1579     return 0;
1580
1581   if (!iapIsValidSector ((int) sector))
1582   {
1583     printf ("Sector number out of range\n");
1584     return 0;
1585   }
1586
1587   switch (iapBlankCheckSectors (sector, sector))
1588   {
1589     case 0 :
1590       printf ("Sector %d is blank\n", sector);
1591       break;
1592
1593     case 1 :
1594       printf ("Sector %d is not blank\n", sector);
1595       break;
1596
1597     default :
1598       printf ("iapBlankCheckSector returned error %d/%s\n", iapGetErrno (), iapStrerror (iapGetErrno ()));
1599       break;
1600   }
1601
1602   return 0;
1603 }
1604
1605 static int monitorIAPID (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1606 {
1607   printf ("IAP ID=0x%08x\n", iapReadPartID ());
1608
1609   return 0;
1610 }
1611
1612 static int monitorIAPVer (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1613 {
1614   printf ("IAP ID=0x%08x\n", iapReadBootCodeVersion ());
1615
1616   return 0;
1617 }
1618
1619 static int monitorIAPISP (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1620 {
1621   iapISP ();
1622
1623   return 0;
1624 }
1625
1626 //
1627 //
1628 //
1629 int monitorLM75Init (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1630 {
1631   if (lm75Init ())
1632     printf ("lm75Init() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1633
1634   return 0;
1635 }
1636
1637 int monitorLM75Mode (int argc __attribute__ ((unused)), portCHAR **argv)
1638 {
1639   unsigned int mode;
1640
1641   if (!getNumber (argv [0], &mode))
1642     return 0;
1643
1644   if (mode > 1)
1645     printf ("Error: mode must be 0 or 1\n");
1646   else
1647   {
1648     lm75SetMode (mode);
1649
1650     if (!mode)
1651       printf ("lm75 using I2C repeated start for write then read\n");
1652     else
1653       printf ("lm75 using I2C stop then start for read\n");
1654   }
1655
1656   return 0;
1657 }
1658
1659 int monitorLM75Addr (int argc __attribute__ ((unused)), portCHAR **argv)
1660 {
1661   unsigned int address;
1662
1663   if (!getNumber (argv [0], &address))
1664     return 0;
1665
1666   if (address > 0xff)
1667     printf ("Error: address must be 0x00..0xff (0..255)\n");
1668   else
1669     lm75SetAddress (address);
1670
1671   return 0;
1672 }
1673
1674 int monitorLM75ReRead (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1675 {
1676   int value;
1677
1678   if (lm75ReRead (&value))
1679     printf ("lm75Read() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1680   else
1681     printf ("value=0x%x\n", value);
1682
1683   return 0;
1684 }
1685
1686 int monitorLM75Temp (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1687 {
1688   int temp;
1689
1690   if (lm75TemperatureRead (&temp))
1691     printf ("lm75TemperatureRead() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1692   else
1693     printf ("temp=%d.%dC\n", temp >> 1, (temp & 0x01) ? 5 : 0);
1694
1695   return 0;
1696 }
1697
1698 int monitorLM75Config (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1699 {
1700   int config;
1701
1702   if (lm75ConfigRead (&config))
1703     printf ("lm75ConfigRead() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1704   else
1705     printf ("config=0x%02x\n", config);
1706
1707   return 0;
1708 }
1709
1710 int monitorLM75Thyst (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1711 {
1712   int thyst;
1713
1714   if (!argc)
1715   {
1716     if (lm75THYSTRead (&thyst))
1717       printf ("lm75THYSTRead() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1718     else
1719       printf ("THYST=%d.%dC\n", thyst / 2, (thyst & 0x01) ? 5 : 0);
1720   }
1721   else
1722   {
1723     if (!getNumber (argv [0], (unsigned int *) &thyst))
1724       return 0;
1725
1726     if ((thyst < -55) || (thyst > 125))
1727       printf ("Error: THYST range is -55C to +125C\n");
1728     else if (lm75THYSTWrite (thyst << 1))
1729       printf ("lm75THYSTWrite() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1730   }
1731   return 0;
1732 }
1733
1734 int monitorLM75Tos (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1735 {
1736   int tos;
1737
1738   if (!argc)
1739   {
1740     if (lm75TOSTRead (&tos))
1741       printf ("lm75TOSRead() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1742     else
1743       printf ("TOS=%d.%dC\n", tos / 2, (tos & 0x01) ? 5 : 0);
1744   }
1745   else 
1746   {
1747     if (!getNumber (argv [0], (unsigned int *) &tos))
1748       return 0;
1749     
1750     if ((tos < -55) || (tos > 125))
1751       printf ("Error: TOS range is -55C to +125C\n");
1752     else if (lm75TOSWrite (tos << 1))
1753       printf ("lm75TOSWrite() returned error %d/%s\n", i2cGetErrno (), i2cStrerror (i2cGetErrno ()));
1754   }
1755
1756   return 0;
1757 }
1758
1759 //
1760 //  6 tasks, each task needs about 42 bytes to display
1761 //
1762 #define monitorTask_BUFFERSIZE (6 * 42)
1763
1764 static int monitorMemTask (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1765 {
1766 #if configUSE_TRACE_FACILITY == 1
1767   signed portCHAR buffer [monitorTask_BUFFERSIZE];
1768   int bytesFree;
1769   int bytesUsed;
1770   int blocksFree;
1771
1772   vTaskList (buffer);
1773   vPortUsedMem (&bytesFree, &bytesUsed, &blocksFree);
1774   printf ("%s\nHeap size=%ld, used=%d, free=%d (%d blocks)\n", buffer, configTOTAL_HEAP_SIZE, bytesUsed, bytesFree, blocksFree);
1775 #else
1776   printf ("Not implemented (requires configUSE_TRACE_FACILITY in FreeRTOSConfig.h)\n");
1777 #endif
1778
1779   return 0;
1780 }
1781
1782 typedef struct memMap_s
1783 {
1784   char *desc;
1785   int m;
1786   unsigned int start;
1787   unsigned int end;
1788 }
1789 memMap_t;
1790
1791 typedef union 
1792 {
1793   void *v;
1794   unsigned int i;
1795 }
1796 sbrkConv_t;
1797
1798 static inline unsigned __get_cpsr (void)
1799 {
1800   unsigned long retval;
1801
1802   asm volatile (" mrs  %0, cpsr" : "=r" (retval) : /* no inputs */  );
1803
1804   return retval;
1805 }
1806
1807 static int monitorMemMap (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1808 {
1809   unsigned int i;
1810   sbrkConv_t sbrkConv;
1811   static memMap_t memMap [] = 
1812   {
1813     { ".startup .....", 0, (unsigned int) &__start_of_startup__, (unsigned int) &__end_of_startup__ },
1814     { ".text ........", 0, (unsigned int) &__start_of_text__,    (unsigned int) &__end_of_text__ },
1815     { ".code ........", 0, (unsigned int) &__start_of_prog__,    (unsigned int) &__end_of_prog__ },
1816     { ".rodata ......", 0, (unsigned int) &__start_of_rodata__,  (unsigned int) &__end_of_rodata__ },
1817     { ".data ........", 0, (unsigned int) &__data_beg__,         (unsigned int) &__data_end__ },
1818     { ".bss .........", 0, (unsigned int) &__bss_beg__,          (unsigned int) &__bss_end__ },
1819     { "heap .........", 1, (unsigned int) &__heap_beg,           (unsigned int) &__heap_end },
1820     { "heap range ...", 1, (unsigned int) &__heap_beg,           (unsigned int) &__heap_max },
1821 //  { "SYS stack ....", 1, (unsigned int) &__stack_beg_sys,      (unsigned int) &__stack_end_sys }, // Not relevant to FreeRTOS
1822     { "SVC stack ....", 1, (unsigned int) &__stack_beg_svc,      (unsigned int) &__stack_end_svc },
1823     { "IRQ stack ....", 1, (unsigned int) &__stack_beg_irq,      (unsigned int) &__stack_end_irq },
1824     { "FIQ stack ....", 1, (unsigned int) &__stack_beg_fiq,      (unsigned int) &__stack_end_fiq },
1825     { "abort stack ..", 1, (unsigned int) &__stack_beg_abt,      (unsigned int) &__stack_end_abt },
1826     { "undef stack ..", 1, (unsigned int) &__stack_beg_und,      (unsigned int) &__stack_end_und },
1827   };
1828
1829   sbrkConv.v = sbrk (0);
1830   __heap_end = sbrkConv.i;
1831   __stack_end_sys = sbrkConv.i;
1832
1833   printf ("Section        Start      End        Length\n");
1834   printf ("-------------------------------------------\n");
1835
1836   for (i = 0; i < arrsizeof (memMap); i++)
1837   {
1838     if (!memMap [i].m)
1839       printf ("%s 0x%08x 0x%08x 0x%x\n", memMap [i].desc, memMap [i].start, memMap [i].end, abs (memMap [i].end - memMap [i].start));
1840     else
1841       printf ("%s 0x%08x 0x%08x 0x%x\n", memMap [i].desc, *(unsigned int *) memMap [i].start, *(unsigned int *) memMap [i].end, abs (*(unsigned int *) memMap [i].end - *(unsigned int *) memMap [i].start));
1842   }
1843
1844 #if 0
1845   printf ("\nProcessor mode ");
1846
1847   switch ((i = __get_cpsr ()) & 0x1f)
1848   {
1849     case 0x10 : printf ("User"); break;
1850     case 0x11 : printf ("FIQ"); break;
1851     case 0x12 : printf ("IRQ"); break;
1852     case 0x13 : printf ("Supervisor"); break;
1853     case 0x17 : printf ("Abort"); break;
1854     case 0x1b : printf ("Undefined"); break;
1855     case 0x1f : printf ("System"); break;
1856     default   : printf ("Unknown");
1857   }
1858
1859   printf (", IRQ %s", (i & 0x80) ? "disabled" : "enabled");
1860   printf (", FIQ %s", (i & 0x40) ? "disabled" : "enabled");
1861   printf (", mode %s\n", (i & 0x20) ? "THUMB" : "ARM");
1862 #endif
1863
1864   printf ("\n");
1865   malloc_stats ();
1866
1867   return 0;
1868 }
1869
1870 typedef struct memorySlots_s
1871 {
1872   unsigned char *p;
1873   unsigned int size;
1874 }
1875 memorySlots_t;
1876
1877 memorySlots_t memorySlots [8];
1878
1879 static int monitorMemAlloc (int argc __attribute__ ((unused)), portCHAR **argv)
1880 {
1881   unsigned int size;
1882   unsigned int slot;
1883   unsigned char *p;
1884
1885   if (!getNumber (argv [0], &slot) || !getNumber (argv [0], &size))
1886     return 0;
1887
1888   if (slot >= arrsizeof (memorySlots))
1889   {
1890     printf ("slot must be 0..%lu\n", arrsizeof (memorySlots) - 1);
1891     return 0;
1892   }
1893
1894   if (memorySlots [slot].p)
1895     printf ("Slot %d in use, free it first, or use realloc\n", slot);
1896   else if (!(p = malloc (size)))
1897     printf ("malloc() failed, error %d/%s\n", errno, strerror (errno));
1898   else
1899   {
1900     memorySlots [slot].p = p;
1901     memorySlots [slot].size = size;
1902   }
1903
1904   return 0;
1905 }
1906
1907 static int monitorMemRealloc (int argc __attribute__ ((unused)), portCHAR **argv)
1908 {
1909   unsigned int size;
1910   unsigned int slot;
1911   unsigned char *p;
1912
1913   if (!getNumber (argv [0], &slot) || !getNumber (argv [0], &size))
1914     return 0;
1915
1916   if (slot >= arrsizeof (memorySlots))
1917   {
1918     printf ("slot must be 0..%lu\n", arrsizeof (memorySlots) - 1);
1919     return 0;
1920   }
1921
1922   if (!(p = realloc (memorySlots [slot].p, size)))
1923     printf ("realloc() failed, error %d/%s\n", errno, strerror (errno));
1924   else
1925   {
1926     memorySlots [slot].p = p;
1927     memorySlots [slot].size = size;
1928   }
1929
1930   return 0;
1931 }
1932
1933 static int monitorMemFree (int argc __attribute__ ((unused)), portCHAR **argv)
1934 {
1935   unsigned int slot;
1936
1937   if (!getNumber (argv [0], &slot))
1938     return 0;
1939
1940   if (slot >= arrsizeof (memorySlots))
1941   {
1942     printf ("slot must be 0..%lu\n", arrsizeof (memorySlots) - 1);
1943     return 0;
1944   }
1945
1946   if (!memorySlots [slot].p)
1947     printf ("Can't free it, slot %d not in use\n", slot);
1948   else
1949   {
1950     free (memorySlots [slot].p);
1951     memorySlots [slot].p = NULL;
1952     memorySlots [slot].size = 0;
1953   }
1954
1955   return 0;
1956 }
1957
1958 static int monitorMemList (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1959 {
1960   unsigned int i;
1961
1962   printf ("Slot  Address     Size\n");
1963   printf ("----------------------\n");
1964
1965   for (i = 0; i < arrsizeof (memorySlots); i++)
1966     printf ("%4d  0x%08x  %d\n", i, (unsigned int) memorySlots [i].p, memorySlots [i].size);
1967
1968   return 0;
1969 }
1970
1971 //
1972 //
1973 //
1974 static int monitorMiscSizeof (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1975 {
1976   printf ("sizeof (char)      = %lu\n", sizeof (char));
1977   printf ("sizeof (short)     = %lu\n", sizeof (short));
1978   printf ("sizeof (int)       = %lu\n", sizeof (int));
1979   printf ("sizeof (long)      = %lu\n", sizeof (long));
1980   printf ("sizeof (long long) = %lu\n", sizeof (long long));
1981   printf ("sizeof (float)     = %lu\n", sizeof (float));
1982   printf ("sizeof (double)    = %lu\n", sizeof (double));
1983   printf ("sizeof (void *)    = %lu\n", sizeof (void *));
1984
1985   return 0;
1986 }
1987
1988 //
1989 //
1990 //
1991 static int monitorRTCGet (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
1992 {
1993   time_t now;
1994   char buffer [32];
1995
1996   now = time (NULL);
1997   ctime_r (&now, buffer);
1998   printf ("%s", buffer);
1999
2000   return 0;
2001 }
2002
2003 //
2004 //  This works because atoi() stops on a non-digit.  We already know the 
2005 //  string values are digits, because of isGoodString().
2006 //
2007 static int tmSetElement (int *element, int minValue, int maxValue, int adjustValue, char *s)
2008 {
2009   int v;
2010   
2011   if (((v = atoi (s)) < minValue) || (v > maxValue))
2012   {
2013     printf ("Illegal value encountered in parameter\n");
2014     return FALSE;
2015   }
2016
2017   *element = (v + adjustValue);
2018
2019   return TRUE;
2020 }
2021
2022 static int isGoodString (char *s, char *fmt)
2023 {
2024   unsigned int i;
2025   unsigned int l;
2026
2027   if ((l = strlen (s)) != strlen (fmt))
2028     return FALSE;
2029
2030   for (i = 0; i < l; i++, s++, fmt++)
2031   {
2032     if (*fmt == 'N')
2033     {
2034       if (!isdigit (*s))
2035         return FALSE;
2036     }
2037     else if (*fmt != *s)
2038       return FALSE;
2039   }
2040
2041   return TRUE;
2042 }
2043
2044 static int monitorRTCSet (int argc, portCHAR **argv)
2045 {
2046   if ((argc == 1) && !strcmp (argv [0], "gps"))
2047   {
2048     gpsData_t gpsData;
2049
2050     if (gpsCopyData (&gpsData))
2051     {
2052       if (gpsData.valid)
2053       {
2054         struct tm tm;
2055
2056         tm.tm_sec   = gpsData.utcSeconds;
2057         tm.tm_min   = gpsData.utcMinutes;
2058         tm.tm_hour  = gpsData.utcHours;
2059         tm.tm_mday  = gpsData.utcDay;
2060         tm.tm_mon   = gpsData.utcMonth - 1;
2061         tm.tm_year  = gpsData.utcYear - 1900;
2062         tm.tm_wday  = 0;
2063         tm.tm_yday  = 0;
2064         tm.tm_isdst = 0;
2065
2066         rtcSetEpochSeconds (mktime (&tm));
2067
2068         printf ("Date/time set from GPS\n");
2069       }
2070       else
2071         printf ("GPS data not valid\n");
2072     }
2073     else
2074       printf ("Unable to get GPS data\n");
2075   }
2076   else if (isGoodString (argv [0], "NNNN/NN/NN") && isGoodString (argv [1], "NN:NN:NN"))
2077   {
2078     struct tm tm;
2079
2080     if (!tmSetElement (&tm.tm_year, 1900, 2038, -1900, &argv [0][0]))
2081       return 0;
2082     if (!tmSetElement (&tm.tm_mon, 1, 12, -1, &argv [0][5]))
2083       return 0;
2084     if (!tmSetElement (&tm.tm_mday, 1, 31, 0, &argv [0][8]))
2085       return 0;
2086     if (!tmSetElement (&tm.tm_hour, 0, 23, 0, &argv [1][0]))
2087       return 0;
2088     if (!tmSetElement (&tm.tm_min, 0, 59, 0, &argv [1][3]))
2089       return 0;
2090     if (!tmSetElement (&tm.tm_sec, 0, 59, 0, &argv [1][6]))
2091       return 0;
2092
2093     tm.tm_wday  = 0;
2094     tm.tm_yday  = 0;
2095     tm.tm_isdst = 0;
2096
2097     rtcSetEpochSeconds (mktime (&tm));
2098   }
2099   else
2100     printf ("Parameter(s) either not 'gps' or not 'YYYYY/MM/DD HH:MM:SS'\n");
2101
2102   return 0;
2103 }
2104
2105 static int monitorRTCAlarm (int argc, portCHAR **argv)
2106 {
2107   if (argc == 0)
2108   {
2109     time_t a;
2110
2111     if ((a = rtcGetAlarmEpochSeconds ()))
2112     {
2113       char buffer [32];
2114       ctime_r (&a, buffer);
2115       printf ("%s", buffer);
2116     }
2117     else
2118       printf ("alarm not enabled\n");
2119   }
2120   else if (argc == 1)
2121   {
2122     if (!strcmp (argv [0], "off"))
2123       rtcSetAlarm (NULL);
2124     else
2125       printf ("'rtc alarm' requires either 'off' or 'YYYY/MM/DD HH:MM:SS' as arguments\n");
2126   }
2127   else if (isGoodString (argv [0], "NNNN/NN/NN") && isGoodString (argv [1], "NN:NN:NN"))
2128   {
2129     struct tm tm;
2130
2131     if (!tmSetElement (&tm.tm_year, 1900, 2038, -1900, &argv [0][0]))
2132       return 0;
2133     if (!tmSetElement (&tm.tm_mon, 1, 12, -1, &argv [0][5]))
2134       return 0;
2135     if (!tmSetElement (&tm.tm_mday, 1, 31, 0, &argv [0][8]))
2136       return 0;
2137     if (!tmSetElement (&tm.tm_hour, 0, 23, 0, &argv [1][0]))
2138       return 0;
2139     if (!tmSetElement (&tm.tm_min, 0, 59, 0, &argv [1][3]))
2140       return 0;
2141     if (!tmSetElement (&tm.tm_sec, 0, 59, 0, &argv [1][6]))
2142       return 0;
2143
2144     if (rtcSetAlarm (&tm))
2145       printf ("Cannot set the alarm for the past\n");
2146   }
2147   else
2148     printf ("Parameter(s) either not 'off' or not 'YYYYY/MM/DD HH:MM:SS'\n");
2149
2150   return 0;
2151 }
2152
2153 static int monitorRTCPeriodic (int argc, portCHAR **argv)
2154 {
2155   if (!argc)
2156     printf ("Current periodic alarm state is %s\n", rtcPeriodicAlarm (-1) ? "on" : "off");
2157   else if (!strcmp (argv [0], "off"))
2158     rtcPeriodicAlarm (0);
2159   else if (!strcmp (argv [0], "on"))
2160     rtcPeriodicAlarm (1);
2161   else
2162     printf ("Error: if argument present, must be 'off' or 'on'\n");
2163
2164   return 0;
2165 }
2166
2167 //
2168 //
2169 //
2170 static inline unsigned long monitorSWICommon (unsigned long swi);
2171 static inline unsigned long monitorSWICommon (unsigned long swi)
2172 {
2173   unsigned long result;
2174
2175   SWICALL (swi, result);
2176
2177   return result;
2178 }
2179
2180 static inline unsigned long monitorSWICommon2 (unsigned long swi, unsigned long state);
2181 static inline unsigned long monitorSWICommon2 (unsigned long swi, unsigned long state)
2182 {
2183   unsigned long result;
2184
2185   SWICALL1 (swi, state, result);
2186
2187   return result;
2188 }
2189
2190 int monitorSWISetAsm (int argc __attribute__ ((unused)), portCHAR **argv)
2191 {
2192   unsigned int state;
2193
2194   if (!strcmp (argv [0], "on"))
2195     state = 0;
2196   else if (!strcmp (argv [0], "off"))
2197     state = 1;
2198   else 
2199   {
2200     printf ("State must be 'on' or 'off'\n");
2201     return 0;
2202   }
2203   
2204   printf ("Setting LED2 %s via C, previous state was %s\n", state ? "off" : "on", monitorSWICommon2 (SWICALL_A_LED2SET, state) ? "off" : "on");
2205
2206   return 0;
2207 }
2208
2209 int monitorSWIOnAsm (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2210 {
2211   printf ("Setting LED2 on via assembly, previous state was %s\n", monitorSWICommon (SWICALL_A_LED2ON) ? "off" : "on");
2212
2213   return 0;
2214 }
2215
2216 int monitorSWIOffAsm (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2217 {
2218   printf ("Setting LED2 off via assembly, previous state was %s\n", monitorSWICommon (SWICALL_A_LED2OFF) ? "off" : "on");
2219
2220   return 0;
2221 }
2222
2223 int monitorSWIToggleAsm (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2224 {
2225   printf ("Toggling LED2 via assembly, previous state was %s\n", monitorSWICommon (SWICALL_A_LED2TOGGLE) ? "off" : "on");
2226
2227   return 0;
2228 }
2229
2230 int monitorSWISetC (int argc __attribute__ ((unused)), portCHAR **argv)
2231 {
2232   unsigned int state;
2233
2234   if (!strcmp (argv [0], "on"))
2235     state = 0;
2236   else if (!strcmp (argv [0], "off"))
2237     state = 1;
2238   else 
2239   {
2240     printf ("State must be 'on' or 'off'\n");
2241     return 0;
2242   }
2243   
2244   printf ("Setting LED2 %s via C, previous state was %s\n", state ? "off" : "on", monitorSWICommon2 (SWICALL_C_LED2SET, state) ? "off" : "on");
2245
2246   return 0;
2247 }
2248
2249 int monitorSWIOnC (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2250 {
2251   printf ("Setting LED2 on via C, previous state was %s\n", monitorSWICommon (SWICALL_C_LED2ON) ? "off" : "on");
2252
2253   return 0;
2254 }
2255
2256 int monitorSWIOffC (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2257 {
2258   printf ("Setting LED2 off via C, previous state was %s\n", monitorSWICommon (SWICALL_C_LED2OFF) ? "off" : "on");
2259
2260   return 0;
2261 }
2262
2263 int monitorSWIToggleC (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2264 {
2265   printf ("Toggling LED2 via C, previous state was %s\n", monitorSWICommon (SWICALL_C_LED2TOGGLE) ? "off" : "on");
2266
2267   return 0;
2268 }
2269
2270 //
2271 //
2272 //
2273 int monitorWDTTest (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2274 {
2275   printf ("The watchdog is disabled, by default.  This command enables the watchdog, and if\n"
2276           "no command is typed for 10 seconds, the watchdog will cause the system reset.\n"
2277           "The 10 seconds is based on a 48Mhz PCLK (12Mhz xtal, PLL x 4, VBPDIV = /1).  The\n"
2278           "'wdt status' command will show the cause of a system reset.  RSIR is reset by\n"
2279           "this command.\n");
2280
2281   SCB_RSIR = SCB_RSIR_MASK;
2282   WD_MOD = WD_MOD_WDEN | WD_MOD_RESET;
2283   WD_TC = 120000000;
2284   WD_FEED = WD_FEED_FEED1;
2285   WD_FEED = WD_FEED_FEED2;
2286
2287   return 0;
2288 }
2289
2290 int monitorWDTStatus (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2291 {
2292   int regRSIR = SCB_RSIR;
2293   int regWDMOD = WD_MOD;
2294   int regWDTC = WD_TC;
2295   int regWDTV = WD_TV;
2296
2297   printf ("Watchdog enabled .................. : %s\n", (regWDMOD & WD_MOD_WDEN) ? "Yes" : "No");
2298   printf ("Watchdog timeout generates reset .. : %s\n", (regWDMOD & WD_MOD_RESET) ? "Yes" : "No");
2299   printf ("Watchdog timeout (in PCLK/4's) .... : %d\n", regWDTC);
2300   printf ("Watchdog timeout counter .......... : %d\n", regWDTV);
2301   printf ("\n");
2302   printf ("Reset because of POR .............. : %s\n", (regRSIR & SCB_RSIR_POR) ? "Yes" : "No");
2303   printf ("Reset because of /RESET ........... : %s\n", (regRSIR & SCB_RSIR_EXTR) ? "Yes" : "No");
2304   printf ("Reset because of watchdog ......... : %s\n", (regRSIR & SCB_RSIR_WDTR) ? "Yes" : "No");
2305   printf ("Reset because of BOD .............. : %s\n", (regRSIR & SCB_RSIR_BODR) ? "Yes" : "No");
2306
2307   return 0;
2308 }
2309
2310 int monitorWDTClear (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2311 {
2312   SCB_RSIR = SCB_RSIR_MASK;
2313   WD_MOD = 0;
2314
2315   return 0;
2316 }
2317
2318 //
2319 //
2320 //
2321 static int monitorVersion (int argc __attribute__ ((unused)), portCHAR **argv __attribute__ ((unused)))
2322 {
2323   printf ("LPC-P2148 Demo, Version " __VERSION ", " __DATE__ " " __TIME__ "\n");
2324   printf ("Copyright (c) 2007, J.C. Wren\n");
2325
2326   return 0;
2327 }
2328
2329 //
2330 //
2331 //
2332 #if defined CFG_CONSOLE_USB || defined CFG_CONSOLE_UART1
2333 static void monitorReassignFD (FILE *fp, int fd);
2334 static void monitorReassignFD (FILE *fp, int fd)
2335 {
2336   fp->_file = fd;
2337 }
2338 #endif
2339
2340 static void argsDispatch (commandList_t *cl, int argc, char **argv)
2341 {
2342   activeCommandList = cl;
2343
2344   while (cl->command)
2345   {
2346     if (!strcmp (cl->command, argv [0]))
2347     {
2348       if ((argc == 2) && !strcmp (argv [1], "?"))
2349         printf ("%s\n", cl->parameters);
2350       else if ((argc - 1) < cl->minArgs)
2351         printf ("Too few arguments to command (%d expected)\n", cl->minArgs);
2352       else if (cl->cmdType == CMDTYPE_CMDLIST)
2353         argsDispatch (cl->commandList, argc - 1, &argv [1]);
2354       else if ((argc - 1) > cl->maxArgs)
2355         printf ("Too many arguments to command (%d maximum)\n", cl->maxArgs);
2356       else
2357         (*cl->handler) (argc - 1, &argv [1]);
2358
2359       return;
2360     }
2361
2362     cl++;
2363   }
2364
2365   if (!cl->command)
2366     printf ("Unknown command \"%s\"\n", argv [0]);
2367 }
2368
2369 portTASK_FUNCTION (vMonitorTask, pvParameters __attribute__ ((unused)))
2370 {
2371   static U8 buffer [256];
2372   static portCHAR *argv [34];
2373   int argc;
2374   int fd = fileno (stdin);
2375
2376   fclose (stderr);
2377   stderr = stdout;
2378
2379 #if defined CFG_CONSOLE_USB
2380   fd = open ("/dev/usb", O_RDWR);
2381 #elif defined CFG_CONSOLE_UART1
2382   fd = open ("/dev/uart1", O_RDWR);
2383 #endif
2384
2385 #if defined CFG_CONSOLE_USB || defined CFG_CONSOLE_UART1
2386   monitorReassignFD (stdin, fd);
2387   monitorReassignFD (stdout, fd);
2388 #endif
2389
2390   monitorVersion (0, NULL);
2391
2392 #ifndef CFG_USB_MSC
2393   //
2394   //  If CFG_USB_MSC defined, this gets done by mscblockInit()
2395   //
2396   {
2397     FRESULT f;
2398
2399     if ((f = diskInitialize (0)) != FR_OK)
2400       f_printerror (f);
2401   }
2402 #endif
2403
2404   for (;;)
2405   {
2406     int l;
2407
2408     if ((l = argsGetLine (fd, buffer, sizeof (buffer))))
2409     {
2410       if ((l == 1) && ((buffer [0] == 0xfe) || (buffer [0] == 0xff)))
2411       {
2412         int type = buffer [0];
2413         time_t now = time (NULL);
2414         ctime_r (&now, (char *) buffer);
2415         printf ("%s -- %s", (type == 0xfe) ? "ALARM" : "PERIODIC", buffer);
2416       }
2417       else if (argsParse ((char *) buffer, argv, sizeof (argv), &argc))
2418         printf ("Too many arguments (max %ld)\n", arrsizeof (argv));
2419       else if (argv [0])
2420         argsDispatch (commandList, argc, &argv [0]);
2421     }
2422
2423     WD_FEED = WD_FEED_FEED1;
2424     WD_FEED = WD_FEED_FEED2;
2425   }
2426 }