S7-300 FB14 Error 20: Fixing Parallel GET Job Limit on CPU 317

David Krause12 min read
S7-300SiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Problem Description

A peer-to-peer S7-300 installation exhibits an intermittent data-read failure when polling a remote CPU over Ethernet. The configuration consists of two S7-300 stations each fitted with a CP 343-1 communications processor. A bidirectional, unspecified S7 connection has been configured on the partner station, and the project containing the user program on the master station cannot be modified. The task is to read 33 variables of type DINT from different data blocks on the master PLC.

The reading PLC implements this by calling FB14 "GET" from the STEP 7 Standard Library 33 separate times, each in its own network with a separate instance DB (DB60 through DB92). With all 33 calls active in OB1, the following symptoms appear:

  • Networks 1 through 7 and 16 through 23 read correctly. NDR rises, ERROR remains FALSE, STATUS = 0.
  • All other networks (for example, network 8) return NDR = FALSE, ERROR = FALSE, STATUS = 0. The instance DBs of the failing networks never receive data.
  • When the program is reduced to a single calling network (e.g., network 8 alone), the read completes and the DINT is delivered.

Once the technician monitors STATUS on the failing calls, the output returns the constant value 20 (decimal) / 0014 hex. This is the only symptom that is required to identify the root cause.

Critical diagnostic step: Always evaluate STATUS when ERROR = TRUE or when NDR = FALSE after the first call. A silent zero-status on a multi-call configuration usually means the job was never accepted, not that it succeeded.

System Configuration

Component Value / Catalog Number
Local CPU S7-300 CPU 317-2 DP (6ES7317-2AK14-0AB0 or similar)
Partner CPU S7-300 (DP), project read-only
Communications processor (both stations) CP 343-1 (6GK7343-1EX30-0XE0 or compatible)
Connection type Unspecified S7 connection (bidirectional)
User program STEP 7 V5.x, FB14 "GET" with instance DBs DB60–DB92
Poll mechanism Sequential timer-driven calls in OB1 (0–3 s = DB60, 3–6 s = DB61, ..., 99–102 s = DB93)
Polling cycle 0–102 s active, 102–110 s idle

The block layout (1 network per DB) is acceptable from a programming standpoint; the failure is not a syntactic problem with FB14. The error is in how the 33 instances are scheduled against the CPU's communication resources.

Root Cause: CPU Communication Resource Exhaustion

For the S7-300 family, every active call to a communication function block (BSEND/BRCV, PUT/GET, USEND/URCV, ISO-on-TCP send/receive, etc.) consumes an entry from the CPU's communication-job table. The maximum depth of this table is fixed by the CPU type and is not user-configurable beyond the S7-connection count.

For the CPU 317-2 DP, the relevant data-sheet values from the SIMATIC S7-300 CPU 31xC and CPU 31x - Technical Data manual are:

