24 /*for memcpy*/ |
24 /*for memcpy*/ |
25 #include <string.h> |
25 #include <string.h> |
26 #include <stdio.h> |
26 #include <stdio.h> |
27 |
27 |
28 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
28 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
29 #define BUFFER_SIZE %(buffer_size)d |
29 #define TRACE_BUFFER_SIZE 4096 |
|
30 #define TRACE_LIST_SIZE 1024 |
30 |
31 |
31 /* Atomically accessed variable for buffer state */ |
32 /* Atomically accessed variable for buffer state */ |
32 #define BUFFER_FREE 0 |
33 #define BUFFER_FREE 0 |
33 #define BUFFER_BUSY 1 |
34 #define BUFFER_BUSY 1 |
34 static long buffer_state = BUFFER_FREE; |
35 static long trace_buffer_state = BUFFER_FREE; |
35 |
36 |
36 /* The buffer itself */ |
37 typedef unsigned int dbgvardsc_index_t; |
37 char debug_buffer[BUFFER_SIZE]; |
38 typedef unsigned short trace_buf_offset_t; |
|
39 |
|
40 typedef struct trace_item_s { |
|
41 dbgvardsc_index_t dbgvardsc_index; |
|
42 } trace_item_t; |
|
43 |
|
44 trace_item_t trace_list[TRACE_LIST_SIZE]; |
|
45 char trace_buffer[TRACE_BUFFER_SIZE]; |
38 |
46 |
39 /* Buffer's cursor*/ |
47 /* Buffer's cursor*/ |
40 static char* buffer_cursor = debug_buffer; |
48 static trace_item_t *trace_list_collect_cursor = trace_list; |
|
49 static trace_item_t *trace_list_addvar_cursor = trace_list; |
|
50 static const trace_item_t *trace_list_end = |
|
51 &trace_list[TRACE_LIST_SIZE-1]; |
|
52 static char *trace_buffer_cursor = trace_buffer; |
|
53 static const char *trace_buffer_end = trace_buffer + TRACE_BUFFER_SIZE; |
41 #endif |
54 #endif |
42 |
55 |
43 static unsigned int retain_offset = 0; |
56 static unsigned int retain_offset = 0; |
44 /*** |
57 /*** |
45 * Declare programs |
58 * Declare programs |
145 void *visible_value_p = NULL; |
160 void *visible_value_p = NULL; |
146 char flags = 0; |
161 char flags = 0; |
147 |
162 |
148 visible_value_p = UnpackVar(dsc, &real_value_p, &flags); |
163 visible_value_p = UnpackVar(dsc, &real_value_p, &flags); |
149 |
164 |
150 if(flags & ( __IEC_DEBUG_FLAG | __IEC_RETAIN_FLAG)){ |
165 if(flags & __IEC_RETAIN_FLAG || |
|
166 ((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG))){ |
151 USINT size = __get_type_enum_size(dsc->type); |
167 USINT size = __get_type_enum_size(dsc->type); |
152 |
168 |
153 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
169 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
154 if(flags & __IEC_DEBUG_FLAG){ |
170 if((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG)){ |
155 /* copy visible variable to buffer */; |
171 if(__Is_a_string(dsc)){ |
156 if(do_debug){ |
172 /* optimization for strings */ |
157 /* compute next cursor positon. |
173 size = ((STRING*)visible_value_p)->len + 1; |
158 No need to check overflow, as BUFFER_SIZE |
|
159 is computed large enough */ |
|
160 if(__Is_a_string(dsc)){ |
|
161 /* optimization for strings */ |
|
162 size = ((STRING*)visible_value_p)->len + 1; |
|
163 } |
|
164 char* next_cursor = buffer_cursor + size; |
|
165 /* copy data to the buffer */ |
|
166 memcpy(buffer_cursor, visible_value_p, size); |
|
167 /* increment cursor according size*/ |
|
168 buffer_cursor = next_cursor; |
|
169 } |
174 } |
170 /* re-force real value of outputs (M and Q)*/ |
175 /* re-force real value of outputs (M and Q)*/ |
171 if((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG)){ |
176 memcpy(real_value_p, visible_value_p, size); |
172 memcpy(real_value_p, visible_value_p, size); |
|
173 } |
|
174 } |
177 } |
175 #endif |
178 #endif |
176 |
179 |
177 if(flags & __IEC_RETAIN_FLAG){ |
180 if(flags & __IEC_RETAIN_FLAG){ |
178 /* compute next cursor positon*/ |
181 /* compute next cursor positon*/ |
234 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
237 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
235 /* Check there is no running debugger re-configuration */ |
238 /* Check there is no running debugger re-configuration */ |
236 if(TryEnterDebugSection()){ |
239 if(TryEnterDebugSection()){ |
237 /* Lock buffer */ |
240 /* Lock buffer */ |
238 long latest_state = AtomicCompareExchange( |
241 long latest_state = AtomicCompareExchange( |
239 &buffer_state, |
242 &trace_buffer_state, |
240 BUFFER_FREE, |
243 BUFFER_FREE, |
241 BUFFER_BUSY); |
244 BUFFER_BUSY); |
242 |
245 |
243 /* If buffer was free */ |
246 /* If buffer was free */ |
244 if(latest_state == BUFFER_FREE) |
247 if(latest_state == BUFFER_FREE) |
245 { |
248 { |
246 /* Reset buffer cursor */ |
249 /* Reset buffer cursor */ |
247 buffer_cursor = debug_buffer; |
250 trace_buffer_cursor = trace_buffer; |
|
251 /* Reset trace list cursor */ |
|
252 trace_list_collect_cursor = trace_list; |
248 /* Iterate over all variables to fill debug buffer */ |
253 /* Iterate over all variables to fill debug buffer */ |
249 __for_each_variable_do(DebugIterator); |
254 __for_each_variable_do(DebugIterator); |
|
255 while(trace_list_collect_cursor < trace_list_addvar_cursor){ |
|
256 void *real_value_p = NULL; |
|
257 void *visible_value_p = NULL; |
|
258 char flags = 0; |
|
259 USINT size; |
|
260 char* next_cursor; |
|
261 |
|
262 dbgvardsc_t *dsc = &dbgvardsc[ |
|
263 trace_list_collect_cursor->dbgvardsc_index]; |
|
264 |
|
265 visible_value_p = UnpackVar(dsc, &real_value_p, &flags); |
|
266 |
|
267 /* copy visible variable to buffer */; |
|
268 if(__Is_a_string(dsc)){ |
|
269 /* optimization for strings */ |
|
270 /* assume NULL terminated strings */ |
|
271 size = ((STRING*)visible_value_p)->len + 1; |
|
272 }else{ |
|
273 size = __get_type_enum_size(dsc->type); |
|
274 } |
|
275 |
|
276 /* compute next cursor positon.*/ |
|
277 next_cursor = trace_buffer_cursor + size; |
|
278 /* check for buffer overflow */ |
|
279 if(next_cursor < trace_buffer_end) |
|
280 /* copy data to the buffer */ |
|
281 memcpy(trace_buffer_cursor, visible_value_p, size); |
|
282 else |
|
283 /* stop looping in case of overflow */ |
|
284 break; |
|
285 /* increment cursor according size*/ |
|
286 trace_buffer_cursor = next_cursor; |
|
287 trace_list_collect_cursor++; |
|
288 } |
250 |
289 |
251 /* Leave debug section, |
290 /* Leave debug section, |
252 * Trigger asynchronous transmission |
291 * Trigger asynchronous transmission |
253 * (returns immediately) */ |
292 * (returns immediately) */ |
254 InitiateDebugTransfer(); /* size */ |
293 InitiateDebugTransfer(); /* size */ |
255 }else{ |
|
256 /* when not debugging, do only retain */ |
|
257 __for_each_variable_do(RetainIterator); |
|
258 } |
294 } |
259 LeaveDebugSection(); |
295 LeaveDebugSection(); |
260 }else |
296 } |
261 #endif |
297 #endif |
262 { |
298 /* when not debugging, do only retain */ |
263 /* when not debugging, do only retain */ |
299 __for_each_variable_do(RetainIterator); |
264 __for_each_variable_do(RetainIterator); |
|
265 } |
|
266 ValidateRetainBuffer(); |
300 ValidateRetainBuffer(); |
267 } |
301 } |
268 |
302 |
269 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
303 #ifndef TARGET_ONLINE_DEBUG_DISABLE |
270 #define __RegisterDebugVariable_case_t(TYPENAME) \ |
304 #define __RegisterDebugVariable_case_t(TYPENAME) \ |
271 case TYPENAME##_ENUM :\ |
305 case TYPENAME##_ENUM :\ |
272 ((__IEC_##TYPENAME##_t *)varp)->flags |= flags;\ |
306 ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_FORCE_FLAG;\ |
273 if(force)\ |
307 ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force);\ |
274 ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force);\ |
|
275 break; |
308 break; |
276 #define __RegisterDebugVariable_case_p(TYPENAME)\ |
309 #define __RegisterDebugVariable_case_p(TYPENAME)\ |
277 case TYPENAME##_P_ENUM :\ |
310 case TYPENAME##_P_ENUM :\ |
278 ((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\ |
311 ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG;\ |
279 if(force)\ |
312 ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\ |
280 ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\ |
|
281 break;\ |
313 break;\ |
282 case TYPENAME##_O_ENUM :\ |
314 case TYPENAME##_O_ENUM :\ |
283 ((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\ |
315 ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG;\ |
284 if(force){\ |
316 ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\ |
285 ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\ |
317 *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\ |
286 *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\ |
|
287 }\ |
|
288 break; |
318 break; |
289 void RegisterDebugVariable(unsigned int idx, void* force) |
319 void RegisterDebugVariable(dbgvardsc_index_t idx, void* force) |
290 { |
320 { |
291 if(idx < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){ |
321 if(idx < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){ |
292 unsigned char flags = force ? |
322 /* add to trace_list, inc tracelist_addvar_cursor*/ |
293 __IEC_DEBUG_FLAG | __IEC_FORCE_FLAG : |
323 if(trace_list_addvar_cursor <= trace_list_end){ |
294 __IEC_DEBUG_FLAG; |
324 trace_list_addvar_cursor->dbgvardsc_index = idx; |
295 dbgvardsc_t *dsc = &dbgvardsc[idx]; |
325 trace_list_addvar_cursor++; |
296 void *varp = dsc->ptr; |
326 } |
297 switch(dsc->type){ |
327 if(force){ |
298 __ANY(__RegisterDebugVariable_case_t) |
328 dbgvardsc_t *dsc = &dbgvardsc[idx]; |
299 __ANY(__RegisterDebugVariable_case_p) |
329 void *varp = dsc->ptr; |
300 default: |
330 switch(dsc->type){ |
301 break; |
331 __ANY(__RegisterDebugVariable_case_t) |
|
332 __ANY(__RegisterDebugVariable_case_p) |
|
333 default: |
|
334 break; |
|
335 } |
302 } |
336 } |
303 } |
337 } |
304 } |
338 } |
305 |
339 |
306 #define __ResetDebugVariablesIterator_case_t(TYPENAME) \ |
340 #define __ResetDebugVariablesIterator_case_t(TYPENAME) \ |
307 case TYPENAME##_ENUM :\ |
341 case TYPENAME##_ENUM :\ |
308 ((__IEC_##TYPENAME##_t *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\ |
342 ((__IEC_##TYPENAME##_t *)varp)->flags &= ~(__IEC_FORCE_FLAG);\ |
309 break; |
343 break; |
310 |
344 |
311 #define __ResetDebugVariablesIterator_case_p(TYPENAME)\ |
345 #define __ResetDebugVariablesIterator_case_p(TYPENAME)\ |
312 case TYPENAME##_P_ENUM :\ |
346 case TYPENAME##_P_ENUM :\ |
313 case TYPENAME##_O_ENUM :\ |
347 case TYPENAME##_O_ENUM :\ |
314 ((__IEC_##TYPENAME##_p *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\ |
348 ((__IEC_##TYPENAME##_p *)varp)->flags &= ~(__IEC_FORCE_FLAG);\ |
315 break; |
349 break; |
316 |
350 |
317 void ResetDebugVariablesIterator(dbgvardsc_t *dsc) |
351 void ResetDebugVariablesIterator(dbgvardsc_t *dsc) |
318 { |
352 { |
319 /* force debug flag to 0*/ |
353 /* force debug flag to 0*/ |