diff -r cd81a7a6e55c -r cb9901076a21 runtime/plc_debug.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/runtime/plc_debug.c Wed Aug 20 00:11:40 2008 +0200 @@ -0,0 +1,151 @@ +/* + * DEBUGGER code + * + * On "publish", when buffer is free, debugger stores arbitrary variables + * content into, and mark this buffer as filled + * + * + * Buffer content is read asynchronously, (from non real time part), + * and then buffer marked free again. + * + * + * */ +#include "iec_types_all.h" +#include "POUS.h" +/*for memcpy*/ +#include + +#define BUFFER_SIZE 1024 +#define MAX_SUBSCRIBTION %(subscription_table_count)d + +/* 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; + +typedef struct{ + void* ptrvalue; + __IEC_types_enum type; +}struct_plcvar; + +/*** + * Declare programs + **/ +%(programs_declarations)s + +/*** + * Declare global variables from resources and conf + **/ +%(extern_variables_declarations)s + +static int subscription_table[MAX_SUBSCRIBTION]; +static int* latest_subscription = subscription_table; +static int* subscription_cursor = subscription_table; + +struct_plcvar variable_table[%(variables_pointer_type_table_count)d]; + +void __init_debug() +{ +%(variables_pointer_type_table_initializer)s +}; + +void __cleanup_debug() +{ +} + +void __retrieve_debug() +{ +} + +void __publish_debug() +{ + /* Lock buffer */ + long latest_state = AtomicCompareExchange( + &buffer_state, + BUFFER_FREE, + BUFFER_BUSY); + + /* If buffer was free */ + if(latest_state == BUFFER_FREE) + { + int* subscription; + + /* Reset buffer cursor */ + buffer_cursor = debug_buffer; + + /* iterate over subscriptions */ + for(subscription=subscription_table; + subscription < latest_subscription; + subscription++) + { + /* get variable descriptor */ + struct_plcvar* my_var = &variable_table[*subscription]; + char* next_cursor; + /* get variable size*/ + USINT size = __get_type_enum_size(my_var->type); + /* compute next cursor positon*/ + next_cursor = buffer_cursor + size; + /* if buffer not full */ + if(next_cursor < debug_buffer + BUFFER_SIZE) + { + /* copy data to the buffer */ + memcpy(buffer_cursor, my_var->ptrvalue, size); + /* increment cursor according size*/ + buffer_cursor = next_cursor; + }else{ + /*TODO : signal overflow*/ + } + } + + /* Reset buffer cursor again (for IterDebugData)*/ + buffer_cursor = debug_buffer; + subscription_cursor = subscription_table; + + /* Trigger asynchronous transmission (returns immediately) */ + InitiateDebugTransfer(); /* size */ + } +} + +void RegisterDebugVariable(int idx) +{ + /*If subscription table not full */ + if(latest_subscription - subscription_table < MAX_SUBSCRIBTION) + { + *(latest_subscription++) = idx; + /* TODO pre-calc buffer size and signal overflow*/ + }else{ + /*TODO : signal subscription overflow*/ + } +} + +void ResetDebugVariables(void) +{ + latest_subscription = subscription_table; +} + +void FreeDebugData() +{ + /* atomically mark buffer as free */ + long latest_state = AtomicCompareExchange( + &buffer_state, + BUFFER_BUSY, + BUFFER_FREE); +} + +void* IterDebugData(int* idx, const char **type_name) +{ + if(subscription_cursor < latest_subscription){ + *idx = *subscription_cursor; + struct_plcvar* my_var = &variable_table[*subscription_cursor++]; + *type_name = __get_type_enum_name(my_var->type); + return my_var->ptrvalue; + } + return NULL; +} +