runtime/plc_debug.c
author etisserant
Wed, 20 Aug 2008 00:11:40 +0200
changeset 203 cb9901076a21
permissions -rw-r--r--
Added concepts :
- connector class (for PLC control, debug and flashing abstraction).
- builder class (C toolchain abstraction)

Added features :
- Pyro based connector.
- ctypes loader, load PLC shared object and run it
- ctypes based debugger embryo (not tested)
- gcc builder

Broken:
- Win32 runtime
- Most tests
/*
 * 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;
}