Commit | Line | Data |
---|---|---|
23839b8c | 1 | /* Copyright 2016 Fred Sundvik |
2 | * | |
3 | * This program is free software: you can redistribute it and/or modify | |
4 | * it under the terms of the GNU General Public License as published by | |
5 | * the Free Software Foundation, either version 2 of the License, or | |
6 | * (at your option) any later version. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
15 | */ | |
16 | ||
f519b94b FS |
17 | #include "variable_trace.h" |
18 | #include <stddef.h> | |
19 | #include <string.h> | |
20 | ||
21 | #ifdef NO_PRINT | |
b624f32f | 22 | # error "You need undef NO_PRINT to use the variable trace feature" |
f519b94b FS |
23 | #endif |
24 | ||
25 | #ifndef CONSOLE_ENABLE | |
b624f32f | 26 | # error "The console needs to be enabled in the makefile to use the variable trace feature" |
f519b94b FS |
27 | #endif |
28 | ||
f519b94b | 29 | #define NUM_TRACED_VARIABLES 1 |
a377017c | 30 | #ifndef MAX_VARIABLE_TRACE_SIZE |
b624f32f | 31 | # define MAX_VARIABLE_TRACE_SIZE 4 |
a377017c | 32 | #endif |
f519b94b FS |
33 | |
34 | typedef struct { | |
35 | const char* name; | |
b624f32f | 36 | void* addr; |
37 | unsigned size; | |
f519b94b | 38 | const char* func; |
b624f32f | 39 | int line; |
40 | uint8_t last_value[MAX_VARIABLE_TRACE_SIZE]; | |
f519b94b FS |
41 | |
42 | } traced_variable_t; | |
43 | ||
44 | static traced_variable_t traced_variables[NUM_TRACED_VARIABLES]; | |
45 | ||
46 | void add_traced_variable(const char* name, void* addr, unsigned size, const char* func, int line) { | |
47 | verify_traced_variables(func, line); | |
a377017c | 48 | if (size > MAX_VARIABLE_TRACE_SIZE) { |
f519b94b | 49 | #if defined(__AVR__) |
b624f32f | 50 | xprintf("Traced variable \"%S\" exceeds the maximum size %d\n", name, size); |
f519b94b | 51 | #else |
b624f32f | 52 | xprintf("Traced variable \"%s\" exceeds the maximum size %d\n", name, size); |
f519b94b | 53 | #endif |
b624f32f | 54 | size = MAX_VARIABLE_TRACE_SIZE; |
f519b94b FS |
55 | } |
56 | int index = -1; | |
57 | for (int i = 0; i < NUM_TRACED_VARIABLES; i++) { | |
b624f32f | 58 | if (index == -1 && traced_variables[i].addr == NULL) { |
f519b94b | 59 | index = i; |
b624f32f | 60 | } else if (strcmp_P(name, traced_variables[i].name) == 0) { |
f519b94b FS |
61 | index = i; |
62 | break; | |
63 | } | |
64 | } | |
65 | ||
66 | if (index == -1) { | |
67 | xprintf("You can only trace %d variables at the same time\n", NUM_TRACED_VARIABLES); | |
68 | return; | |
69 | } | |
70 | ||
71 | traced_variable_t* t = &traced_variables[index]; | |
b624f32f | 72 | t->name = name; |
73 | t->addr = addr; | |
74 | t->size = size; | |
75 | t->func = func; | |
76 | t->line = line; | |
f519b94b | 77 | memcpy(&t->last_value[0], addr, size); |
f519b94b FS |
78 | } |
79 | ||
80 | void remove_traced_variable(const char* name, const char* func, int line) { | |
81 | verify_traced_variables(func, line); | |
82 | for (int i = 0; i < NUM_TRACED_VARIABLES; i++) { | |
b624f32f | 83 | if (strcmp_P(name, traced_variables[i].name) == 0) { |
f519b94b FS |
84 | traced_variables[i].name = 0; |
85 | traced_variables[i].addr = NULL; | |
86 | break; | |
87 | } | |
88 | } | |
89 | } | |
90 | ||
91 | void verify_traced_variables(const char* func, int line) { | |
92 | for (int i = 0; i < NUM_TRACED_VARIABLES; i++) { | |
93 | traced_variable_t* t = &traced_variables[i]; | |
94 | if (t->addr != NULL && t->name != NULL) { | |
b624f32f | 95 | if (memcmp(t->last_value, t->addr, t->size) != 0) { |
f519b94b | 96 | #if defined(__AVR__) |
b624f32f | 97 | xprintf("Traced variable \"%S\" has been modified\n", t->name); |
98 | xprintf("Between %S:%d\n", t->func, t->line); | |
99 | xprintf("And %S:%d\n", func, line); | |
f519b94b FS |
100 | |
101 | #else | |
b624f32f | 102 | xprintf("Traced variable \"%s\" has been modified\n", t->name); |
103 | xprintf("Between %s:%d\n", t->func, t->line); | |
104 | xprintf("And %s:%d\n", func, line); | |
f519b94b | 105 | #endif |
b624f32f | 106 | xprintf("Previous value "); |
107 | for (int j = 0; j < t->size; j++) { | |
108 | print_hex8(t->last_value[j]); | |
109 | } | |
110 | xprintf("\nNew value "); | |
111 | uint8_t* addr = (uint8_t*)(t->addr); | |
112 | for (int j = 0; j < t->size; j++) { | |
113 | print_hex8(addr[j]); | |
114 | } | |
115 | xprintf("\n"); | |
116 | memcpy(t->last_value, addr, t->size); | |
117 | } | |
f519b94b FS |
118 | } |
119 | ||
120 | t->func = func; | |
121 | t->line = line; | |
122 | } | |
123 | } |