targets/plc_debug.c
branchwxPython4
changeset 3405 fdc12f7d27c8
parent 3396 8c8cb5c9ff38
child 3441 710eec6eb01c
equal deleted inserted replaced
3391:0ae5a15efa18 3405:fdc12f7d27c8
    23 #include "POUS.h"
    23 #include "POUS.h"
    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 typedef unsigned int dbgvardsc_index_t;
       
    29 typedef unsigned short trace_buf_offset_t;
       
    30 
       
    31 #define BUFFER_EMPTY 0
       
    32 #define BUFFER_FULL 1
       
    33 
    28 #ifndef TARGET_ONLINE_DEBUG_DISABLE
    34 #ifndef TARGET_ONLINE_DEBUG_DISABLE
    29 #define BUFFER_SIZE %(buffer_size)d
    35 
       
    36 #define TRACE_BUFFER_SIZE 4096
       
    37 #define TRACE_LIST_SIZE 1024
    30 
    38 
    31 /* Atomically accessed variable for buffer state */
    39 /* Atomically accessed variable for buffer state */
    32 #define BUFFER_FREE 0
    40 static long trace_buffer_state = BUFFER_EMPTY;
    33 #define BUFFER_BUSY 1
    41 
    34 static long buffer_state = BUFFER_FREE;
    42 typedef struct trace_item_s {
    35 
    43     dbgvardsc_index_t dbgvardsc_index;
    36 /* The buffer itself */
    44 } trace_item_t;
    37 char debug_buffer[BUFFER_SIZE];
    45 
    38 
    46 trace_item_t trace_list[TRACE_LIST_SIZE];
    39 /* Buffer's cursor*/
    47 char trace_buffer[TRACE_BUFFER_SIZE];
    40 static char* buffer_cursor = debug_buffer;
    48 
       
    49 /* Trace's cursor*/
       
    50 static trace_item_t *trace_list_collect_cursor = trace_list;
       
    51 static trace_item_t *trace_list_addvar_cursor = trace_list;
       
    52 static const trace_item_t *trace_list_end = 
       
    53     &trace_list[TRACE_LIST_SIZE-1];
       
    54 static char *trace_buffer_cursor = trace_buffer;
       
    55 static const char *trace_buffer_end = trace_buffer + TRACE_BUFFER_SIZE;
       
    56 
       
    57 
       
    58 
       
    59 #define FORCE_BUFFER_SIZE 1024
       
    60 #define FORCE_LIST_SIZE 256
       
    61 
       
    62 typedef struct force_item_s {
       
    63     dbgvardsc_index_t dbgvardsc_index;
       
    64     void *value_pointer_backup;
       
    65 } force_item_t;
       
    66 
       
    67 force_item_t force_list[FORCE_LIST_SIZE];
       
    68 char force_buffer[FORCE_BUFFER_SIZE];
       
    69 
       
    70 /* Force's cursor*/
       
    71 static force_item_t *force_list_apply_cursor = force_list;
       
    72 static force_item_t *force_list_addvar_cursor = force_list;
       
    73 static const force_item_t *force_list_end = 
       
    74     &force_list[FORCE_LIST_SIZE-1];
       
    75 static char *force_buffer_cursor = force_buffer;
       
    76 static const char *force_buffer_end = force_buffer + FORCE_BUFFER_SIZE;
       
    77 
       
    78 
    41 #endif
    79 #endif
    42 
    80 
    43 static unsigned int retain_offset = 0;
       
    44 /***
    81 /***
    45  * Declare programs 
    82  * Declare programs 
    46  **/
    83  **/
    47 %(programs_declarations)s
    84 %(programs_declarations)s
    48 
    85 
    54 typedef const struct {
    91 typedef const struct {
    55     void *ptr;
    92     void *ptr;
    56     __IEC_types_enum type;
    93     __IEC_types_enum type;
    57 } dbgvardsc_t;
    94 } dbgvardsc_t;
    58 
    95 
    59 static dbgvardsc_t dbgvardsc[] = {
    96 static const dbgvardsc_t dbgvardsc[] = {
    60 %(variable_decl_array)s
    97 %(variable_decl_array)s
    61 };
    98 };
       
    99 
       
   100 static const dbgvardsc_index_t retain_list[] = {
       
   101 %(retain_vardsc_index_array)s
       
   102 };
       
   103 static unsigned int retain_list_collect_cursor = 0;
       
   104 static const unsigned int retain_list_size = sizeof(retain_list)/sizeof(dbgvardsc_index_t);
    62 
   105 
    63 typedef void(*__for_each_variable_do_fp)(dbgvardsc_t*);
   106 typedef void(*__for_each_variable_do_fp)(dbgvardsc_t*);
    64 void __for_each_variable_do(__for_each_variable_do_fp fp)
   107 void __for_each_variable_do(__for_each_variable_do_fp fp)
    65 {
   108 {
    66     unsigned int i;
   109     unsigned int i;
    75 
   118 
    76 %(var_access_code)s
   119 %(var_access_code)s
    77 
   120 
    78 void Remind(unsigned int offset, unsigned int count, void * p);
   121 void Remind(unsigned int offset, unsigned int count, void * p);
    79 
   122 
    80 void RemindIterator(dbgvardsc_t *dsc)
       
    81 {
       
    82     void *real_value_p = NULL;
       
    83     char flags = 0;
       
    84     UnpackVar(dsc, &real_value_p, &flags);
       
    85 
       
    86     if(flags & __IEC_RETAIN_FLAG){
       
    87         USINT size = __get_type_enum_size(dsc->type);
       
    88         /* compute next cursor positon*/
       
    89         unsigned int next_retain_offset = retain_offset + size;
       
    90         /* if buffer not full */
       
    91         Remind(retain_offset, size, real_value_p);
       
    92         /* increment cursor according size*/
       
    93         retain_offset = next_retain_offset;
       
    94     }
       
    95 }
       
    96 
       
    97 extern int CheckRetainBuffer(void);
   123 extern int CheckRetainBuffer(void);
    98 extern void InitRetain(void);
   124 extern void InitRetain(void);
    99 
   125 
   100 void __init_debug(void)
   126 void __init_debug(void)
   101 {
   127 {
   102     /* init local static vars */
   128     /* init local static vars */
   103 #ifndef TARGET_ONLINE_DEBUG_DISABLE
   129 #ifndef TARGET_ONLINE_DEBUG_DISABLE
   104     buffer_cursor = debug_buffer;
   130     trace_buffer_cursor = trace_buffer;
   105     buffer_state = BUFFER_FREE;
   131     trace_list_addvar_cursor = trace_list;
       
   132     trace_list_collect_cursor = trace_list;
       
   133     trace_buffer_state = BUFFER_EMPTY;
       
   134 
       
   135     force_buffer_cursor = force_buffer;
       
   136     force_list_addvar_cursor = force_list;
       
   137     force_list_apply_cursor = force_list;
   106 #endif
   138 #endif
   107 
   139 
   108     retain_offset = 0;
       
   109     InitRetain();
   140     InitRetain();
   110     /* Iterate over all variables to fill debug buffer */
   141     /* Iterate over all variables to fill debug buffer */
   111     if(CheckRetainBuffer()){
   142     if(CheckRetainBuffer()){
   112         __for_each_variable_do(RemindIterator);
   143         static unsigned int retain_offset = 0;
       
   144         retain_list_collect_cursor = 0;
       
   145 
       
   146         /* iterate over retain list */
       
   147         while(retain_list_collect_cursor < retain_list_size){
       
   148             void *value_p = NULL;
       
   149             size_t size;
       
   150             char* next_cursor;
       
   151 
       
   152             dbgvardsc_t *dsc = &dbgvardsc[
       
   153                 retain_list[retain_list_collect_cursor]];
       
   154 
       
   155             UnpackVar(dsc, &value_p, NULL, &size);
       
   156 
       
   157             printf("Reminding %%d %%ld \n", retain_list_collect_cursor, size);
       
   158 
       
   159             /* if buffer not full */
       
   160             Remind(retain_offset, size, value_p);
       
   161             /* increment cursor according size*/
       
   162             retain_offset += size;
       
   163 
       
   164             retain_list_collect_cursor++;
       
   165         }
   113     }else{
   166     }else{
   114         char mstr[] = "RETAIN memory invalid - defaults used";
   167         char mstr[] = "RETAIN memory invalid - defaults used";
   115         LogMessage(LOG_WARNING, mstr, sizeof(mstr));
   168         LogMessage(LOG_WARNING, mstr, sizeof(mstr));
   116     }
   169     }
   117     retain_offset = 0;
       
   118 }
   170 }
   119 
   171 
   120 extern void InitiateDebugTransfer(void);
   172 extern void InitiateDebugTransfer(void);
   121 extern void CleanupRetain(void);
   173 extern void CleanupRetain(void);
   122 
   174 
   123 extern unsigned long __tick;
   175 extern unsigned long __tick;
   124 
   176 
   125 void __cleanup_debug(void)
   177 void __cleanup_debug(void)
   126 {
   178 {
   127 #ifndef TARGET_ONLINE_DEBUG_DISABLE
   179 #ifndef TARGET_ONLINE_DEBUG_DISABLE
   128     buffer_cursor = debug_buffer;
   180     trace_buffer_cursor = trace_buffer;
   129     InitiateDebugTransfer();
   181     InitiateDebugTransfer();
   130 #endif    
   182 #endif    
   131 
   183 
   132     CleanupRetain();
   184     CleanupRetain();
   133 }
   185 }
   134 
   186 
   135 void __retrieve_debug(void)
   187 void __retrieve_debug(void)
   136 {
   188 {
   137 }
   189 }
   138 
   190 
   139 
       
   140 void Retain(unsigned int offset, unsigned int count, void * p);
   191 void Retain(unsigned int offset, unsigned int count, void * p);
   141 
       
   142 static inline void BufferIterator(dbgvardsc_t *dsc, int do_debug)
       
   143 {
       
   144     void *real_value_p = NULL;
       
   145     void *visible_value_p = NULL;
       
   146     char flags = 0;
       
   147 
       
   148     visible_value_p = UnpackVar(dsc, &real_value_p, &flags);
       
   149 
       
   150     if(flags & ( __IEC_DEBUG_FLAG | __IEC_RETAIN_FLAG)){
       
   151         USINT size = __get_type_enum_size(dsc->type);
       
   152 
       
   153 #ifndef TARGET_ONLINE_DEBUG_DISABLE
       
   154         if(flags & __IEC_DEBUG_FLAG){
       
   155             /* copy visible variable to buffer */;
       
   156             if(do_debug){
       
   157                 /* compute next cursor positon.
       
   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             }
       
   170             /* re-force real value of outputs (M and Q)*/
       
   171             if((flags & __IEC_FORCE_FLAG) && (flags & __IEC_OUTPUT_FLAG)){
       
   172                 memcpy(real_value_p, visible_value_p, size);
       
   173             }
       
   174         }
       
   175 #endif
       
   176 
       
   177         if(flags & __IEC_RETAIN_FLAG){
       
   178             /* compute next cursor positon*/
       
   179             unsigned int next_retain_offset = retain_offset + size;
       
   180             /* if buffer not full */
       
   181             Retain(retain_offset, size, real_value_p);
       
   182             /* increment cursor according size*/
       
   183             retain_offset = next_retain_offset;
       
   184         }
       
   185     }
       
   186 }
       
   187 
       
   188 void DebugIterator(dbgvardsc_t *dsc){
       
   189     BufferIterator(dsc, 1);
       
   190 }
       
   191 
       
   192 void RetainIterator(dbgvardsc_t *dsc){
       
   193     BufferIterator(dsc, 0);
       
   194 }
       
   195 
       
   196 
       
   197 unsigned int retain_size = 0;
       
   198 
       
   199 /* GetRetainSizeIterator */
       
   200 void GetRetainSizeIterator(dbgvardsc_t *dsc)
       
   201 {
       
   202     void *real_value_p = NULL;
       
   203     char flags = 0;
       
   204     UnpackVar(dsc, &real_value_p, &flags);
       
   205 
       
   206     if(flags & __IEC_RETAIN_FLAG){
       
   207         USINT size = __get_type_enum_size(dsc->type);
       
   208         /* Calc retain buffer size */
       
   209         retain_size += size;
       
   210     }
       
   211 }
       
   212 
   192 
   213 /* Return size of all retain variables */
   193 /* Return size of all retain variables */
   214 unsigned int GetRetainSize(void)
   194 unsigned int GetRetainSize(void)
   215 {
   195 {
   216     __for_each_variable_do(GetRetainSizeIterator);
   196     unsigned int retain_size = 0;
       
   197     retain_list_collect_cursor = 0;
       
   198 
       
   199     /* iterate over retain list */
       
   200     while(retain_list_collect_cursor < retain_list_size){
       
   201         void *value_p = NULL;
       
   202         size_t size;
       
   203         char* next_cursor;
       
   204 
       
   205         dbgvardsc_t *dsc = &dbgvardsc[
       
   206             retain_list[retain_list_collect_cursor]];
       
   207 
       
   208         UnpackVar(dsc, &value_p, NULL, &size);
       
   209 
       
   210         retain_size += size;
       
   211         retain_list_collect_cursor++;
       
   212     }
       
   213 
       
   214     printf("Retain size %%d \n", retain_size);
       
   215             
   217     return retain_size;
   216     return retain_size;
   218 }
   217 }
   219 
   218 
   220 
   219 
   221 extern void PLC_GetTime(IEC_TIME*);
   220 extern void PLC_GetTime(IEC_TIME*);
   224 extern long long AtomicCompareExchange64(long long* , long long , long long);
   223 extern long long AtomicCompareExchange64(long long* , long long , long long);
   225 extern void LeaveDebugSection(void);
   224 extern void LeaveDebugSection(void);
   226 extern void ValidateRetainBuffer(void);
   225 extern void ValidateRetainBuffer(void);
   227 extern void InValidateRetainBuffer(void);
   226 extern void InValidateRetainBuffer(void);
   228 
   227 
       
   228 #define __ReForceOutput_case_p(TYPENAME)                                                            \
       
   229         case TYPENAME##_P_ENUM :                                                                    \
       
   230         case TYPENAME##_O_ENUM :                                                                    \
       
   231             {                                                                                       \
       
   232                 char *next_cursor = force_buffer_cursor + sizeof(TYPENAME);                         \
       
   233                 if(next_cursor <= force_buffer_end ){                                               \
       
   234                     /* outputs real value must be systematically forced */                          \
       
   235                     if(vartype == TYPENAME##_O_ENUM)                                                \
       
   236                         /* overwrite value pointed by backup */                                     \
       
   237                         *((TYPENAME *)force_list_apply_cursor->value_pointer_backup) =  \
       
   238                             *((TYPENAME *)force_buffer_cursor);                                     \
       
   239                     /* inc force_buffer cursor */                                                   \
       
   240                     force_buffer_cursor = next_cursor;                                              \
       
   241                 }else{                                                                              \
       
   242                     stop = 1;                                                                       \
       
   243                 }                                                                                   \
       
   244             }                                                                                       \
       
   245             break;
   229 void __publish_debug(void)
   246 void __publish_debug(void)
   230 {
   247 {
   231     retain_offset = 0;
       
   232     InValidateRetainBuffer();
   248     InValidateRetainBuffer();
   233     
   249     
   234 #ifndef TARGET_ONLINE_DEBUG_DISABLE 
   250 #ifndef TARGET_ONLINE_DEBUG_DISABLE 
   235     /* Check there is no running debugger re-configuration */
   251     /* Check there is no running debugger re-configuration */
   236     if(TryEnterDebugSection()){
   252     if(TryEnterDebugSection()){
   237         /* Lock buffer */
   253         /* Lock buffer */
   238         long latest_state = AtomicCompareExchange(
   254         long latest_state = AtomicCompareExchange(
   239             &buffer_state,
   255             &trace_buffer_state,
   240             BUFFER_FREE,
   256             BUFFER_EMPTY,
   241             BUFFER_BUSY);
   257             BUFFER_FULL);
   242             
   258             
   243         /* If buffer was free */
   259         /* If buffer was free */
   244         if(latest_state == BUFFER_FREE)
   260         if(latest_state == BUFFER_EMPTY)
   245         {
   261         {
       
   262             int stop = 0;
       
   263             /* Reset force list cursor */
       
   264             force_list_apply_cursor = force_list;
       
   265 
       
   266             /* iterate over force list */
       
   267             while(!stop && force_list_apply_cursor < force_list_addvar_cursor){
       
   268                 dbgvardsc_t *dsc = &dbgvardsc[
       
   269                     force_list_apply_cursor->dbgvardsc_index];
       
   270                 void *varp = dsc->ptr;
       
   271                 __IEC_types_enum vartype = dsc->type;
       
   272                 switch(vartype){
       
   273                     __ANY(__ReForceOutput_case_p)
       
   274                 default:
       
   275                     break;
       
   276                 }
       
   277                 force_list_apply_cursor++;                                                      \
       
   278             }
       
   279 
   246             /* Reset buffer cursor */
   280             /* Reset buffer cursor */
   247             buffer_cursor = debug_buffer;
   281             trace_buffer_cursor = trace_buffer;
   248             /* Iterate over all variables to fill debug buffer */
   282             /* Reset trace list cursor */
   249             __for_each_variable_do(DebugIterator);
   283             trace_list_collect_cursor = trace_list;
       
   284 
       
   285             /* iterate over trace list */
       
   286             while(trace_list_collect_cursor < trace_list_addvar_cursor){
       
   287                 void *value_p = NULL;
       
   288                 size_t size;
       
   289                 char* next_cursor;
       
   290 
       
   291                 dbgvardsc_t *dsc = &dbgvardsc[
       
   292                     trace_list_collect_cursor->dbgvardsc_index];
       
   293 
       
   294                 UnpackVar(dsc, &value_p, NULL, &size);
       
   295 
       
   296                 /* copy visible variable to buffer */;
       
   297                 if(__Is_a_string(dsc)){
       
   298                     /* optimization for strings */
       
   299                     /* assume NULL terminated strings */
       
   300                     size = ((STRING*)value_p)->len + 1;
       
   301                 }
       
   302 
       
   303                 /* compute next cursor positon.*/
       
   304                 next_cursor = trace_buffer_cursor + size;
       
   305                 /* check for buffer overflow */
       
   306                 if(next_cursor < trace_buffer_end)
       
   307                     /* copy data to the buffer */
       
   308                     memcpy(trace_buffer_cursor, value_p, size);
       
   309                 else
       
   310                     /* stop looping in case of overflow */
       
   311                     break;
       
   312                 /* increment cursor according size*/
       
   313                 trace_buffer_cursor = next_cursor;
       
   314                 trace_list_collect_cursor++;
       
   315             }
   250             
   316             
   251             /* Leave debug section,
   317             /* Leave debug section,
   252              * Trigger asynchronous transmission 
   318              * Trigger asynchronous transmission 
   253              * (returns immediately) */
   319              * (returns immediately) */
   254             InitiateDebugTransfer(); /* size */
   320             InitiateDebugTransfer(); /* size */
   255         }else{
       
   256             /* when not debugging, do only retain */
       
   257             __for_each_variable_do(RetainIterator);
       
   258         }
   321         }
   259         LeaveDebugSection();
   322         LeaveDebugSection();
   260     }else
   323     }
   261 #endif
   324 #endif
   262     {
   325     static unsigned int retain_offset = 0;
   263         /* when not debugging, do only retain */
   326     /* when not debugging, do only retain */
   264         __for_each_variable_do(RetainIterator);
   327     retain_list_collect_cursor = 0;
       
   328 
       
   329     /* iterate over retain list */
       
   330     while(retain_list_collect_cursor < retain_list_size){
       
   331         void *value_p = NULL;
       
   332         size_t size;
       
   333         char* next_cursor;
       
   334 
       
   335         dbgvardsc_t *dsc = &dbgvardsc[
       
   336             retain_list[retain_list_collect_cursor]];
       
   337 
       
   338         UnpackVar(dsc, &value_p, NULL, &size);
       
   339 
       
   340         printf("Retaining %%d %%ld \n", retain_list_collect_cursor, size);
       
   341 
       
   342         /* if buffer not full */
       
   343         Retain(retain_offset, size, value_p);
       
   344         /* increment cursor according size*/
       
   345         retain_offset += size;
       
   346 
       
   347         retain_list_collect_cursor++;
   265     }
   348     }
   266     ValidateRetainBuffer();
   349     ValidateRetainBuffer();
   267 }
   350 }
   268 
   351 
   269 #ifndef TARGET_ONLINE_DEBUG_DISABLE
   352 #ifndef TARGET_ONLINE_DEBUG_DISABLE
   270 #define __RegisterDebugVariable_case_t(TYPENAME) \
   353 
   271         case TYPENAME##_ENUM :\
   354 #define TRACE_LIST_OVERFLOW    1
   272             ((__IEC_##TYPENAME##_t *)varp)->flags |= flags;\
   355 #define FORCE_LIST_OVERFLOW    2
   273             if(force)\
   356 #define FORCE_BUFFER_OVERFLOW  3
   274              ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force);\
   357 
       
   358 #define __ForceVariable_case_t(TYPENAME)                                                \
       
   359         case TYPENAME##_ENUM :                                                          \
       
   360             /* add to force_list*/                                                      \
       
   361             force_list_addvar_cursor->dbgvardsc_index = idx;                            \
       
   362             ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_FORCE_FLAG;                  \
       
   363             ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force);               \
   275             break;
   364             break;
   276 #define __RegisterDebugVariable_case_p(TYPENAME)\
   365 #define __ForceVariable_case_p(TYPENAME)                                                \
   277         case TYPENAME##_P_ENUM :\
   366         case TYPENAME##_P_ENUM :                                                        \
   278             ((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\
   367         case TYPENAME##_O_ENUM :                                                        \
   279             if(force)\
   368             {                                                                           \
   280              ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\
   369                 char *next_cursor = force_buffer_cursor + sizeof(TYPENAME);             \
   281             break;\
   370                 if(next_cursor <= force_buffer_end ){                                   \
   282         case TYPENAME##_O_ENUM :\
   371                     /* add to force_list*/                                              \
   283             ((__IEC_##TYPENAME##_p *)varp)->flags |= flags;\
   372                     force_list_addvar_cursor->dbgvardsc_index = idx;                    \
   284             if(force){\
   373                     /* save pointer to backup */                                        \
   285              ((__IEC_##TYPENAME##_p *)varp)->fvalue = *((TYPENAME *)force);\
   374                     force_list_addvar_cursor->value_pointer_backup =                    \
   286              *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\
   375                         ((__IEC_##TYPENAME##_p *)varp)->value;                          \
   287             }\
   376                     /* store forced value in force_buffer */                            \
       
   377                     *((TYPENAME *)force_buffer_cursor) = *((TYPENAME *)force);          \
       
   378                     /* replace pointer with pointer to force_buffer */                  \
       
   379                     ((__IEC_##TYPENAME##_p *)varp)->value =                             \
       
   380                         (TYPENAME *)force_buffer_cursor;                                \
       
   381                     /* mark variable as forced */                                       \
       
   382                     ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG;          \
       
   383                     /* inc force_buffer cursor */                                       \
       
   384                     force_buffer_cursor = next_cursor;                                  \
       
   385                     /* outputs real value must be systematically forced */              \
       
   386                     if(vartype == TYPENAME##_O_ENUM)                                    \
       
   387                         *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\
       
   388                 } else {                                                                \
       
   389                     error_code = FORCE_BUFFER_OVERFLOW;                                 \
       
   390                     goto error_cleanup;                                                 \
       
   391                 }                                                                       \
       
   392             }                                                                           \
   288             break;
   393             break;
   289 void RegisterDebugVariable(unsigned int idx, void* force)
   394 
   290 {
   395 
   291     if(idx  < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){
   396 void ResetDebugVariables(void);
   292         unsigned char flags = force ?
   397 
   293             __IEC_DEBUG_FLAG | __IEC_FORCE_FLAG :
   398 int RegisterDebugVariable(dbgvardsc_index_t idx, void* force)
   294             __IEC_DEBUG_FLAG;
   399 {
   295         dbgvardsc_t *dsc = &dbgvardsc[idx];
   400     int error_code = 0;
       
   401     if(idx < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){
       
   402         /* add to trace_list, inc trace_list_addvar_cursor*/
       
   403         if(trace_list_addvar_cursor <= trace_list_end){
       
   404             trace_list_addvar_cursor->dbgvardsc_index = idx;
       
   405             trace_list_addvar_cursor++;
       
   406         } else {
       
   407             error_code = TRACE_LIST_OVERFLOW;
       
   408             goto error_cleanup;
       
   409         }
       
   410         if(force){
       
   411             if(force_list_addvar_cursor <= force_list_end){
       
   412                 dbgvardsc_t *dsc = &dbgvardsc[idx];
       
   413                 void *varp = dsc->ptr;
       
   414                 __IEC_types_enum vartype = dsc->type;
       
   415 
       
   416                 switch(vartype){
       
   417                     __ANY(__ForceVariable_case_t)
       
   418                     __ANY(__ForceVariable_case_p)
       
   419                 default:
       
   420                     break;
       
   421                 }
       
   422                 /* inc force_list cursor */
       
   423                 force_list_addvar_cursor++;
       
   424             } else {
       
   425                 error_code = FORCE_LIST_OVERFLOW;
       
   426                 goto error_cleanup;
       
   427             }
       
   428         }
       
   429     }
       
   430     return 0;
       
   431 
       
   432 error_cleanup:
       
   433     ResetDebugVariables();
       
   434     trace_buffer_state = BUFFER_EMPTY;
       
   435     return error_code;
       
   436     
       
   437 }
       
   438 
       
   439 #define ResetForcedVariable_case_t(TYPENAME)                                            \
       
   440         case TYPENAME##_ENUM :                                                          \
       
   441             ((__IEC_##TYPENAME##_t *)varp)->flags &= ~__IEC_FORCE_FLAG;                 \
       
   442             /* for local variable we don't restore original value */                    \
       
   443             /* that can be added if needed, but it was like that since ever */          \
       
   444             break;
       
   445 
       
   446 #define ResetForcedVariable_case_p(TYPENAME)                                            \
       
   447         case TYPENAME##_P_ENUM :                                                        \
       
   448         case TYPENAME##_O_ENUM :                                                        \
       
   449             ((__IEC_##TYPENAME##_p *)varp)->flags &= ~__IEC_FORCE_FLAG;                 \
       
   450             /* restore backup to pointer */                                             \
       
   451             ((__IEC_##TYPENAME##_p *)varp)->value =                                     \
       
   452                 force_list_apply_cursor->value_pointer_backup;                          \
       
   453             break;
       
   454 
       
   455 void ResetDebugVariables(void)
       
   456 {
       
   457     /* Reset trace list */
       
   458     trace_list_addvar_cursor = trace_list;
       
   459 
       
   460     force_list_apply_cursor = force_list;
       
   461     /* Restore forced variables */
       
   462     while(force_list_apply_cursor < force_list_addvar_cursor){
       
   463         dbgvardsc_t *dsc = &dbgvardsc[
       
   464             force_list_apply_cursor->dbgvardsc_index];
   296         void *varp = dsc->ptr;
   465         void *varp = dsc->ptr;
   297         switch(dsc->type){
   466         switch(dsc->type){
   298             __ANY(__RegisterDebugVariable_case_t)
   467             __ANY(ResetForcedVariable_case_t)
   299             __ANY(__RegisterDebugVariable_case_p)
   468             __ANY(ResetForcedVariable_case_p)
   300         default:
   469         default:
   301             break;
   470             break;
   302         }
   471         }
   303     }
   472         /* inc force_list cursor */
   304 }
   473         force_list_apply_cursor++;
   305 
   474     } /* else TODO: warn user about failure to force */ 
   306 #define __ResetDebugVariablesIterator_case_t(TYPENAME) \
   475 
   307         case TYPENAME##_ENUM :\
   476     /* Reset force list */
   308             ((__IEC_##TYPENAME##_t *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\
   477     force_list_addvar_cursor = force_list;
   309             break;
   478     /* Reset force buffer */
   310 
   479     force_buffer_cursor = force_buffer;
   311 #define __ResetDebugVariablesIterator_case_p(TYPENAME)\
       
   312         case TYPENAME##_P_ENUM :\
       
   313         case TYPENAME##_O_ENUM :\
       
   314             ((__IEC_##TYPENAME##_p *)varp)->flags &= ~(__IEC_DEBUG_FLAG|__IEC_FORCE_FLAG);\
       
   315             break;
       
   316 
       
   317 void ResetDebugVariablesIterator(dbgvardsc_t *dsc)
       
   318 {
       
   319     /* force debug flag to 0*/
       
   320     void *varp = dsc->ptr;
       
   321     switch(dsc->type){
       
   322         __ANY(__ResetDebugVariablesIterator_case_t)
       
   323         __ANY(__ResetDebugVariablesIterator_case_p)
       
   324     default:
       
   325         break;
       
   326     }
       
   327 }
       
   328 
       
   329 void ResetDebugVariables(void)
       
   330 {
       
   331     __for_each_variable_do(ResetDebugVariablesIterator);
       
   332 }
   480 }
   333 
   481 
   334 void FreeDebugData(void)
   482 void FreeDebugData(void)
   335 {
   483 {
   336     /* atomically mark buffer as free */
   484     /* atomically mark buffer as free */
   337     AtomicCompareExchange(
   485     AtomicCompareExchange(
   338         &buffer_state,
   486         &trace_buffer_state,
   339         BUFFER_BUSY,
   487         BUFFER_FULL,
   340         BUFFER_FREE);
   488         BUFFER_EMPTY);
   341 }
   489 }
   342 int WaitDebugData(unsigned long *tick);
   490 int WaitDebugData(unsigned long *tick);
   343 /* Wait until debug data ready and return pointer to it */
   491 /* Wait until debug data ready and return pointer to it */
   344 int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){
   492 int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){
   345     int wait_error = WaitDebugData(tick);
   493     int wait_error = WaitDebugData(tick);
   346     if(!wait_error){
   494     if(!wait_error){
   347         *size = buffer_cursor - debug_buffer;
   495         *size = trace_buffer_cursor - trace_buffer;
   348         *buffer = debug_buffer;
   496         *buffer = trace_buffer;
   349     }
   497     }
   350     return wait_error;
   498     return wait_error;
   351 }
   499 }
   352 #endif
   500 #endif
   353 #endif
   501 #endif