28 char debug_buffer[BUFFER_SIZE]; |
28 char debug_buffer[BUFFER_SIZE]; |
29 |
29 |
30 /* Buffer's cursor*/ |
30 /* Buffer's cursor*/ |
31 static char* buffer_cursor = debug_buffer; |
31 static char* buffer_cursor = debug_buffer; |
32 |
32 |
33 typedef struct{ |
|
34 void* ptrvalue; |
|
35 __IEC_types_enum type; |
|
36 }struct_plcvar; |
|
37 |
|
38 /*** |
33 /*** |
39 * Declare programs |
34 * Declare programs |
40 **/ |
35 **/ |
41 %(programs_declarations)s |
36 %(programs_declarations)s |
42 |
37 |
43 /*** |
38 /*** |
44 * Declare global variables from resources and conf |
39 * Declare global variables from resources and conf |
45 **/ |
40 **/ |
46 %(extern_variables_declarations)s |
41 %(extern_variables_declarations)s |
47 |
42 |
48 static int subscription_table[MAX_SUBSCRIBTION]; |
43 typedef void(*__for_each_variable_do_fp)(void*, __IEC_types_enum); |
49 static int* latest_subscription = subscription_table; |
44 __for_each_variable_do(__for_each_variable_do_fp fp) |
50 static int* subscription_cursor = subscription_table; |
45 { |
|
46 %(for_each_variable_do_code)s |
|
47 } |
51 |
48 |
52 struct_plcvar variable_table[%(variables_pointer_type_table_count)d]; |
49 __IEC_types_enum __find_variable(unsigned int varindex, void ** varp) |
|
50 { |
|
51 switch(varindex){ |
|
52 %(find_variable_case_code)s |
|
53 } |
|
54 *varp = NULL; |
|
55 return UNKNOWN_ENUM; |
|
56 } |
53 |
57 |
54 void __init_debug(void) |
58 void __init_debug(void) |
55 { |
59 { |
56 %(variables_pointer_type_table_initializer)s |
|
57 buffer_state = BUFFER_FREE; |
60 buffer_state = BUFFER_FREE; |
58 } |
61 } |
59 |
62 |
60 void __cleanup_debug(void) |
63 void __cleanup_debug(void) |
61 { |
64 { |
69 extern void LeaveDebugSection(void); |
72 extern void LeaveDebugSection(void); |
70 extern long AtomicCompareExchange(long*, long, long); |
73 extern long AtomicCompareExchange(long*, long, long); |
71 extern void InitiateDebugTransfer(void); |
74 extern void InitiateDebugTransfer(void); |
72 |
75 |
73 extern unsigned long __tick; |
76 extern unsigned long __tick; |
|
77 |
|
78 #define __BufferDebugDataIterator_case_t(TYPENAME) \ |
|
79 case TYPENAME##_ENUM :\ |
|
80 flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\ |
|
81 ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value; |
|
82 |
|
83 #define __BufferDebugDataIterator_case_p(TYPENAME)\ |
|
84 case TYPENAME##_P_ENUM :\ |
|
85 flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\ |
|
86 ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value; |
|
87 |
|
88 void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype) |
|
89 { |
|
90 void *ptrvalue = NULL; |
|
91 char flags = 0; |
|
92 /* find data to copy*/ |
|
93 switch(vartype){ |
|
94 ANY(__BufferDebugDataIterator_case_t) |
|
95 ANY(__BufferDebugDataIterator_case_p) |
|
96 } |
|
97 if(flags && __IEC_DEBUG_FLAG){ |
|
98 USINT size = __get_type_enum_size(vartype); |
|
99 /* compute next cursor positon*/ |
|
100 char* next_cursor = buffer_cursor + size; |
|
101 /* if buffer not full */ |
|
102 if(next_cursor <= debug_buffer + BUFFER_SIZE) |
|
103 { |
|
104 /* copy data to the buffer */ |
|
105 memcpy(buffer_cursor, ptrvalue, size); |
|
106 /* increment cursor according size*/ |
|
107 buffer_cursor = next_cursor; |
|
108 }else{ |
|
109 /*TODO : signal overflow*/ |
|
110 } |
|
111 } |
|
112 } |
|
113 |
|
114 |
74 void __publish_debug(void) |
115 void __publish_debug(void) |
75 { |
116 { |
76 /* Check there is no running debugger re-configuration */ |
117 /* Check there is no running debugger re-configuration */ |
77 if(TryEnterDebugSection()){ |
118 if(TryEnterDebugSection()){ |
78 /* Lock buffer */ |
119 /* Lock buffer */ |
82 BUFFER_BUSY); |
123 BUFFER_BUSY); |
83 |
124 |
84 /* If buffer was free */ |
125 /* If buffer was free */ |
85 if(latest_state == BUFFER_FREE) |
126 if(latest_state == BUFFER_FREE) |
86 { |
127 { |
87 int* subscription; |
|
88 |
|
89 /* Reset buffer cursor */ |
128 /* Reset buffer cursor */ |
90 buffer_cursor = debug_buffer; |
129 buffer_cursor = debug_buffer; |
91 |
130 /* Iterate over all variables to fill debug buffer */ |
92 /* iterate over subscriptions */ |
131 __for_each_variable_do(BufferDebugDataIterator); |
93 for(subscription=subscription_table; |
|
94 subscription < latest_subscription; |
|
95 subscription++) |
|
96 { |
|
97 /* get variable descriptor */ |
|
98 struct_plcvar* my_var = &variable_table[*subscription]; |
|
99 char* next_cursor; |
|
100 /* get variable size*/ |
|
101 USINT size = __get_type_enum_size(my_var->type); |
|
102 /* compute next cursor positon*/ |
|
103 next_cursor = buffer_cursor + size; |
|
104 /* if buffer not full */ |
|
105 if(next_cursor <= debug_buffer + BUFFER_SIZE) |
|
106 { |
|
107 /* copy data to the buffer */ |
|
108 memcpy(buffer_cursor, my_var->ptrvalue, size); |
|
109 /* increment cursor according size*/ |
|
110 buffer_cursor = next_cursor; |
|
111 }else{ |
|
112 /*TODO : signal overflow*/ |
|
113 } |
|
114 } |
|
115 |
|
116 /* Reset buffer cursor again (for IterDebugData)*/ |
|
117 buffer_cursor = debug_buffer; |
|
118 subscription_cursor = subscription_table; |
|
119 |
132 |
120 /* Leave debug section, |
133 /* Leave debug section, |
121 * Trigger asynchronous transmission |
134 * Trigger asynchronous transmission |
122 * (returns immediately) */ |
135 * (returns immediately) */ |
123 InitiateDebugTransfer(); /* size */ |
136 InitiateDebugTransfer(); /* size */ |
124 } |
137 } |
125 LeaveDebugSection(); |
138 LeaveDebugSection(); |
126 } |
139 } |
127 } |
140 } |
128 |
141 |
|
142 #define __RegisterDebugVariable_case_t(TYPENAME) \ |
|
143 case TYPENAME##_ENUM :\ |
|
144 ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_DEBUG_FLAG; |
|
145 #define __RegisterDebugVariable_case_p(TYPENAME)\ |
|
146 case TYPENAME##_P_ENUM :\ |
|
147 ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_DEBUG_FLAG; |
129 void RegisterDebugVariable(int idx) |
148 void RegisterDebugVariable(int idx) |
130 { |
149 { |
131 /*If subscription table not full */ |
150 void *varp; |
132 if(latest_subscription - subscription_table < MAX_SUBSCRIBTION) |
151 switch(__find_variable(idx, varp)){ |
133 { |
152 ANY(__RegisterDebugVariable_case_t) |
134 *(latest_subscription++) = idx; |
153 ANY(__RegisterDebugVariable_case_p) |
135 /* TODO pre-calc buffer size and signal overflow*/ |
154 } |
136 }else{ |
155 } |
137 /*TODO : signal subscription overflow*/ |
156 |
|
157 #define __ResetDebugVariablesIterator_case_t(TYPENAME) \ |
|
158 case TYPENAME##_ENUM :\ |
|
159 ((__IEC_##TYPENAME##_t *)varp)->flags &= ~__IEC_DEBUG_FLAG; |
|
160 |
|
161 #define __ResetDebugVariablesIterator_case_p(TYPENAME)\ |
|
162 case TYPENAME##_P_ENUM :\ |
|
163 ((__IEC_##TYPENAME##_p *)varp)->flags &= ~__IEC_DEBUG_FLAG;\ |
|
164 |
|
165 void ResetDebugVariablesIterator(void* varp, __IEC_types_enum vartype) |
|
166 { |
|
167 /* force debug flag to 0*/ |
|
168 switch(vartype){ |
|
169 ANY(__ResetDebugVariablesIterator_case_t) |
|
170 ANY(__ResetDebugVariablesIterator_case_p) |
138 } |
171 } |
139 } |
172 } |
140 |
173 |
141 void ResetDebugVariables(void) |
174 void ResetDebugVariables(void) |
142 { |
175 { |
143 latest_subscription = subscription_table; |
176 __for_each_variable_do(ResetDebugVariablesIterator); |
144 } |
177 } |
145 |
178 |
146 void FreeDebugData(void) |
179 void FreeDebugData(void) |
147 { |
180 { |
148 /* atomically mark buffer as free */ |
181 /* atomically mark buffer as free */ |
151 &buffer_state, |
184 &buffer_state, |
152 BUFFER_BUSY, |
185 BUFFER_BUSY, |
153 BUFFER_FREE); |
186 BUFFER_FREE); |
154 } |
187 } |
155 |
188 |
156 void* IterDebugData(int* idx, const char **type_name) |
189 /* Wait until debug data ready and return pointer to it */ |
157 { |
190 int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){ |
158 struct_plcvar* my_var; |
191 int res = WaitDebugData(tick); |
159 USINT size; |
192 *size = buffer_cursor - debug_buffer; |
160 if(subscription_cursor < latest_subscription){ |
193 *buffer = NULL; |
161 char* old_cursor = buffer_cursor; |
194 return res; |
162 *idx = *subscription_cursor; |
|
163 my_var = &variable_table[*(subscription_cursor++)]; |
|
164 *type_name = __get_type_enum_name(my_var->type); |
|
165 /* get variable size*/ |
|
166 size = __get_type_enum_size(my_var->type); |
|
167 /* compute next cursor position*/ |
|
168 buffer_cursor = buffer_cursor + size; |
|
169 if(old_cursor < debug_buffer + BUFFER_SIZE) |
|
170 { |
|
171 return old_cursor; |
|
172 }else{ |
|
173 //printf("%%d > %%d\n", old_cursor - debug_buffer, BUFFER_SIZE); |
|
174 return NULL; |
|
175 } |
|
176 } |
|
177 *idx = -1; |
|
178 *type_name = NULL; |
|
179 return NULL; |
|
180 } |
195 } |
181 |
196 |