Commit | Line | Data |
---|---|---|
f519b94b FS |
1 | #include "variable_trace.h" |
2 | #include <stddef.h> | |
3 | #include <string.h> | |
4 | ||
5 | #ifdef NO_PRINT | |
6 | #error "You need undef NO_PRINT to use the variable trace feature" | |
7 | #endif | |
8 | ||
9 | #ifndef CONSOLE_ENABLE | |
10 | #error "The console needs to be enabled in the makefile to use the variable trace feature" | |
11 | #endif | |
12 | ||
13 | ||
14 | #define NUM_TRACED_VARIABLES 1 | |
a377017c FS |
15 | #ifndef MAX_VARIABLE_TRACE_SIZE |
16 | #define MAX_VARIABLE_TRACE_SIZE 4 | |
17 | #endif | |
f519b94b FS |
18 | |
19 | typedef struct { | |
20 | const char* name; | |
21 | void* addr; | |
22 | unsigned size; | |
23 | const char* func; | |
24 | int line; | |
a377017c | 25 | uint8_t last_value[MAX_VARIABLE_TRACE_SIZE]; |
f519b94b FS |
26 | |
27 | } traced_variable_t; | |
28 | ||
29 | static traced_variable_t traced_variables[NUM_TRACED_VARIABLES]; | |
30 | ||
31 | void add_traced_variable(const char* name, void* addr, unsigned size, const char* func, int line) { | |
32 | verify_traced_variables(func, line); | |
a377017c | 33 | if (size > MAX_VARIABLE_TRACE_SIZE) { |
f519b94b FS |
34 | #if defined(__AVR__) |
35 | xprintf("Traced variable \"%S\" exceeds the maximum size %d\n", name, size); | |
36 | #else | |
37 | xprintf("Traced variable \"%s\" exceeds the maximum size %d\n", name, size); | |
38 | #endif | |
a377017c | 39 | size = MAX_VARIABLE_TRACE_SIZE; |
f519b94b FS |
40 | } |
41 | int index = -1; | |
42 | for (int i = 0; i < NUM_TRACED_VARIABLES; i++) { | |
43 | if (index == -1 && traced_variables[i].addr == NULL){ | |
44 | index = i; | |
45 | } | |
46 | else if (strcmp_P(name, traced_variables[i].name)==0) { | |
47 | index = i; | |
48 | break; | |
49 | } | |
50 | } | |
51 | ||
52 | if (index == -1) { | |
53 | xprintf("You can only trace %d variables at the same time\n", NUM_TRACED_VARIABLES); | |
54 | return; | |
55 | } | |
56 | ||
57 | traced_variable_t* t = &traced_variables[index]; | |
58 | t->name = name; | |
59 | t->addr = addr; | |
60 | t->size = size; | |
61 | t->func = func; | |
62 | t->line = line; | |
63 | memcpy(&t->last_value[0], addr, size); | |
64 | ||
65 | } | |
66 | ||
67 | void remove_traced_variable(const char* name, const char* func, int line) { | |
68 | verify_traced_variables(func, line); | |
69 | for (int i = 0; i < NUM_TRACED_VARIABLES; i++) { | |
70 | if (strcmp_P(name, traced_variables[i].name)==0) { | |
71 | traced_variables[i].name = 0; | |
72 | traced_variables[i].addr = NULL; | |
73 | break; | |
74 | } | |
75 | } | |
76 | } | |
77 | ||
78 | void verify_traced_variables(const char* func, int line) { | |
79 | for (int i = 0; i < NUM_TRACED_VARIABLES; i++) { | |
80 | traced_variable_t* t = &traced_variables[i]; | |
81 | if (t->addr != NULL && t->name != NULL) { | |
82 | if (memcmp(t->last_value, t->addr, t->size)!=0){ | |
83 | #if defined(__AVR__) | |
84 | xprintf("Traced variable \"%S\" has been modified\n", t->name); | |
85 | xprintf("Between %S:%d\n", t->func, t->line); | |
86 | xprintf("And %S:%d\n", func, line); | |
87 | ||
88 | #else | |
89 | xprintf("Traced variable \"%s\" has been modified\n", t->name); | |
90 | xprintf("Between %s:%d\n", t->func, t->line); | |
91 | xprintf("And %s:%d\n", func, line); | |
92 | #endif | |
93 | xprintf("Previous value "); | |
94 | for (int j=0; j<t->size;j++) { | |
95 | print_hex8(t->last_value[j]); | |
96 | } | |
97 | xprintf("\nNew value "); | |
98 | uint8_t* addr = (uint8_t*)(t->addr); | |
99 | for (int j=0; j<t->size;j++) { | |
100 | print_hex8(addr[j]); | |
101 | } | |
102 | xprintf("\n"); | |
103 | memcpy(t->last_value, addr, t->size); | |
104 | } | |
105 | } | |
106 | ||
107 | t->func = func; | |
108 | t->line = line; | |
109 | } | |
110 | } |