Resource CPU 317-2 DP (typical)
Maximum S7 connections (total, CPU + CP) 16 (firmware-dependent; 32 on newer 6ES7317-2EK14)
Reserved for PG / OP / S7 routing 4 (2 PG + 1 OP + 1 routed minimum)
Available for user S7 connections 12 nominal, often 8 in practice
Parallel PUT/GET jobs on a single S7 connection 1 (configurable only via the connection's "Operating Mode")
Total parallel communication jobs (CPU-wide) 8 (FB-call resources, "Communication jobs" tab in PLC → Properties → Communication)

The error code 20 / 0x0014 returned by FB14 maps in the STEP 7 online help ("FB14 / FB15 - PUT / GET - Error Information") to:

"The maximum number of parallel jobs has been exceeded. The job could not be carried out because all communication resources of the CPU are occupied."

This is the exact scenario in the failing installation: the technician had 33 FB14 instances being triggered inside a single 3-second time slice, far in excess of the CPU 317-2 DP's eight parallel-job pool. Some instances slip through (the first 7 in the current cycle, plus 8 more from a previous cycle whose status word was still valid), and the remaining ~18 are rejected with STATUS = 20.

Why a Silent STATUS = 0 Also Appears

STEP 7's documentation allows ERROR = FALSE, STATUS = 0 to be reported on the rising edge of REQ when the job is queued but not yet executed. When the job is subsequently rejected by the resource manager, the STATUS word of the instance DB is overwritten with the failure code on the next call. In ladder logic where each call is one-shot on a timer pulse, the STATUS observed by the technician is the result of the last execution, not the queued one. This is why the symptoms flip between "some networks work" and "networks show zero" depending on which 8 instances win the resource race in a given OB1 pass.

Important rule: In any FB14/FB15 application, latch STATUS into a separate word the moment ERROR goes high. Do not rely on the instance-DB status to be visible from a single-shot network.

Diagnostic Procedure

  1. Open the STEP 7 project for the reading PLC and go to PLC → Properties → Communication. Note the values of S7 connections configured and Communication jobs (resources for parallel communication functions).
  2. Open PLC → Diagnostics/Setting → Communication with the CPU online. The table Communication Jobs shows the live state of all active jobs. A count equal to the maximum means the resource pool is saturated.
  3. In the offline program, count the number of FB14/FB15, FB12/FB13, FB20/FB21/FB22/FB23, FC5/FC6, and AG_SEND/AG_RECV calls that can be active in the same OB1 pass. Subtract any calls that are gated by an EN input that is permanently FALSE (they still consume a slot on some firmware versions).
  4. Insert a temporary network that latches iSTATUS from each instance DB into a global data block on every call: L "db_inst".STATUS; T "db_diag".status[i] with i as the loop index.
  5. Run the program and trigger all 33 timer slots. Confirm that exactly 8 (or whatever the limit is) jobs complete, and the remaining 25 show STATUS = 0014h.

Solution: Batching the GET Calls

The fix is to never trigger more FB14 jobs in parallel than the CPU's communication-job pool allows. With the CPU 317-2 DP set to the default of 8 parallel jobs, that means a maximum of 8 GET instances active at once. The remaining 25 must be either gated out or scheduled sequentially.

Option A: Sequential Polling (Recommended)

Replace the 33 single-shot networks with a single network containing an indexed call to FB14, advanced by a cyclic interrupt (e.g., OB35 at 100 ms) or by a longer timer. One GET per OB cycle guarantees the job is always within the resource limit.

// OB1 - call sequence manager
CALL FB 100, DB100  // "GET_Scheduler" - user block
  REQ     :=  M10.0    // tick from OB35 / cyclic interrupt
  CYCLE_MS := 200      // time between successive GETs
  LAST_DB := 92        // DB92 is the 33rd instance
  NDR     := M10.1
  ERROR   := M10.2
  STATUS  := MW12
  // .. user logic ..\code>

The internal block increments a counter ix on every REQ rising edge and calls FB14 with the instance DB DB[60 + ix], advancing ix on NDR or ERROR. A 200 ms cycle reads 33 blocks in 6.6 s, well within the existing 110 s loop budget.

Option B: Group Polling (Faster, Higher CPU Load)

Group the 33 DINTs into 8 batches of 4 blocks each, where each batch performs 4 GETs to the same target DB range and then waits for all 4 to complete before advancing. This keeps 8 jobs in flight constantly and reads all 33 DINTs in roughly 4× the per-call latency, but it stresses the CPU's OB1 time budget.

// Group 1 - active while BatchSel = 0
      A   M 20.0
      CC  FB14, DB60    // READ  DBD0   -> DB120.DBD0
      A   M 20.0
      CC  FB14, DB61    // READ  DBD4   -> DB120.DBD4
      A   M 20.0
      CC  FB14, DB62    // READ  DBD8   -> DB120.DBD8
      A   M 20.0
      CC  FB14, DB63    // READ  DBD12  -> DB120.DBD12

Use a small step chain (BatchSel = 0..7) to enable one group at a time, advancing on NDR of the last instance in the group.

Option C: Single GET with Larger SDT

If the 33 DINTs are at known, contiguous offsets across the 33 source DBs, fold them into a single fetch with a larger SDT (Source Data Type) area. This reduces 33 GETs to 1 GET and removes the resource problem entirely. It requires the source data layout to be known, which is usually not the case on a partner project that cannot be modified, but it is the most efficient option when possible.

Configuration Changes That Will Not Help

Two configuration paths that look promising but do not fix error 20:

  1. Increasing the number of S7 connections in NetPro. The CPU 317-2 DP allows multiple S7 connections, but FB14/FB15 are tied to one specific connection ID. Adding more connections does not increase the number of jobs that can run on the one connection the FB is using.
  2. Reusing the same instance DB for all networks. All 33 calls using FB14, DB60 still trigger 33 jobs; instance DBs are scratch-pad storage, not resource handles. Reusing DB60 is actually counterproductive, as each call will overwrite the previous STATUS and the diagnostic picture is lost.

Step-by-Step Implementation (Option A)

  1. Create a new FB (for example FB100 "GET_Scheduler") with instance DB100 as a static store for ix (INT) and busy (BOOL).
  2. Inside FB100, on a rising REQ, call FB14 with REQ = TRUE, the connection ID of the unspecified S7 connection, and the source area = P#DB[60+ix].DBX0.0 BYTE 4 (or wherever the DINT sits in each partner DB).
  3. Map the output to NDR_OUT, ERROR_OUT, STATUS_OUT, and copy the received DINT into DB130.DBD[ix*4].
  4. On NDR_OUT rising or ERROR_OUT rising, advance ix by 1 modulo 33. On ERROR_OUT, log STATUS_OUT to a diagnostic ring buffer and continue.
  5. Wire OB35 (100 ms) to a pulse generator that produces a 1-cycle TRUE on M10.0 every 200 ms. Pass M10.0 to FB100.REQ.
  6. From OB1, call only CALL FB100, DB100. Remove all 33 individual FB14 networks.
  7. Download the program to the CPU in STOP and restart.

Verification

  1. Open a watch table on the new DB130 containing the 33 received DINTs. All 33 should now be updated every 200 ms × 33 = 6.6 s.
  2. In PLC → Diagnostics/Setting → Communication online, confirm that the "Communication Jobs" table never shows more than one job with the ID of the S7 connection used for GET.
  3. Force a STOP on the partner CPU. STATUS on the next call should be 0005h (partner in STOP). Confirm the error latch mechanism captures it.
  4. Disconnect the Ethernet cable between the CP 343-1 modules. STATUS should be 0001h (connection error). Reconnect and confirm that NDR resumes within 1 s of cable restoration.
  5. Cycle the partner CPU power. The GET should re-establish automatically on the next REQ; the S7 connection is unspecified and therefore initiated by the local station, so no NetPro download on the partner is required.

Best Practices for S7-300 PUT/GET on CP 343-1

  • Always assume the default 8-job pool when sizing GET/PUT traffic. Calculate worst-case latency as max_jobs × (call_processing_time + partner_ack_time) and check it against the application cycle time.
  • Latch STATUS on every ERROR rising edge into a separate diagnostic DB. The STEP 7 online help for FB14/FB15 enumerates all status codes - the most important are 0x0001 (connection), 0x0005 (partner STOP), 0x0006 (data type), 0x0014 (job limit), and 0x0002 (negative ack from partner CPU).
  • On the SIMATIC NET CP 343-1 - Manual, note that the CP provides additional connection resources, but the CPU-side resource limit applies to the FB14/FB15 function calls, not to the underlying CP connection.
  • For very large polling workloads (more than 50 DINTs/cycle), migrate to FB12 / FB13 (BSEND / BRCV) on a single ISO-on-TCP connection - these support larger data blocks and use only 1 communication job per send/recv cycle.
  • If the partner project is also accessible, prefer an unspecified S7 connection on the reading side only; the partner then has no project-time dependency on connection ID changes.
  • Do not use EN gating to "save" resources - the S7-300 firmware still allocates a job slot for any FB-call token that is in the code path. Move gated calls into a different OB (e.g., OB35 at a lower rate) to keep the OB1 footprint clean.

Quick Reference: FB14 Error Codes Relevant to This Failure

STATUS (hex) STATUS (dec) Meaning Action
0000 0 Job queued / no error Wait for NDR
0001 1 Connection error (cable / CP / partner down) Check physical layer, CP343-1 LEDs
0002 2 Negative ack from partner CPU Check partner DB exists, partner in RUN
0003 3 DB/DX does not exist on partner Correct partner DB number
0004 4 Error in partner DB Check partner DB length and consistency
0005 5 Partner CPU in STOP Restart partner
0006 6 Data type mismatch (SDT) Recheck SDT length and alignment
0014 20 Max parallel jobs exceeded Batch the GET calls (this article)
0081 129 Partner busy / no resources Reduce partner-side load, retry

Frequently Asked Questions

What does FB14 error code 20 mean on an S7-300 CPU 317?

FB14 error code 20 (0x0014 hex) means the maximum number of parallel PUT/GET jobs on the CPU has been exceeded. The CPU 317-2 DP has a default pool of 8 communication jobs; triggering more than 8 simultaneous FB14 calls returns 0x0014 on the rejected instances.

How many simultaneous FB14 GET calls can the CPU 317-2 DP handle?

Eight by default. The exact value is shown in STEP 7 under PLC → Properties → Communication → "Communication jobs". On a CPU 317-2 DP with firmware V3.x or higher, do not assume more than 8 in any cycle.

Does adding a second S7 connection in NetPro increase the number of parallel GET jobs?

No. Each FB14/FB15 instance is bound to a specific connection ID. The 8-job limit is CPU-wide across all connections, not per-connection. Multiple connections do not multiply the available job slots.

Can I reuse the same instance DB for all 33 FB14 calls to save resources?

Reusing one instance DB does not change the resource usage; each call still consumes a job slot. It also overwrites the STATUS word, destroying diagnostic data. Use a scheduler block with separate instance DBs or a single FB100 that updates a results DB.

What is the fastest way to read 33 DINTs from a read-only S7-300 master via CP 343-1?

Use a single indexed FB14 scheduler in OB35 at 200 ms, advancing one DB per call. That yields a 6.6 s full refresh, uses 1 communication job at a time, and keeps the program under 8 parallel jobs. For very large fetches, consolidate the 33 DINTs into one SDT and reduce to a single FB14 call.

Back to blog