# HG changeset patch # User etisserant # Date 1219331856 -7200 # Node ID 08dc3d064cb56238be1efb88a2f9ab1cb7c63529 # Parent dd630979f628ffcf4ddd0464e356e3dc5879405b Moved template C code to targets dir. Cleaned up some forgotten print. diff -r dd630979f628 -r 08dc3d064cb5 plugger.py --- a/plugger.py Thu Aug 21 13:21:37 2008 +0200 +++ b/plugger.py Thu Aug 21 17:17:36 2008 +0200 @@ -613,7 +613,6 @@ DebugTypes = [t for t in zip(*TypeHierarchy_list)[0] if not t.startswith("ANY")] + \ ["STEP","TRANSITION","ACTION"] -import runtime import re import targets import connectors @@ -1039,7 +1038,7 @@ self.GetIECProgramsAndVariables() # prepare debug code - debug_code = runtime.code("plc_debug") % { + debug_code = targets.code("plc_debug") % { "programs_declarations": "\n".join(["extern %(type)s %(C_path)s;"%p for p in self._ProgramList]), "extern_variables_declarations":"\n".join([ @@ -1100,7 +1099,7 @@ [loc for loc,Cfiles,DoCalls in self.LocationCFilesAndCFLAGS if loc and DoCalls]) # Generate main, based on template - plc_main_code = runtime.code("plc_common_main") % { + plc_main_code = targets.code("plc_common_main") % { "calls_prototypes":"\n".join([( "int __init_%(s)s(int argc,char **argv);\n"+ "void __cleanup_%(s)s();\n"+ @@ -1121,7 +1120,7 @@ } target_name = self.BeremizRoot.getTargetType().getcontent()["name"] - plc_main_code += targets.code(target_name) + plc_main_code += targets.targetcode(target_name) return plc_main_code @@ -1176,7 +1175,6 @@ os.mkdir(extrafilespath) # Then write the files for fname,fobject in ExtraFiles: - print fname,fobject fpath = os.path.join(extrafilespath,fname) open(fpath, "wb").write(fobject.read()) # Now we can forget ExtraFiles (will close files object) @@ -1439,9 +1437,6 @@ for name in os.listdir(extrafilespath) \ if not name=="CVS"] - for filename, unused in extrafiles: - print filename - # Send PLC on target builder = self.GetBuilder() if builder is not None: diff -r dd630979f628 -r 08dc3d064cb5 runtime/PLCObject.py --- a/runtime/PLCObject.py Thu Aug 21 13:21:37 2008 +0200 +++ b/runtime/PLCObject.py Thu Aug 21 17:17:36 2008 +0200 @@ -24,9 +24,7 @@ import Pyro.core as pyro from threading import Timer -import ctypes, os, dl, commands -#, sys -#sys.setdlopenflags(dl.RTLD_NOW | dl.RTLD_GLOBAL) +import ctypes, os, commands if os.name == ("nt", "ce"): from _ctypes import LoadLibrary as dlopen @@ -42,8 +40,9 @@ }.get(sys.platform, "") class PLCObject(pyro.ObjBase): - def __init__(self, workingdir, daemon): + def __init__(self, workingdir, daemon, argv): pyro.ObjBase.__init__(self) + self.argv=argv self.workingdir = workingdir self.PLCStatus = "Stopped" self.PLClibraryHandle = None @@ -142,7 +141,7 @@ "libpan", "libX11", ]: - badhandle = dlopen(badlib, dl.RTLD_NOLOAD) + #badhandle = dlopen(badlib, dl.RTLD_NOLOAD) print "Dirty lib detected :" + badlib #dlclose(badhandle) return True @@ -153,20 +152,24 @@ print "StartPLC" if self.CurrentPLCFilename is not None and self.PLCStatus == "Stopped": c_argv = ctypes.c_char_p * len(sys.argv) - if self._LoadNewPLC() and self._startPLC(len(sys.argv),c_argv(*sys.argv)) == 0: + if self._LoadNewPLC() and self._startPLC(len(self.argv),c_argv(*self.argv)) == 0: self.PLCStatus = "Started" return True else: print "_StartPLC did not return 0 !" - return False + self._DoStopPLC() + return False + + def _DoStopPLC(self): + self._stopPLC() + self.PLCStatus = "Stopped" + if self._FreePLC(): + self.PLCStatus = "Dirty" + return True def StopPLC(self): if self.PLCStatus == "Started": - self._stopPLC() - self.PLCStatus = "Stopped" - if self._FreePLC(): - self.PLCStatus = "Dirty" - return True + self._DoStopPLC() return False def _Reload(self): diff -r dd630979f628 -r 08dc3d064cb5 runtime/__init__.py --- a/runtime/__init__.py Thu Aug 21 13:21:37 2008 +0200 +++ b/runtime/__init__.py Thu Aug 21 17:17:36 2008 +0200 @@ -2,12 +2,5 @@ import os -def code(name): - filename = os.path.join(os.path.split(__file__)[0],name + ".c") - if os.path.exists(filename): - return open(filename).read() - else: - return "#error %s target not implemented !!!\n"%name - from PLCObject import PLCObject import ServicePublisher diff -r dd630979f628 -r 08dc3d064cb5 runtime/plc_common_main.c --- a/runtime/plc_common_main.c Thu Aug 21 13:21:37 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,177 +0,0 @@ -/* - * Prototypes for function provided by arch-specific code (main) - * concatained after this template - ** / - - -/* - * Functions and variables provied by generated C softPLC - **/ -extern int common_ticktime__; - -/* - * Functions and variables provied by plc.c - **/ -void run(long int tv_sec, long int tv_nsec); - -#define maxval(a,b) ((a>b)?a:b) - -#include "iec_types.h" -/*#include "stdio.h" /* For debug */ - -/* - * Functions and variables provied by generated C softPLC - **/ -void config_run__(int tick); -void config_init__(void); - -/* - * Functions and variables to export to generated C softPLC and plugins - **/ - -IEC_TIME __CURRENT_TIME; -int __tick = 0; - -static int init_level = 0; -static int Debugging = 1; - -/* - * Prototypes of functions exported by plugins - **/ -%(calls_prototypes)s - -/* - * Retrieve input variables, run PLC and publish output variables - **/ -void __run() -{ - %(retrieve_calls)s - - if(Debugging) __retrieve_debug(); - - config_run__(__tick); - - if(Debugging) __publish_debug(); - - %(publish_calls)s - - __tick++; -} - -/* - * Initialize variables according to PLC's defalut values, - * and then init plugins with that values - **/ -int __init(int argc,char **argv) -{ - int res; - config_init__(); - %(init_calls)s - return 0; -} -/* - * Calls plugin cleanup proc. - **/ -void __cleanup() -{ - %(cleanup_calls)s -} - - -void PLC_GetTime(IEC_TIME *CURRENT_TIME); -void PLC_SetTimer(long long next, long long period); - -#define CALIBRATED -2 -#define NOT_CALIBRATED -1 -static int calibration_count = NOT_CALIBRATED; -static IEC_TIME cal_begin; -static long long Tsync = 0; -static long long FreqCorr = 0; -static int Nticks = 0; -static int last_tick = 0; -static long long Ttick = 0; -#define mod %% -/* - * Call this on each external sync, - * @param sync_align_ratio 0->100 : align ratio, < 0 : no align, calibrate period - **/ -void align_tick(int sync_align_ratio) -{ - /* - printf("align_tick(%%d)\n", calibrate); - */ - if(sync_align_ratio < 0){ /* Calibration */ - if(calibration_count == CALIBRATED) - /* Re-calibration*/ - calibration_count = NOT_CALIBRATED; - if(calibration_count == NOT_CALIBRATED) - /* Calibration start, get time*/ - PLC_GetTime(&cal_begin); - calibration_count++; - }else{ /* do alignment (if possible) */ - if(calibration_count >= 0){ - /* End of calibration */ - /* Get final time */ - IEC_TIME cal_end; - PLC_GetTime(&cal_end); - /*adjust calibration_count*/ - calibration_count++; - /* compute mean of Tsync, over calibration period */ - Tsync = ((long long)(cal_end.tv_sec - cal_begin.tv_sec) * (long long)1000000000 + - (cal_end.tv_nsec - cal_begin.tv_nsec)) / calibration_count; - if( (Nticks = (Tsync / Ttick)) > 0){ - FreqCorr = (Tsync mod Ttick); /* to be divided by Nticks */ - }else{ - FreqCorr = Tsync - (Ttick mod Tsync); - } - /* - printf("Tsync = %%ld\n", Tsync); - printf("calibration_count = %%d\n", calibration_count); - printf("Nticks = %%d\n", Nticks); - */ - calibration_count = CALIBRATED; - } - if(calibration_count == CALIBRATED){ - /* Get Elapsed time since last PLC tick (__CURRENT_TIME) */ - IEC_TIME now; - long long elapsed; - long long Tcorr; - long long PhaseCorr; - long long PeriodicTcorr; - PLC_GetTime(&now); - elapsed = (now.tv_sec - __CURRENT_TIME.tv_sec) * 1000000000 + now.tv_nsec - __CURRENT_TIME.tv_nsec; - if(Nticks > 0){ - PhaseCorr = elapsed - (Ttick + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */ - Tcorr = Ttick + (PhaseCorr + FreqCorr) / Nticks; - if(Nticks < 2){ - /* When Sync source period is near Tick time */ - /* PhaseCorr may not be applied to Periodic time given to timer */ - PeriodicTcorr = Ttick + FreqCorr / Nticks; - }else{ - PeriodicTcorr = Tcorr; - } - }else if(__tick > last_tick){ - last_tick = __tick; - PhaseCorr = elapsed - (Tsync*sync_align_ratio/100); - PeriodicTcorr = Tcorr = Ttick + PhaseCorr + FreqCorr; - }else{ - /*PLC did not run meanwhile. Nothing to do*/ - return; - } - /* DO ALIGNEMENT */ - PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr); - } - } -} - -int suspendDebug() -{ - /* Prevent PLC to enter debug code */ - Debugging = 0; -} - -int resumeDebug() -{ - /* Let PLC enter debug code */ - Debugging = 1; -} diff -r dd630979f628 -r 08dc3d064cb5 runtime/plc_debug.c --- a/runtime/plc_debug.c Thu Aug 21 13:21:37 2008 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -/* - * 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; -} - diff -r dd630979f628 -r 08dc3d064cb5 targets/__init__.py --- a/targets/__init__.py Thu Aug 21 13:21:37 2008 +0200 +++ b/targets/__init__.py Thu Aug 21 17:17:36 2008 +0200 @@ -64,11 +64,14 @@ for target in DictXSD_target.keys(): targetchoices += DictXSD_target[target] -def code(target_name): - filename = path.join(path.split(__file__)[0], target_name, "plc_%s_main.c"%target_name) - if path.exists(filename): - return open(filename).read() - else: - return "#error %s target not implemented !!!\n"%target_name +def targetcode(target_name, code_name=None): + if code_name is None: + code_name="plc_%s_main.c"%target_name + filename = path.join(path.split(__file__)[0], target_name, code_name) + return open(filename).read() + +def code(name): + filename = path.join(path.split(__file__)[0],name + ".c") + return open(filename).read() from toolchain_gcc import toolchain_gcc \ No newline at end of file diff -r dd630979f628 -r 08dc3d064cb5 targets/plc_common_main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/targets/plc_common_main.c Thu Aug 21 17:17:36 2008 +0200 @@ -0,0 +1,177 @@ +/* + * Prototypes for function provided by arch-specific code (main) + * concatained after this template + ** / + + +/* + * Functions and variables provied by generated C softPLC + **/ +extern int common_ticktime__; + +/* + * Functions and variables provied by plc.c + **/ +void run(long int tv_sec, long int tv_nsec); + +#define maxval(a,b) ((a>b)?a:b) + +#include "iec_types.h" +/*#include "stdio.h" /* For debug */ + +/* + * Functions and variables provied by generated C softPLC + **/ +void config_run__(int tick); +void config_init__(void); + +/* + * Functions and variables to export to generated C softPLC and plugins + **/ + +IEC_TIME __CURRENT_TIME; +int __tick = 0; + +static int init_level = 0; +static int Debugging = 1; + +/* + * Prototypes of functions exported by plugins + **/ +%(calls_prototypes)s + +/* + * Retrieve input variables, run PLC and publish output variables + **/ +void __run() +{ + %(retrieve_calls)s + + if(Debugging) __retrieve_debug(); + + config_run__(__tick); + + if(Debugging) __publish_debug(); + + %(publish_calls)s + + __tick++; +} + +/* + * Initialize variables according to PLC's defalut values, + * and then init plugins with that values + **/ +int __init(int argc,char **argv) +{ + int res; + config_init__(); + %(init_calls)s + return 0; +} +/* + * Calls plugin cleanup proc. + **/ +void __cleanup() +{ + %(cleanup_calls)s +} + + +void PLC_GetTime(IEC_TIME *CURRENT_TIME); +void PLC_SetTimer(long long next, long long period); + +#define CALIBRATED -2 +#define NOT_CALIBRATED -1 +static int calibration_count = NOT_CALIBRATED; +static IEC_TIME cal_begin; +static long long Tsync = 0; +static long long FreqCorr = 0; +static int Nticks = 0; +static int last_tick = 0; +static long long Ttick = 0; +#define mod %% +/* + * Call this on each external sync, + * @param sync_align_ratio 0->100 : align ratio, < 0 : no align, calibrate period + **/ +void align_tick(int sync_align_ratio) +{ + /* + printf("align_tick(%%d)\n", calibrate); + */ + if(sync_align_ratio < 0){ /* Calibration */ + if(calibration_count == CALIBRATED) + /* Re-calibration*/ + calibration_count = NOT_CALIBRATED; + if(calibration_count == NOT_CALIBRATED) + /* Calibration start, get time*/ + PLC_GetTime(&cal_begin); + calibration_count++; + }else{ /* do alignment (if possible) */ + if(calibration_count >= 0){ + /* End of calibration */ + /* Get final time */ + IEC_TIME cal_end; + PLC_GetTime(&cal_end); + /*adjust calibration_count*/ + calibration_count++; + /* compute mean of Tsync, over calibration period */ + Tsync = ((long long)(cal_end.tv_sec - cal_begin.tv_sec) * (long long)1000000000 + + (cal_end.tv_nsec - cal_begin.tv_nsec)) / calibration_count; + if( (Nticks = (Tsync / Ttick)) > 0){ + FreqCorr = (Tsync mod Ttick); /* to be divided by Nticks */ + }else{ + FreqCorr = Tsync - (Ttick mod Tsync); + } + /* + printf("Tsync = %%ld\n", Tsync); + printf("calibration_count = %%d\n", calibration_count); + printf("Nticks = %%d\n", Nticks); + */ + calibration_count = CALIBRATED; + } + if(calibration_count == CALIBRATED){ + /* Get Elapsed time since last PLC tick (__CURRENT_TIME) */ + IEC_TIME now; + long long elapsed; + long long Tcorr; + long long PhaseCorr; + long long PeriodicTcorr; + PLC_GetTime(&now); + elapsed = (now.tv_sec - __CURRENT_TIME.tv_sec) * 1000000000 + now.tv_nsec - __CURRENT_TIME.tv_nsec; + if(Nticks > 0){ + PhaseCorr = elapsed - (Ttick + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */ + Tcorr = Ttick + (PhaseCorr + FreqCorr) / Nticks; + if(Nticks < 2){ + /* When Sync source period is near Tick time */ + /* PhaseCorr may not be applied to Periodic time given to timer */ + PeriodicTcorr = Ttick + FreqCorr / Nticks; + }else{ + PeriodicTcorr = Tcorr; + } + }else if(__tick > last_tick){ + last_tick = __tick; + PhaseCorr = elapsed - (Tsync*sync_align_ratio/100); + PeriodicTcorr = Tcorr = Ttick + PhaseCorr + FreqCorr; + }else{ + /*PLC did not run meanwhile. Nothing to do*/ + return; + } + /* DO ALIGNEMENT */ + PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr); + } + } +} + +int suspendDebug() +{ + /* Prevent PLC to enter debug code */ + Debugging = 0; +} + +int resumeDebug() +{ + /* Let PLC enter debug code */ + Debugging = 1; +} diff -r dd630979f628 -r 08dc3d064cb5 targets/plc_debug.c --- /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 + +#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; +} +