Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

EN and ENO

Any function call may pass EN := c, an enable input, and ENO => x (or NOT ENO => x), which tells whether the call went well (Ed.3 6.6.1.5). The standard leaves what happens in detail to the implementer; iecf decided, 2026-11-07 (Implementer choices):

  • EN = FALSE: the call does not happen. Its inputs are not evaluated — a division by zero among them does not fault — the function is not called, ENO is FALSE, and the statement the call is in is left undone: an assignment keeps its target’s value, as when a REAL does not fit an integer. Nothing is flagged. This is Ed.3’s “external implementation” (its Example 2), and what CODESYS does with a box whose EN is FALSE.
  • ENO is FALSE when the function’s own operation raised a flag: an overflow, a conversion that does not fit, a string length or position outside its string. A flag raised while computing an argument is the argument’s, not the function’s, and leaves ENO TRUE. The flag still reaches ctx->flag as any flag does. This is Ed.3’s rule 3, and what Siemens does.
  • Otherwise ENO is TRUE. A fault stops the task, as without ENO.
ExpressionTypeResultFlagNote
DIV(EN := TRUE, IN1 := INT#7, IN2 := INT#2, ENO => eno)INT3, ENO TRUE—
DIV(EN := FALSE, IN1 := INT#7, IN2 := INT#2, ENO => eno)INTunchanged, ENO FALSE—the assignment is left undone
DIV(EN := FALSE, IN1 := INT#7, IN2 := INT#0, ENO => eno)INTunchanged, ENO FALSE—not called: no fault
DIV(EN := TRUE, IN1 := DINT#7, IN2 := DINT#0, ENO => eno)DINT—fault DIVISION_BY_ZEROa fault still stops the task
ADD(IN1 := INT#32767, IN2 := INT#1, ENO => eno)INT-32768, ENO FALSEflag OVERFLOWits own overflow
ADD(IN1 := INT#32767 + INT#1, IN2 := INT#1, ENO => eno)INT-32767, ENO TRUEflag OVERFLOWthe argument’s overflow, not ADD’s
ADD(IN1 := INT#1, IN2 := INT#1, NOT ENO => eno)INT2, ENO FALSE—ENO negated
REAL_TO_INT(IN := REAL#40000.0, ENO => eno)INTunchanged, ENO FALSEflag CONVERSION
LEFT(IN := 'abc', L := 5, ENO => eno)STRING'abc', ENO FALSEflag STRING_POSITION
CONCAT(EN := FALSE, IN1 := 'a', IN2 := 'b')STRINGunchanged—
MAX(EN := TRUE, IN1 := INT#1, IN2 := INT#2)INT2—EN without ENO

The same holds for the project’s own FUNCTIONs, those with effects too

  • an in-out, a VAR_EXTERNAL written, an output taken: with EN = FALSE the function is not called, so its in-outs and globals stay as they were and its outputs are not stored; ENO is not cleared by a flag from storing an output (into a subrange, clamped), only by one the function raised. The harness case fneffen runs each, with values worked by hand.

A call with EN inside another’s arguments is one of its inputs: not evaluated when the outer EN is FALSE, so nothing of it runs; with its own EN FALSE the statement is left undone, the outer call having no input to work on. An inner call’s flag is an argument’s to the outer: ADD(IN1 := ADD(IN1 := t, IN2 := 1, ENO => e2), IN2 := 0, ENO => e1) with t 32767 clears e2 and leaves e1 TRUE. A FUNCTION giving an array or a structure takes EN too, a := Make(EN := go, x := 4); with EN FALSE the store is left undone. A statement left undone faults on nothing it computes after, as one whose conversion failed (Conversions). The harness case nesten runs these.

ExpressionTypeResultFlagNote
ADD(EN := TRUE, IN1 := ADD(EN := TRUE, IN1 := INT#1, IN2 := INT#2), IN2 := INT#3)INT6—nested
ADD(EN := TRUE, IN1 := ADD(EN := FALSE, IN1 := INT#1, IN2 := INT#2), IN2 := INT#3)INTunchanged—the inner’s EN FALSE undoes the statement

On a function block call

t(EN := c, IN := x, PT := T#1s, Q => q, ENO => ok); follows the same rules (decided 2026-11-08):

  • EN = FALSE: the block is not called. Its inputs are neither evaluated nor set in the instance, its body does not run — a timer or counter stays as it was — its outputs are not taken (q keeps its value), and ok is FALSE. Nothing is flagged.
  • ENO is FALSE when a flag is raised while the block runs, in its body or anything it calls; not one from computing its inputs or from storing its outputs.
  • A block that declares EN or ENO itself gets them as plain parameters, and its body decides.

The harness’s fbenable and fbskip cases run these. ENO is taken into a BOOL variable, an element, a field or a bit of a bit string (ENO => ok[i], NOT ENO => w.3), found - its index checked - before the block runs, as an output’s target is (the harness case enointo).

On a SPLIT

SPLIT_DATE(EN := run, IN := days[i], YEAR => y, MONTH => m, DAY => d, ENO => ok);
  • EN = FALSE: nothing is split. IN is not evaluated - days[i] with i out of bounds does not fault - every output keeps its value, and ok is FALSE.
  • ENO is FALSE when a part does not fit its output - the year into a USINT - besides being wrapped and flagged CONVERSION. Unlike a block’s output, a SPLIT’s output has no type of its own: the call picks it, so the narrowing is the call’s own work (decided 2026-11-08, florin; dependencies).

The harness’s splitenable case runs these.

Set in a POU’s own body

Every FUNCTION and FUNCTION_BLOCK has ENO without declaring it: TRUE as each run starts, its body may read it and set it (decided 2026-11-08). The caller’s ENO is FALSE when the body set it FALSE, or a flag was raised while it ran — ENO := TRUE cannot hide an overflow.

FUNCTION half : INT
VAR_INPUT x : INT; END_VAR
half := x / 2;
ENO := x >= 0;          (* half(x := -4, ENO => ok): ok is FALSE *)
END_FUNCTION

A PROGRAM has no ENO. The harness’s enobody case runs these.