Debugging¶
Note
Debugging is early and in development. Breakpoints, stepping, and variable inspection work for Structured Text programs, but some capabilities are missing or limited. Each section notes the limits that apply to it.
The IronPLC extension debugs Structured Text programs: set breakpoints on source lines, step through the code, and inspect variables while the program is paused.
Debugging is driven by ironplcvmd, which installs alongside the ironplcc compiler. There is no separate debug extension to install. See ironplcvmd for the server itself.
Before You Start¶
Debugging needs two things:
Starting a Session¶
To debug the file in the active editor:
Open a Structured Text file.
Set a breakpoint by clicking the gutter to the left of a line number.
Press F5.
No launch.json is required. When you press F5 with no debug
configuration, the extension debugs the active file.
The extension compiles the file to a temporary .iplc container, starts
ironplcvmd, and runs the program. Compiler output appears in the
IronPLC Debug output channel
().
Launch Configuration¶
To keep a configuration, create a .vscode/launch.json from the
Run and Debug view. The extension supplies a starting
configuration:
{
"version": "0.2.0",
"configurations": [
{
"type": "ironplc",
"request": "launch",
"name": "IronPLC: Debug Active File",
"program": "${file}",
"stopOnEntry": false
}
]
}
Attributes¶
Attribute |
Type |
Description |
|---|---|---|
|
string |
Required. Path to a Structured Text source file or a compiled
|
|
boolean |
Pause before the first scan cycle begins. Defaults to |
|
number |
Stop the session after this many scan cycles. |
Only the launch request is supported. There is no attach
configuration: the debugger starts the program it debugs.
A program that is neither a source file nor a .iplc container is
rejected before the session starts. See E0005.
Debug a Compiled Container¶
Point program at a container to debug a whole project rather than a
single file:
{
"type": "ironplc",
"request": "launch",
"name": "IronPLC: Debug Project",
"program": "${workspaceFolder}/myproject.iplc"
}
Produce the container with the build task or with ironplcc compile . -o myproject.iplc. Breakpoints still bind to your source files: the container records which file each line came from.
Rebuild the container after changing the source. The debugger launches the container as it finds it and does not recompile it.
Limiting a Run¶
A PLC program does not finish. It scans until something stops it, so a debug session with no breakpoint runs until you press Stop.
Set scanLimit to end the session after a fixed number of scan cycles:
{
"type": "ironplc",
"request": "launch",
"name": "IronPLC: Debug One Scan",
"program": "${file}",
"scanLimit": 1
}
Breakpoints¶
Click the gutter to the left of a line number to set a breakpoint, or press F9 on the current line. Set breakpoints before you launch or while the program is paused.
Breakpoints bind to lines that generate code. A breakpoint on a blank line, a comment, or a declaration moves down to the next line that does, and the dot in the gutter moves with it to show where the breakpoint actually bound.
A breakpoint that cannot bind — on END_IF, on END_PROGRAM, or past
the end of the code — stays unverified, and the editor shows it as a hollow
dot. The session still runs; that breakpoint never pauses it.
A breakpoint in a scan-cycle program pauses every scan, not once. Continuing from a breakpoint runs to the same breakpoint on the next cycle.
Note
Breakpoints are line-level and unconditional. Conditional breakpoints, hit counts, logpoints, function breakpoints, data breakpoints, and inline (column) breakpoints are not supported. A breakpoint set on a column within a line binds to the whole line.
Execution Control¶
While the program is paused:
Action |
Shortcut |
Behavior |
|---|---|---|
Continue |
F5 |
Resume until the next breakpoint, the scan limit, or the program ends. |
Step Over |
F10 |
Run the current line, including any call it makes, and stop on the next. |
Step Into |
F11 |
Stop on the first line of the function or function block being called. |
Step Out |
Shift+F11 |
Run to the end of the current POU and stop in its caller. |
Step Scan Cycle |
None |
Run the rest of the current scan cycle and stop at the start of the next one. |
Stop |
Shift+F5 |
End the session. |
Scan Stepping¶
Step Scan Cycle is on the debug toolbar and in the Command Palette. It is the scan-cycle equivalent of Step Over: one press advances the program by exactly one cycle, no matter how many lines that takes.
The stop lands on the first line of the next cycle. The cycle you stepped
has finished — its outputs are written and scanCount in the
Runtime scope has gone up by one — so the values you see are
that cycle’s results.
A breakpoint reached partway through the cycle stops there instead, the same way one reached during Step Over does. The scan step ends at that breakpoint; press Step Scan Cycle again to run out the rest of the cycle.
If the cycle you step is the last one allowed by scanLimit, the session
ends rather than stopping again.
Inspecting Variables¶
The Variables view shows two scopes while the program is paused.
Program¶
The variables your program declares, by name and type:
Counter : DINT = 42
Running : BOOL = TRUE
Label : STRING = 'ready'
Values refresh at every stop.
Runtime¶
State the virtual machine owns rather than your program:
Variable |
Type |
Description |
|---|---|---|
|
|
The number of scan cycles the program has completed. It increments as you continue, which is how you tell one scan from the next. |
|
|
The virtual machine’s monotonic clock, in milliseconds, as of the start
of the scan cycle you are paused in. This is the value a program reads
from |
Note
Values are read-only. Setting a variable while paused, forcing a value, and watch expressions are not supported, and expressions typed into the Debug Console are not evaluated. To change what the program does, edit the source and launch again.
Call Stack¶
The Call Stack view names each frame by its POU and highlights the paused line in the editor. Stepping into a function or function block pushes a frame; stepping out pops it.
When the Program Traps¶
A runtime error — a division by zero, an out-of-range array index — stops the program at the failing instruction and reports the problem code. The session stays open so you can inspect the state that caused it: the Variables and Call Stack views still work. Execution cannot resume from a trap; stop the session and launch again.
See Problem Code Index for the problem codes the runtime reports.
Settings¶
ironplc.debugServerPath overrides the discovery of the debug server. See
Settings Reference.
Supported Languages¶
The debugger is registered for Structured Text (.st) and TwinCAT POU
(.TcPOU) files. Breakpoints can be set in both.
See Also¶
Debugging Your Program — debug a program for the first time
Debug a Program — task recipes
ironplcvmd — the debug server
Problem Codes — extension problem codes