1 /* |
|
2 * DEBUGGER code |
|
3 * |
|
4 * On "publish", when buffer is free, debugger stores arbitrary variables |
|
5 * content into, and mark this buffer as filled |
|
6 * |
|
7 * |
|
8 * Buffer content is read asynchronously, (from non real time part), |
|
9 * and then buffer marked free again. |
|
10 * |
|
11 * |
|
12 * */ |
|
13 #include "iec_types_all.h" |
|
14 #include "POUS.h" |
|
15 /*for memcpy*/ |
|
16 #include <string.h> |
|
17 |
|
18 #define BUFFER_SIZE 1024 |
|
19 #define MAX_SUBSCRIBTION %(subscription_table_count)d |
|
20 |
|
21 /* Atomically accessed variable for buffer state */ |
|
22 #define BUFFER_FREE 0 |
|
23 #define BUFFER_BUSY 1 |
|
24 static long buffer_state = BUFFER_FREE; |
|
25 |
|
26 /* The buffer itself */ |
|
27 char debug_buffer[BUFFER_SIZE]; |
|
28 |
|
29 /* Buffer's cursor*/ |
|
30 static char* buffer_cursor = debug_buffer; |
|
31 |
|
32 typedef struct{ |
|
33 void* ptrvalue; |
|
34 __IEC_types_enum type; |
|
35 }struct_plcvar; |
|
36 |
|
37 /*** |
|
38 * Declare programs |
|
39 **/ |
|
40 %(programs_declarations)s |
|
41 |
|
42 /*** |
|
43 * Declare global variables from resources and conf |
|
44 **/ |
|
45 %(extern_variables_declarations)s |
|
46 |
|
47 static int subscription_table[MAX_SUBSCRIBTION]; |
|
48 static int* latest_subscription = subscription_table; |
|
49 static int* subscription_cursor = subscription_table; |
|
50 |
|
51 struct_plcvar variable_table[%(variables_pointer_type_table_count)d]; |
|
52 |
|
53 void __init_debug() |
|
54 { |
|
55 %(variables_pointer_type_table_initializer)s |
|
56 }; |
|
57 |
|
58 void __cleanup_debug() |
|
59 { |
|
60 } |
|
61 |
|
62 void __retrieve_debug() |
|
63 { |
|
64 } |
|
65 |
|
66 void __publish_debug() |
|
67 { |
|
68 /* Lock buffer */ |
|
69 long latest_state = AtomicCompareExchange( |
|
70 &buffer_state, |
|
71 BUFFER_FREE, |
|
72 BUFFER_BUSY); |
|
73 |
|
74 /* If buffer was free */ |
|
75 if(latest_state == BUFFER_FREE) |
|
76 { |
|
77 int* subscription; |
|
78 |
|
79 /* Reset buffer cursor */ |
|
80 buffer_cursor = debug_buffer; |
|
81 |
|
82 /* iterate over subscriptions */ |
|
83 for(subscription=subscription_table; |
|
84 subscription < latest_subscription; |
|
85 subscription++) |
|
86 { |
|
87 /* get variable descriptor */ |
|
88 struct_plcvar* my_var = &variable_table[*subscription]; |
|
89 char* next_cursor; |
|
90 /* get variable size*/ |
|
91 USINT size = __get_type_enum_size(my_var->type); |
|
92 /* compute next cursor positon*/ |
|
93 next_cursor = buffer_cursor + size; |
|
94 /* if buffer not full */ |
|
95 if(next_cursor < debug_buffer + BUFFER_SIZE) |
|
96 { |
|
97 /* copy data to the buffer */ |
|
98 memcpy(buffer_cursor, my_var->ptrvalue, size); |
|
99 /* increment cursor according size*/ |
|
100 buffer_cursor = next_cursor; |
|
101 }else{ |
|
102 /*TODO : signal overflow*/ |
|
103 } |
|
104 } |
|
105 |
|
106 /* Reset buffer cursor again (for IterDebugData)*/ |
|
107 buffer_cursor = debug_buffer; |
|
108 subscription_cursor = subscription_table; |
|
109 |
|
110 /* Trigger asynchronous transmission (returns immediately) */ |
|
111 InitiateDebugTransfer(); /* size */ |
|
112 } |
|
113 } |
|
114 |
|
115 void RegisterDebugVariable(int idx) |
|
116 { |
|
117 /*If subscription table not full */ |
|
118 if(latest_subscription - subscription_table < MAX_SUBSCRIBTION) |
|
119 { |
|
120 *(latest_subscription++) = idx; |
|
121 /* TODO pre-calc buffer size and signal overflow*/ |
|
122 }else{ |
|
123 /*TODO : signal subscription overflow*/ |
|
124 } |
|
125 } |
|
126 |
|
127 void ResetDebugVariables(void) |
|
128 { |
|
129 latest_subscription = subscription_table; |
|
130 } |
|
131 |
|
132 void FreeDebugData() |
|
133 { |
|
134 /* atomically mark buffer as free */ |
|
135 long latest_state = AtomicCompareExchange( |
|
136 &buffer_state, |
|
137 BUFFER_BUSY, |
|
138 BUFFER_FREE); |
|
139 } |
|
140 |
|
141 void* IterDebugData(int* idx, const char **type_name) |
|
142 { |
|
143 if(subscription_cursor < latest_subscription){ |
|
144 *idx = *subscription_cursor; |
|
145 struct_plcvar* my_var = &variable_table[*subscription_cursor++]; |
|
146 *type_name = __get_type_enum_name(my_var->type); |
|
147 return my_var->ptrvalue; |
|
148 } |
|
149 return NULL; |
|
150 } |
|
151 |
|