Problem Statement
When programming an S7-300 CPU with TIA Portal Professional V11 SP2 Update 5 and using STL (Statement List) with indirect addressing, the absolute byte/bit offsets for elements inside an ARRAY data type do not appear in the Offset column of the data block editor. Only the parent tag (the array itself) shows an offset; the indexed members show empty cells.
This breaks the engineer's ability to compute pointer arithmetic correctly. STL indirect addressing operators such as OPN DB[AR1,P#0.0], L DBB[AR1,P#0.0], or the legacy LAR1 P##Tag + +AR1 P#2.0 pattern require a known byte offset for every member. If TIA Portal refuses to publish that offset, the programmer must fall back to manual counting, which is error-prone on packed symbolic DBs.
The phenomenon is specific to the S7-300/400 storage model: TIA Portal optimises symbolic DBs to save memory, and the absolute address of an array element is not stable until the block is compiled in S7-300/400 compatible mode.
Affected Products and Versions
| Component | Version Tested | Behaviour |
|---|---|---|
| TIA Portal STEP 7 Professional | V11 SP2 Update 5 | Offsets hidden for array members |
| TIA Portal STEP 7 Professional | V12 / V13 / V14 | Same behaviour; resolved only by compatibility flag |
| CPU family | S7-300 / S7-400 (any firmware) | Compatibility flag available |
| CPU family | S7-1200 / S7-1500 | STL not supported; symbolic only, no offsets exposed |
Per the Siemens support entry 109800438 - FAQs and manual information for indirect addressing in STEP 7 (TIA Portal), indirect-addressing behaviour is consistent from V11 onwards, and switching projects between V11 and newer versions does not alter the offset-publication logic for arrays.
Root Cause Analysis
TIA Portal maintains two parallel storage layouts for every data block:
- Optimised symbolic layout (default for S7-1200/1500, also offered for S7-300/400 in V11). The compiler packs tags to minimise memory consumption. Tag order in the editor is not the same as physical address order. The Offset column is therefore suppressed for members of complex types whose byte position is not fixed at edit time.
- Absolute (S7-300/400 compatible) layout. Tags are stored in the order they appear in the declaration table, with no padding, and every member receives a stable, visible byte/bit offset. This is the layout the legacy STL programmer expects.
When you create a DB in V11 the default is Optimised. The TIA Portal declaration grid will show:
- Offset for scalar tags at the top of the DB.
- Offset for the first member of a STRUCT.
- Offset for the parent tag of an ARRAY.
- No offset for ARRAY elements (empty cells, no tooltip).
This is a deliberate design decision: TIA Portal does not want you writing code that depends on the layout of an optimised block, because the linker is free to reorder the data later. Since STL cannot be rewritten automatically, the only honest fix is to tell the compiler not to optimise the block.
Prerequisites
- TIA Portal STEP 7 Professional V11 SP2 or later installed with administrator rights.
- A project targeting an S7-300 or S7-400 CPU. STL is unavailable on S7-1200 and S7-1500 in this version family.
- PLC programming rights on the project (read/write to the DB object).
- Source backup of the affected DB, in case the recompile introduces alignment differences with the HMI or another controller that consumes the same offsets.
Resolution Procedure
Two actions are required, in this order. Skipping step 1 will leave the column empty even after step 2.
Step 1 - Recompile the Existing Data Block
- Open the project in TIA Portal V11 SP2.
- Right-click the data block in the project tree and select Compile > Software (rebuild all blocks). A single-block compile is sometimes insufficient because cross-references from other blocks are not refreshed.
- Wait for the message Compilation finished without errors in the Inspector window. Warnings about Initial value mismatch are tolerable.
- Re-open the DB and inspect the Offset column. If member offsets are still hidden, proceed to step 2.
Step 2 - Recreate the DB with S7-300/400 Compatibility
- In the project tree, select Program blocks > Add new block > Data block.
- In the Add new block dialog, choose the type DB and the option Data block with assigned user-defined data structure (this is the default).
- Open the new DB and declare the same tags, or copy the declaration table from the old DB using Edit > Copy / Edit > Paste in the declaration view.
- Right-click inside the declaration table (or the DB header in older V11 builds) and choose Properties > Attributes.
- Clear the checkbox Optimised block (German: Optimierter Baustein). In the V11 dialog the option may be labelled IEC-compliant with a sub-option Non-optimised, S7-300/400 compatible. Tick the compatibility option.
- Click OK and confirm the warning that the DB will be recreated with a new symbolic name suffix.
- Reassign the new DB to every call site (OB1, FB, FC) using Right-click > Go to > Usage on the old DB before deletion.
- Compile the entire program again with Software (rebuild all blocks).
After these two steps the Offset column of the recreated DB will show the byte address of every scalar tag, every member of a STRUCT, and every element of an ARRAY, exactly as STEP 7 V5.5 did.
Alternative Workarounds if Compatibility Mode Is Not Available
In some V11 SP2 service packs the Optimised block checkbox is greyed out because the CPU firmware does not accept non-optimised blocks. The following patterns let you compute offsets manually or eliminate the need for them.
Workaround A - Replace the ARRAY with Individual Tags or a STRUCT
TIA Portal publishes offsets for Struct members and for individual tags, but not for ARRAY elements. The transformation is mechanical:
| Original ARRAY | Replacement STRUCT | Effective offset |
|---|---|---|
myArray : ARRAY[0..10] OF DWord |
myArray_0, myArray_1, ... myArray_10 : DWord |
0, 4, 8, 12, ... 40 |
myArray : ARRAY[0..10] OF DWord |
myArray : STRUCT |
0, 4, 8, 12, ... 40 |
Either form restores the Offset column. The downside is that indexed loops such as FOR i := 0 TO 10 DO myArray[i] := ...; END_FOR must be rewritten as an unrolled or computed loop over the member names.
Workaround B - Use the P## Operator to Recover the Runtime Address
If the compiler refuses to publish the offset, the STL code can still discover the address at runtime with the P## operator:
// Symbolischer Aufbau, ANY-konformer Pointer
LAR1 P##myArray // Basisadresse in AR1
+AR1 P#0.0 // Element 0 (Offset 0)
+AR1 P#4.0 // Element 1 (Offset 4)
L DBD [AR1,P#0.0] // Lade DWord an AR1
T MD 100
// Index-Berechnung
L #i // i = 0..10
L 4 // 4 Bytes pro DWord
*D
SLD 3 // *8 -> Pointergranularitaet
LAR1 P##myArray
+AR1
L DBD [AR1,P#0.0]
This pattern matches the syntax documented for S7-1500 STL in Indirect addressing in STL (S7-1500) - STEP 7 documentation. The same operators apply to S7-300/400 in V11.
Workaround C - Submit a Support Request
Siemens Support (Entry ID 109800438) accepts enhancement requests. A formal request is the right channel when the project is locked to an optimised DB because of an HMI tag binding that cannot be broken.
STL Indirect Addressing Operators - Quick Reference
| Operator | Operand | Effect |
|---|---|---|
LAR1 |
P##Tag |
Load the absolute address of Tag into AR1. |
+AR1 |
P#n.m |
Add the byte/bit offset to AR1. |
L DBB[AR1,P#0.0] |
memory-indirect, area-internal | Load byte at AR1 + 0.0. |
OPN DB[AR1,P#0.0] |
memory-indirect, area-crossing | Open DB whose number is the byte at AR1 + 0.0. |
L DBB[AR2,P#0.0] |
register-indirect, area-internal | Same as above with AR2. |
L DBB[MD 200] |
DB-indirect via MD | Pointer is supplied in a tag. |
All five forms require that the pointed-to tag (or the element computed from it) has a known absolute address. This is exactly what the compatibility flag provides.
Verification Procedure
- Open the recreated DB. Each tag, every STRUCT member, and every ARRAY element must show a non-empty byte/bit offset in the rightmost column.
- Trigger an Online > Compile and download blocks pass to the S7-300 CPU and watch for the diagnostic message No compilation errors.
- Place a watchpoint on the first ARRAY element, force a value into it from the watch table, and read back. The value at the byte offset shown in the editor must match the value at the byte computed in STL using the
+AR1pattern. - Download the program to the target and observe the diagnostic buffer. An entry Area length error writing indicates that the pointer arithmetic drifted, which means the DB is still optimised.
- Open the cross-reference (Ctrl+Shift+F) and confirm that the new DB is referenced by every block that used to reference the old one.
Troubleshooting Matrix
| Symptom | Likely cause | Fix |
|---|---|---|
| Offset column empty for ARRAY members even after recompile | DB still optimised | Recreate DB with S7-300/400 compatibility flag cleared |
| Compatibility flag greyed out | CPU firmware does not support non-optimised DBs (S7-1200/1500 family) | Switch to S7-300/400 or use runtime P## pointer trick |
| Offsets jump by more than the tag size | Alignment padding inserted by compiler | Pack tags manually, set Pack attribute on the STRUCT |
| Cross-reference still points to old DB name | DB recreated but call sites not updated | Right-click old DB > Go to usage; replace with new name; recompile |
| HMI tags lose connection after DB swap | HMI binds to absolute address, not symbol | Re-bind HMI tags to the new DB; or keep old DB and add a new non-optimised DB only for STL access |
STL instruction LAR1 P##myArray rejected |
Compiler cannot resolve symbol on optimised DB | Apply compatibility fix or use individual tags |
| Runtime Area length error | Pointer index exceeded array bounds | Bound-check the index before +AR1; ensure P# offset uses 8-bit granularity |
Edge Cases and Field Notes
- Multi-instance DBs: the compatibility flag is set on the instance DB, not on the FB itself. The FB may remain optimised; the instance DB that the STL block opens must be non-optimised.
- HMI connections: WinCC V11 will still bind to absolute addresses, so changing the DB to non-optimised does not break HMI communication. The opposite case (HMI binding to optimised-only symbols) requires the HMI to use symbolic access; check the HMI tag properties Access mode.
- Upgrade to V12+: the behaviour carries over. V12 added a clearer label Data block with optimised access, but the underlying flag is the same. The TIA Portal upgrade checklist (see Siemens entry 109800438) recommends a fresh compile after upgrade.
-
Arrays of STRUCTs: even with the compatibility flag, only the parent array tag gets a single offset; the individual elements of the inner STRUCT will display offsets. The byte stride of one array element equals the inner STRUCT size; you still cannot see the inner offset for the array element itself in the grid, but
P##myArray[i]will compute it at runtime. - BOOL packing: in non-optimised mode TIA Portal may insert padding between BOOL members for byte alignment. Add an explicit BYTE tag if bit-precise addressing is required.
-
S7-1500 portability: if you plan to migrate the project to an S7-1500, convert the STL to SCL or LAD/FBD before migrating. S7-1500 accepts optimised DBs only; the offset arithmetic must be replaced by symbolic
myArray[i]access.
Safety Considerations
Non-optimised DBs allow direct memory access from any block. Ensure the STL code respects the array bounds; an out-of-range +AR1 P#x.y with x larger than the array length will silently overwrite the next tag in the DB and may corrupt process data. Use a comparison with the array length stored in a separate constant tag before the pointer arithmetic.
Related Siemens Documentation
- Entry 109800438 - Indirect addressing FAQ for STEP 7 (TIA Portal)
- Indirect addressing in STL (S7-1500) - TIA Portal documentation
Why does the Offset column show empty cells for ARRAY elements in TIA Portal V11?
Because the data block is in optimised storage mode. TIA Portal V11 only publishes stable byte/bit offsets for members of a non-optimised, S7-300/400-compatible DB. Clear the Optimised block attribute on the DB and recompile to restore the offsets.
Is the Optimised block option available on S7-1200 or S7-1500 CPUs?
No. S7-1200 and S7-1500 use optimised blocks exclusively and do not accept a non-optimised flag. They also do not support STL in V11; convert to SCL or LAD/FBD and use symbolic myArray[i] access instead of pointer arithmetic.
Can I keep my old DB and add a new non-optimised DB only for the STL block?
Yes. Create a new DB with the same tag layout, uncheck Optimised block, and have the STL code open the new DB explicitly with OPN DB n. The HMI and SCL blocks can keep using the original optimised DB.
What is the byte stride of ARRAY[0..10] OF DWord for pointer arithmetic?
Four bytes per element. The base address of element i is P##myArray + i * 4 in byte units, which corresponds to i * 4 * 8 = i * 32 in pointer granularity (P# units). Use +AR1 P#4.0 per step or a runtime calculation with *D and SLD 3.
Does the fix survive an upgrade to TIA Portal V12 or later?
Yes. The Optimised block attribute is preserved by the project upgrade. The offset-display behaviour for ARRAY elements is identical from V11 through V20. Re-verify the DB attribute after the upgrade and re-compile all blocks.