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