00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #if defined(__GNUC__) && defined(__AVR__)
00043
00044
00045
00046
00047 #include <sys/tracer.h>
00048 #include <sys/heap.h>
00049 #include <sys/timer.h>
00050 #include <sys/thread.h>
00051 #include <sys/atom.h>
00052 #include <dev/irqreg.h>
00053 #include <stdio.h>
00054 #include <string.h>
00055
00056
00057
00058
00059 unsigned int micros_high = 0;
00060 t_traceitem *trace_items = 0;
00061 t_traceitem *trace_current = 0;
00062 int trace_head = 0;
00063 int trace_size = 0;
00064 char trace_isfull = 0;
00065 char trace_isinit = 0;
00066 char trace_mode = TRACE_MODE_OFF;
00067
00068 char trace_mask[TRACE_TAG_LAST+1] = {
00069 0,
00070 0,
00071 1,
00072 1,
00073 1,
00074 1,
00075 0,
00076 0,
00077 1,
00078 1,
00079 1
00080 };
00081
00082 char* tag_string[TRACE_TAG_LAST+1] = {
00083 "Critical Enter",
00084 "Critical Exit",
00085 "Thread Yield",
00086 "Thread SetPrio",
00087 "Thread Wait",
00088 "Thread Sleep",
00089 "Interrupt Enter",
00090 "Interrupt Exit",
00091 "Trace Start",
00092 "Trace Stop",
00093 "User *"
00094 };
00095
00096 char* int_string[TRACE_INT_LAST+1] = {
00097 "UART0_CTS",
00098 "UART0_RXCOMPL",
00099 "UART0_TXEMPTY",
00100 "UART1_CTS",
00101 "UART1_RXCOMPL",
00102 "UART1_TXEMPTY",
00103 "TIMER0_OVERFL",
00104 "TIMER1_OVERFL",
00105 "SUART_TIMER",
00106 "SUART_RX"
00107 };
00108
00109 char* mode_string[TRACE_MODE_LAST+1] = {
00110 "OFF",
00111 "CIRCULAR",
00112 "ONESHOT"
00113 };
00114
00115 char* user_string[TRACE_MAX_USER];
00116
00117
00118
00119
00120 static void NutTraceTimer1IRQ(void *arg)
00121 {
00122
00123 micros_high++;
00124
00125 }
00126
00127
00128
00129 int NutTraceInit(int size, char mode)
00130 {
00131 if (!trace_isinit) {
00132
00133 outp(2,TCCR1B);
00134 NutRegisterIrqHandler(&sig_OVERFLOW1, NutTraceTimer1IRQ, 0);
00135 sbi(TIMSK, TOIE1);
00136 trace_isinit = 1;
00137 }
00138 if (size==0) {
00139 size = TRACE_SIZE_DEFAULT;
00140 }
00141 if (size != trace_size) {
00142
00143 if (trace_items != 0) {
00144
00145 NutHeapFree(trace_items);
00146 }
00147
00148 trace_items = (t_traceitem *)NutHeapAlloc(size * sizeof(t_traceitem));
00149 if (trace_items == 0) {
00150
00151 return trace_size = 0;
00152 }
00153 else {
00154 trace_size = size;
00155 }
00156 }
00157
00158
00159
00160
00161
00162
00163 trace_mode = mode;
00164 NutTraceClear();
00165 return trace_size;
00166 }
00167
00168
00169
00170 void NutTraceClear()
00171 {
00172 trace_head = trace_isfull = 0;
00173 TRACE_ADD_ITEM(TRACE_TAG_START,0);
00174 }
00175
00176 void NutTraceStop()
00177 {
00178 TRACE_ADD_ITEM(TRACE_TAG_STOP,0);
00179 trace_mode = TRACE_MODE_OFF;
00180 }
00181
00182 void NutTraceTerminal(char* arg)
00183 {
00184 int val;
00185
00186 if (sscanf(arg,"print%d",&val)==1) {
00187 NutTracePrint(val);
00188 return;
00189 }
00190 if (!strncmp(arg,"print",5)) {
00191 NutTracePrint(0);
00192 return;
00193 }
00194 if (!strncmp(arg,"oneshot",7)) {
00195 NutTraceInit(trace_size,TRACE_MODE_ONESHOT);
00196 printf("TRACE mode %s, restarted\n",mode_string[(int)trace_mode]);
00197 return;
00198 }
00199 if (!strncmp(arg,"circular",8)) {
00200 NutTraceInit(trace_size,TRACE_MODE_CIRCULAR);
00201 printf("TRACE mode %s, restarted\n",mode_string[(int)trace_mode]);
00202 return;
00203 }
00204 if (sscanf(arg,"size%d",&val)==1) {
00205 printf("TRACE new size: %d\n",NutTraceInit(val,trace_mode));
00206 return;
00207 }
00208 if (!strncmp(arg,"stop",4)) {
00209 NutTraceStop();
00210 printf("TRACE stopped\n");
00211 return;
00212 }
00213 if (sscanf(arg,"mask%d",&val)==1) {
00214 if (val<=TRACE_TAG_LAST) {
00215 trace_mask[val]=trace_mask[val] ? 0 : 1;
00216 NutTraceClear();
00217 }
00218 NutTraceMaskPrint();
00219 return;
00220 }
00221 if (!strncmp(arg,"mask",4)) {
00222 NutTraceMaskPrint();
00223 return;
00224 }
00225
00226
00227 NutTraceStatusPrint();
00228 printf("SYNTAX: trace [print [<size>]|oneshot|circular|size <size>|stop|mask [<tag>]]\n");
00229 }
00230
00231 void NutTraceStatusPrint(void)
00232 {
00233 printf("TRACE STATUS\n");
00234 printf(" Mode is %s\n",mode_string[(int)trace_mode]);
00235 printf(" Size is %d\n",trace_size);
00236 if (trace_isfull)
00237 printf(" is full\n");
00238 else
00239 printf(" contains %d elements\n",trace_head);
00240 }
00241
00242 void NutTracePrint(int size)
00243 {
00244 int i,index;
00245 uint32_t time;
00246 char mode;
00247 unsigned int micros, millis, secs;
00248
00249 mode = trace_mode;
00250 trace_mode = TRACE_MODE_OFF;
00251 printf("\nTRACE");
00252 if (trace_size == 0) {
00253 printf(" not initialized!\n\n");
00254 return;
00255 }
00256 printf(" contains %d items, ",(trace_isfull ? trace_size : trace_head));
00257 if (size == 0) {
00258 size = trace_size;
00259 }
00260 if (trace_isfull) {
00261 if (size > trace_size) {
00262 size = trace_size;
00263 }
00264 }
00265 else {
00266 if (size > trace_head) {
00267 size = trace_head;
00268 }
00269 }
00270 printf(" printing %d items.\n",size);
00271 printf("%-20s%-12s%-12s\n","TAG","PC/Info","Time [s:ms:us]");
00272 printf("-----------------------------------------------\n");
00273 for (i=size-1;i>=0;i--) {
00274 index = trace_head - i - 1;
00275 if (index<0) {
00276 index += trace_size;
00277 }
00278 time = ((uint32_t)trace_items[index].time_h)<<16 | trace_items[index].time_l;
00279 micros = (int)(time%1000);
00280 millis = (int)((time/1000)%1000);
00281 secs = (int)(time/1000000);
00282 switch (trace_items[index].tag) {
00283 case TRACE_TAG_THREAD_YIELD:
00284 case TRACE_TAG_THREAD_SETPRIO:
00285 case TRACE_TAG_THREAD_WAIT:
00286 case TRACE_TAG_THREAD_SLEEP:
00287 printf("%-20s%-15s%7u:%03u:%03u\n",
00288 tag_string[(int)trace_items[index].tag],
00289 ((NUTTHREADINFO*)(trace_items[index].pc))->td_name,
00290 secs,millis,micros);
00291 break;
00292 case TRACE_TAG_INTERRUPT_ENTER:
00293 case TRACE_TAG_INTERRUPT_EXIT:
00294 printf("%-20s%-15s%7u:%03u:%03u\n",
00295 tag_string[(int)trace_items[index].tag],
00296 int_string[(int)trace_items[index].pc],
00297 secs,millis,micros);
00298 break;
00299 case TRACE_TAG_USER:
00300 printf("%-20s%-15s%7u:%03u:%03u\n",
00301 tag_string[(int)trace_items[index].tag],
00302 user_string[(int)trace_items[index].pc],
00303 secs,millis,micros);
00304 break;
00305 default:
00306 printf("%-20s%-#15x%7u:%03u:%03u\n",
00307 tag_string[(int)trace_items[index].tag],
00308 trace_items[index].pc,
00309 secs,millis,micros);
00310 }
00311 }
00312 trace_mode = mode;
00313 }
00314
00315 int NutTraceGetPC(void)
00316 {
00317 int pc = ((int)(*((char*)SP+1)));
00318 pc = (pc<<8)|(0x00ff&(int)(*((char*)SP+2)));
00319 return pc<<1;
00320 }
00321
00322
00323 void NutTraceMaskSet(int tag)
00324 {
00325 if (tag<=TRACE_TAG_LAST) {
00326 trace_mask[tag] = 1;
00327 }
00328 }
00329
00330 void NutTraceMaskClear(int tag)
00331 {
00332 if (tag<=TRACE_TAG_LAST) {
00333 trace_mask[tag] = 0;
00334 }
00335 }
00336
00337 void NutTraceMaskPrint(void)
00338 {
00339 int tag;
00340 printf("TRACEMASK\n");
00341 for (tag=0;tag<=TRACE_TAG_LAST;tag++) {
00342 printf(" %d %s ",tag,tag_string[tag]);
00343 if (trace_mask[tag])
00344 printf("ON\n");
00345 else
00346 printf("OFF\n");
00347 }
00348 }
00349
00350 int NutTraceRegisterUserTag(int tag, char* tag_string)
00351 {
00352 if (tag >= TRACE_MAX_USER)
00353 return -1;
00354
00355 user_string[tag] = tag_string;
00356 return tag;
00357 }
00358 #endif