--- a/targets/plc_debug.c Tue Nov 30 09:52:42 2021 +0100
+++ b/targets/plc_debug.c Sun Jan 16 16:57:56 2022 +0100
@@ -25,22 +25,59 @@
#include <string.h>
#include <stdio.h>
+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 BUFFER_SIZE %(buffer_size)d
+
+#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 buffer_state = BUFFER_FREE;
-
-/* The buffer itself */
-char debug_buffer[BUFFER_SIZE];
-
-/* Buffer's cursor*/
-static char* buffer_cursor = debug_buffer;
+static long trace_buffer_state = BUFFER_EMPTY;
+
+typedef struct trace_item_s {
+ dbgvardsc_index_t dbgvardsc_index;
+} trace_item_t;
+
+trace_item_t trace_list[TRACE_LIST_SIZE];
+char trace_buffer[TRACE_BUFFER_SIZE];
+
+/* 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;
/***
* Declare programs
**/
@@ -56,10 +93,16 @@
__IEC_types_enum type;
} dbgvardsc_t;
-static dbgvardsc_t dbgvardsc[] = {
+static const dbgvardsc_t dbgvardsc[] = {
%(variable_decl_array)s
};
+static const dbgvardsc_index_t retain_list[] = {
+%(retain_vardsc_index_array)s
+};
+static unsigned int retain_list_collect_cursor = 0;
+static const unsigned int retain_list_size = sizeof(retain_list)/sizeof(dbgvardsc_index_t);
+
typedef void(*__for_each_variable_do_fp)(dbgvardsc_t*);
void __for_each_variable_do(__for_each_variable_do_fp fp)
{
@@ -77,23 +120,6 @@
void Remind(unsigned int offset, unsigned int count, void * p);
-void RemindIterator(dbgvardsc_t *dsc)
-{
- void *real_value_p = NULL;
- char flags = 0;
- UnpackVar(dsc, &real_value_p, &flags);
-
- 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);
- /* increment cursor according size*/
- retain_offset = next_retain_offset;
- }
-}
-
extern int CheckRetainBuffer(void);
extern void InitRetain(void);
@@ -101,20 +127,46 @@
{
/* init local static vars */
#ifndef TARGET_ONLINE_DEBUG_DISABLE
- buffer_cursor = debug_buffer;
- buffer_state = BUFFER_FREE;
+ trace_buffer_cursor = trace_buffer;
+ trace_list_addvar_cursor = trace_list;
+ trace_list_collect_cursor = trace_list;
+ 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;
InitRetain();
/* Iterate over all variables to fill debug buffer */
if(CheckRetainBuffer()){
- __for_each_variable_do(RemindIterator);
+ static unsigned int retain_offset = 0;
+ retain_list_collect_cursor = 0;
+
+ /* iterate over retain list */
+ while(retain_list_collect_cursor < retain_list_size){
+ void *value_p = NULL;
+ size_t size;
+ char* next_cursor;
+
+ dbgvardsc_t *dsc = &dbgvardsc[
+ retain_list[retain_list_collect_cursor]];
+
+ UnpackVar(dsc, &value_p, NULL, &size);
+
+ printf("Reminding %%d %%ld \n", retain_list_collect_cursor, size);
+
+ /* if buffer not full */
+ Remind(retain_offset, size, value_p);
+ /* increment cursor according size*/
+ retain_offset += size;
+
+ retain_list_collect_cursor++;
+ }
}else{
char mstr[] = "RETAIN memory invalid - defaults used";
LogMessage(LOG_WARNING, mstr, sizeof(mstr));
}
- retain_offset = 0;
}
extern void InitiateDebugTransfer(void);
@@ -125,7 +177,7 @@
void __cleanup_debug(void)
{
#ifndef TARGET_ONLINE_DEBUG_DISABLE
- buffer_cursor = debug_buffer;
+ trace_buffer_cursor = trace_buffer;
InitiateDebugTransfer();
#endif
@@ -136,84 +188,31 @@
{
}
-
void Retain(unsigned int offset, unsigned int count, void * p);
-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_DEBUG_FLAG | __IEC_RETAIN_FLAG)){
- USINT size = __get_type_enum_size(dsc->type);
-
-#ifndef TARGET_ONLINE_DEBUG_DISABLE
- if(flags & __IEC_DEBUG_FLAG){
- /* copy visible variable to buffer */;
- if(do_debug){
- /* compute next cursor positon.
- No need to check overflow, as BUFFER_SIZE
- is computed large enough */
- if(__Is_a_string(dsc)){
- /* optimization for strings */
- size = ((STRING*)visible_value_p)->len + 1;
- }
- char* next_cursor = buffer_cursor + size;
- /* copy data to the buffer */
- memcpy(buffer_cursor, visible_value_p, size);
- /* increment cursor according size*/
- buffer_cursor = next_cursor;
- }
- /* re-force real value of outputs (M and Q)*/
- if((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG)){
- memcpy(real_value_p, visible_value_p, size);
- }
- }
-#endif
-
- 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);
- /* increment cursor according size*/
- retain_offset = next_retain_offset;
- }
- }
-}
-
-void DebugIterator(dbgvardsc_t *dsc){
- BufferIterator(dsc, 1);
-}
-
-void RetainIterator(dbgvardsc_t *dsc){
- BufferIterator(dsc, 0);
-}
-
-
-unsigned int retain_size = 0;
-
-/* GetRetainSizeIterator */
-void GetRetainSizeIterator(dbgvardsc_t *dsc)
-{
- void *real_value_p = NULL;
- char flags = 0;
- UnpackVar(dsc, &real_value_p, &flags);
-
- if(flags & __IEC_RETAIN_FLAG){
- USINT size = __get_type_enum_size(dsc->type);
- /* Calc retain buffer size */
- retain_size += size;
- }
-}
-
/* Return size of all retain variables */
unsigned int GetRetainSize(void)
{
- __for_each_variable_do(GetRetainSizeIterator);
+ unsigned int retain_size = 0;
+ retain_list_collect_cursor = 0;
+
+ /* iterate over retain list */
+ while(retain_list_collect_cursor < retain_list_size){
+ void *value_p = NULL;
+ size_t size;
+ char* next_cursor;
+
+ dbgvardsc_t *dsc = &dbgvardsc[
+ retain_list[retain_list_collect_cursor]];
+
+ UnpackVar(dsc, &value_p, NULL, &size);
+
+ retain_size += size;
+ retain_list_collect_cursor++;
+ }
+
+ printf("Retain size %%d \n", retain_size);
+
return retain_size;
}
@@ -226,9 +225,26 @@
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;
InValidateRetainBuffer();
#ifndef TARGET_ONLINE_DEBUG_DISABLE
@@ -236,116 +252,248 @@
if(TryEnterDebugSection()){
/* Lock buffer */
long latest_state = AtomicCompareExchange(
- &buffer_state,
- BUFFER_FREE,
- BUFFER_BUSY);
+ &trace_buffer_state,
+ 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 */
- buffer_cursor = debug_buffer;
- /* Iterate over all variables to fill debug buffer */
- __for_each_variable_do(DebugIterator);
+ trace_buffer_cursor = trace_buffer;
+ /* Reset trace list cursor */
+ trace_list_collect_cursor = trace_list;
+
+ /* iterate over trace list */
+ while(trace_list_collect_cursor < trace_list_addvar_cursor){
+ void *value_p = NULL;
+ size_t size;
+ char* next_cursor;
+
+ dbgvardsc_t *dsc = &dbgvardsc[
+ trace_list_collect_cursor->dbgvardsc_index];
+
+ 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*)value_p)->len + 1;
+ }
+
+ /* compute next cursor positon.*/
+ next_cursor = trace_buffer_cursor + size;
+ /* check for buffer overflow */
+ if(next_cursor < trace_buffer_end)
+ /* copy data to the buffer */
+ memcpy(trace_buffer_cursor, value_p, size);
+ else
+ /* stop looping in case of overflow */
+ break;
+ /* increment cursor according size*/
+ trace_buffer_cursor = next_cursor;
+ trace_list_collect_cursor++;
+ }
/* Leave debug section,
* Trigger asynchronous transmission
* (returns immediately) */
InitiateDebugTransfer(); /* size */
- }else{
- /* when not debugging, do only retain */
- __for_each_variable_do(RetainIterator);
}
LeaveDebugSection();
- }else
+ }
#endif
- {
- /* when not debugging, do only retain */
- __for_each_variable_do(RetainIterator);
+ static unsigned int retain_offset = 0;
+ /* when not debugging, do only retain */
+ retain_list_collect_cursor = 0;
+
+ /* iterate over retain list */
+ while(retain_list_collect_cursor < retain_list_size){
+ void *value_p = NULL;
+ size_t size;
+ char* next_cursor;
+
+ dbgvardsc_t *dsc = &dbgvardsc[
+ retain_list[retain_list_collect_cursor]];
+
+ UnpackVar(dsc, &value_p, NULL, &size);
+
+ printf("Retaining %%d %%ld \n", retain_list_collect_cursor, size);
+
+ /* if buffer not full */
+ Retain(retain_offset, size, value_p);
+ /* increment cursor according size*/
+ retain_offset += size;
+
+ retain_list_collect_cursor++;
}
ValidateRetainBuffer();
}
#ifndef TARGET_ONLINE_DEBUG_DISABLE
-#define __RegisterDebugVariable_case_t(TYPENAME) \
- case TYPENAME##_ENUM :\
- ((__IEC_##TYPENAME##_t *)varp)->flags |= flags;\
- if(force)\
- ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)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 __RegisterDebugVariable_case_p(TYPENAME)\
- case TYPENAME##_P_ENUM :\
- ((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\
- if(force)\
- ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\
- break;\
- case TYPENAME##_O_ENUM :\
- ((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\
- if(force){\
- ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\
- *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\
- }\
+#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 RegisterDebugVariable(unsigned int idx, void* force)
-{
- if(idx < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){
- unsigned char flags = force ?
- __IEC_DEBUG_FLAG | __IEC_FORCE_FLAG :
- __IEC_DEBUG_FLAG;
- dbgvardsc_t *dsc = &dbgvardsc[idx];
+
+
+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 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){
+ 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;
+ }
+ }
+ }
+ 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;
+
+ 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(__RegisterDebugVariable_case_t)
- __ANY(__RegisterDebugVariable_case_p)
+ __ANY(ResetForcedVariable_case_t)
+ __ANY(ResetForcedVariable_case_p)
default:
break;
}
- }
-}
-
-#define __ResetDebugVariablesIterator_case_t(TYPENAME) \
- case TYPENAME##_ENUM :\
- ((__IEC_##TYPENAME##_t *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\
- break;
-
-#define __ResetDebugVariablesIterator_case_p(TYPENAME)\
- case TYPENAME##_P_ENUM :\
- case TYPENAME##_O_ENUM :\
- ((__IEC_##TYPENAME##_p *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__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;
- }
-}
-
-void ResetDebugVariables(void)
-{
- __for_each_variable_do(ResetDebugVariablesIterator);
+ /* 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)
{
/* atomically mark buffer as free */
AtomicCompareExchange(
- &buffer_state,
- BUFFER_BUSY,
- BUFFER_FREE);
+ &trace_buffer_state,
+ BUFFER_FULL,
+ BUFFER_EMPTY);
}
int WaitDebugData(unsigned long *tick);
/* Wait until debug data ready and return pointer to it */
int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){
int wait_error = WaitDebugData(tick);
if(!wait_error){
- *size = buffer_cursor - debug_buffer;
- *buffer = debug_buffer;
+ *size = trace_buffer_cursor - trace_buffer;
+ *buffer = trace_buffer;
}
return wait_error;
}