targets/plc_debug.c
changeset 209 08dc3d064cb5
child 235 a66e150f2888
equal deleted inserted replaced
208:dd630979f628 209:08dc3d064cb5
       
     1 /*
       
     2  * DEBUGGER code
       
     3  * 
       
     4  * On "publish", when buffer is free, debugger stores arbitrary variables 
       
     5  * content into, and mark this buffer as filled
       
     6  * 
       
     7  * 
       
     8  * Buffer content is read asynchronously, (from non real time part), 
       
     9  * and then buffer marked free again.
       
    10  *  
       
    11  * 
       
    12  * */
       
    13 #include "iec_types_all.h"
       
    14 #include "POUS.h"
       
    15 /*for memcpy*/
       
    16 #include <string.h>
       
    17 
       
    18 #define BUFFER_SIZE 1024
       
    19 #define MAX_SUBSCRIBTION %(subscription_table_count)d
       
    20 
       
    21 /* Atomically accessed variable for buffer state */
       
    22 #define BUFFER_FREE 0
       
    23 #define BUFFER_BUSY 1
       
    24 static long buffer_state = BUFFER_FREE;
       
    25 
       
    26 /* The buffer itself */
       
    27 char debug_buffer[BUFFER_SIZE];
       
    28 
       
    29 /* Buffer's cursor*/
       
    30 static char* buffer_cursor = debug_buffer;
       
    31 
       
    32 typedef struct{
       
    33     void* ptrvalue;
       
    34     __IEC_types_enum type;
       
    35 }struct_plcvar;
       
    36 
       
    37 /***
       
    38  * Declare programs 
       
    39  **/
       
    40 %(programs_declarations)s
       
    41 
       
    42 /***
       
    43  * Declare global variables from resources and conf 
       
    44  **/
       
    45 %(extern_variables_declarations)s
       
    46 
       
    47 static int subscription_table[MAX_SUBSCRIBTION];
       
    48 static int* latest_subscription = subscription_table;
       
    49 static int* subscription_cursor = subscription_table;
       
    50 
       
    51 struct_plcvar variable_table[%(variables_pointer_type_table_count)d];
       
    52 
       
    53 void __init_debug()
       
    54 {
       
    55 %(variables_pointer_type_table_initializer)s
       
    56 };
       
    57 
       
    58 void __cleanup_debug()
       
    59 {
       
    60 }
       
    61 
       
    62 void __retrieve_debug()
       
    63 {
       
    64 }
       
    65 
       
    66 void __publish_debug()
       
    67 {
       
    68     /* Lock buffer */
       
    69     long latest_state = AtomicCompareExchange(
       
    70         &buffer_state,
       
    71         BUFFER_FREE,
       
    72         BUFFER_BUSY);
       
    73         
       
    74     /* If buffer was free */
       
    75     if(latest_state == BUFFER_FREE)
       
    76     {
       
    77         int* subscription;
       
    78         
       
    79         /* Reset buffer cursor */
       
    80         buffer_cursor = debug_buffer;
       
    81         
       
    82         /* iterate over subscriptions */
       
    83         for(subscription=subscription_table;
       
    84             subscription < latest_subscription;
       
    85             subscription++)
       
    86         {
       
    87             /* get variable descriptor */
       
    88             struct_plcvar* my_var = &variable_table[*subscription];
       
    89             char* next_cursor;
       
    90             /* get variable size*/
       
    91             USINT size = __get_type_enum_size(my_var->type);
       
    92             /* compute next cursor positon*/
       
    93             next_cursor = buffer_cursor + size;
       
    94             /* if buffer not full */
       
    95             if(next_cursor < debug_buffer + BUFFER_SIZE)
       
    96             {
       
    97                 /* copy data to the buffer */
       
    98                 memcpy(buffer_cursor, my_var->ptrvalue, size);
       
    99                 /* increment cursor according size*/
       
   100                 buffer_cursor = next_cursor;
       
   101             }else{
       
   102                 /*TODO : signal overflow*/
       
   103             }
       
   104         }
       
   105 
       
   106         /* Reset buffer cursor again (for IterDebugData)*/
       
   107         buffer_cursor = debug_buffer;
       
   108         subscription_cursor = subscription_table;
       
   109         
       
   110         /* Trigger asynchronous transmission (returns immediately) */
       
   111         InitiateDebugTransfer(); /* size */
       
   112     }
       
   113 }
       
   114 
       
   115 void RegisterDebugVariable(int idx)
       
   116 {
       
   117     /*If subscription table not full */
       
   118     if(latest_subscription - subscription_table < MAX_SUBSCRIBTION)
       
   119     {
       
   120         *(latest_subscription++) = idx;
       
   121         /* TODO pre-calc buffer size and signal overflow*/
       
   122     }else{
       
   123         /*TODO : signal subscription overflow*/
       
   124     }
       
   125 }
       
   126 
       
   127 void ResetDebugVariables(void)
       
   128 {
       
   129     latest_subscription = subscription_table;
       
   130 }
       
   131 
       
   132 void FreeDebugData()
       
   133 {
       
   134     /* atomically mark buffer as free */
       
   135     long latest_state = AtomicCompareExchange(
       
   136         &buffer_state,
       
   137         BUFFER_BUSY,
       
   138         BUFFER_FREE);
       
   139 }
       
   140 
       
   141 void* IterDebugData(int* idx, const char **type_name)
       
   142 {
       
   143     if(subscription_cursor < latest_subscription){
       
   144         *idx = *subscription_cursor;
       
   145         struct_plcvar* my_var = &variable_table[*subscription_cursor++];
       
   146         *type_name = __get_type_enum_name(my_var->type);
       
   147         return my_var->ptrvalue;
       
   148     }
       
   149     return NULL;
       
   150 }
       
   151