diff -r 9ea29ac18837 -r 93ad018fb602 targets/plc_debug.c --- a/targets/plc_debug.c Wed Dec 01 09:54:02 2021 +0100 +++ b/targets/plc_debug.c Thu Dec 09 10:21:45 2021 +0100 @@ -25,17 +25,19 @@ #include #include +typedef unsigned int dbgvardsc_index_t; +typedef unsigned short trace_buf_offset_t; + +#define BUFFER_EMPTY 0 +#define BUFFER_FULL 1 + #ifndef TARGET_ONLINE_DEBUG_DISABLE + #define TRACE_BUFFER_SIZE 4096 #define TRACE_LIST_SIZE 1024 /* Atomically accessed variable for buffer state */ -#define BUFFER_FREE 0 -#define BUFFER_BUSY 1 -static long trace_buffer_state = BUFFER_FREE; - -typedef unsigned int dbgvardsc_index_t; -typedef unsigned short trace_buf_offset_t; +static long trace_buffer_state = BUFFER_EMPTY; typedef struct trace_item_s { dbgvardsc_index_t dbgvardsc_index; @@ -44,13 +46,36 @@ trace_item_t trace_list[TRACE_LIST_SIZE]; char trace_buffer[TRACE_BUFFER_SIZE]; -/* Buffer's cursor*/ +/* Trace's cursor*/ static trace_item_t *trace_list_collect_cursor = trace_list; static trace_item_t *trace_list_addvar_cursor = trace_list; static const trace_item_t *trace_list_end = &trace_list[TRACE_LIST_SIZE-1]; static char *trace_buffer_cursor = trace_buffer; static const char *trace_buffer_end = trace_buffer + TRACE_BUFFER_SIZE; + + + +#define FORCE_BUFFER_SIZE 1024 +#define FORCE_LIST_SIZE 256 + +typedef struct force_item_s { + dbgvardsc_index_t dbgvardsc_index; + void *value_pointer_backup; +} force_item_t; + +force_item_t force_list[FORCE_LIST_SIZE]; +char force_buffer[FORCE_BUFFER_SIZE]; + +/* Force's cursor*/ +static force_item_t *force_list_apply_cursor = force_list; +static force_item_t *force_list_addvar_cursor = force_list; +static const force_item_t *force_list_end = + &force_list[FORCE_LIST_SIZE-1]; +static char *force_buffer_cursor = force_buffer; +static const char *force_buffer_end = force_buffer + FORCE_BUFFER_SIZE; + + #endif static unsigned int retain_offset = 0; @@ -92,16 +117,16 @@ void RemindIterator(dbgvardsc_t *dsc) { - void *real_value_p = NULL; - char flags = 0; - UnpackVar(dsc, &real_value_p, &flags); + void *value_p = NULL; + char flags; + size_t size; + UnpackVar(dsc, &value_p, &flags, &size); if(flags & __IEC_RETAIN_FLAG){ - USINT size = __get_type_enum_size(dsc->type); /* compute next cursor positon*/ unsigned int next_retain_offset = retain_offset + size; /* if buffer not full */ - Remind(retain_offset, size, real_value_p); + Remind(retain_offset, size, value_p); /* increment cursor according size*/ retain_offset = next_retain_offset; } @@ -117,7 +142,11 @@ trace_buffer_cursor = trace_buffer; trace_list_addvar_cursor = trace_list; trace_list_collect_cursor = trace_list; - trace_buffer_state = BUFFER_FREE; + trace_buffer_state = BUFFER_EMPTY; + + force_buffer_cursor = force_buffer; + force_list_addvar_cursor = force_list; + force_list_apply_cursor = force_list; #endif retain_offset = 0; @@ -156,40 +185,21 @@ static inline void BufferIterator(dbgvardsc_t *dsc, int do_debug) { - void *real_value_p = NULL; - void *visible_value_p = NULL; - char flags = 0; - - visible_value_p = UnpackVar(dsc, &real_value_p, &flags); - - if(flags & __IEC_RETAIN_FLAG || - ((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG))){ - USINT size = __get_type_enum_size(dsc->type); - -#ifndef TARGET_ONLINE_DEBUG_DISABLE - if((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG)){ - if(__Is_a_string(dsc)){ - /* optimization for strings */ - size = ((STRING*)visible_value_p)->len + 1; - } - /* re-force real value of outputs (M and Q)*/ - memcpy(real_value_p, visible_value_p, size); - } -#endif - - if(flags & __IEC_RETAIN_FLAG){ + void *value_p = NULL; + char flags; + size_t size; + + UnpackVar(dsc, &value_p, &flags, &size); + + if(flags & __IEC_RETAIN_FLAG){ + /* compute next cursor positon*/ unsigned int next_retain_offset = retain_offset + size; /* if buffer not full */ - Retain(retain_offset, size, real_value_p); + Retain(retain_offset, size, value_p); /* increment cursor according size*/ retain_offset = next_retain_offset; - } - } -} - -void DebugIterator(dbgvardsc_t *dsc){ - BufferIterator(dsc, 1); + } } void RetainIterator(dbgvardsc_t *dsc){ @@ -202,12 +212,11 @@ /* GetRetainSizeIterator */ void GetRetainSizeIterator(dbgvardsc_t *dsc) { - void *real_value_p = NULL; - char flags = 0; - UnpackVar(dsc, &real_value_p, &flags); + char flags; + size_t size; + UnpackVar(dsc, NULL, &flags, &size); if(flags & __IEC_RETAIN_FLAG){ - USINT size = __get_type_enum_size(dsc->type); /* Calc retain buffer size */ retain_size += size; } @@ -229,6 +238,24 @@ extern void ValidateRetainBuffer(void); extern void InValidateRetainBuffer(void); +#define __ReForceOutput_case_p(TYPENAME) \ + case TYPENAME##_P_ENUM : \ + case TYPENAME##_O_ENUM : \ + { \ + char *next_cursor = force_buffer_cursor + sizeof(TYPENAME); \ + if(next_cursor <= force_buffer_end ){ \ + /* outputs real value must be systematically forced */ \ + if(vartype == TYPENAME##_O_ENUM) \ + /* overwrite value pointed by backup */ \ + *((TYPENAME *)force_list_apply_cursor->value_pointer_backup) = \ + *((TYPENAME *)force_buffer_cursor); \ + /* inc force_buffer cursor */ \ + force_buffer_cursor = next_cursor; \ + }else{ \ + stop = 1; \ + } \ + } \ + break; void __publish_debug(void) { retain_offset = 0; @@ -240,37 +267,51 @@ /* Lock buffer */ long latest_state = AtomicCompareExchange( &trace_buffer_state, - BUFFER_FREE, - BUFFER_BUSY); + BUFFER_EMPTY, + BUFFER_FULL); /* If buffer was free */ - if(latest_state == BUFFER_FREE) + if(latest_state == BUFFER_EMPTY) { + int stop = 0; + /* Reset force list cursor */ + force_list_apply_cursor = force_list; + + /* iterate over force list */ + while(!stop && force_list_apply_cursor < force_list_addvar_cursor){ + dbgvardsc_t *dsc = &dbgvardsc[ + force_list_apply_cursor->dbgvardsc_index]; + void *varp = dsc->ptr; + __IEC_types_enum vartype = dsc->type; + switch(vartype){ + __ANY(__ReForceOutput_case_p) + default: + break; + } + force_list_apply_cursor++; \ + } + /* Reset buffer cursor */ trace_buffer_cursor = trace_buffer; /* Reset trace list cursor */ trace_list_collect_cursor = trace_list; - /* Iterate over all variables to fill debug buffer */ - __for_each_variable_do(DebugIterator); + + /* iterate over trace list */ while(trace_list_collect_cursor < trace_list_addvar_cursor){ - void *real_value_p = NULL; - void *visible_value_p = NULL; - char flags = 0; - USINT size; + void *value_p = NULL; + size_t size; char* next_cursor; dbgvardsc_t *dsc = &dbgvardsc[ trace_list_collect_cursor->dbgvardsc_index]; - visible_value_p = UnpackVar(dsc, &real_value_p, &flags); + UnpackVar(dsc, &value_p, NULL, &size); /* copy visible variable to buffer */; if(__Is_a_string(dsc)){ /* optimization for strings */ /* assume NULL terminated strings */ - size = ((STRING*)visible_value_p)->len + 1; - }else{ - size = __get_type_enum_size(dsc->type); + size = ((STRING*)value_p)->len + 1; } /* compute next cursor positon.*/ @@ -278,7 +319,7 @@ /* check for buffer overflow */ if(next_cursor < trace_buffer_end) /* copy data to the buffer */ - memcpy(trace_buffer_cursor, visible_value_p, size); + memcpy(trace_buffer_cursor, value_p, size); else /* stop looping in case of overflow */ break; @@ -301,69 +342,133 @@ } #ifndef TARGET_ONLINE_DEBUG_DISABLE -#define __RegisterDebugVariable_case_t(TYPENAME) \ - case TYPENAME##_ENUM :\ - ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_FORCE_FLAG;\ - ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force);\ - break; -#define __RegisterDebugVariable_case_p(TYPENAME)\ - case TYPENAME##_P_ENUM :\ - ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG;\ - ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\ - break;\ - case TYPENAME##_O_ENUM :\ - ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG;\ - ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\ - *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\ - break; -void RegisterDebugVariable(dbgvardsc_index_t idx, void* force) -{ + +#define TRACE_LIST_OVERFLOW 1 +#define FORCE_LIST_OVERFLOW 2 +#define FORCE_BUFFER_OVERFLOW 3 + +#define __ForceVariable_case_t(TYPENAME) \ + case TYPENAME##_ENUM : \ + /* add to force_list*/ \ + force_list_addvar_cursor->dbgvardsc_index = idx; \ + ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_FORCE_FLAG; \ + ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force); \ + break; +#define __ForceVariable_case_p(TYPENAME) \ + case TYPENAME##_P_ENUM : \ + case TYPENAME##_O_ENUM : \ + { \ + char *next_cursor = force_buffer_cursor + sizeof(TYPENAME); \ + if(next_cursor <= force_buffer_end ){ \ + /* add to force_list*/ \ + force_list_addvar_cursor->dbgvardsc_index = idx; \ + /* save pointer to backup */ \ + force_list_addvar_cursor->value_pointer_backup = \ + ((__IEC_##TYPENAME##_p *)varp)->value; \ + /* store forced value in force_buffer */ \ + *((TYPENAME *)force_buffer_cursor) = *((TYPENAME *)force); \ + /* replace pointer with pointer to force_buffer */ \ + ((__IEC_##TYPENAME##_p *)varp)->value = \ + (TYPENAME *)force_buffer_cursor; \ + /* mark variable as forced */ \ + ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG; \ + /* inc force_buffer cursor */ \ + force_buffer_cursor = next_cursor; \ + /* outputs real value must be systematically forced */ \ + if(vartype == TYPENAME##_O_ENUM) \ + *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\ + } else { \ + error_code = FORCE_BUFFER_OVERFLOW; \ + goto error_cleanup; \ + } \ + } \ + break; + + +void ResetDebugVariables(void); + +int RegisterDebugVariable(dbgvardsc_index_t idx, void* force) +{ + int error_code = 0; if(idx < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){ - /* add to trace_list, inc tracelist_addvar_cursor*/ + /* add to trace_list, inc trace_list_addvar_cursor*/ if(trace_list_addvar_cursor <= trace_list_end){ trace_list_addvar_cursor->dbgvardsc_index = idx; trace_list_addvar_cursor++; + } else { + error_code = TRACE_LIST_OVERFLOW; + goto error_cleanup; } if(force){ - dbgvardsc_t *dsc = &dbgvardsc[idx]; - void *varp = dsc->ptr; - switch(dsc->type){ - __ANY(__RegisterDebugVariable_case_t) - __ANY(__RegisterDebugVariable_case_p) - default: - break; + if(force_list_addvar_cursor <= force_list_end){ + dbgvardsc_t *dsc = &dbgvardsc[idx]; + void *varp = dsc->ptr; + __IEC_types_enum vartype = dsc->type; + + switch(vartype){ + __ANY(__ForceVariable_case_t) + __ANY(__ForceVariable_case_p) + default: + break; + } + /* inc force_list cursor */ + force_list_addvar_cursor++; + } else { + error_code = FORCE_LIST_OVERFLOW; + goto error_cleanup; } } } -} - -#define __ResetDebugVariablesIterator_case_t(TYPENAME) \ - case TYPENAME##_ENUM :\ - ((__IEC_##TYPENAME##_t *)varp)->flags &= ~(__IEC_FORCE_FLAG);\ - break; - -#define __ResetDebugVariablesIterator_case_p(TYPENAME)\ - case TYPENAME##_P_ENUM :\ - case TYPENAME##_O_ENUM :\ - ((__IEC_##TYPENAME##_p *)varp)->flags &= ~(__IEC_FORCE_FLAG);\ - break; - -void ResetDebugVariablesIterator(dbgvardsc_t *dsc) -{ - /* force debug flag to 0*/ - void *varp = dsc->ptr; - switch(dsc->type){ - __ANY(__ResetDebugVariablesIterator_case_t) - __ANY(__ResetDebugVariablesIterator_case_p) - default: - break; - } -} + return 0; + +error_cleanup: + ResetDebugVariables(); + trace_buffer_state = BUFFER_EMPTY; + return error_code; + +} + +#define ResetForcedVariable_case_t(TYPENAME) \ + case TYPENAME##_ENUM : \ + ((__IEC_##TYPENAME##_t *)varp)->flags &= ~__IEC_FORCE_FLAG; \ + /* for local variable we don't restore original value */ \ + /* that can be added if needed, but it was like that since ever */ \ + break; + +#define ResetForcedVariable_case_p(TYPENAME) \ + case TYPENAME##_P_ENUM : \ + case TYPENAME##_O_ENUM : \ + ((__IEC_##TYPENAME##_p *)varp)->flags &= ~__IEC_FORCE_FLAG; \ + /* restore backup to pointer */ \ + ((__IEC_##TYPENAME##_p *)varp)->value = \ + force_list_apply_cursor->value_pointer_backup; \ + break; void ResetDebugVariables(void) { + /* Reset trace list */ trace_list_addvar_cursor = trace_list; - __for_each_variable_do(ResetDebugVariablesIterator); + + force_list_apply_cursor = force_list; + /* Restore forced variables */ + while(force_list_apply_cursor < force_list_addvar_cursor){ + dbgvardsc_t *dsc = &dbgvardsc[ + force_list_apply_cursor->dbgvardsc_index]; + void *varp = dsc->ptr; + switch(dsc->type){ + __ANY(ResetForcedVariable_case_t) + __ANY(ResetForcedVariable_case_p) + default: + break; + } + /* inc force_list cursor */ + force_list_apply_cursor++; + } /* else TODO: warn user about failure to force */ + + /* Reset force list */ + force_list_addvar_cursor = force_list; + /* Reset force buffer */ + force_buffer_cursor = force_buffer; } void FreeDebugData(void) @@ -371,8 +476,8 @@ /* atomically mark buffer as free */ AtomicCompareExchange( &trace_buffer_state, - BUFFER_BUSY, - BUFFER_FREE); + BUFFER_FULL, + BUFFER_EMPTY); } int WaitDebugData(unsigned long *tick); /* Wait until debug data ready and return pointer to it */