115 #ifdef REALTIME_LINUX |
115 #ifdef REALTIME_LINUX |
116 struct timespec deadline_time; |
116 struct timespec deadline_time; |
117 struct timespec plc_start_time; |
117 struct timespec plc_start_time; |
118 #endif |
118 #endif |
119 |
119 |
|
120 // BEREMIZ_TEST_CYCLES is defined in tests that need to emulate time: |
|
121 // - all BEREMIZ_TEST_CYCLES cycles are executed in a row with no pause |
|
122 // - __CURRENT_TIME is incremented each cycle according to emulated cycle period |
|
123 |
|
124 #ifndef BEREMIZ_TEST_CYCLES |
120 // Sleep until next PLC run |
125 // Sleep until next PLC run |
121 res = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_cycle_time, NULL); |
126 res = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_cycle_time, NULL); |
122 if(res==EINTR){ |
127 if(res==EINTR){ |
123 continue; |
128 continue; |
124 } |
129 } |
125 if(res!=0){ |
130 if(res!=0){ |
126 _LogError("PLC thread timer returned error %d \n", res); |
131 _LogError("PLC thread timer returned error %d \n", res); |
127 return; |
132 return; |
128 } |
133 } |
|
134 #endif // BEREMIZ_TEST_CYCLES |
129 |
135 |
130 #ifdef REALTIME_LINUX |
136 #ifdef REALTIME_LINUX |
131 // timer overrun detection |
137 // timer overrun detection |
132 clock_gettime(CLOCK_MONOTONIC, &plc_start_time); |
138 clock_gettime(CLOCK_MONOTONIC, &plc_start_time); |
133 deadline_time=next_cycle_time; |
139 deadline_time=next_cycle_time; |
135 if(timespec_gt(plc_start_time, deadline_time)){ |
141 if(timespec_gt(plc_start_time, deadline_time)){ |
136 _LogWarning("PLC thread woken up too late. PLC cyclic task interval is too small.\n"); |
142 _LogWarning("PLC thread woken up too late. PLC cyclic task interval is too small.\n"); |
137 } |
143 } |
138 #endif |
144 #endif |
139 |
145 |
|
146 #ifdef BEREMIZ_TEST_CYCLES |
|
147 #define xstr(s) str(s) |
|
148 #define str(arg) #arg |
|
149 // fake current time |
|
150 __CURRENT_TIME.tv_sec = next_cycle_time.tv_sec; |
|
151 __CURRENT_TIME.tv_nsec = next_cycle_time.tv_nsec; |
|
152 // exit loop when enough cycles |
|
153 if(__tick >= BEREMIZ_TEST_CYCLES) { |
|
154 _LogWarning("TEST PLC thread ended after "xstr(BEREMIZ_TEST_CYCLES)" cycles.\n"); |
|
155 // After pre-defined test cycles count, PLC thread exits. |
|
156 // Remaining PLC runtime is expected to be cleaned-up/killed by test script |
|
157 return; |
|
158 } |
|
159 #else |
140 PLC_GetTime(&__CURRENT_TIME); |
160 PLC_GetTime(&__CURRENT_TIME); |
|
161 #endif |
141 __run(); |
162 __run(); |
142 |
163 |
|
164 #ifndef BEREMIZ_TEST_CYCLES |
143 // ensure next PLC cycle occurence is in the future |
165 // ensure next PLC cycle occurence is in the future |
144 clock_gettime(CLOCK_MONOTONIC, &plc_end_time); |
166 clock_gettime(CLOCK_MONOTONIC, &plc_end_time); |
145 while(timespec_gt(plc_end_time, next_cycle_time)){ |
167 while(timespec_gt(plc_end_time, next_cycle_time)) |
|
168 #endif |
|
169 { |
146 periods += 1; |
170 periods += 1; |
147 inc_timespec(&next_cycle_time, period_ns); |
171 inc_timespec(&next_cycle_time, period_ns); |
148 } |
172 } |
149 |
173 |
150 // plc execution time overrun detection |
174 // plc execution time overrun detection |