From 869f498daff99f317a72470f6de3c4fe3766980d Mon Sep 17 00:00:00 2001 From: wikano Date: Thu, 4 Dec 2025 22:55:32 +0100 Subject: [PATCH] ex 4 --- motor/build/Config0.c | 29 - motor/build/Config0.h | 2 - motor/build/Config0.o | Bin 994 -> 0 bytes motor/build/LOCATED_VARIABLES.h | 0 motor/build/POUS.c | 74 - motor/build/POUS.h | 50 - motor/build/Res0.c | 37 - motor/build/Res0.o | Bin 3048 -> 0 bytes motor/build/VARIABLES.csv | 30 - motor/build/beremiz.h | 44 - motor/build/generated_plc.st | 84 + motor/build/lastbuildPLC.md5 | 1 - motor/build/motor.dll | Bin 86078 -> 0 bytes motor/build/plc.st | 84 + motor/build/plc_debugger.c | 548 ------- motor/build/plc_debugger.o | Bin 13217 -> 0 bytes motor/build/plc_main.c | 980 ------------ motor/build/plc_main.o | Bin 18389 -> 0 bytes motor/plc.xml | 2655 ++++++++++--------------------- 19 files changed, 973 insertions(+), 3645 deletions(-) delete mode 100644 motor/build/Config0.c delete mode 100644 motor/build/Config0.h delete mode 100644 motor/build/Config0.o delete mode 100644 motor/build/LOCATED_VARIABLES.h delete mode 100644 motor/build/POUS.c delete mode 100644 motor/build/POUS.h delete mode 100644 motor/build/Res0.c delete mode 100644 motor/build/Res0.o delete mode 100644 motor/build/VARIABLES.csv delete mode 100644 motor/build/beremiz.h delete mode 100644 motor/build/lastbuildPLC.md5 delete mode 100644 motor/build/motor.dll delete mode 100644 motor/build/plc_debugger.c delete mode 100644 motor/build/plc_debugger.o delete mode 100644 motor/build/plc_main.c delete mode 100644 motor/build/plc_main.o diff --git a/motor/build/Config0.c b/motor/build/Config0.c deleted file mode 100644 index a824b83..0000000 --- a/motor/build/Config0.c +++ /dev/null @@ -1,29 +0,0 @@ -/*******************************************/ -/* FILE GENERATED BY iec2c */ -/* Editing this file is not recommended... */ -/*******************************************/ - -#include "iec_std_lib.h" - -#include "accessor.h" - -#include "POUS.h" - -// CONFIGURATION CONFIG0 - -void RES0_init__(void); - -void config_init__(void) { - BOOL retain; - retain = 0; - - RES0_init__(); -} - -void RES0_run__(unsigned long tick); - -void config_run__(unsigned long tick) { - RES0_run__(tick); -} -unsigned long long common_ticktime__ = 20000000ULL; /*ns*/ -unsigned long greatest_tick_count__ = (unsigned long)0UL; /*tick*/ diff --git a/motor/build/Config0.h b/motor/build/Config0.h deleted file mode 100644 index 680f75c..0000000 --- a/motor/build/Config0.h +++ /dev/null @@ -1,2 +0,0 @@ -#include "beremiz.h" - diff --git a/motor/build/Config0.o b/motor/build/Config0.o deleted file mode 100644 index c907a24381809eb635ca8f9848aa28dcd94ecf9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 994 zcmZuw!AiqG5S^GRf`W<)Uc^0kP%&%NT0}eqi}WBuQNfeMHcjiIO(oev?a709_9OfV zkN%E#&+5$XMziX`?##S-Gm{-At;aDSd3ONjl~n>Rrnn zmpZy(vdGDSQI(KP~SoA&mMMnl9Pa_uwq5nf8!b0e;;wf$K@^CnWNR2%diI8EKducyG or@-o@aYM$L45f&!!>HF!G`rjFB?^EN,__BOOL_LITERAL(TRUE),retain) - __INIT_VAR(data__->ENO,__BOOL_LITERAL(TRUE),retain) - __INIT_VAR(data__->TRIG,__BOOL_LITERAL(FALSE),retain) - __INIT_VAR(data__->MSG,__STRING_LITERAL(0,""),retain) - __INIT_VAR(data__->LEVEL,LOGLEVEL__INFO,retain) - __INIT_VAR(data__->TRIG0,__BOOL_LITERAL(FALSE),retain) -} - -// Code part -void LOGGER_body__(LOGGER *data__) { - // Control execution - if (!__GET_VAR(data__->EN)) { - __SET_VAR(data__->,ENO,,__BOOL_LITERAL(FALSE)); - return; - } - else { - __SET_VAR(data__->,ENO,,__BOOL_LITERAL(TRUE)); - } - // Initialise TEMP variables - - if ((__GET_VAR(data__->TRIG,) && !(__GET_VAR(data__->TRIG0,)))) { - #define GetFbVar(var,...) __GET_VAR(data__->var,__VA_ARGS__) - #define SetFbVar(var,val,...) __SET_VAR(data__->,var,__VA_ARGS__,val) - - LogMessage(GetFbVar(LEVEL),(char*)GetFbVar(MSG, .body),GetFbVar(MSG, .len)); - - #undef GetFbVar - #undef SetFbVar -; - }; - __SET_VAR(data__->,TRIG0,,__GET_VAR(data__->TRIG,)); - - goto __end; - -__end: - return; -} // LOGGER_body__() - - - - - -void MOTOR_init__(MOTOR *data__, BOOL retain) { - __INIT_VAR(data__->START,__BOOL_LITERAL(FALSE),retain) - __INIT_VAR(data__->STOP,__BOOL_LITERAL(FALSE),retain) - __INIT_VAR(data__->DELAY,__time_to_timespec(1, 100, 0, 0, 0, 0),retain) - __INIT_VAR(data__->RUNNING,__BOOL_LITERAL(FALSE),retain) - RS_init__(&data__->RS0,retain); - TON_init__(&data__->TON0,retain); -} - -// Code part -void MOTOR_body__(MOTOR *data__) { - // Initialise TEMP variables - - __SET_VAR(data__->TON0.,IN,,__GET_VAR(data__->START,)); - __SET_VAR(data__->TON0.,PT,,__GET_VAR(data__->DELAY,)); - TON_body__(&data__->TON0); - __SET_VAR(data__->RS0.,S,,__GET_VAR(data__->TON0.Q,)); - __SET_VAR(data__->RS0.,R1,,__GET_VAR(data__->STOP,)); - RS_body__(&data__->RS0); - __SET_VAR(data__->,RUNNING,,__GET_VAR(data__->RS0.Q1,)); - - goto __end; - -__end: - return; -} // MOTOR_body__() - - - - - diff --git a/motor/build/POUS.h b/motor/build/POUS.h deleted file mode 100644 index 10a17cf..0000000 --- a/motor/build/POUS.h +++ /dev/null @@ -1,50 +0,0 @@ -#include "beremiz.h" -#ifndef __POUS_H -#define __POUS_H - -#include "accessor.h" -#include "iec_std_lib.h" - -__DECLARE_ENUMERATED_TYPE(LOGLEVEL, - LOGLEVEL__CRITICAL, - LOGLEVEL__WARNING, - LOGLEVEL__INFO, - LOGLEVEL__DEBUG -) -// FUNCTION_BLOCK LOGGER -// Data part -typedef struct { - // FB Interface - IN, OUT, IN_OUT variables - __DECLARE_VAR(BOOL,EN) - __DECLARE_VAR(BOOL,ENO) - __DECLARE_VAR(BOOL,TRIG) - __DECLARE_VAR(STRING,MSG) - __DECLARE_VAR(LOGLEVEL,LEVEL) - - // FB private variables - TEMP, private and located variables - __DECLARE_VAR(BOOL,TRIG0) - -} LOGGER; - -void LOGGER_init__(LOGGER *data__, BOOL retain); -// Code part -void LOGGER_body__(LOGGER *data__); -// PROGRAM MOTOR -// Data part -typedef struct { - // PROGRAM Interface - IN, OUT, IN_OUT variables - - // PROGRAM private variables - TEMP, private and located variables - __DECLARE_VAR(BOOL,START) - __DECLARE_VAR(BOOL,STOP) - __DECLARE_VAR(TIME,DELAY) - __DECLARE_VAR(BOOL,RUNNING) - RS RS0; - TON TON0; - -} MOTOR; - -void MOTOR_init__(MOTOR *data__, BOOL retain); -// Code part -void MOTOR_body__(MOTOR *data__); -#endif //__POUS_H diff --git a/motor/build/Res0.c b/motor/build/Res0.c deleted file mode 100644 index 61156b7..0000000 --- a/motor/build/Res0.c +++ /dev/null @@ -1,37 +0,0 @@ -/*******************************************/ -/* FILE GENERATED BY iec2c */ -/* Editing this file is not recommended... */ -/*******************************************/ - -#include "iec_std_lib.h" - -// RESOURCE RES0 - -extern unsigned long long common_ticktime__; - -#include "accessor.h" -#include "POUS.h" - -#include "Config0.h" - -#include "POUS.c" - -BOOL TASK0; -MOTOR RES0__INSTANCE0; -#define INSTANCE0 RES0__INSTANCE0 - -void RES0_init__(void) { - BOOL retain; - retain = 0; - - TASK0 = __BOOL_LITERAL(FALSE); - MOTOR_init__(&INSTANCE0,retain); -} - -void RES0_run__(unsigned long tick) { - TASK0 = !(tick % 1); - if (TASK0) { - MOTOR_body__(&INSTANCE0); - } -} - diff --git a/motor/build/Res0.o b/motor/build/Res0.o deleted file mode 100644 index 2191f0fdf4b049ddf9047656c885df29db1f4c3e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3048 zcmZ`*?N3`(7(e&6ushv$*<^#k1{bYyDs*LI2pfy{v?a6(qe68{=2Bp^jAR0#y^-NW z2rwat!I&jxiHXL4U>^*bnwa92Zow}bPO}gDfJPGtnrId=PP6)Z?pxapPdMj!e?8AF zr~87$Xx#_ct7A^)PDFb*NqpTz89?EsN53BQM zSd;-n0HKZast@HT7J&K$dcT`-(ITc6gw(+Juf;RXE`MOw?^2tm7X#CNmox)Buy9}D z^$Uq@{`wp8$H~C>wc@LCIjg^A5iz;k&)CFL;5zT8Q1ZoON)Q&7#S|9>iQ~^9@jPj4 z5;AG*J)9}-#Lj21&@%><$r7;0gyklD#)SJ#_<{*vG+~noTTOV}gb@?=m{2p}+XSzV zP2m)=Q)6?)kj6g1c{LVu%jFZqU~}zgh$7E($M~{1TF(O0-)e;uNzI9(7^-2%a2w?kuaJ19#H%IVAaO2npTwIbej>#cx&oITm3s)+hb+Zan0tx#lMFCKFsEN= zS6y&=ah+F)TE09lOmT&;dn-jv3eI?)!D+9H%k$oHbd!$`?_u)fhww0wlqa6T1VXb& z)HaibhfjHTf!=M>BIsfg>@-YwFwI3~cVP~-?WS4@)C$nyI?U!ML~yO;@szhvAlp*d zYPS%$m}!LoyVw<)drbmfLhXfh$=YSPT(#`V1UPRNwQYeJ{E(pL8HO7Ch;;h%IGoj8RYtWJno`A}CHQ0G?E0yi#nqh^(X(0?~52>le9Io+Y0 z?o1{}-Umz~sSB$b^Ti(FWiP=gFz1tuQS*d6 zk>wo_JUUMNE|X7=u?`!6selkO>Q4dSyVzTR&jHq;|AoL+z+#MOF>nR&5Vk^mz;|{kwi+A3}ezLK@ZR}}OvrV^s-o|`37PK+S;4y3mqF9*TL7hkaGo&=y21XeX<d4t(5&D!|*`olr6K6?AI9GzC)m! z%3awnF(d+=Fi!n{t*z+JdWF$r&LPnE_2~M@WYIImA?S~hN0dG@In+I)XJ48eszPL8 z-u^Pp&g<9)hs29?=*zmn?=1$P$bQCYWa%0n9=1^TU^F(67<5M>zE|7Y8jpn|;b2Q6 zYi@07YHW-2_Vp$r5sT{T?>+~rr8V4Yiwwe)nC}0_XIo>t$MUG-gIXWl<>a(sGP-gk ac&t6lkNFxsthv9ZB^r-+_C(o3Y5xb!J8KXC diff --git a/motor/build/VARIABLES.csv b/motor/build/VARIABLES.csv deleted file mode 100644 index d7ad373..0000000 --- a/motor/build/VARIABLES.csv +++ /dev/null @@ -1,30 +0,0 @@ -// Programs -0;CONFIG0.RES0.INSTANCE0;MOTOR; - -// Variables -0;FB;CONFIG0.RES0.INSTANCE0;CONFIG0.RES0.INSTANCE0;MOTOR; -1;VAR;CONFIG0.RES0.INSTANCE0.START;CONFIG0.RES0.INSTANCE0.START;BOOL; -2;VAR;CONFIG0.RES0.INSTANCE0.STOP;CONFIG0.RES0.INSTANCE0.STOP;BOOL; -3;VAR;CONFIG0.RES0.INSTANCE0.DELAY;CONFIG0.RES0.INSTANCE0.DELAY;TIME; -4;VAR;CONFIG0.RES0.INSTANCE0.RUNNING;CONFIG0.RES0.INSTANCE0.RUNNING;BOOL; -5;FB;CONFIG0.RES0.INSTANCE0.RS0;CONFIG0.RES0.INSTANCE0.RS0;RS; -6;VAR;CONFIG0.RES0.INSTANCE0.RS0.EN;CONFIG0.RES0.INSTANCE0.RS0.EN;BOOL; -7;VAR;CONFIG0.RES0.INSTANCE0.RS0.ENO;CONFIG0.RES0.INSTANCE0.RS0.ENO;BOOL; -8;VAR;CONFIG0.RES0.INSTANCE0.RS0.S;CONFIG0.RES0.INSTANCE0.RS0.S;BOOL; -9;VAR;CONFIG0.RES0.INSTANCE0.RS0.R1;CONFIG0.RES0.INSTANCE0.RS0.R1;BOOL; -10;VAR;CONFIG0.RES0.INSTANCE0.RS0.Q1;CONFIG0.RES0.INSTANCE0.RS0.Q1;BOOL; -11;FB;CONFIG0.RES0.INSTANCE0.TON0;CONFIG0.RES0.INSTANCE0.TON0;TON; -12;VAR;CONFIG0.RES0.INSTANCE0.TON0.EN;CONFIG0.RES0.INSTANCE0.TON0.EN;BOOL; -13;VAR;CONFIG0.RES0.INSTANCE0.TON0.ENO;CONFIG0.RES0.INSTANCE0.TON0.ENO;BOOL; -14;VAR;CONFIG0.RES0.INSTANCE0.TON0.IN;CONFIG0.RES0.INSTANCE0.TON0.IN;BOOL; -15;VAR;CONFIG0.RES0.INSTANCE0.TON0.PT;CONFIG0.RES0.INSTANCE0.TON0.PT;TIME; -16;VAR;CONFIG0.RES0.INSTANCE0.TON0.Q;CONFIG0.RES0.INSTANCE0.TON0.Q;BOOL; -17;VAR;CONFIG0.RES0.INSTANCE0.TON0.ET;CONFIG0.RES0.INSTANCE0.TON0.ET;TIME; -18;VAR;CONFIG0.RES0.INSTANCE0.TON0.STATE;CONFIG0.RES0.INSTANCE0.TON0.STATE;SINT; -19;VAR;CONFIG0.RES0.INSTANCE0.TON0.PREV_IN;CONFIG0.RES0.INSTANCE0.TON0.PREV_IN;BOOL; -20;VAR;CONFIG0.RES0.INSTANCE0.TON0.CURRENT_TIME;CONFIG0.RES0.INSTANCE0.TON0.CURRENT_TIME;TIME; -21;VAR;CONFIG0.RES0.INSTANCE0.TON0.START_TIME;CONFIG0.RES0.INSTANCE0.TON0.START_TIME;TIME; - - -// Ticktime -20000000 diff --git a/motor/build/beremiz.h b/motor/build/beremiz.h deleted file mode 100644 index 89f7b4b..0000000 --- a/motor/build/beremiz.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef _BEREMIZ_H_ -#define _BEREMIZ_H_ - -/* Beremiz' header file for use by extensions */ - -#include "iec_types.h" - -#define LOG_LEVELS 4 -#define LOG_CRITICAL 0 -#define LOG_WARNING 1 -#define LOG_INFO 2 -#define LOG_DEBUG 3 - -extern unsigned long long common_ticktime__; - -#ifdef TARGET_LOGGING_DISABLE -static inline int LogMessage(uint8_t level, char* buf, uint32_t size) -{ - (void)level; - (void)buf; - (void)size; - return 0; -} -#else -int LogMessage(uint8_t level, char* buf, uint32_t size); -#endif - -long AtomicCompareExchange(long* atomicvar,long compared, long exchange); -void *create_RT_to_nRT_signal(char* name); -void delete_RT_to_nRT_signal(void* handle); -int wait_RT_to_nRT_signal(void* handle); -int unblock_RT_to_nRT_signal(void* handle); -void nRT_reschedule(void); - - -#ifdef REALTIME_LINUX - -#ifndef PLC_THREAD_PRIORITY -#define PLC_THREAD_PRIORITY 80 -#endif - -#endif - -#endif diff --git a/motor/build/generated_plc.st b/motor/build/generated_plc.st index 0cefef6..2c32d01 100644 --- a/motor/build/generated_plc.st +++ b/motor/build/generated_plc.st @@ -13,6 +13,90 @@ PROGRAM motor RUNNING := RS0.Q1; END_PROGRAM +PROGRAM traffic_light + VAR + RED : BOOL; + RED0 : BOOL; + ORANGE : BOOL; + GREEN : BOOL; + DELAY : TIME := T#30s; + TON0 : TON; + TON1 : TON; + TON2 : TON; + WAIT : BOOL := 1; + TON3 : TON; + DELAY2 : TIME := T#1s; + DELAY3 : TIME := T#10s; + END_VAR + + INITIAL_STEP Step0: + GREEN(N); + COMPUTE_FUNCTION_BLOCKS(S); + END_STEP + + ACTION COMPUTE_FUNCTION_BLOCKS: + TON0(IN := WAIT, PT := DELAY); + TON4(IN := WAIT, PT := DELAY3); + TON3(IN := WAIT, PT := DELAY2); + END_ACTION + + TRANSITION FROM Step0 TO Step1 + := TON0.Q; + END_TRANSITION + + STEP Step1: + ORANGE(N); + END_STEP + + TRANSITION FROM Step1 TO Step2 + := TON3.Q; + END_TRANSITION + + STEP Step2: + RED(N); + END_STEP + + TRANSITION FROM Step2 TO Step0 + := TON4.Q; + END_TRANSITION + +END_PROGRAM + +PROGRAM automate_controle_commande_ld + VAR + P1_enc : BOOL; + P1_run : BOOL; + P2_enc : BOOL; + P2_run : BOOL; + P3_enc : BOOL; + P3_run : BOOL; + Pump_def : BOOL; + WAIT7 : TIME; + secours : BOOL; + only_one_run : BOOL; + TON0 : TON; + WAIT13 : TIME; + TON1 : TON; + secours_c_ok : BOOL; + CTU0 : CTU; + R_TRIG1 : R_TRIG; + _TMP_GT33_ENO : BOOL; + _TMP_GT33_OUT : BOOL; + END_VAR + + Pump_def := NOT(P1_run) AND P1_enc OR NOT(P2_run) AND P2_enc OR NOT(P3_run) AND P3_enc; + Pump_def := TRUE; + TON0(IN := TRUE, PT := WAIT7); + secours := TON0.Q; + only_one_run := NOT(P3_run) AND NOT(P2_run) AND P1_run OR NOT(P3_run) AND P2_run AND NOT(P1_run) OR P3_run AND NOT(P2_enc) AND NOT(P1_run); + Pump_def := TRUE; + TON1(IN := TRUE, PT := WAIT13); + R_TRIG1(CLK := ); + CTU0(CU := R_TRIG1.Q, R := true); + _TMP_GT33_OUT := GT(EN := TON1.Q, IN1 := CTU0.Q, IN2 := 1, ENO => _TMP_GT33_ENO); + secours_c_ok := _TMP_GT33_OUT; +END_PROGRAM + CONFIGURATION Config0 diff --git a/motor/build/lastbuildPLC.md5 b/motor/build/lastbuildPLC.md5 deleted file mode 100644 index a72dd3c..0000000 --- a/motor/build/lastbuildPLC.md5 +++ /dev/null @@ -1 +0,0 @@ -533fc3297d0bbb235fea6b21736971d0 \ No newline at end of file diff --git a/motor/build/motor.dll b/motor/build/motor.dll deleted file mode 100644 index f59ed9033ade58ea13cfe2062260bbe1ce201a34..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 86078 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 nrin-&66=?o=i&Zta{*|bAPGfrU=Q{n#upAz^l diff --git a/motor/build/plc.st b/motor/build/plc.st index 8bc6c81..58e2df4 100644 --- a/motor/build/plc.st +++ b/motor/build/plc.st @@ -36,6 +36,90 @@ PROGRAM motor RUNNING := RS0.Q1; END_PROGRAM +PROGRAM traffic_light + VAR + RED : BOOL; + RED0 : BOOL; + ORANGE : BOOL; + GREEN : BOOL; + DELAY : TIME := T#30s; + TON0 : TON; + TON1 : TON; + TON2 : TON; + WAIT : BOOL := 1; + TON3 : TON; + DELAY2 : TIME := T#1s; + DELAY3 : TIME := T#10s; + END_VAR + + INITIAL_STEP Step0: + GREEN(N); + COMPUTE_FUNCTION_BLOCKS(S); + END_STEP + + ACTION COMPUTE_FUNCTION_BLOCKS: + TON0(IN := WAIT, PT := DELAY); + TON4(IN := WAIT, PT := DELAY3); + TON3(IN := WAIT, PT := DELAY2); + END_ACTION + + TRANSITION FROM Step0 TO Step1 + := TON0.Q; + END_TRANSITION + + STEP Step1: + ORANGE(N); + END_STEP + + TRANSITION FROM Step1 TO Step2 + := TON3.Q; + END_TRANSITION + + STEP Step2: + RED(N); + END_STEP + + TRANSITION FROM Step2 TO Step0 + := TON4.Q; + END_TRANSITION + +END_PROGRAM + +PROGRAM automate_controle_commande_ld + VAR + P1_enc : BOOL; + P1_run : BOOL; + P2_enc : BOOL; + P2_run : BOOL; + P3_enc : BOOL; + P3_run : BOOL; + Pump_def : BOOL; + WAIT7 : TIME; + secours : BOOL; + only_one_run : BOOL; + TON0 : TON; + WAIT13 : TIME; + TON1 : TON; + secours_c_ok : BOOL; + CTU0 : CTU; + R_TRIG1 : R_TRIG; + _TMP_GT33_ENO : BOOL; + _TMP_GT33_OUT : BOOL; + END_VAR + + Pump_def := NOT(P1_run) AND P1_enc OR NOT(P2_run) AND P2_enc OR NOT(P3_run) AND P3_enc; + Pump_def := TRUE; + TON0(IN := TRUE, PT := WAIT7); + secours := TON0.Q; + only_one_run := NOT(P3_run) AND NOT(P2_run) AND P1_run OR NOT(P3_run) AND P2_run AND NOT(P1_run) OR P3_run AND NOT(P2_enc) AND NOT(P1_run); + Pump_def := TRUE; + TON1(IN := TRUE, PT := WAIT13); + R_TRIG1(CLK := ); + CTU0(CU := R_TRIG1.Q, R := true); + _TMP_GT33_OUT := GT(EN := TON1.Q, IN1 := CTU0.Q, IN2 := 1, ENO => _TMP_GT33_ENO); + secours_c_ok := _TMP_GT33_OUT; +END_PROGRAM + CONFIGURATION Config0 diff --git a/motor/build/plc_debugger.c b/motor/build/plc_debugger.c deleted file mode 100644 index 078388c..0000000 --- a/motor/build/plc_debugger.c +++ /dev/null @@ -1,548 +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. - * - * - * */ -#ifdef TARGET_DEBUG_AND_RETAIN_DISABLE - -void __init_debug (void){} -void __cleanup_debug (void){} -void __retrieve_debug(void){} -void __publish_debug (void){} - -#else - -#include "iec_types_all.h" -#include "POUS.h" -/*for memcpy*/ -#include -#include - -typedef unsigned int dbgvardsc_index_t; -typedef unsigned short trace_buf_offset_t; - -#define BUFFER_EMPTY 0 -#define BUFFER_FULL 1 - -#ifndef TARGET_ONLINE_DEBUG_DISABLE - -#define TRACE_BUFFER_SIZE 4096 -#define TRACE_LIST_SIZE 1024 - -/* Atomically accessed variable for buffer state */ -static long trace_buffer_state = BUFFER_EMPTY; - -typedef struct trace_item_s { - dbgvardsc_index_t dbgvardsc_index; -} trace_item_t; - -trace_item_t trace_list[TRACE_LIST_SIZE]; -char trace_buffer[TRACE_BUFFER_SIZE]; - -/* Trace's cursor*/ -static trace_item_t *trace_list_collect_cursor = trace_list; -static trace_item_t *trace_list_addvar_cursor = trace_list; -static const trace_item_t *trace_list_end = - &trace_list[TRACE_LIST_SIZE-1]; -static char *trace_buffer_cursor = trace_buffer; -static const char *trace_buffer_end = trace_buffer + TRACE_BUFFER_SIZE; - - - -#define FORCE_BUFFER_SIZE 1024 -#define FORCE_LIST_SIZE 256 - -typedef struct force_item_s { - dbgvardsc_index_t dbgvardsc_index; - void *value_pointer_backup; -} force_item_t; - -force_item_t force_list[FORCE_LIST_SIZE]; -char force_buffer[FORCE_BUFFER_SIZE]; - -/* Force's cursor*/ -static force_item_t *force_list_apply_cursor = force_list; -static force_item_t *force_list_addvar_cursor = force_list; -static const force_item_t *force_list_end = - &force_list[FORCE_LIST_SIZE-1]; -static char *force_buffer_cursor = force_buffer; -static const char *force_buffer_end = force_buffer + FORCE_BUFFER_SIZE; - - -#endif - -/*** - * Declare programs - **/ -extern MOTOR RES0__INSTANCE0; - -/*** - * Declare global variables from resources and conf - **/ -extern MOTOR RES0__INSTANCE0; - -typedef const struct { - void *ptr; - __IEC_types_enum type; -} dbgvardsc_t; - -static const dbgvardsc_t dbgvardsc[] = { -{&(RES0__INSTANCE0.START), BOOL_ENUM}, -{&(RES0__INSTANCE0.STOP), BOOL_ENUM}, -{&(RES0__INSTANCE0.DELAY), TIME_ENUM}, -{&(RES0__INSTANCE0.RUNNING), BOOL_ENUM}, -{&(RES0__INSTANCE0.RS0.EN), BOOL_ENUM}, -{&(RES0__INSTANCE0.RS0.ENO), BOOL_ENUM}, -{&(RES0__INSTANCE0.RS0.S), BOOL_ENUM}, -{&(RES0__INSTANCE0.RS0.R1), BOOL_ENUM}, -{&(RES0__INSTANCE0.RS0.Q1), BOOL_ENUM}, -{&(RES0__INSTANCE0.TON0.EN), BOOL_ENUM}, -{&(RES0__INSTANCE0.TON0.ENO), BOOL_ENUM}, -{&(RES0__INSTANCE0.TON0.IN), BOOL_ENUM}, -{&(RES0__INSTANCE0.TON0.PT), TIME_ENUM}, -{&(RES0__INSTANCE0.TON0.Q), BOOL_ENUM}, -{&(RES0__INSTANCE0.TON0.ET), TIME_ENUM}, -{&(RES0__INSTANCE0.TON0.STATE), SINT_ENUM}, -{&(RES0__INSTANCE0.TON0.PREV_IN), BOOL_ENUM}, -{&(RES0__INSTANCE0.TON0.CURRENT_TIME), TIME_ENUM}, -{&(RES0__INSTANCE0.TON0.START_TIME), TIME_ENUM} -}; - -static const dbgvardsc_index_t retain_list[] = { - -}; -static unsigned int retain_list_collect_cursor = 0; -static const unsigned int retain_list_size = sizeof(retain_list)/sizeof(dbgvardsc_index_t); - -typedef void(*__for_each_variable_do_fp)(dbgvardsc_t*); -void __for_each_variable_do(__for_each_variable_do_fp fp) -{ - unsigned int i; - for(i = 0; i < sizeof(dbgvardsc)/sizeof(dbgvardsc_t); i++){ - dbgvardsc_t *dsc = &dbgvardsc[i]; - if(dsc->type != UNKNOWN_ENUM) - (*fp)(dsc); - } -} - -#define __Unpack_desc_type dbgvardsc_t - - -#define __Unpack_case_t(TYPENAME) \ - case TYPENAME##_ENUM : \ - if(flags) *flags = ((__IEC_##TYPENAME##_t *)varp)->flags; \ - if(value_p) *value_p = &((__IEC_##TYPENAME##_t *)varp)->value; \ - if(size) *size = sizeof(TYPENAME); \ - break; - -#define __Unpack_case_p(TYPENAME) \ - case TYPENAME##_O_ENUM : \ - case TYPENAME##_P_ENUM : \ - if(flags) *flags = ((__IEC_##TYPENAME##_p *)varp)->flags; \ - if(value_p) *value_p = ((__IEC_##TYPENAME##_p *)varp)->value; \ - if(size) *size = sizeof(TYPENAME); \ - break; - -#define __Is_a_string(dsc) (dsc->type == STRING_ENUM) ||\ - (dsc->type == STRING_P_ENUM) ||\ - (dsc->type == STRING_O_ENUM) - -static int UnpackVar(__Unpack_desc_type *dsc, void **value_p, char *flags, size_t *size) -{ - void *varp = dsc->ptr; - /* find data to copy*/ - switch(dsc->type){ - __ANY(__Unpack_case_t) - __ANY(__Unpack_case_p) - default: - return 0; /* should never happen */ - } - return 1; -} - - - -void Remind(unsigned int offset, unsigned int count, void * p); - -extern int CheckRetainBuffer(void); -extern void InitRetain(void); - -void __init_debug(void) -{ - /* init local static vars */ -#ifndef TARGET_ONLINE_DEBUG_DISABLE - trace_buffer_cursor = trace_buffer; - trace_list_addvar_cursor = trace_list; - trace_list_collect_cursor = trace_list; - trace_buffer_state = BUFFER_EMPTY; - - force_buffer_cursor = force_buffer; - force_list_addvar_cursor = force_list; - force_list_apply_cursor = force_list; -#endif - - InitRetain(); - /* Iterate over all variables to fill debug buffer */ - if(CheckRetainBuffer()){ - unsigned int retain_offset = 0; - retain_list_collect_cursor = 0; - - /* iterate over retain list */ - while(retain_list_collect_cursor < retain_list_size){ - void *value_p = NULL; - size_t size; - char* next_cursor; - - dbgvardsc_t *dsc = &dbgvardsc[ - retain_list[retain_list_collect_cursor]]; - - UnpackVar(dsc, &value_p, NULL, &size); - - /* if buffer not full */ - Remind(retain_offset, size, value_p); - /* increment cursor according size*/ - retain_offset += size; - - retain_list_collect_cursor++; - } - }else{ - char mstr[] = "RETAIN memory invalid - defaults used"; - LogMessage(LOG_WARNING, mstr, sizeof(mstr)); - } -} - -extern void InitiateDebugTransfer(void); -extern void CleanupRetain(void); - -extern unsigned long __tick; - -void __cleanup_debug(void) -{ -#ifndef TARGET_ONLINE_DEBUG_DISABLE - trace_buffer_cursor = trace_buffer; - InitiateDebugTransfer(); -#endif - - CleanupRetain(); -} - -void __retrieve_debug(void) -{ -} - -void Retain(unsigned int offset, unsigned int count, void * p); - -/* Return size of all retain variables */ -unsigned int GetRetainSize(void) -{ - unsigned int retain_size = 0; - retain_list_collect_cursor = 0; - - /* iterate over retain list */ - while(retain_list_collect_cursor < retain_list_size){ - void *value_p = NULL; - size_t size; - char* next_cursor; - - dbgvardsc_t *dsc = &dbgvardsc[ - retain_list[retain_list_collect_cursor]]; - - UnpackVar(dsc, &value_p, NULL, &size); - - retain_size += size; - retain_list_collect_cursor++; - } - - return retain_size; -} - - -extern void PLC_GetTime(IEC_TIME*); -extern int TryEnterDebugSection(void); -extern long AtomicCompareExchange(long*, long, long); -extern long long AtomicCompareExchange64(long long* , long long , long long); -extern void LeaveDebugSection(void); -extern void ValidateRetainBuffer(void); -extern void InValidateRetainBuffer(void); - -#define __ReForceOutput_case_p(TYPENAME) \ - case TYPENAME##_P_ENUM : \ - case TYPENAME##_O_ENUM : \ - { \ - char *next_cursor = force_buffer_cursor + sizeof(TYPENAME); \ - if(next_cursor <= force_buffer_end ){ \ - /* outputs real value must be systematically forced */ \ - if(vartype == TYPENAME##_O_ENUM) \ - /* overwrite value pointed by backup */ \ - *((TYPENAME *)force_list_apply_cursor->value_pointer_backup) = \ - *((TYPENAME *)force_buffer_cursor); \ - /* inc force_buffer cursor */ \ - force_buffer_cursor = next_cursor; \ - }else{ \ - stop = 1; \ - } \ - } \ - break; -void __publish_debug(void) -{ - InValidateRetainBuffer(); - -#ifndef TARGET_ONLINE_DEBUG_DISABLE - /* Check there is no running debugger re-configuration */ - if(TryEnterDebugSection()){ - /* Lock buffer */ - long latest_state = AtomicCompareExchange( - &trace_buffer_state, - BUFFER_EMPTY, - BUFFER_FULL); - - /* If buffer was free */ - if(latest_state == BUFFER_EMPTY) - { - int stop = 0; - /* Reset force list cursor */ - force_list_apply_cursor = force_list; - - /* iterate over force list */ - while(!stop && force_list_apply_cursor < force_list_addvar_cursor){ - dbgvardsc_t *dsc = &dbgvardsc[ - force_list_apply_cursor->dbgvardsc_index]; - void *varp = dsc->ptr; - __IEC_types_enum vartype = dsc->type; - switch(vartype){ - __ANY(__ReForceOutput_case_p) - default: - break; - } - force_list_apply_cursor++; - } - - /* Reset buffer cursor */ - trace_buffer_cursor = trace_buffer; - /* Reset trace list cursor */ - trace_list_collect_cursor = trace_list; - - /* iterate over trace list */ - while(trace_list_collect_cursor < trace_list_addvar_cursor){ - void *value_p = NULL; - size_t size; - char* next_cursor; - - dbgvardsc_t *dsc = &dbgvardsc[ - trace_list_collect_cursor->dbgvardsc_index]; - - UnpackVar(dsc, &value_p, NULL, &size); - - /* copy visible variable to buffer */; - if(__Is_a_string(dsc)){ - /* optimization for strings */ - /* assume NULL terminated strings */ - size = ((STRING*)value_p)->len + 1; - } - - /* compute next cursor positon.*/ - next_cursor = trace_buffer_cursor + size; - /* check for buffer overflow */ - if(next_cursor < trace_buffer_end) - /* copy data to the buffer */ - memcpy(trace_buffer_cursor, value_p, size); - else - /* stop looping in case of overflow */ - break; - /* increment cursor according size*/ - trace_buffer_cursor = next_cursor; - trace_list_collect_cursor++; - } - - /* Leave debug section, - * Trigger asynchronous transmission - * (returns immediately) */ - InitiateDebugTransfer(); /* size */ - } - LeaveDebugSection(); - } -#endif - unsigned int retain_offset = 0; - /* when not debugging, do only retain */ - retain_list_collect_cursor = 0; - - /* iterate over retain list */ - while(retain_list_collect_cursor < retain_list_size){ - void *value_p = NULL; - size_t size; - char* next_cursor; - - dbgvardsc_t *dsc = &dbgvardsc[ - retain_list[retain_list_collect_cursor]]; - - UnpackVar(dsc, &value_p, NULL, &size); - - /* if buffer not full */ - Retain(retain_offset, size, value_p); - /* increment cursor according size*/ - retain_offset += size; - - retain_list_collect_cursor++; - } - ValidateRetainBuffer(); -} - -#ifndef TARGET_ONLINE_DEBUG_DISABLE - -#define TRACE_LIST_OVERFLOW 1 -#define FORCE_LIST_OVERFLOW 2 -#define FORCE_BUFFER_OVERFLOW 3 - -#define __ForceVariable_case_t(TYPENAME) \ - case TYPENAME##_ENUM : \ - /* add to force_list*/ \ - force_list_addvar_cursor->dbgvardsc_index = idx; \ - ((__IEC_##TYPENAME##_t *)varp)->flags |= __IEC_FORCE_FLAG; \ - ((__IEC_##TYPENAME##_t *)varp)->value = *((TYPENAME *)force); \ - break; -#define __ForceVariable_case_p(TYPENAME) \ - case TYPENAME##_P_ENUM : \ - case TYPENAME##_O_ENUM : \ - { \ - char *next_cursor = force_buffer_cursor + sizeof(TYPENAME); \ - if(next_cursor <= force_buffer_end ){ \ - /* add to force_list*/ \ - force_list_addvar_cursor->dbgvardsc_index = idx; \ - /* save pointer to backup */ \ - force_list_addvar_cursor->value_pointer_backup = \ - ((__IEC_##TYPENAME##_p *)varp)->value; \ - /* store forced value in force_buffer */ \ - *((TYPENAME *)force_buffer_cursor) = *((TYPENAME *)force); \ - /* replace pointer with pointer to force_buffer */ \ - ((__IEC_##TYPENAME##_p *)varp)->value = \ - (TYPENAME *)force_buffer_cursor; \ - (((__IEC_##TYPENAME##_p *)varp)->fvalue) = *((TYPENAME *)force); \ - /* mark variable as forced */ \ - ((__IEC_##TYPENAME##_p *)varp)->flags |= __IEC_FORCE_FLAG; \ - /* inc force_buffer cursor */ \ - force_buffer_cursor = next_cursor; \ - /* outputs real value must be systematically forced */ \ - if(vartype == TYPENAME##_O_ENUM) \ - *(((__IEC_##TYPENAME##_p *)varp)->value) = *((TYPENAME *)force);\ - } else { \ - error_code = FORCE_BUFFER_OVERFLOW; \ - goto error_cleanup; \ - } \ - } \ - break; - - -void ResetDebugVariables(void); - -int RegisterDebugVariable(dbgvardsc_index_t idx, void* force) -{ - int error_code = 0; - if(idx < sizeof(dbgvardsc)/sizeof(dbgvardsc_t)){ - /* add to trace_list, inc trace_list_addvar_cursor*/ - if(trace_list_addvar_cursor <= trace_list_end){ - trace_list_addvar_cursor->dbgvardsc_index = idx; - trace_list_addvar_cursor++; - } else { - error_code = TRACE_LIST_OVERFLOW; - goto error_cleanup; - } - if(force){ - if(force_list_addvar_cursor <= force_list_end){ - dbgvardsc_t *dsc = &dbgvardsc[idx]; - void *varp = dsc->ptr; - __IEC_types_enum vartype = dsc->type; - - switch(vartype){ - __ANY(__ForceVariable_case_t) - __ANY(__ForceVariable_case_p) - default: - break; - } - /* inc force_list cursor */ - force_list_addvar_cursor++; - } else { - error_code = FORCE_LIST_OVERFLOW; - goto error_cleanup; - } - } - } - return 0; - -error_cleanup: - ResetDebugVariables(); - trace_buffer_state = BUFFER_EMPTY; - return error_code; - -} - -#define ResetForcedVariable_case_t(TYPENAME) \ - case TYPENAME##_ENUM : \ - ((__IEC_##TYPENAME##_t *)varp)->flags &= ~__IEC_FORCE_FLAG; \ - /* for local variable we don't restore original value */ \ - /* that can be added if needed, but it was like that since ever */ \ - break; - -#define ResetForcedVariable_case_p(TYPENAME) \ - case TYPENAME##_P_ENUM : \ - case TYPENAME##_O_ENUM : \ - ((__IEC_##TYPENAME##_p *)varp)->flags &= ~__IEC_FORCE_FLAG; \ - /* restore backup to pointer */ \ - ((__IEC_##TYPENAME##_p *)varp)->value = \ - force_list_apply_cursor->value_pointer_backup; \ - break; - -void ResetDebugVariables(void) -{ - /* Reset trace list */ - trace_list_addvar_cursor = trace_list; - - force_list_apply_cursor = force_list; - /* Restore forced variables */ - while(force_list_apply_cursor < force_list_addvar_cursor){ - dbgvardsc_t *dsc = &dbgvardsc[ - force_list_apply_cursor->dbgvardsc_index]; - void *varp = dsc->ptr; - switch(dsc->type){ - __ANY(ResetForcedVariable_case_t) - __ANY(ResetForcedVariable_case_p) - default: - break; - } - /* inc force_list cursor */ - force_list_apply_cursor++; - } /* else TODO: warn user about failure to force */ - - /* Reset force list */ - force_list_addvar_cursor = force_list; - /* Reset force buffer */ - force_buffer_cursor = force_buffer; -} - -void FreeDebugData(void) -{ - /* atomically mark buffer as free */ - AtomicCompareExchange( - &trace_buffer_state, - BUFFER_FULL, - BUFFER_EMPTY); -} -int WaitDebugData(unsigned long *tick); -/* Wait until debug data ready and return pointer to it */ -int GetDebugData(unsigned long *tick, unsigned long *size, void **buffer){ - int wait_error = WaitDebugData(tick); - if(!wait_error){ - *size = trace_buffer_cursor - trace_buffer; - *buffer = trace_buffer; - } - return wait_error; -} -#endif -#endif - diff --git a/motor/build/plc_debugger.o b/motor/build/plc_debugger.o deleted file mode 100644 index 7eeb5db4c1d8edbb3a3792971844a0f6026e562f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13217 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 Q_bGK -/* - * Prototypes of functions provided by generated C softPLC - **/ -void config_run__(unsigned long tick); -void config_init__(void); - -/* - * Prototypes of functions provided by generated target C code - * */ -long long AtomicCompareExchange64(long long*, long long, long long); -void __init_debug(void); -void __cleanup_debug(void); -/*void __retrieve_debug(void);*/ -void __publish_debug(void); - -/* - * Variables used by generated C softPLC and plugins - **/ -IEC_TIME __CURRENT_TIME; -IEC_BOOL __DEBUG = 0; -unsigned long __tick = 0; -char *PLC_ID = NULL; - -/* - * Variable generated by C softPLC and plugins - **/ -extern unsigned long greatest_tick_count__; - -/* Help to quit cleanly when init fail at a certain level */ -static int init_level = 0; - -/* - * Prototypes of functions exported by plugins - **/ - - - -/* - * Retrieve input variables, run PLC and publish output variables - **/ -void __run(void) -{ - __tick++; - if (greatest_tick_count__) - __tick %= greatest_tick_count__; - - - - - /*__retrieve_debug();*/ - - config_run__(__tick); - - __publish_debug(); - - - - -} - -/* - * Initialize variables according to PLC's default values, - * and then init plugins with that values - **/ -int __init(int argc,char **argv) -{ - int res = 0; - init_level = 0; - - /* Effective tick time with 1ms default value */ - if(!common_ticktime__) - common_ticktime__ = 1000000; - - config_init__(); - __init_debug(); - - - return res; -} -/* - * Calls plugin cleanup proc. - **/ -void __cleanup(void) -{ - - - __cleanup_debug(); -} - -void PLC_GetTime(IEC_TIME *CURRENT_TIME); -void PLC_SetTimer(unsigned long long next, unsigned long long period); - - - -/** - * Win32 specific code - **/ - -#include -#include -#include -#include -#include - - -long AtomicCompareExchange(long* atomicvar, long compared, long exchange) -{ - return InterlockedCompareExchange(atomicvar, exchange, compared); -} -CRITICAL_SECTION Atomic64CS; -long long AtomicCompareExchange64(long long* atomicvar, long long compared, long long exchange) -{ - long long res; - EnterCriticalSection(&Atomic64CS); - res=*atomicvar; - if(*atomicvar == compared){ - *atomicvar = exchange; - } - LeaveCriticalSection(&Atomic64CS); - return res; -} - -struct timeb timetmp; -void PLC_GetTime(IEC_TIME *CURRENT_TIME) -{ - ftime(&timetmp); - - (*CURRENT_TIME).tv_sec = timetmp.time; - (*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000; -} - -HANDLE PLC_timer = NULL; -void PLC_SetTimer(unsigned long long next, unsigned long long period) -{ - LARGE_INTEGER liDueTime; - /* arg 2 of SetWaitableTimer take 100 ns interval*/ - liDueTime.QuadPart = next / (-100); - - if (!SetWaitableTimer(PLC_timer, &liDueTime, period<1000000?1:period/1000000, NULL, NULL, 0)) - { - printf("SetWaitableTimer failed (%d)\n", GetLastError()); - } -} - -int PLC_shutdown; - -int ForceSaveRetainReq(void) { - return PLC_shutdown; -} - -/* Variable used to stop plcloop thread */ -void PlcLoop() -{ - PLC_shutdown = 0; - while(!PLC_shutdown) { - if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0){ - PLC_shutdown = 1; - break; - } - PLC_GetTime(&__CURRENT_TIME); - __run(); - } -} - -HANDLE PLC_thread; -HANDLE debug_sem; -HANDLE debug_wait_sem; -HANDLE python_sem; -HANDLE python_wait_sem; - -#define maxval(a,b) ((a>b)?a:b) -int startPLC(int argc,char **argv) -{ - unsigned long thread_id = 0; - BOOL tmp; - - debug_sem = CreateSemaphore( - NULL, // default security attributes - 1, // initial count - 1, // maximum count - NULL); // unnamed semaphore - if (debug_sem == NULL) - { - printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError()); - return 1; - } - - debug_wait_sem = CreateSemaphore( - NULL, // default security attributes - 0, // initial count - 1, // maximum count - NULL); // unnamed semaphore - - if (debug_wait_sem == NULL) - { - printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError()); - return 1; - } - - python_sem = CreateSemaphore( - NULL, // default security attributes - 1, // initial count - 1, // maximum count - NULL); // unnamed semaphore - - if (python_sem == NULL) - { - printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError()); - return 1; - } - python_wait_sem = CreateSemaphore( - NULL, // default security attributes - 0, // initial count - 1, // maximum count - NULL); // unnamed semaphore - - - if (python_wait_sem == NULL) - { - printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError()); - return 1; - } - - - /* Create a waitable timer */ - timeBeginPeriod(1); - PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer"); - if(NULL == PLC_timer) - { - printf("CreateWaitableTimer failed (%d)\n", GetLastError()); - return 1; - } - if( __init(argc,argv) == 0 ) - { - PLC_SetTimer(common_ticktime__,common_ticktime__); - PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id); - } - else{ - return 1; - } - return 0; -} -static unsigned long __debug_tick; - -int TryEnterDebugSection(void) -{ - //printf("TryEnterDebugSection\n"); - if(WaitForSingleObject(debug_sem, 0) == WAIT_OBJECT_0){ - /* Only enter if debug active */ - if(__DEBUG){ - return 1; - } - ReleaseSemaphore(debug_sem, 1, NULL); - } - return 0; -} - -void LeaveDebugSection(void) -{ - ReleaseSemaphore(debug_sem, 1, NULL); - //printf("LeaveDebugSection\n"); -} - -int stopPLC() -{ - - PLC_shutdown = 1; - // force last wakeup of PLC thread - SetWaitableTimer(PLC_timer, 0, 0, NULL, NULL, 0); - // wait end of PLC thread - WaitForSingleObject(PLC_thread, INFINITE); - - __cleanup(); - - CloseHandle(PLC_timer); - CloseHandle(debug_wait_sem); - CloseHandle(debug_sem); - CloseHandle(python_wait_sem); - CloseHandle(python_sem); - CloseHandle(PLC_thread); -} - -/* from plc_debugger.c */ -int WaitDebugData(unsigned long *tick) -{ - DWORD res; - res = WaitForSingleObject(debug_wait_sem, INFINITE); - *tick = __debug_tick; - /* Wait signal from PLC thread */ - return res != WAIT_OBJECT_0; -} - -/* Called by PLC thread when debug_publish finished - * This is supposed to unlock debugger thread in WaitDebugData*/ -void InitiateDebugTransfer() -{ - /* remember tick */ - __debug_tick = __tick; - /* signal debugger thread it can read data */ - ReleaseSemaphore(debug_wait_sem, 1, NULL); -} - -int suspendDebug(int disable) -{ - /* Prevent PLC to enter debug code */ - WaitForSingleObject(debug_sem, INFINITE); - __DEBUG = !disable; - if(disable) - ReleaseSemaphore(debug_sem, 1, NULL); - return 0; -} - -void resumeDebug() -{ - __DEBUG = 1; - /* Let PLC enter debug code */ - ReleaseSemaphore(debug_sem, 1, NULL); -} - -/* from plc_python.c */ -int WaitPythonCommands(void) -{ - /* Wait signal from PLC thread */ - return WaitForSingleObject(python_wait_sem, INFINITE); -} - -/* Called by PLC thread on each new python command*/ -void UnBlockPythonCommands(void) -{ - /* signal debugger thread it can read data */ - ReleaseSemaphore(python_wait_sem, 1, NULL); -} - -int TryLockPython(void) -{ - return WaitForSingleObject(python_sem, 0) == WAIT_OBJECT_0; -} - -void UnLockPython(void) -{ - ReleaseSemaphore(python_sem, 1, NULL); -} - -void LockPython(void) -{ - WaitForSingleObject(python_sem, INFINITE); -} - -static void __attribute__((constructor)) -beremiz_dll_init(void) -{ - InitializeCriticalSection(&Atomic64CS); - -} - -static void __attribute__((destructor)) -beremiz_dll_destroy(void) -{ - DeleteCriticalSection(&Atomic64CS); -} - -struct RT_to_nRT_signal_s { - HANDLE sem; -}; - -typedef struct RT_to_nRT_signal_s RT_to_nRT_signal_t; - -#define _LogAndReturnNull(text) \ - {\ - char mstr[256] = text " for ";\ - strncat(mstr, name, 255);\ - LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\ - return NULL;\ - } - -void *create_RT_to_nRT_signal(char* name){ - RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)malloc(sizeof(RT_to_nRT_signal_t)); - - if(!sig) - _LogAndReturnNull("Failed allocating memory for RT_to_nRT signal"); - - sig->sem = CreateSemaphore( - NULL, // default security attributes - 1, // initial count - 1, // maximum count - NULL); // unnamed semaphore - - if(sig->sem == NULL) - { - char mstr[256]; - snprintf(mstr, 255, "startPLC CreateSemaphore %s error: %d\n", name, GetLastError()); - LogMessage(LOG_CRITICAL, mstr, strlen(mstr)); - return NULL; - } - - return (void*)sig; -} - -void delete_RT_to_nRT_signal(void* handle){ - RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle; - - CloseHandle(python_sem); - - free(sig); -} - -int wait_RT_to_nRT_signal(void* handle){ - int ret; - RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle; - return WaitForSingleObject(sig->sem, INFINITE); -} - -int unblock_RT_to_nRT_signal(void* handle){ - RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle; - return ReleaseSemaphore(sig->sem, 1, NULL); -} - -void nRT_reschedule(void){ - SwitchToThread(); -} - - -/* - This file is part of Beremiz, a Integrated Development Environment for - programming IEC 61131-3 automates supporting plcopen standard and CanFestival. - - See COPYING.runtime - - Copyright (C) 2018: Sergey Surkov - Copyright (C) 2018: Andrey Skvortsov - -*/ - -#ifndef HAVE_RETAIN -#include -#include -#include -#include "iec_types.h" - -int GetRetainSize(void); - -/* Retain buffer. */ -FILE *retain_buffer; -const char rb_file[] = "retain_buffer_file"; -const char rb_file_bckp[] = "retain_buffer_file.bak"; - - -/* Retain header struct. */ -struct retain_info_t { - uint32_t retain_size; - uint32_t hash_size; - uint8_t* hash; - uint32_t header_offset; - uint32_t header_crc; -}; - -/* Init retain info structure. */ -struct retain_info_t retain_info; - -/* CRC lookup table and initial state. */ -static const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, -}; -uint32_t retain_crc; - - -/* Calculate CRC32 for len bytes from pointer buf with init starting value. */ -uint32_t GenerateCRC32Sum(const void* buf, unsigned int len, uint32_t init) -{ - uint32_t crc = ~init; - unsigned char* current = (unsigned char*) buf; - while (len--) - crc = crc32_table[(crc ^ *current++) & 0xFF] ^ (crc >> 8); - return ~crc; -} - -/* Calc CRC32 for retain file byte by byte. */ -int CheckFileCRC(FILE* file_buffer) -{ - /* Set the magic constant for one-pass CRC calc according to ZIP CRC32. */ - const uint32_t magic_number = 0x2144df1c; - - /* CRC initial state. */ - uint32_t calc_crc32 = 0; - char data_block = 0; - - while(!feof(file_buffer)){ - if (fread(&data_block, sizeof(data_block), 1, file_buffer)) - calc_crc32 = GenerateCRC32Sum(&data_block, sizeof(data_block), calc_crc32); - } - - /* Compare crc result with a magic number. */ - return (calc_crc32 == magic_number) ? 1 : 0; -} - -/* Compare current hash with hash from file byte by byte. */ -int CheckFilehash(void) -{ - unsigned int k; - int offset = sizeof(retain_info.retain_size); - - rewind(retain_buffer); - fseek(retain_buffer, offset , SEEK_SET); - - uint32_t size; - fread(&size, sizeof(size), 1, retain_buffer); - if (size != retain_info.hash_size) - return 0; - - for(k = 0; k < retain_info.hash_size; k++){ - uint8_t file_digit; - fread(&file_digit, sizeof(file_digit), 1, retain_buffer); - if (file_digit != *(retain_info.hash+k)) - return 0; - } - - return 1; -} - -void InitRetain(void) -{ - unsigned int i; - - /* Get retain size in bytes */ - retain_info.retain_size = GetRetainSize(); - - /* Hash stored in retain file as array of char in hex digits - (that's why we divide strlen in two). */ - retain_info.hash_size = PLC_ID ? strlen(PLC_ID)/2 : 0; - //retain_info.hash_size = 0; - retain_info.hash = malloc(retain_info.hash_size); - - /* Transform hash string into byte sequence. */ - for (i = 0; i < retain_info.hash_size; i++) { - int byte = 0; - sscanf((PLC_ID + i*2), "%02X", &byte); - retain_info.hash[i] = byte; - } - - /* Calc header offset. */ - retain_info.header_offset = sizeof(retain_info.retain_size) + \ - sizeof(retain_info.hash_size) + \ - retain_info.hash_size; - - /* Set header CRC initial state. */ - retain_info.header_crc = 0; - - /* Calc crc for header. */ - retain_info.header_crc = GenerateCRC32Sum( - &retain_info.retain_size, - sizeof(retain_info.retain_size), - retain_info.header_crc); - - retain_info.header_crc = GenerateCRC32Sum( - &retain_info.hash_size, - sizeof(retain_info.hash_size), - retain_info.header_crc); - - retain_info.header_crc = GenerateCRC32Sum( - retain_info.hash, - retain_info.hash_size, - retain_info.header_crc); -} - -void CleanupRetain(void) -{ - /* Free hash memory. */ - free(retain_info.hash); -} - -int CheckRetainFile(const char * file) -{ - retain_buffer = fopen(file, "rb"); - if (retain_buffer) { - /* Check CRC32 and hash. */ - if (CheckFileCRC(retain_buffer)) - if (CheckFilehash()) - return 1; - fclose(retain_buffer); - retain_buffer = NULL; - } - return 0; -} - -int CheckRetainBuffer(void) -{ - retain_buffer = NULL; - if (!retain_info.retain_size) - return 1; - - /* Check latest retain file. */ - if (CheckRetainFile(rb_file)) - return 1; - - /* Check if we have backup. */ - if (CheckRetainFile(rb_file_bckp)) - return 1; - - /* We don't have any valid retain buffer - nothing to remind. */ - return 0; -} - -#ifndef FILE_RETAIN_SAVE_PERIOD_S -#define FILE_RETAIN_SAVE_PERIOD_S 1.0 -#endif - -static double CalcDiffSeconds(IEC_TIME* t1, IEC_TIME *t2) -{ - IEC_TIME dt ={ - t1->tv_sec - t2->tv_sec, - t1->tv_nsec - t2->tv_nsec - }; - - if ((dt.tv_nsec < -1000000000) || ((dt.tv_sec > 0) && (dt.tv_nsec < 0))){ - dt.tv_sec--; - dt.tv_nsec += 1000000000; - } - if ((dt.tv_nsec > +1000000000) || ((dt.tv_sec < 0) && (dt.tv_nsec > 0))){ - dt.tv_sec++; - dt.tv_nsec -= 1000000000; - } - return dt.tv_sec + 1e-9*dt.tv_nsec; -} - - -int RetainSaveNeeded(void) -{ - int ret = 0; - static IEC_TIME last_save; - IEC_TIME now; - double diff_s; - - /* no retain */ - if (!retain_info.retain_size) - return 0; - - /* periodic retain flush to avoid high I/O load */ - PLC_GetTime(&now); - - diff_s = CalcDiffSeconds(&now, &last_save); - - if ((diff_s > FILE_RETAIN_SAVE_PERIOD_S) || ForceSaveRetainReq()) { - ret = 1; - last_save = now; - } - return ret; -} - -void ValidateRetainBuffer(void) -{ - if (!retain_buffer) - return; - - /* Add retain data CRC to the end of buffer file. */ - fseek(retain_buffer, 0, SEEK_END); - fwrite(&retain_crc, sizeof(retain_crc), 1, retain_buffer); - - /* Sync file buffer and close file. */ -#ifdef __WIN32 - fflush(retain_buffer); -#else - fsync(fileno(retain_buffer)); -#endif - - fclose(retain_buffer); - retain_buffer = NULL; -} - -void InValidateRetainBuffer(void) -{ - if (!RetainSaveNeeded()) - return; - - /* Rename old retain file into *.bak if it exists. */ - rename(rb_file, rb_file_bckp); - - /* Set file CRC initial value. */ - retain_crc = retain_info.header_crc; - - /* Create new retain file. */ - retain_buffer = fopen(rb_file, "wb+"); - if (!retain_buffer) { - fprintf(stderr, "Failed to create retain file : %s\n", rb_file); - return; - } - - /* Write header to the new file. */ - fwrite(&retain_info.retain_size, - sizeof(retain_info.retain_size), 1, retain_buffer); - fwrite(&retain_info.hash_size, - sizeof(retain_info.hash_size), 1, retain_buffer); - fwrite(retain_info.hash , - sizeof(char), retain_info.hash_size, retain_buffer); -} - -void Retain(unsigned int offset, unsigned int count, void *p) -{ - if (!retain_buffer) - return; - - /* Generate CRC 32 for each data block. */ - retain_crc = GenerateCRC32Sum(p, count, retain_crc); - - /* Save current var in file. */ - fseek(retain_buffer, retain_info.header_offset+offset, SEEK_SET); - fwrite(p, count, 1, retain_buffer); -} - -void Remind(unsigned int offset, unsigned int count, void *p) -{ - /* Remind variable from file. */ - fseek(retain_buffer, retain_info.header_offset+offset, SEEK_SET); - fread((void *)p, count, 1, retain_buffer); -} -#endif // !HAVE_RETAIN -/** - * Tail of code common to all C targets - **/ - -/** - * LOGGING - **/ -#ifndef TARGET_LOGGING_DISABLE - -#ifndef LOG_BUFFER_SIZE -#define LOG_BUFFER_SIZE (1<<14) /*16Ko*/ -#endif -#ifndef LOG_BUFFER_ATTRS -#define LOG_BUFFER_ATTRS -#endif - -#define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1) - -static char LogBuff[LOG_LEVELS][LOG_BUFFER_SIZE] LOG_BUFFER_ATTRS; -static void inline copy_to_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ - if(buffpos + size < LOG_BUFFER_SIZE){ - memcpy(&LogBuff[level][buffpos], buf, size); - }else{ - uint32_t remaining = LOG_BUFFER_SIZE - buffpos; - memcpy(&LogBuff[level][buffpos], buf, remaining); - memcpy(LogBuff[level], (char*)buf + remaining, size - remaining); - } -} -static void inline copy_from_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ - if(buffpos + size < LOG_BUFFER_SIZE){ - memcpy(buf, &LogBuff[level][buffpos], size); - }else{ - uint32_t remaining = LOG_BUFFER_SIZE - buffpos; - memcpy(buf, &LogBuff[level][buffpos], remaining); - memcpy((char*)buf + remaining, LogBuff[level], size - remaining); - } -} - -/* Log buffer structure - - |<-Tail1.msgsize->|<-sizeof(mTail)->|<--Tail2.msgsize-->|<-sizeof(mTail)->|... - | Message1 Body | Tail1 | Message2 Body | Tail2 | - -*/ -typedef struct { - uint32_t msgidx; - uint32_t msgsize; - unsigned long tick; - IEC_TIME time; -} mTail; - -/* Log cursor : 64b - |63 ... 32|31 ... 0| - | Message | Buffer | - | counter | Index | */ -static uint64_t LogCursor[LOG_LEVELS] LOG_BUFFER_ATTRS = {0x0,0x0,0x0,0x0}; - -void ResetLogCount(void) { - uint8_t level; - for(level=0;level> 32); - new_cursor = ((uint64_t)(tail.msgidx + 1)<<32) - | (uint64_t)((buffpos + size + sizeof(mTail)) & LOG_BUFFER_MASK); - }while(AtomicCompareExchange64( - (long long*)&LogCursor[level], - (long long)old_cursor, - (long long)new_cursor)!=(long long)old_cursor); - - copy_to_log(level, buffpos, buf, size); - copy_to_log(level, (buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); - - return 1; /* Success */ - }else{ - char mstr[] = "Logging error : message too big"; - LogMessage(LOG_CRITICAL, mstr, sizeof(mstr)); - } - return 0; -} - -uint32_t GetLogCount(uint8_t level){ - return (uint64_t)LogCursor[level] >> 32; -} - -/* Return message size and content */ -uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size, uint32_t* tick, uint32_t* tv_sec, uint32_t* tv_nsec){ - uint64_t cursor = LogCursor[level]; - if(cursor){ - /* seach cursor */ - uint32_t stailpos = (uint32_t)cursor; - uint32_t smsgidx; - mTail tail; - tail.msgidx = cursor >> 32; - tail.msgsize = 0; - - /* Message search loop */ - do { - smsgidx = tail.msgidx; - stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK; - copy_from_log(level, stailpos, &tail, sizeof(mTail)); - }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx)); - - if(tail.msgidx == msgidx){ - uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; - uint32_t totalsize = tail.msgsize; - *tick = tail.tick; - *tv_sec = tail.time.tv_sec; - *tv_nsec = tail.time.tv_nsec; - copy_from_log(level, sbuffpos, buf, - totalsize > max_size ? max_size : totalsize); - return totalsize; - } - } - return 0; -} - -#endif - -#ifndef TARGET_EXT_SYNC_DISABLE - -#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 unsigned long last_tick = 0; - -/* - * Called on each external periodic sync event - * make PLC tick synchronous with external sync - * ratio defines when PLC tick occurs between two 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 / common_ticktime__)) > 0){ - FreqCorr = (Tsync % common_ticktime__); /* to be divided by Nticks */ - }else{ - FreqCorr = Tsync - (common_ticktime__ % 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 - (common_ticktime__ + FreqCorr/Nticks)*sync_align_ratio/100; /* to be divided by Nticks */ - Tcorr = common_ticktime__ + (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 = common_ticktime__ + FreqCorr / Nticks; - }else{ - PeriodicTcorr = Tcorr; - } - }else if(__tick > last_tick){ - last_tick = __tick; - PhaseCorr = elapsed - (Tsync*sync_align_ratio/100); - PeriodicTcorr = Tcorr = common_ticktime__ + PhaseCorr + FreqCorr; - }else{ - /*PLC did not run meanwhile. Nothing to do*/ - return; - } - /* DO ALIGNEMENT */ - PLC_SetTimer(Tcorr - elapsed, PeriodicTcorr); - } - } -} - -#endif diff --git a/motor/build/plc_main.o b/motor/build/plc_main.o deleted file mode 100644 index 73cddaf78ba63754e87612293d6eba223a6f1c19..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18389 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 diff --git a/motor/plc.xml b/motor/plc.xml index cd0f0a1..ca960ad 100644 --- a/motor/plc.xml +++ b/motor/plc.xml @@ -1,7 +1,7 @@ - + @@ -204,21 +204,6 @@ - - - - - - - - - - - - - - - @@ -620,7 +605,7 @@ - + @@ -628,14 +613,9 @@ - + - - - - - - + @@ -663,81 +643,44 @@ + + + + + + + + + - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + @@ -745,130 +688,201 @@ + + + + + - - - - - - + - - - - - - - - - - - - - - - - + - - - - - - + + + - + - - - - - - + + + + + + + + + + + + + + + + + + + + P1_enc + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - + P1_run + + + + + + + + + + + + + + + + P2_enc + + + + + + + + + + + + + + P2_run + + + + + + + + + + + + + + P3_enc + + + + + + + + + + + + + + P3_run + + + + + + + + + + + + + + + + + + + + + + + + + + Pump_def + + + + + + + + + + + + + WAIT7 + + + + + + + + + + + + + + Pump_def + + + - - - + + + - - - - - + + + + + @@ -887,211 +901,210 @@ - - - - - - not (secours) - - - - - - - WAIT1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - secours - - - - - - - WAIT1 - - - + + - + + + + + + + + + + secours + + + + + + + + + + + + + + + + + + + + + + + + + + P1_run + + + + + + + + + + + + + + P2_run + + + + + + + + + + + + + + P3_run + + + + + + + + + + + + + + + + P1_run + + + + + + + + + + + + + + + + P1_run + + + + + + + + + + + + + + P2_run + + + + + - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - + P2_enc + + + - - - - - - - - + + + + - + - - - - - - - - - - - - - + P3_run + + + - - - - - - - - - - - - - - - - - - - - - - - - - - Pump_def - - - - - + - - - - + + - - + + - - - + P3_run + + + - - - - - - + + + + + + + + + + + + + + + + - - + + - - - + only_one_run + + + + + + + + + + + + + WAIT2 + + + - - - - - + + + @@ -1099,8 +1112,10 @@ - - + + + + @@ -1119,457 +1134,117 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - WAIT2 + true - - - - - - TRUE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - secours_c - - - - - - - 0 - - - - - - - - - - - - + + - + - - + + + + + - - - + WAIT13 + + + - - - - - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + Pump_def + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRUE - - - - - - - WAIT3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRUE - - - - - - - WAIT2 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - secours_c - - - - - - - 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - P1_enc - - - - - - - P2_enc - - - - - - - P3_enc - - - - - - - - - - - - + + + + - - - - - + + + + + @@ -1588,216 +1263,305 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - TRUE - - - + secours + + + - WAIT3 + true - - + + - + - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + - + + + + + + - - + + - + - P1_enc + 1 - - + + + + + + + + + - + - P2_enc - - - + secours_c_ok + + + + + + + + + + - + - P3_enc - - - + secours + + + - + + + + + + + + + + + + - - - - + + + + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + P1_enc + + + + + + + + + + + + + + + + P2_enc + + + + + + + + + + + + + + + + P3_enc + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + @@ -1815,48 +1579,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + P1_enc + + + + + + + + + + + + + + + + P2_enc + + + + + + + + + + + + + + + + P3_enc + + + + + + + 1 + + + - - - - - + + + + + - - - + + + + + @@ -1870,926 +1681,70 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + 1 - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - not (only_one_run) - - - - - - - WAIT4 - - - - - - - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRUE - - - - - - - WAIT3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - P1_enc - - - - - - - P2_enc - - - - - - - P3_enc - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TRUE - - - - - - - WAIT3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - P1_enc - - - - - - - P2_enc - - - - - - - 1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - only_one_run - - - - - - - WAIT4 - - - - - - - - - - - - - - - - - - - - + req_enc_ok + +