--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/plc_debug.c Thu Aug 21 17:17:36 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 <string.h>
+
+#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;
+}
+