]> git.donarmstrong.com Git - qmk_firmware.git/blob - quantum/variable_trace.c
Add variable trace
[qmk_firmware.git] / quantum / variable_trace.c
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
15 #define MAX_TRACE_SIZE 4
16
17 typedef struct {
18     const char* name;
19     void* addr;
20     unsigned size;
21     const char* func;
22     int line;
23     uint8_t last_value[MAX_TRACE_SIZE];
24
25 } traced_variable_t;
26
27 static traced_variable_t traced_variables[NUM_TRACED_VARIABLES];
28
29 void add_traced_variable(const char* name, void* addr, unsigned size, const char* func, int line) {
30     verify_traced_variables(func, line);
31     if (size > MAX_TRACE_SIZE) {
32 #if defined(__AVR__)
33        xprintf("Traced variable \"%S\" exceeds the maximum size %d\n", name, size);
34 #else
35        xprintf("Traced variable \"%s\" exceeds the maximum size %d\n", name, size);
36 #endif
37        size = MAX_TRACE_SIZE;
38     }
39     int index = -1;
40     for (int i = 0; i < NUM_TRACED_VARIABLES; i++) {
41         if (index == -1 && traced_variables[i].addr == NULL){
42             index = i;
43         }
44         else if (strcmp_P(name, traced_variables[i].name)==0) {
45             index = i;
46             break;
47         }
48     }
49
50     if (index == -1) {
51         xprintf("You can only trace %d variables at the same time\n", NUM_TRACED_VARIABLES);
52         return;
53     }
54
55     traced_variable_t* t = &traced_variables[index];
56     t->name = name;
57     t->addr = addr;
58     t->size = size;
59     t->func = func;
60     t->line = line;
61     memcpy(&t->last_value[0], addr, size);
62
63 }
64
65 void remove_traced_variable(const char* name, const char* func, int line) {
66     verify_traced_variables(func, line);
67     for (int i = 0; i < NUM_TRACED_VARIABLES; i++) {
68         if (strcmp_P(name, traced_variables[i].name)==0) {
69             traced_variables[i].name = 0;
70             traced_variables[i].addr = NULL;
71             break;
72         }
73     }
74 }
75
76 void verify_traced_variables(const char* func, int line) {
77     for (int i = 0; i < NUM_TRACED_VARIABLES; i++) {
78         traced_variable_t* t = &traced_variables[i];
79         if (t->addr != NULL && t->name != NULL) {
80             if (memcmp(t->last_value, t->addr, t->size)!=0){
81 #if defined(__AVR__)
82                xprintf("Traced variable \"%S\" has been modified\n", t->name);
83                xprintf("Between %S:%d\n", t->func, t->line);
84                xprintf("And %S:%d\n", func, line);
85
86 #else
87                xprintf("Traced variable \"%s\" has been modified\n", t->name);
88                xprintf("Between %s:%d\n", t->func, t->line);
89                xprintf("And %s:%d\n", func, line);
90 #endif
91                xprintf("Previous value ");
92                for (int j=0; j<t->size;j++) {
93                    print_hex8(t->last_value[j]);
94                }
95                xprintf("\nNew value ");
96                uint8_t* addr = (uint8_t*)(t->addr);
97                for (int j=0; j<t->size;j++) {
98                    print_hex8(addr[j]);
99                }
100                xprintf("\n");
101                memcpy(t->last_value, addr, t->size);
102            }
103         }
104
105         t->func = func;
106         t->line = line;
107     }
108 }