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