--- 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"]
@@ -1039,7 +1038,7 @@
self.GetIECProgramsAndVariables()
- debug_code = runtime.code("plc_debug") % {
+ debug_code = targets.code("plc_debug") % { "\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) @@ -1176,7 +1175,6 @@
for fname,fobject in ExtraFiles:
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) \
- for filename, unused in extrafiles:
builder = self.GetBuilder()
--- 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 @@
from threading import Timer
-import ctypes, os, dl, commands
-#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 @@
class PLCObject(pyro.ObjBase):
- def __init__(self, workingdir, daemon):
+ def __init__(self, workingdir, daemon, argv): pyro.ObjBase.__init__(self)
self.workingdir = workingdir
self.PLCStatus = "Stopped"
self.PLClibraryHandle = None
@@ -142,7 +141,7 @@
- badhandle = dlopen(badlib, dl.RTLD_NOLOAD)
+ #badhandle = dlopen(badlib, dl.RTLD_NOLOAD) print "Dirty lib detected :" + badlib
@@ -153,20 +152,24 @@
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"
print "_StartPLC did not return 0 !"
+ self.PLCStatus = "Stopped" + self.PLCStatus = "Dirty" if self.PLCStatus == "Started":
- self.PLCStatus = "Stopped"
- self.PLCStatus = "Dirty"
--- 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 @@
- filename = os.path.join(os.path.split(__file__)[0],name + ".c")
- if os.path.exists(filename):
- return open(filename).read()
- return "#error %s target not implemented !!!\n"%name
from PLCObject import PLCObject
--- 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 "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;
-static int init_level = 0;
-static int Debugging = 1;
- * Prototypes of functions exported by plugins
- * Retrieve input variables, run PLC and publish output variables
- if(Debugging) __retrieve_debug();
- if(Debugging) __publish_debug();
- * Initialize variables according to PLC's defalut values,
- * and then init plugins with that values
-int __init(int argc,char **argv)
- * Calls plugin cleanup proc.
-void PLC_GetTime(IEC_TIME *CURRENT_TIME);
-void PLC_SetTimer(long long next, long long period);
-#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 last_tick = 0;
-static long long Ttick = 0;
- * 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)
- calibration_count = NOT_CALIBRATED;
- if(calibration_count == NOT_CALIBRATED)
- /* Calibration start, get time*/
- PLC_GetTime(&cal_begin);
- }else{ /* do alignment (if possible) */
- if(calibration_count >= 0){
- /* End of calibration */
- /*adjust 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 */
- 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) */
- long long PeriodicTcorr;
- elapsed = (now.tv_sec - __CURRENT_TIME.tv_sec) * 1000000000 + now.tv_nsec - __CURRENT_TIME.tv_nsec;
- PhaseCorr = elapsed - (Ttick + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */
- Tcorr = Ttick + (PhaseCorr + FreqCorr) / Nticks;
- /* When Sync source period is near Tick time */
- /* PhaseCorr may not be applied to Periodic time given to timer */
- PeriodicTcorr = Ttick + FreqCorr / Nticks;
- }else if(__tick > last_tick){
- PhaseCorr = elapsed - (Tsync*sync_align_ratio/100);
- PeriodicTcorr = Tcorr = Ttick + PhaseCorr + FreqCorr;
- /*PLC did not run meanwhile. Nothing to do*/
- PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr);
- /* Prevent PLC to enter debug code */
- /* Let PLC enter debug code */
--- 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 @@
- * 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"
-#define BUFFER_SIZE 1024
-#define MAX_SUBSCRIBTION %(subscription_table_count)d
-/* Atomically accessed variable for buffer state */
-static long buffer_state = BUFFER_FREE;
-char debug_buffer[BUFFER_SIZE];
-static char* buffer_cursor = debug_buffer;
-%(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];
-%(variables_pointer_type_table_initializer)s
- long latest_state = AtomicCompareExchange(
- /* If buffer was free */
- if(latest_state == BUFFER_FREE)
- /* Reset buffer cursor */
- buffer_cursor = debug_buffer;
- /* iterate over subscriptions */
- for(subscription=subscription_table;
- subscription < latest_subscription;
- /* get variable descriptor */
- struct_plcvar* my_var = &variable_table[*subscription];
- 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;
- /*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*/
- /*TODO : signal subscription overflow*/
-void ResetDebugVariables(void)
- latest_subscription = subscription_table;
- /* atomically mark buffer as free */
- long latest_state = AtomicCompareExchange(
-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;
--- 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]
- filename = path.join(path.split(__file__)[0], target_name, "plc_%s_main.c"%target_name)
- if path.exists(filename):
- return open(filename).read()
- return "#error %s target not implemented !!!\n"%target_name
+def targetcode(target_name, code_name=None): + code_name="plc_%s_main.c"%target_name + filename = path.join(path.split(__file__)[0], target_name, code_name) + return open(filename).read() + 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
--- /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 "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; +static int init_level = 0; +static int Debugging = 1; + * Prototypes of functions exported by plugins + * Retrieve input variables, run PLC and publish output variables + if(Debugging) __retrieve_debug(); + if(Debugging) __publish_debug(); + * Initialize variables according to PLC's defalut values, + * and then init plugins with that values +int __init(int argc,char **argv) + * Calls plugin cleanup proc. +void PLC_GetTime(IEC_TIME *CURRENT_TIME); +void PLC_SetTimer(long long next, long long period); +#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 last_tick = 0; +static long long Ttick = 0; + * 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) + calibration_count = NOT_CALIBRATED; + if(calibration_count == NOT_CALIBRATED) + /* Calibration start, get time*/ + PLC_GetTime(&cal_begin); + }else{ /* do alignment (if possible) */ + if(calibration_count >= 0){ + /* End of calibration */ + /*adjust 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 */ + 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) */ + long long PeriodicTcorr; + elapsed = (now.tv_sec - __CURRENT_TIME.tv_sec) * 1000000000 + now.tv_nsec - __CURRENT_TIME.tv_nsec; + PhaseCorr = elapsed - (Ttick + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */ + Tcorr = Ttick + (PhaseCorr + FreqCorr) / Nticks; + /* When Sync source period is near Tick time */ + /* PhaseCorr may not be applied to Periodic time given to timer */ + PeriodicTcorr = Ttick + FreqCorr / Nticks; + }else if(__tick > last_tick){ + PhaseCorr = elapsed - (Tsync*sync_align_ratio/100); + PeriodicTcorr = Tcorr = Ttick + PhaseCorr + FreqCorr; + /*PLC did not run meanwhile. Nothing to do*/ + PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr); + /* Prevent PLC to enter debug code */ + /* Let PLC enter debug code */ --- /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 @@
+ * 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" +#define BUFFER_SIZE 1024 +#define MAX_SUBSCRIBTION %(subscription_table_count)d +/* Atomically accessed variable for buffer state */ +static long buffer_state = BUFFER_FREE; +char debug_buffer[BUFFER_SIZE]; +static char* buffer_cursor = debug_buffer; +%(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]; +%(variables_pointer_type_table_initializer)s + long latest_state = AtomicCompareExchange( + /* If buffer was free */ + if(latest_state == BUFFER_FREE) + /* Reset buffer cursor */ + buffer_cursor = debug_buffer; + /* iterate over subscriptions */ + for(subscription=subscription_table; + subscription < latest_subscription; + /* get variable descriptor */ + struct_plcvar* my_var = &variable_table[*subscription]; + 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; + /*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*/ + /*TODO : signal subscription overflow*/ +void ResetDebugVariables(void) + latest_subscription = subscription_table; + /* atomically mark buffer as free */ + long latest_state = AtomicCompareExchange( +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;